From 859c098747ce58dc9b88b662aac67a704af4614a Mon Sep 17 00:00:00 2001 From: franco Date: Tue, 16 Jun 2026 11:26:26 -0300 Subject: [PATCH 001/181] Fix nested comment warning in RX GCC ports (#550) The RX GCC assembly port contains an unclosed C-style comment in tx_thread_context_save.S. Because .S files are passed through the C preprocessor before assembly, the nested comment can trigger GCC warnings. Close the affected comment block without changing assembly instructions or runtime behavior. Signed-off-by: FranCDoc --- ports/rxv1/gnu/src/tx_thread_context_save.S | 2 +- ports/rxv2/gnu/src/tx_thread_context_save.S | 2 +- ports/rxv3/gnu/src/tx_thread_context_save.S | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/ports/rxv1/gnu/src/tx_thread_context_save.S b/ports/rxv1/gnu/src/tx_thread_context_save.S index 228c4991a..97ac6af9a 100644 --- a/ports/rxv1/gnu/src/tx_thread_context_save.S +++ b/ports/rxv1/gnu/src/tx_thread_context_save.S @@ -69,7 +69,7 @@ __tx_thread_context_save: ; SP+4 -> Saved R1 ; SP+8 -> Saved R2 ; SP+12-> Interrupted PC -; SP+16-> Interrupted PSW +; SP+16-> Interrupted PSW */ ; ; /* Check for a nested interrupt condition. */ ; if (_tx_thread_system_state++) diff --git a/ports/rxv2/gnu/src/tx_thread_context_save.S b/ports/rxv2/gnu/src/tx_thread_context_save.S index f08f24504..89fe833e5 100644 --- a/ports/rxv2/gnu/src/tx_thread_context_save.S +++ b/ports/rxv2/gnu/src/tx_thread_context_save.S @@ -79,7 +79,7 @@ __tx_thread_context_save: ; SP+4 -> Saved R1 ; SP+8 -> Saved R2 ; SP+12-> Interrupted PC -; SP+16-> Interrupted PSW +; SP+16-> Interrupted PSW */ ; ; /* Check for a nested interrupt condition. */ ; if (_tx_thread_system_state++) diff --git a/ports/rxv3/gnu/src/tx_thread_context_save.S b/ports/rxv3/gnu/src/tx_thread_context_save.S index 3fbfc3a18..e44373183 100644 --- a/ports/rxv3/gnu/src/tx_thread_context_save.S +++ b/ports/rxv3/gnu/src/tx_thread_context_save.S @@ -79,7 +79,7 @@ __tx_thread_context_save: ; SP+4 -> Saved R1 ; SP+8 -> Saved R2 ; SP+12-> Interrupted PC -; SP+16-> Interrupted PSW +; SP+16-> Interrupted PSW */ ; ; /* Check for a nested interrupt condition. */ ; if (_tx_thread_system_state++) From b880ffeadab06d008529fad99bb50457af4d9d16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 22 Jun 2026 08:03:46 -0400 Subject: [PATCH 002/181] Fixed SMP execution profile total getters (#553) Updated the SMP execution profile aggregate getters to copy each core's total into the matching output array element. Added a focused regression test for thread, ISR, and idle total getters. Co-authored-by: Codex --- test/smp/cmake/regression/CMakeLists.txt | 16 +++ .../execution_profile_test/tx_api.h | 40 ++++++ .../threadx_smp_execution_profile_get_test.c | 126 ++++++++++++++++++ .../smp_version/tx_execution_profile.c | 7 +- 4 files changed, 186 insertions(+), 3 deletions(-) create mode 100644 test/smp/regression/execution_profile_test/tx_api.h create mode 100644 test/smp/regression/threadx_smp_execution_profile_get_test.c diff --git a/test/smp/cmake/regression/CMakeLists.txt b/test/smp/cmake/regression/CMakeLists.txt index b448ae3e3..908ac5c72 100644 --- a/test/smp/cmake/regression/CMakeLists.txt +++ b/test/smp/cmake/regression/CMakeLists.txt @@ -162,3 +162,19 @@ foreach(test_case ${regression_test_cases}) target_link_libraries(${test_name} PRIVATE azrtos::threadx_smp) add_test(${CMAKE_BUILD_TYPE}::${test_name} ${test_name}) endforeach() + +add_executable(threadx_smp_execution_profile_get_test + ${SOURCE_DIR}/threadx_smp_execution_profile_get_test.c + ${REPO_ROOT}/utility/execution_profile_kit/smp_version/tx_execution_profile.c) +target_include_directories(threadx_smp_execution_profile_get_test + PRIVATE + ${SOURCE_DIR}/execution_profile_test + ${REPO_ROOT}/utility/execution_profile_kit/smp_version) +target_compile_definitions(threadx_smp_execution_profile_get_test + PRIVATE CTEST BATCH_TEST TEST_STACK_SIZE_PRINTF=4096) +if(NOT MSVC) + target_compile_options(threadx_smp_execution_profile_get_test PRIVATE -m64) + target_link_options(threadx_smp_execution_profile_get_test PRIVATE -m64) +endif() +add_test(${CMAKE_BUILD_TYPE}::threadx_smp_execution_profile_get_test + threadx_smp_execution_profile_get_test) diff --git a/test/smp/regression/execution_profile_test/tx_api.h b/test/smp/regression/execution_profile_test/tx_api.h new file mode 100644 index 000000000..aef253c6d --- /dev/null +++ b/test/smp/regression/execution_profile_test/tx_api.h @@ -0,0 +1,40 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Codex (GPT-5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +#ifndef TX_API_H +#define TX_API_H + +#define TX_THREAD_SMP_MAX_CORES 4U +#define TX_SUCCESS 0U +#define TX_NOT_DONE 20U +#define TX_NULL ((void *) 0) +#define TX_SMP_CORE_ID 0U + +typedef unsigned int UINT; +typedef unsigned long ULONG; +typedef void VOID; + +typedef struct TX_THREAD_STRUCT +{ + unsigned long long tx_thread_execution_time_total; + unsigned long tx_thread_execution_time_last_start; + struct TX_THREAD_STRUCT *tx_thread_created_next; +} TX_THREAD; + +#define TX_INTERRUPT_SAVE_AREA +#define TX_DISABLE +#define TX_RESTORE + +#endif diff --git a/test/smp/regression/threadx_smp_execution_profile_get_test.c b/test/smp/regression/threadx_smp_execution_profile_get_test.c new file mode 100644 index 000000000..ccfd3b2a4 --- /dev/null +++ b/test/smp/regression/threadx_smp_execution_profile_get_test.c @@ -0,0 +1,126 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Codex (GPT-5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/* This test verifies that the SMP execution profile aggregate getters copy every core value. */ + +#include +#include "tx_api.h" +#include "tx_execution_profile.h" + +extern EXECUTION_TIME _tx_execution_thread_time_total[TX_THREAD_SMP_MAX_CORES]; +extern EXECUTION_TIME _tx_execution_isr_time_total[TX_THREAD_SMP_MAX_CORES]; +extern EXECUTION_TIME _tx_execution_idle_time_total[TX_THREAD_SMP_MAX_CORES]; + +ULONG _tx_thread_system_state[TX_THREAD_SMP_MAX_CORES]; +UINT _tx_thread_preempt_disable; +TX_THREAD *_tx_thread_current_ptr[TX_THREAD_SMP_MAX_CORES]; +TX_THREAD *_tx_thread_execute_ptr[TX_THREAD_SMP_MAX_CORES]; +TX_THREAD *_tx_thread_created_ptr; +ULONG _tx_thread_created_count; + + +ULONG _tx_thread_smp_time_get(void) +{ + + return(0); +} + + +static UINT verify_time_values(EXECUTION_TIME *actual, EXECUTION_TIME *expected) +{ + +UINT core; + + + for (core = 0; core < TX_THREAD_SMP_MAX_CORES; core++) + { + + if (actual[core] != expected[core]) + { + + return(1); + } + } + + return(0); +} + + +int main(void) +{ + +EXECUTION_TIME thread_time[TX_THREAD_SMP_MAX_CORES]; +EXECUTION_TIME isr_time[TX_THREAD_SMP_MAX_CORES]; +EXECUTION_TIME idle_time[TX_THREAD_SMP_MAX_CORES]; +EXECUTION_TIME expected_thread_time[TX_THREAD_SMP_MAX_CORES]; +EXECUTION_TIME expected_isr_time[TX_THREAD_SMP_MAX_CORES]; +EXECUTION_TIME expected_idle_time[TX_THREAD_SMP_MAX_CORES]; +UINT core; +UINT status; + + + printf("Running SMP Execution Profile Get Test............................... "); + + for (core = 0; core < TX_THREAD_SMP_MAX_CORES; core++) + { + + expected_thread_time[core] = ((EXECUTION_TIME) 1000U) + ((EXECUTION_TIME) core); + expected_isr_time[core] = ((EXECUTION_TIME) 2000U) + ((EXECUTION_TIME) core); + expected_idle_time[core] = ((EXECUTION_TIME) 3000U) + ((EXECUTION_TIME) core); + + _tx_execution_thread_time_total[core] = expected_thread_time[core]; + _tx_execution_isr_time_total[core] = expected_isr_time[core]; + _tx_execution_idle_time_total[core] = expected_idle_time[core]; + + thread_time[core] = 0xFFFFFFFFFFFFFFFFULL; + isr_time[core] = 0xFFFFFFFFFFFFFFFFULL; + idle_time[core] = 0xFFFFFFFFFFFFFFFFULL; + } + + status = _tx_execution_thread_total_time_get(thread_time); + status += _tx_execution_isr_time_get(isr_time); + status += _tx_execution_idle_time_get(idle_time); + + if (status != TX_SUCCESS) + { + + printf("ERROR #1\n"); + return(1); + } + + if (verify_time_values(thread_time, expected_thread_time) != 0U) + { + + printf("ERROR #2\n"); + return(1); + } + + if (verify_time_values(isr_time, expected_isr_time) != 0U) + { + + printf("ERROR #3\n"); + return(1); + } + + if (verify_time_values(idle_time, expected_idle_time) != 0U) + { + + printf("ERROR #4\n"); + return(1); + } + + printf("SUCCESS!\n"); + return(0); +} diff --git a/utility/execution_profile_kit/smp_version/tx_execution_profile.c b/utility/execution_profile_kit/smp_version/tx_execution_profile.c index 735dbf147..3739475c1 100644 --- a/utility/execution_profile_kit/smp_version/tx_execution_profile.c +++ b/utility/execution_profile_kit/smp_version/tx_execution_profile.c @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ /**************************************************************************/ @@ -962,7 +963,7 @@ UINT core; for (core = 0; core < TX_THREAD_SMP_MAX_CORES; core++) { - *total_time = _tx_execution_thread_time_total[core]; + total_time[core] = _tx_execution_thread_time_total[core]; } /* Restore interrupts. */ @@ -1025,7 +1026,7 @@ UINT core; { /* Return the total time. */ - *total_time = _tx_execution_isr_time_total[core]; + total_time[core] = _tx_execution_isr_time_total[core]; } /* Restore interrupts. */ @@ -1088,7 +1089,7 @@ UINT core; { /* Return the total time. */ - *total_time = _tx_execution_idle_time_total[core]; + total_time[core] = _tx_execution_idle_time_total[core]; } /* Restore interrupts. */ From 32a68cc69ae87ece4d71f2426ca5725bcd3e3c64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 22 Jun 2026 08:07:16 -0400 Subject: [PATCH 003/181] Fixed private-timer timestamp issue in several ports (A5, A7, A9, R8) (#554) * Fixed Cortex-A9 SMP time source Updated Cortex-A9 SMP timestamp reads to use the global timer low counter instead of the decrementing private timer counter. Applied the change to GNU and AC5 ports. * Fixed remaining Arm SMP time sources Updated Cortex-A5, Cortex-A7, and Cortex-R8 SMP timestamp hooks so execution profiling uses incrementing time sources instead of the decrementing private timer count register. Cortex-A5 and Cortex-R8 now read the global timer count low register, matching the Cortex-A9 fix. Cortex-A7 now reads the generic timer physical count register. --------- Co-authored-by: Codex --- ports_smp/cortex_a5_smp/ac5/src/tx_thread_smp_time_get.s | 5 +++-- ports_smp/cortex_a5_smp/gnu/src/tx_thread_smp_time_get.S | 5 +++-- ports_smp/cortex_a7_smp/ac5/src/tx_thread_smp_time_get.s | 6 +++--- ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_time_get.S | 6 +++--- ports_smp/cortex_a9_smp/ac5/src/tx_thread_smp_time_get.s | 5 +++-- ports_smp/cortex_a9_smp/gnu/src/tx_thread_smp_time_get.S | 6 +++--- ports_smp/cortex_r8_smp/ac5/src/tx_thread_smp_time_get.s | 3 ++- 7 files changed, 20 insertions(+), 16 deletions(-) diff --git a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_smp_time_get.s b/ports_smp/cortex_a5_smp/ac5/src/tx_thread_smp_time_get.s index a378060e0..8c4b09710 100644 --- a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_smp_time_get.s +++ b/ports_smp/cortex_a5_smp/ac5/src/tx_thread_smp_time_get.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026-present Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -8,6 +9,7 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ ; +; Some portions generated by Codex (GPT-5). ; ;/**************************************************************************/ ;/**************************************************************************/ @@ -69,7 +71,7 @@ _tx_thread_smp_time_get MRC p15, 4, r0, c15, c0, 0 ; Read periph base address - LDR r0, [r0, #0x604] ; Read count register + LDR r0, [r0, #0x200] ; Read global timer count low register IF {INTER} = {TRUE} BX lr ; Return to caller @@ -78,4 +80,3 @@ _tx_thread_smp_time_get ENDIF END - diff --git a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a5_smp/gnu/src/tx_thread_smp_time_get.S index 7e399690a..04099aeff 100644 --- a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a5_smp/gnu/src/tx_thread_smp_time_get.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * Copyright (c) 2026-present Eclipse ThreadX contributors @ * @ * This program and the accompanying materials are made available under the @ * terms of the MIT License which is available at @@ -8,6 +9,7 @@ @ * SPDX-License-Identifier: MIT @ **************************************************************************/ @ +@ Some portions generated by Codex (GPT-5). @ @/**************************************************************************/ @/**************************************************************************/ @@ -71,7 +73,7 @@ _tx_thread_smp_time_get: MRC p15, 4, r0, c15, c0, 0 @ Read periph base address - LDR r0, [r0, #0x604] @ Read count register + LDR r0, [r0, #0x200] @ Read global timer count low register #ifdef __THUMB_INTERWORK BX lr @ Return to caller @@ -79,4 +81,3 @@ _tx_thread_smp_time_get: MOV pc, lr @ Return to caller #endif - diff --git a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_smp_time_get.s b/ports_smp/cortex_a7_smp/ac5/src/tx_thread_smp_time_get.s index 627d36f32..e3935200e 100644 --- a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_smp_time_get.s +++ b/ports_smp/cortex_a7_smp/ac5/src/tx_thread_smp_time_get.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026-present Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -8,6 +9,7 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ ; +; Some portions generated by Codex (GPT-5). ; ;/**************************************************************************/ ;/**************************************************************************/ @@ -68,8 +70,7 @@ EXPORT _tx_thread_smp_time_get _tx_thread_smp_time_get - MRC p15, 4, r0, c15, c0, 0 ; Read periph base address - LDR r0, [r0, #0x604] ; Read count register + MRRC p15, 0, r0, r1, c14 ; Read generic timer physical count IF {INTER} = {TRUE} BX lr ; Return to caller @@ -78,4 +79,3 @@ _tx_thread_smp_time_get ENDIF END - diff --git a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_time_get.S index 067f50d8c..9eb5b12c1 100644 --- a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_time_get.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * Copyright (c) 2026-present Eclipse ThreadX contributors @ * @ * This program and the accompanying materials are made available under the @ * terms of the MIT License which is available at @@ -8,6 +9,7 @@ @ * SPDX-License-Identifier: MIT @ **************************************************************************/ @ +@ Some portions generated by Codex (GPT-5). @ @/**************************************************************************/ @/**************************************************************************/ @@ -70,8 +72,7 @@ .type _tx_thread_smp_time_get,function _tx_thread_smp_time_get: - MRC p15, 4, r0, c15, c0, 0 @ Read periph base address - LDR r0, [r0, #0x604] @ Read count register + MRRC p15, 0, r0, r1, c14 @ Read generic timer physical count #ifdef __THUMB_INTERWORK BX lr @ Return to caller @@ -79,4 +80,3 @@ _tx_thread_smp_time_get: MOV pc, lr @ Return to caller #endif - diff --git a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_smp_time_get.s b/ports_smp/cortex_a9_smp/ac5/src/tx_thread_smp_time_get.s index 5b67b2836..d656d1c22 100644 --- a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_smp_time_get.s +++ b/ports_smp/cortex_a9_smp/ac5/src/tx_thread_smp_time_get.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026-present Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -8,6 +9,7 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ ; +; Some portions generated by Codex (GPT-5). ; ;/**************************************************************************/ ;/**************************************************************************/ @@ -69,7 +71,7 @@ _tx_thread_smp_time_get MRC p15, 4, r0, c15, c0, 0 ; Read periph base address - LDR r0, [r0, #0x604] ; Read count register + LDR r0, [r0, #0x200] ; Read global timer count low register IF {INTER} = {TRUE} BX lr ; Return to caller @@ -78,4 +80,3 @@ _tx_thread_smp_time_get ENDIF END - diff --git a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a9_smp/gnu/src/tx_thread_smp_time_get.S index 9cebe0f21..cf8374adc 100644 --- a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a9_smp/gnu/src/tx_thread_smp_time_get.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * Copyright (c) 2026-present Eclipse ThreadX contributors @ * @ * This program and the accompanying materials are made available under the @ * terms of the MIT License which is available at @@ -8,6 +9,7 @@ @ * SPDX-License-Identifier: MIT @ **************************************************************************/ @ +@ Some portions generated by Codex (GPT-5). @ @/**************************************************************************/ @/**************************************************************************/ @@ -71,12 +73,10 @@ _tx_thread_smp_time_get: MRC p15, 4, r0, c15, c0, 0 @ Read periph base address - LDR r0, [r0, #0x604] @ Read count register + LDR r0, [r0, #0x200] @ Read global timer count low register #ifdef __THUMB_INTERWORK BX lr @ Return to caller #else MOV pc, lr @ Return to caller #endif - - diff --git a/ports_smp/cortex_r8_smp/ac5/src/tx_thread_smp_time_get.s b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_smp_time_get.s index a43484d7c..c17143896 100644 --- a/ports_smp/cortex_r8_smp/ac5/src/tx_thread_smp_time_get.s +++ b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_smp_time_get.s @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ /**************************************************************************/ @@ -57,7 +58,7 @@ _tx_thread_smp_time_get MRC p15, 4, r0, c15, c0, 0 // Read periph base address - LDR r0, [r0, #0x604] // Read count register + LDR r0, [r0, #0x200] // Read global timer count low register IF {INTER} = {TRUE} BX lr // Return to caller From 2dfe5acfb0927c5b32d4810dbdbc18aeae5860a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 22 Jun 2026 08:27:10 -0400 Subject: [PATCH 004/181] Fixed ARMv8 SMP time sources (#555) Follow up on the issue-541 execution profiling work. PR #553 fixed SMP execution profile total-time aggregation, and PR #554 fixed Armv7/R SMP timestamp hooks that used decrementing private timers. This change addresses the remaining related gap in ARMv8-A SMP ports: their timestamp hooks returned zero, which left execution profiling and trace timestamps without a progressing time source. Replace those stubs with the architectural generic physical counter, CNTPCT_EL0, across the ARMv8-A SMP GNU, AC6, IAR, and GHS variants. The local ARMv8 AArch64 system timer example already uses CNTPCT_EL0 for physical count reads, so this keeps the SMP timestamp hook aligned with the existing port examples while preserving the 32-bit ULONG return contract. Co-authored-by: Codex --- ports_smp/cortex_a34_smp/ac6/src/tx_thread_smp_time_get.S | 3 ++- ports_smp/cortex_a34_smp/gnu/src/tx_thread_smp_time_get.S | 3 ++- ports_smp/cortex_a35_smp/ac6/src/tx_thread_smp_time_get.S | 3 ++- ports_smp/cortex_a35_smp/gnu/src/tx_thread_smp_time_get.S | 3 ++- ports_smp/cortex_a53_smp/ac6/src/tx_thread_smp_time_get.S | 3 ++- ports_smp/cortex_a53_smp/gnu/src/tx_thread_smp_time_get.S | 3 ++- ports_smp/cortex_a55_smp/ac6/src/tx_thread_smp_time_get.S | 3 ++- ports_smp/cortex_a55_smp/gnu/src/tx_thread_smp_time_get.S | 3 ++- ports_smp/cortex_a57_smp/ac6/src/tx_thread_smp_time_get.S | 3 ++- ports_smp/cortex_a57_smp/gnu/src/tx_thread_smp_time_get.S | 3 ++- ports_smp/cortex_a5x_smp/ac6/src/tx_thread_smp_time_get.S | 3 ++- ports_smp/cortex_a5x_smp/gnu/src/tx_thread_smp_time_get.S | 3 ++- ports_smp/cortex_a5x_smp/green/src/tx_thread_smp_time_get.a64 | 4 +++- ports_smp/cortex_a5x_smp/iar/src/tx_thread_smp_time_get.S | 3 ++- ports_smp/cortex_a65_smp/ac6/src/tx_thread_smp_time_get.S | 3 ++- ports_smp/cortex_a65_smp/gnu/src/tx_thread_smp_time_get.S | 3 ++- ports_smp/cortex_a65ae_smp/ac6/src/tx_thread_smp_time_get.S | 3 ++- ports_smp/cortex_a65ae_smp/gnu/src/tx_thread_smp_time_get.S | 3 ++- ports_smp/cortex_a72_smp/ac6/src/tx_thread_smp_time_get.S | 3 ++- ports_smp/cortex_a72_smp/gnu/src/tx_thread_smp_time_get.S | 3 ++- ports_smp/cortex_a73_smp/ac6/src/tx_thread_smp_time_get.S | 3 ++- ports_smp/cortex_a73_smp/gnu/src/tx_thread_smp_time_get.S | 3 ++- ports_smp/cortex_a75_smp/ac6/src/tx_thread_smp_time_get.S | 3 ++- ports_smp/cortex_a75_smp/gnu/src/tx_thread_smp_time_get.S | 3 ++- ports_smp/cortex_a76_smp/ac6/src/tx_thread_smp_time_get.S | 3 ++- ports_smp/cortex_a76_smp/gnu/src/tx_thread_smp_time_get.S | 3 ++- ports_smp/cortex_a76ae_smp/ac6/src/tx_thread_smp_time_get.S | 3 ++- ports_smp/cortex_a76ae_smp/gnu/src/tx_thread_smp_time_get.S | 3 ++- ports_smp/cortex_a77_smp/ac6/src/tx_thread_smp_time_get.S | 3 ++- ports_smp/cortex_a77_smp/gnu/src/tx_thread_smp_time_get.S | 3 ++- ports_smp/cortex_a78_smp/ac6/src/tx_thread_smp_time_get.S | 3 ++- ports_smp/cortex_a78_smp/gnu/src/tx_thread_smp_time_get.S | 3 ++- 32 files changed, 65 insertions(+), 32 deletions(-) diff --git a/ports_smp/cortex_a34_smp/ac6/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a34_smp/ac6/src/tx_thread_smp_time_get.S index f30457383..a5451ff7d 100644 --- a/ports_smp/cortex_a34_smp/ac6/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a34_smp/ac6/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ /**************************************************************************/ @@ -58,5 +59,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a34_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a34_smp/gnu/src/tx_thread_smp_time_get.S index f30457383..a5451ff7d 100644 --- a/ports_smp/cortex_a34_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a34_smp/gnu/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ /**************************************************************************/ @@ -58,5 +59,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a35_smp/ac6/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a35_smp/ac6/src/tx_thread_smp_time_get.S index 335824fbb..81286412e 100644 --- a/ports_smp/cortex_a35_smp/ac6/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a35_smp/ac6/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ /**************************************************************************/ @@ -60,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a35_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a35_smp/gnu/src/tx_thread_smp_time_get.S index 335824fbb..81286412e 100644 --- a/ports_smp/cortex_a35_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a35_smp/gnu/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ /**************************************************************************/ @@ -60,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a53_smp/ac6/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a53_smp/ac6/src/tx_thread_smp_time_get.S index 335824fbb..81286412e 100644 --- a/ports_smp/cortex_a53_smp/ac6/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a53_smp/ac6/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ /**************************************************************************/ @@ -60,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a53_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a53_smp/gnu/src/tx_thread_smp_time_get.S index 335824fbb..81286412e 100644 --- a/ports_smp/cortex_a53_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a53_smp/gnu/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ /**************************************************************************/ @@ -60,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a55_smp/ac6/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a55_smp/ac6/src/tx_thread_smp_time_get.S index 335824fbb..81286412e 100644 --- a/ports_smp/cortex_a55_smp/ac6/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a55_smp/ac6/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ /**************************************************************************/ @@ -60,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a55_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a55_smp/gnu/src/tx_thread_smp_time_get.S index 335824fbb..81286412e 100644 --- a/ports_smp/cortex_a55_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a55_smp/gnu/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ /**************************************************************************/ @@ -60,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a57_smp/ac6/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a57_smp/ac6/src/tx_thread_smp_time_get.S index 335824fbb..81286412e 100644 --- a/ports_smp/cortex_a57_smp/ac6/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a57_smp/ac6/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ /**************************************************************************/ @@ -60,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a57_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a57_smp/gnu/src/tx_thread_smp_time_get.S index 335824fbb..81286412e 100644 --- a/ports_smp/cortex_a57_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a57_smp/gnu/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ /**************************************************************************/ @@ -60,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a5x_smp/ac6/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a5x_smp/ac6/src/tx_thread_smp_time_get.S index efa6d62cb..1c8ea3aeb 100644 --- a/ports_smp/cortex_a5x_smp/ac6/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a5x_smp/ac6/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ /**************************************************************************/ @@ -58,5 +59,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a5x_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a5x_smp/gnu/src/tx_thread_smp_time_get.S index 4a98140ab..e0605debb 100644 --- a/ports_smp/cortex_a5x_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a5x_smp/gnu/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ /**************************************************************************/ @@ -58,5 +59,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a5x_smp/green/src/tx_thread_smp_time_get.a64 b/ports_smp/cortex_a5x_smp/green/src/tx_thread_smp_time_get.a64 index 45d286b0f..b3501d5a0 100644 --- a/ports_smp/cortex_a5x_smp/green/src/tx_thread_smp_time_get.a64 +++ b/ports_smp/cortex_a5x_smp/green/src/tx_thread_smp_time_get.a64 @@ -1,5 +1,6 @@ /*************************************************************************** * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present Eclipse ThreadX contributors * * This program and the accompanying materials are made available under the * terms of the MIT License which is available at @@ -8,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ /**************************************************************************/ @@ -76,7 +78,7 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // Add time source - application specific + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a5x_smp/iar/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a5x_smp/iar/src/tx_thread_smp_time_get.S index 438341963..4808149f7 100644 --- a/ports_smp/cortex_a5x_smp/iar/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a5x_smp/iar/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ /**************************************************************************/ @@ -70,7 +71,7 @@ /**************************************************************************/ PUBLIC _tx_thread_smp_time_get _tx_thread_smp_time_get: - MOV x0, #0 // Add logic to get timer value here for diagnostics + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET END diff --git a/ports_smp/cortex_a65_smp/ac6/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a65_smp/ac6/src/tx_thread_smp_time_get.S index 335824fbb..81286412e 100644 --- a/ports_smp/cortex_a65_smp/ac6/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a65_smp/ac6/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ /**************************************************************************/ @@ -60,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a65_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a65_smp/gnu/src/tx_thread_smp_time_get.S index 335824fbb..81286412e 100644 --- a/ports_smp/cortex_a65_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a65_smp/gnu/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ /**************************************************************************/ @@ -60,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a65ae_smp/ac6/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a65ae_smp/ac6/src/tx_thread_smp_time_get.S index 335824fbb..81286412e 100644 --- a/ports_smp/cortex_a65ae_smp/ac6/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a65ae_smp/ac6/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ /**************************************************************************/ @@ -60,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a65ae_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a65ae_smp/gnu/src/tx_thread_smp_time_get.S index 335824fbb..81286412e 100644 --- a/ports_smp/cortex_a65ae_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a65ae_smp/gnu/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ /**************************************************************************/ @@ -60,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a72_smp/ac6/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a72_smp/ac6/src/tx_thread_smp_time_get.S index 335824fbb..81286412e 100644 --- a/ports_smp/cortex_a72_smp/ac6/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a72_smp/ac6/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ /**************************************************************************/ @@ -60,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a72_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a72_smp/gnu/src/tx_thread_smp_time_get.S index 335824fbb..81286412e 100644 --- a/ports_smp/cortex_a72_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a72_smp/gnu/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ /**************************************************************************/ @@ -60,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a73_smp/ac6/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a73_smp/ac6/src/tx_thread_smp_time_get.S index 335824fbb..81286412e 100644 --- a/ports_smp/cortex_a73_smp/ac6/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a73_smp/ac6/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ /**************************************************************************/ @@ -60,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a73_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a73_smp/gnu/src/tx_thread_smp_time_get.S index 335824fbb..81286412e 100644 --- a/ports_smp/cortex_a73_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a73_smp/gnu/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ /**************************************************************************/ @@ -60,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a75_smp/ac6/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a75_smp/ac6/src/tx_thread_smp_time_get.S index 335824fbb..81286412e 100644 --- a/ports_smp/cortex_a75_smp/ac6/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a75_smp/ac6/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ /**************************************************************************/ @@ -60,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a75_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a75_smp/gnu/src/tx_thread_smp_time_get.S index 335824fbb..81286412e 100644 --- a/ports_smp/cortex_a75_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a75_smp/gnu/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ /**************************************************************************/ @@ -60,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a76_smp/ac6/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a76_smp/ac6/src/tx_thread_smp_time_get.S index 335824fbb..81286412e 100644 --- a/ports_smp/cortex_a76_smp/ac6/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a76_smp/ac6/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ /**************************************************************************/ @@ -60,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a76_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a76_smp/gnu/src/tx_thread_smp_time_get.S index 335824fbb..81286412e 100644 --- a/ports_smp/cortex_a76_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a76_smp/gnu/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ /**************************************************************************/ @@ -60,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a76ae_smp/ac6/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a76ae_smp/ac6/src/tx_thread_smp_time_get.S index 335824fbb..81286412e 100644 --- a/ports_smp/cortex_a76ae_smp/ac6/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a76ae_smp/ac6/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ /**************************************************************************/ @@ -60,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a76ae_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a76ae_smp/gnu/src/tx_thread_smp_time_get.S index 335824fbb..81286412e 100644 --- a/ports_smp/cortex_a76ae_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a76ae_smp/gnu/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ /**************************************************************************/ @@ -60,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a77_smp/ac6/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a77_smp/ac6/src/tx_thread_smp_time_get.S index 335824fbb..81286412e 100644 --- a/ports_smp/cortex_a77_smp/ac6/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a77_smp/ac6/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ /**************************************************************************/ @@ -60,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a77_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a77_smp/gnu/src/tx_thread_smp_time_get.S index 335824fbb..81286412e 100644 --- a/ports_smp/cortex_a77_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a77_smp/gnu/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ /**************************************************************************/ @@ -60,5 +61,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a78_smp/ac6/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a78_smp/ac6/src/tx_thread_smp_time_get.S index f30457383..a5451ff7d 100644 --- a/ports_smp/cortex_a78_smp/ac6/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a78_smp/ac6/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ /**************************************************************************/ @@ -58,5 +59,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET diff --git a/ports_smp/cortex_a78_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a78_smp/gnu/src/tx_thread_smp_time_get.S index f30457383..a5451ff7d 100644 --- a/ports_smp/cortex_a78_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a78_smp/gnu/src/tx_thread_smp_time_get.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ /**************************************************************************/ @@ -58,5 +59,5 @@ .global _tx_thread_smp_time_get .type _tx_thread_smp_time_get, @function _tx_thread_smp_time_get: - MOV x0, #0 // FIXME: Get timer + MRS x0, CNTPCT_EL0 // Read generic timer physical count RET From d9e7dfea89046c901100b42afa230b37823718f7 Mon Sep 17 00:00:00 2001 From: hefanbo Date: Thu, 25 Jun 2026 00:16:51 +0800 Subject: [PATCH 005/181] Add SysTick counter reset in Cortex-M ports (#561) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Add SysTick counter reset in Cortex-M ports The SysTick counter value (SYST_CVR @0xE000E018) is indeterminate after reset. Without clearing it prior to enabling the counter, the first tick interval becomes unpredictable. * Fixed missing comment and added generated-by header in Cortex-M0/AC6 port Added the missing inline comment on the LDR r1, =0 instruction (Build value for SysTick reset) and the required AI-generated attribution comment under the copyright header. --------- Co-authored-by: Frédéric Desbiens Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../example_build/sample_threadx/tx_initialize_low_level.S | 4 ++++ ports/cortex_m23/ac6/example_build/tx_initialize_low_level.S | 3 +++ ports/cortex_m23/gnu/src/tx_initialize_low_level.S | 3 +++ ports/cortex_m23/iar/src/tx_initialize_low_level.s | 3 +++ ports/cortex_m3/ac5/example_build/tx_initialize_low_level.s | 3 +++ .../example_build/sample_threadx/tx_initialize_low_level.S | 3 +++ ports/cortex_m3/ghs/example_build/tx_initialize_low_level.arm | 3 +++ ports/cortex_m3/gnu/example_build/tx_initialize_low_level.S | 3 +++ ports/cortex_m3/iar/example_build/tx_initialize_low_level.s | 3 +++ ports/cortex_m3/keil/example_build/tx_initialize_low_level.s | 3 +++ ports/cortex_m33/ac6/example_build/tx_initialize_low_level.S | 3 +++ ports/cortex_m33/ac6/src/tx_initialize_low_level.S | 3 +++ ports/cortex_m33/gnu/example_build/tx_initialize_low_level.S | 3 +++ ports/cortex_m33/iar/src/tx_initialize_low_level.s | 3 +++ ports/cortex_m4/ac5/example_build/tx_initialize_low_level.s | 3 +++ .../example_build/sample_threadx/tx_initialize_low_level.S | 3 +++ ports/cortex_m4/ghs/example_build/tx_initialize_low_level.arm | 3 +++ ports/cortex_m4/gnu/example_build/tx_initialize_low_level.S | 3 +++ ports/cortex_m4/iar/example_build/tx_initialize_low_level.s | 3 +++ ports/cortex_m4/keil/example_build/tx_initialize_low_level.s | 3 +++ ports/cortex_m55/ac6/example_build/tx_initialize_low_level.S | 3 +++ ports/cortex_m55/ac6/src/tx_initialize_low_level.S | 3 +++ ports/cortex_m55/gnu/example_build/tx_initialize_low_level.S | 3 +++ ports/cortex_m55/iar/src/tx_initialize_low_level.s | 3 +++ ports/cortex_m7/ac5/example_build/tx_initialize_low_level.s | 3 +++ .../example_build/sample_threadx/tx_initialize_low_level.S | 3 +++ ports/cortex_m7/ghs/example_build/tx_initialize_low_level.arm | 3 +++ ports/cortex_m7/gnu/example_build/tx_initialize_low_level.S | 3 +++ ports/cortex_m7/iar/example_build/tx_initialize_low_level.s | 3 +++ ports/cortex_m85/ac6/src/tx_initialize_low_level.S | 3 +++ ports/cortex_m85/gnu/example_build/tx_initialize_low_level.S | 3 +++ ports/cortex_m85/iar/src/tx_initialize_low_level.s | 3 +++ .../threadx/ac5/example_build/tx_initialize_low_level.s | 3 +++ .../example_build/sample_threadx/tx_initialize_low_level.S | 3 +++ .../threadx/ghs/example_build/tx_initialize_low_level.arm | 3 +++ .../threadx/gnu/example_build/tx_initialize_low_level.S | 3 +++ .../threadx/iar/example_build/tx_initialize_low_level.s | 3 +++ ports_arch/ARMv8-M/threadx/ac6/src/tx_initialize_low_level.S | 3 +++ ports_arch/ARMv8-M/threadx/gnu/src/tx_initialize_low_level.S | 3 +++ ports_arch/ARMv8-M/threadx/iar/src/tx_initialize_low_level.s | 3 +++ .../example_build/sample_threadx/tx_initialize_low_level.S | 3 +++ .../sample_threadx_module_manager/tx_initialize_low_level.S | 3 +++ .../example_build/sample_threadx/tx_initialize_low_level.S | 3 +++ .../sample_threadx_module_manager/tx_initialize_low_level.S | 3 +++ .../cortex_m0+/iar/example_build/tx_initialize_low_level.s | 3 +++ .../cortex_m23/ac6/example_build/tx_initialize_low_level.S | 3 +++ .../gnu/module_manager/src/tx_initialize_low_level.S | 3 +++ .../cortex_m23/iar/example_build/tx_initialize_low_level.s | 3 +++ .../cortex_m3/ac5/example_build/tx_initialize_low_level.S | 3 +++ .../example_build/sample_threadx/tx_initialize_low_level.S | 3 +++ .../sample_threadx_module_manager/tx_initialize_low_level.S | 3 +++ .../cortex_m3/gnu/example_build/tx_initialize_low_level.S | 3 +++ .../cortex_m3/iar/example_build/tx_initialize_low_level.s | 3 +++ .../cortex_m33/ac6/example_build/tx_initialize_low_level.S | 3 +++ .../gnu/module_manager/src/tx_initialize_low_level.S | 3 +++ .../cortex_m33/iar/example_build/tx_initialize_low_level.s | 3 +++ .../cortex_m4/ac5/example_build/tx_initialize_low_level.S | 3 +++ .../example_build/sample_threadx/tx_initialize_low_level.S | 3 +++ .../sample_threadx_module_manager/tx_initialize_low_level.S | 3 +++ .../cortex_m4/gnu/example_build/tx_initialize_low_level.S | 3 +++ .../cortex_m4/iar/example_build/tx_initialize_low_level.s | 3 +++ .../cortex_m7/ac5/example_build/tx_initialize_low_level.S | 3 +++ .../example_build/sample_threadx/tx_initialize_low_level.S | 3 +++ .../sample_threadx_module_manager/tx_initialize_low_level.S | 3 +++ .../cortex_m7/gnu/example_build/tx_initialize_low_level.S | 3 +++ .../cortex_m7/iar/example_build/tx_initialize_low_level.s | 3 +++ 66 files changed, 199 insertions(+) diff --git a/ports/cortex_m0/ac6/example_build/sample_threadx/tx_initialize_low_level.S b/ports/cortex_m0/ac6/example_build/sample_threadx/tx_initialize_low_level.S index f7e3eb2da..7aad3a308 100644 --- a/ports/cortex_m0/ac6/example_build/sample_threadx/tx_initialize_low_level.S +++ b/ports/cortex_m0/ac6/example_build/sample_threadx/tx_initialize_low_level.S @@ -7,6 +7,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ +@ // Some portions generated by GitHub Copilot (Claude Sonnet 4.6). @ @ @/**************************************************************************/ @@ -111,6 +112,9 @@ _tx_initialize_low_level: @ /* Configure SysTick for 100Hz clock, or 16384 cycles if no reference. */ @ LDR r0, =0xE000E000 @ Build address of NVIC registers + LDR r1, =0 @ Build value for SysTick reset + STR r1, [r0, #0x10] @ Reset SysTick Control + STR r1, [r0, #0x18] @ Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] @ Setup SysTick Reload Value LDR r1, =0x7 @ Build SysTick Control Enable Value diff --git a/ports/cortex_m23/ac6/example_build/tx_initialize_low_level.S b/ports/cortex_m23/ac6/example_build/tx_initialize_low_level.S index c5565bdda..1625f570d 100644 --- a/ports/cortex_m23/ac6/example_build/tx_initialize_low_level.S +++ b/ports/cortex_m23/ac6/example_build/tx_initialize_low_level.S @@ -106,6 +106,9 @@ _tx_initialize_low_level: /* Configure SysTick. */ LDR r0, =0xE000E000 // Build address of NVIC registers + MOV r1, #0 // Build value for SysTick reset + STR r1, [r0, #0x10] // Reset SysTick Control + STR r1, [r0, #0x18] // Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] // Setup SysTick Reload Value MOVW r1, #0x7 // Build SysTick Control Enable Value diff --git a/ports/cortex_m23/gnu/src/tx_initialize_low_level.S b/ports/cortex_m23/gnu/src/tx_initialize_low_level.S index ba092253d..cc8deeeef 100644 --- a/ports/cortex_m23/gnu/src/tx_initialize_low_level.S +++ b/ports/cortex_m23/gnu/src/tx_initialize_low_level.S @@ -107,6 +107,9 @@ _tx_initialize_low_level: /* Configure SysTick. */ LDR r0, =0xE000E000 // Build address of NVIC registers + MOV r1, #0 // Build value for SysTick reset + STR r1, [r0, #0x10] // Reset SysTick Control + STR r1, [r0, #0x18] // Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] // Setup SysTick Reload Value MOVW r1, #0x7 // Build SysTick Control Enable Value diff --git a/ports/cortex_m23/iar/src/tx_initialize_low_level.s b/ports/cortex_m23/iar/src/tx_initialize_low_level.s index fb6a109f1..90849145d 100644 --- a/ports/cortex_m23/iar/src/tx_initialize_low_level.s +++ b/ports/cortex_m23/iar/src/tx_initialize_low_level.s @@ -104,6 +104,9 @@ _tx_initialize_low_level: /* Configure SysTick. */ LDR r0, =0xE000E000 // Build address of NVIC registers + MOV r1, #0 // Build value for SysTick reset + STR r1, [r0, #0x10] // Reset SysTick Control + STR r1, [r0, #0x18] // Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] // Setup SysTick Reload Value MOV r1, #0x7 // Build SysTick Control Enable Value diff --git a/ports/cortex_m3/ac5/example_build/tx_initialize_low_level.s b/ports/cortex_m3/ac5/example_build/tx_initialize_low_level.s index f0c38db20..cb0b26054 100644 --- a/ports/cortex_m3/ac5/example_build/tx_initialize_low_level.s +++ b/ports/cortex_m3/ac5/example_build/tx_initialize_low_level.s @@ -162,6 +162,9 @@ _tx_initialize_low_level ; /* Configure SysTick for 100Hz clock, or 16384 cycles if no reference. */ ; MOV r0, #0xE000E000 ; Build address of NVIC registers + MOV r1, #0 ; Build value for SysTick reset + STR r1, [r0, #0x10] ; Reset SysTick Control + STR r1, [r0, #0x18] ; Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] ; Setup SysTick Reload Value MOV r1, #0x7 ; Build SysTick Control Enable Value diff --git a/ports/cortex_m3/ac6/example_build/sample_threadx/tx_initialize_low_level.S b/ports/cortex_m3/ac6/example_build/sample_threadx/tx_initialize_low_level.S index b5ef57e5d..325d21b30 100644 --- a/ports/cortex_m3/ac6/example_build/sample_threadx/tx_initialize_low_level.S +++ b/ports/cortex_m3/ac6/example_build/sample_threadx/tx_initialize_low_level.S @@ -116,6 +116,9 @@ _tx_initialize_low_level: @ /* Configure SysTick for 100Hz clock, or 16384 cycles if no reference. */ @ MOV r0, #0xE000E000 @ Build address of NVIC registers + MOV r1, #0 @ Build value for SysTick reset + STR r1, [r0, #0x10] @ Reset SysTick Control + STR r1, [r0, #0x18] @ Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] @ Setup SysTick Reload Value MOV r1, #0x7 @ Build SysTick Control Enable Value diff --git a/ports/cortex_m3/ghs/example_build/tx_initialize_low_level.arm b/ports/cortex_m3/ghs/example_build/tx_initialize_low_level.arm index 9259c2f43..96fa7fa9e 100644 --- a/ports/cortex_m3/ghs/example_build/tx_initialize_low_level.arm +++ b/ports/cortex_m3/ghs/example_build/tx_initialize_low_level.arm @@ -107,6 +107,9 @@ _tx_initialize_low_level: /* Configure SysTick for 100Hz clock, or 16384 cycles if no reference. */ + MOV r1, 0 ; Build value for SysTick reset + STR r1, [r0, 0x10] ; Reset SysTick Control + STR r1, [r0, 0x18] ; Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, 0x14] ; Setup SysTick Reload Value MOV r1, 0x7 ; Build SysTick Control Enable Value diff --git a/ports/cortex_m3/gnu/example_build/tx_initialize_low_level.S b/ports/cortex_m3/gnu/example_build/tx_initialize_low_level.S index 1a7244100..4bf5d3281 100644 --- a/ports/cortex_m3/gnu/example_build/tx_initialize_low_level.S +++ b/ports/cortex_m3/gnu/example_build/tx_initialize_low_level.S @@ -108,6 +108,9 @@ _tx_initialize_low_level: /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers + MOV r1, #0 // Build value for SysTick reset + STR r1, [r0, #0x10] // Reset SysTick Control + STR r1, [r0, #0x18] // Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] // Setup SysTick Reload Value MOV r1, #0x7 // Build SysTick Control Enable Value diff --git a/ports/cortex_m3/iar/example_build/tx_initialize_low_level.s b/ports/cortex_m3/iar/example_build/tx_initialize_low_level.s index bf7b64b08..ef1f8f9ef 100644 --- a/ports/cortex_m3/iar/example_build/tx_initialize_low_level.s +++ b/ports/cortex_m3/iar/example_build/tx_initialize_low_level.s @@ -113,6 +113,9 @@ _tx_initialize_low_level: ; /* Configure SysTick. */ ; MOV r0, #0xE000E000 ; Build address of NVIC registers + MOV r1, #0 ; Build value for SysTick reset + STR r1, [r0, #0x10] ; Reset SysTick Control + STR r1, [r0, #0x18] ; Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] ; Setup SysTick Reload Value MOV r1, #0x7 ; Build SysTick Control Enable Value diff --git a/ports/cortex_m3/keil/example_build/tx_initialize_low_level.s b/ports/cortex_m3/keil/example_build/tx_initialize_low_level.s index 9c6dd97c8..adde4604c 100644 --- a/ports/cortex_m3/keil/example_build/tx_initialize_low_level.s +++ b/ports/cortex_m3/keil/example_build/tx_initialize_low_level.s @@ -161,6 +161,9 @@ _tx_initialize_low_level ; /* Configure SysTick for 100Hz clock, or 16384 cycles if no reference. */ ; MOV r0, #0xE000E000 ; Build address of NVIC registers + MOV r1, #0 ; Build value for SysTick reset + STR r1, [r0, #0x10] ; Reset SysTick Control + STR r1, [r0, #0x18] ; Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] ; Setup SysTick Reload Value MOV r1, #0x7 ; Build SysTick Control Enable Value diff --git a/ports/cortex_m33/ac6/example_build/tx_initialize_low_level.S b/ports/cortex_m33/ac6/example_build/tx_initialize_low_level.S index 2f10e84a3..b32c5ac45 100644 --- a/ports/cortex_m33/ac6/example_build/tx_initialize_low_level.S +++ b/ports/cortex_m33/ac6/example_build/tx_initialize_low_level.S @@ -103,6 +103,9 @@ _tx_initialize_low_level: /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers + MOV r1, #0 // Build value for SysTick reset + STR r1, [r0, #0x10] // Reset SysTick Control + STR r1, [r0, #0x18] // Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] // Setup SysTick Reload Value MOV r1, #0x7 // Build SysTick Control Enable Value diff --git a/ports/cortex_m33/ac6/src/tx_initialize_low_level.S b/ports/cortex_m33/ac6/src/tx_initialize_low_level.S index 896abe063..e74425a43 100644 --- a/ports/cortex_m33/ac6/src/tx_initialize_low_level.S +++ b/ports/cortex_m33/ac6/src/tx_initialize_low_level.S @@ -106,6 +106,9 @@ _tx_initialize_low_level: /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers + MOV r1, #0 // Build value for SysTick reset + STR r1, [r0, #0x10] // Reset SysTick Control + STR r1, [r0, #0x18] // Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] // Setup SysTick Reload Value MOV r1, #0x7 // Build SysTick Control Enable Value diff --git a/ports/cortex_m33/gnu/example_build/tx_initialize_low_level.S b/ports/cortex_m33/gnu/example_build/tx_initialize_low_level.S index 5915dc969..0ddfba102 100644 --- a/ports/cortex_m33/gnu/example_build/tx_initialize_low_level.S +++ b/ports/cortex_m33/gnu/example_build/tx_initialize_low_level.S @@ -106,6 +106,9 @@ _tx_initialize_low_level: /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers + MOV r1, #0 // Build value for SysTick reset + STR r1, [r0, #0x10] // Reset SysTick Control + STR r1, [r0, #0x18] // Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] // Setup SysTick Reload Value MOV r1, #0x7 // Build SysTick Control Enable Value diff --git a/ports/cortex_m33/iar/src/tx_initialize_low_level.s b/ports/cortex_m33/iar/src/tx_initialize_low_level.s index 8544e8a5b..17d29846e 100644 --- a/ports/cortex_m33/iar/src/tx_initialize_low_level.s +++ b/ports/cortex_m33/iar/src/tx_initialize_low_level.s @@ -108,6 +108,9 @@ _tx_initialize_low_level: /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers + MOV r1, #0 // Build value for SysTick reset + STR r1, [r0, #0x10] // Reset SysTick Control + STR r1, [r0, #0x18] // Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] // Setup SysTick Reload Value MOV r1, #0x7 // Build SysTick Control Enable Value diff --git a/ports/cortex_m4/ac5/example_build/tx_initialize_low_level.s b/ports/cortex_m4/ac5/example_build/tx_initialize_low_level.s index 5f5e42b55..c08bd94e4 100644 --- a/ports/cortex_m4/ac5/example_build/tx_initialize_low_level.s +++ b/ports/cortex_m4/ac5/example_build/tx_initialize_low_level.s @@ -166,6 +166,9 @@ _tx_initialize_low_level ; /* Configure SysTick. */ ; MOV r0, #0xE000E000 ; Build address of NVIC registers + MOV r1, #0 ; Build value for SysTick reset + STR r1, [r0, #0x10] ; Reset SysTick Control + STR r1, [r0, #0x18] ; Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] ; Setup SysTick Reload Value MOV r1, #0x7 ; Build SysTick Control Enable Value diff --git a/ports/cortex_m4/ac6/example_build/sample_threadx/tx_initialize_low_level.S b/ports/cortex_m4/ac6/example_build/sample_threadx/tx_initialize_low_level.S index 16dd113ed..9bada308d 100644 --- a/ports/cortex_m4/ac6/example_build/sample_threadx/tx_initialize_low_level.S +++ b/ports/cortex_m4/ac6/example_build/sample_threadx/tx_initialize_low_level.S @@ -116,6 +116,9 @@ _tx_initialize_low_level: @ /* Configure SysTick for 100Hz clock, or 16384 cycles if no reference. */ @ MOV r0, #0xE000E000 @ Build address of NVIC registers + MOV r1, #0 @ Build value for SysTick reset + STR r1, [r0, #0x10] @ Reset SysTick Control + STR r1, [r0, #0x18] @ Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] @ Setup SysTick Reload Value MOV r1, #0x7 @ Build SysTick Control Enable Value diff --git a/ports/cortex_m4/ghs/example_build/tx_initialize_low_level.arm b/ports/cortex_m4/ghs/example_build/tx_initialize_low_level.arm index 1a144b7bc..bf96627de 100644 --- a/ports/cortex_m4/ghs/example_build/tx_initialize_low_level.arm +++ b/ports/cortex_m4/ghs/example_build/tx_initialize_low_level.arm @@ -107,6 +107,9 @@ _tx_initialize_low_level: /* Configure SysTick for 100Hz clock, or 16384 cycles if no reference. */ + MOV r1, 0 ; Build value for SysTick reset + STR r1, [r0, 0x10] ; Reset SysTick Control + STR r1, [r0, 0x18] ; Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, 0x14] ; Setup SysTick Reload Value MOV r1, 0x7 ; Build SysTick Control Enable Value diff --git a/ports/cortex_m4/gnu/example_build/tx_initialize_low_level.S b/ports/cortex_m4/gnu/example_build/tx_initialize_low_level.S index 4c7a6223f..39399ebc4 100644 --- a/ports/cortex_m4/gnu/example_build/tx_initialize_low_level.S +++ b/ports/cortex_m4/gnu/example_build/tx_initialize_low_level.S @@ -118,6 +118,9 @@ _tx_initialize_low_level: @ /* Configure SysTick for 100Hz clock, or 16384 cycles if no reference. */ @ MOV r0, #0xE000E000 @ Build address of NVIC registers + MOV r1, #0 @ Build value for SysTick reset + STR r1, [r0, #0x10] @ Reset SysTick Control + STR r1, [r0, #0x18] @ Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] @ Setup SysTick Reload Value MOV r1, #0x7 @ Build SysTick Control Enable Value diff --git a/ports/cortex_m4/iar/example_build/tx_initialize_low_level.s b/ports/cortex_m4/iar/example_build/tx_initialize_low_level.s index a84667c38..8e3f7d85d 100644 --- a/ports/cortex_m4/iar/example_build/tx_initialize_low_level.s +++ b/ports/cortex_m4/iar/example_build/tx_initialize_low_level.s @@ -113,6 +113,9 @@ _tx_initialize_low_level: ; /* Configure SysTick. */ ; MOV r0, #0xE000E000 ; Build address of NVIC registers + MOV r1, #0 ; Build value for SysTick reset + STR r1, [r0, #0x10] ; Reset SysTick Control + STR r1, [r0, #0x18] ; Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] ; Setup SysTick Reload Value MOV r1, #0x7 ; Build SysTick Control Enable Value diff --git a/ports/cortex_m4/keil/example_build/tx_initialize_low_level.s b/ports/cortex_m4/keil/example_build/tx_initialize_low_level.s index 58aee89c0..4bce73a43 100644 --- a/ports/cortex_m4/keil/example_build/tx_initialize_low_level.s +++ b/ports/cortex_m4/keil/example_build/tx_initialize_low_level.s @@ -181,6 +181,9 @@ _tx_initialize_low_level ; /* Configure SysTick. */ ; MOV r0, #0xE000E000 ; Build address of NVIC registers + MOV r1, #0 ; Build value for SysTick reset + STR r1, [r0, #0x10] ; Reset SysTick Control + STR r1, [r0, #0x18] ; Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] ; Setup SysTick Reload Value MOV r1, #0x7 ; Build SysTick Control Enable Value diff --git a/ports/cortex_m55/ac6/example_build/tx_initialize_low_level.S b/ports/cortex_m55/ac6/example_build/tx_initialize_low_level.S index fdd8aaed5..6e7e9eedd 100644 --- a/ports/cortex_m55/ac6/example_build/tx_initialize_low_level.S +++ b/ports/cortex_m55/ac6/example_build/tx_initialize_low_level.S @@ -103,6 +103,9 @@ _tx_initialize_low_level: /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers + MOV r1, #0 // Build value for SysTick reset + STR r1, [r0, #0x10] // Reset SysTick Control + STR r1, [r0, #0x18] // Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] // Setup SysTick Reload Value MOV r1, #0x7 // Build SysTick Control Enable Value diff --git a/ports/cortex_m55/ac6/src/tx_initialize_low_level.S b/ports/cortex_m55/ac6/src/tx_initialize_low_level.S index d6e397924..45f180127 100644 --- a/ports/cortex_m55/ac6/src/tx_initialize_low_level.S +++ b/ports/cortex_m55/ac6/src/tx_initialize_low_level.S @@ -106,6 +106,9 @@ _tx_initialize_low_level: /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers + MOV r1, #0 // Build value for SysTick reset + STR r1, [r0, #0x10] // Reset SysTick Control + STR r1, [r0, #0x18] // Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] // Setup SysTick Reload Value MOV r1, #0x7 // Build SysTick Control Enable Value diff --git a/ports/cortex_m55/gnu/example_build/tx_initialize_low_level.S b/ports/cortex_m55/gnu/example_build/tx_initialize_low_level.S index ee23d9cb3..0a8d5363a 100644 --- a/ports/cortex_m55/gnu/example_build/tx_initialize_low_level.S +++ b/ports/cortex_m55/gnu/example_build/tx_initialize_low_level.S @@ -106,6 +106,9 @@ _tx_initialize_low_level: /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers + MOV r1, #0 // Build value for SysTick reset + STR r1, [r0, #0x10] // Reset SysTick Control + STR r1, [r0, #0x18] // Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] // Setup SysTick Reload Value MOV r1, #0x7 // Build SysTick Control Enable Value diff --git a/ports/cortex_m55/iar/src/tx_initialize_low_level.s b/ports/cortex_m55/iar/src/tx_initialize_low_level.s index 312e8267b..faf658178 100644 --- a/ports/cortex_m55/iar/src/tx_initialize_low_level.s +++ b/ports/cortex_m55/iar/src/tx_initialize_low_level.s @@ -108,6 +108,9 @@ _tx_initialize_low_level: /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers + MOV r1, #0 // Build value for SysTick reset + STR r1, [r0, #0x10] // Reset SysTick Control + STR r1, [r0, #0x18] // Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] // Setup SysTick Reload Value MOV r1, #0x7 // Build SysTick Control Enable Value diff --git a/ports/cortex_m7/ac5/example_build/tx_initialize_low_level.s b/ports/cortex_m7/ac5/example_build/tx_initialize_low_level.s index 07c27743a..7f3e86907 100644 --- a/ports/cortex_m7/ac5/example_build/tx_initialize_low_level.s +++ b/ports/cortex_m7/ac5/example_build/tx_initialize_low_level.s @@ -171,6 +171,9 @@ _tx_initialize_low_level ; /* Configure SysTick. */ ; MOV r0, #0xE000E000 ; Build address of NVIC registers + MOV r1, #0 ; Build value for SysTick reset + STR r1, [r0, #0x10] ; Reset SysTick Control + STR r1, [r0, #0x18] ; Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] ; Setup SysTick Reload Value MOV r1, #0x7 ; Build SysTick Control Enable Value diff --git a/ports/cortex_m7/ac6/example_build/sample_threadx/tx_initialize_low_level.S b/ports/cortex_m7/ac6/example_build/sample_threadx/tx_initialize_low_level.S index 11525a956..0e50bc488 100644 --- a/ports/cortex_m7/ac6/example_build/sample_threadx/tx_initialize_low_level.S +++ b/ports/cortex_m7/ac6/example_build/sample_threadx/tx_initialize_low_level.S @@ -116,6 +116,9 @@ _tx_initialize_low_level: @ /* Configure SysTick for 100Hz clock, or 16384 cycles if no reference. */ @ MOV r0, #0xE000E000 @ Build address of NVIC registers + MOV r1, #0 @ Build value for SysTick reset + STR r1, [r0, #0x10] @ Reset SysTick Control + STR r1, [r0, #0x18] @ Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] @ Setup SysTick Reload Value MOV r1, #0x7 @ Build SysTick Control Enable Value diff --git a/ports/cortex_m7/ghs/example_build/tx_initialize_low_level.arm b/ports/cortex_m7/ghs/example_build/tx_initialize_low_level.arm index 57c964b34..fc6e19fe8 100644 --- a/ports/cortex_m7/ghs/example_build/tx_initialize_low_level.arm +++ b/ports/cortex_m7/ghs/example_build/tx_initialize_low_level.arm @@ -107,6 +107,9 @@ _tx_initialize_low_level: /* Configure SysTick for 100Hz clock, or 16384 cycles if no reference. */ + MOV r1, 0 ; Build value for SysTick reset + STR r1, [r0, 0x10] ; Reset SysTick Control + STR r1, [r0, 0x18] ; Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, 0x14] ; Setup SysTick Reload Value MOV r1, 0x7 ; Build SysTick Control Enable Value diff --git a/ports/cortex_m7/gnu/example_build/tx_initialize_low_level.S b/ports/cortex_m7/gnu/example_build/tx_initialize_low_level.S index e146e47fc..2b6d9af63 100644 --- a/ports/cortex_m7/gnu/example_build/tx_initialize_low_level.S +++ b/ports/cortex_m7/gnu/example_build/tx_initialize_low_level.S @@ -108,6 +108,9 @@ _tx_initialize_low_level: /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers + MOV r1, #0 // Build value for SysTick reset + STR r1, [r0, #0x10] // Reset SysTick Control + STR r1, [r0, #0x18] // Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] // Setup SysTick Reload Value MOV r1, #0x7 // Build SysTick Control Enable Value diff --git a/ports/cortex_m7/iar/example_build/tx_initialize_low_level.s b/ports/cortex_m7/iar/example_build/tx_initialize_low_level.s index 76d065cff..6e886e7ff 100644 --- a/ports/cortex_m7/iar/example_build/tx_initialize_low_level.s +++ b/ports/cortex_m7/iar/example_build/tx_initialize_low_level.s @@ -113,6 +113,9 @@ _tx_initialize_low_level: ; /* Configure SysTick. */ ; MOV r0, #0xE000E000 ; Build address of NVIC registers + MOV r1, #0 ; Build value for SysTick reset + STR r1, [r0, #0x10] ; Reset SysTick Control + STR r1, [r0, #0x18] ; Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] ; Setup SysTick Reload Value MOV r1, #0x7 ; Build SysTick Control Enable Value diff --git a/ports/cortex_m85/ac6/src/tx_initialize_low_level.S b/ports/cortex_m85/ac6/src/tx_initialize_low_level.S index a3daea70c..776f8760e 100644 --- a/ports/cortex_m85/ac6/src/tx_initialize_low_level.S +++ b/ports/cortex_m85/ac6/src/tx_initialize_low_level.S @@ -106,6 +106,9 @@ _tx_initialize_low_level: /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers + MOV r1, #0 // Build value for SysTick reset + STR r1, [r0, #0x10] // Reset SysTick Control + STR r1, [r0, #0x18] // Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] // Setup SysTick Reload Value MOV r1, #0x7 // Build SysTick Control Enable Value diff --git a/ports/cortex_m85/gnu/example_build/tx_initialize_low_level.S b/ports/cortex_m85/gnu/example_build/tx_initialize_low_level.S index 22dc0780f..317d1d391 100644 --- a/ports/cortex_m85/gnu/example_build/tx_initialize_low_level.S +++ b/ports/cortex_m85/gnu/example_build/tx_initialize_low_level.S @@ -106,6 +106,9 @@ _tx_initialize_low_level: /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers + MOV r1, #0 // Build value for SysTick reset + STR r1, [r0, #0x10] // Reset SysTick Control + STR r1, [r0, #0x18] // Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] // Setup SysTick Reload Value MOV r1, #0x7 // Build SysTick Control Enable Value diff --git a/ports/cortex_m85/iar/src/tx_initialize_low_level.s b/ports/cortex_m85/iar/src/tx_initialize_low_level.s index 64260c520..4935842a2 100644 --- a/ports/cortex_m85/iar/src/tx_initialize_low_level.s +++ b/ports/cortex_m85/iar/src/tx_initialize_low_level.s @@ -108,6 +108,9 @@ _tx_initialize_low_level: /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers + MOV r1, #0 // Build value for SysTick reset + STR r1, [r0, #0x10] // Reset SysTick Control + STR r1, [r0, #0x18] // Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] // Setup SysTick Reload Value MOV r1, #0x7 // Build SysTick Control Enable Value diff --git a/ports_arch/ARMv7-M/threadx/ac5/example_build/tx_initialize_low_level.s b/ports_arch/ARMv7-M/threadx/ac5/example_build/tx_initialize_low_level.s index c51e67cf3..af05fba7b 100644 --- a/ports_arch/ARMv7-M/threadx/ac5/example_build/tx_initialize_low_level.s +++ b/ports_arch/ARMv7-M/threadx/ac5/example_build/tx_initialize_low_level.s @@ -165,6 +165,9 @@ _tx_initialize_low_level #ifndef TX_NO_TIMER /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers + MOV r1, #0 // Build value for SysTick reset + STR r1, [r0, #0x10] // Reset SysTick Control + STR r1, [r0, #0x18] // Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] // Setup SysTick Reload Value MOV r1, #0x7 // Build SysTick Control Enable Value diff --git a/ports_arch/ARMv7-M/threadx/ac6/example_build/sample_threadx/tx_initialize_low_level.S b/ports_arch/ARMv7-M/threadx/ac6/example_build/sample_threadx/tx_initialize_low_level.S index af332d804..617d62de4 100644 --- a/ports_arch/ARMv7-M/threadx/ac6/example_build/sample_threadx/tx_initialize_low_level.S +++ b/ports_arch/ARMv7-M/threadx/ac6/example_build/sample_threadx/tx_initialize_low_level.S @@ -107,6 +107,9 @@ _tx_initialize_low_level: #ifndef TX_NO_TIMER /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers + MOV r1, #0 // Build value for SysTick reset + STR r1, [r0, #0x10] // Reset SysTick Control + STR r1, [r0, #0x18] // Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] // Setup SysTick Reload Value MOV r1, #0x7 // Build SysTick Control Enable Value diff --git a/ports_arch/ARMv7-M/threadx/ghs/example_build/tx_initialize_low_level.arm b/ports_arch/ARMv7-M/threadx/ghs/example_build/tx_initialize_low_level.arm index 57c964b34..fc6e19fe8 100644 --- a/ports_arch/ARMv7-M/threadx/ghs/example_build/tx_initialize_low_level.arm +++ b/ports_arch/ARMv7-M/threadx/ghs/example_build/tx_initialize_low_level.arm @@ -107,6 +107,9 @@ _tx_initialize_low_level: /* Configure SysTick for 100Hz clock, or 16384 cycles if no reference. */ + MOV r1, 0 ; Build value for SysTick reset + STR r1, [r0, 0x10] ; Reset SysTick Control + STR r1, [r0, 0x18] ; Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, 0x14] ; Setup SysTick Reload Value MOV r1, 0x7 ; Build SysTick Control Enable Value diff --git a/ports_arch/ARMv7-M/threadx/gnu/example_build/tx_initialize_low_level.S b/ports_arch/ARMv7-M/threadx/gnu/example_build/tx_initialize_low_level.S index 8fce83db7..41cde1638 100644 --- a/ports_arch/ARMv7-M/threadx/gnu/example_build/tx_initialize_low_level.S +++ b/ports_arch/ARMv7-M/threadx/gnu/example_build/tx_initialize_low_level.S @@ -104,6 +104,9 @@ _tx_initialize_low_level: #ifndef TX_NO_TIMER /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers + MOV r1, #0 // Build value for SysTick reset + STR r1, [r0, #0x10] // Reset SysTick Control + STR r1, [r0, #0x18] // Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] // Setup SysTick Reload Value MOV r1, #0x7 // Build SysTick Control Enable Value diff --git a/ports_arch/ARMv7-M/threadx/iar/example_build/tx_initialize_low_level.s b/ports_arch/ARMv7-M/threadx/iar/example_build/tx_initialize_low_level.s index d2c2e07f3..dd4bfce4a 100644 --- a/ports_arch/ARMv7-M/threadx/iar/example_build/tx_initialize_low_level.s +++ b/ports_arch/ARMv7-M/threadx/iar/example_build/tx_initialize_low_level.s @@ -98,6 +98,9 @@ _tx_initialize_low_level: #ifndef TX_NO_TIMER /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers + MOV r1, #0 // Build value for SysTick reset + STR r1, [r0, #0x10] // Reset SysTick Control + STR r1, [r0, #0x18] // Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] // Setup SysTick Reload Value MOV r1, #0x7 // Build SysTick Control Enable Value diff --git a/ports_arch/ARMv8-M/threadx/ac6/src/tx_initialize_low_level.S b/ports_arch/ARMv8-M/threadx/ac6/src/tx_initialize_low_level.S index 9332b7e1e..e57c6b39e 100644 --- a/ports_arch/ARMv8-M/threadx/ac6/src/tx_initialize_low_level.S +++ b/ports_arch/ARMv8-M/threadx/ac6/src/tx_initialize_low_level.S @@ -106,6 +106,9 @@ _tx_initialize_low_level: /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers + MOV r1, #0 // Build value for SysTick reset + STR r1, [r0, #0x10] // Reset SysTick Control + STR r1, [r0, #0x18] // Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] // Setup SysTick Reload Value MOV r1, #0x7 // Build SysTick Control Enable Value diff --git a/ports_arch/ARMv8-M/threadx/gnu/src/tx_initialize_low_level.S b/ports_arch/ARMv8-M/threadx/gnu/src/tx_initialize_low_level.S index 842dcdf40..f0b326a17 100644 --- a/ports_arch/ARMv8-M/threadx/gnu/src/tx_initialize_low_level.S +++ b/ports_arch/ARMv8-M/threadx/gnu/src/tx_initialize_low_level.S @@ -106,6 +106,9 @@ _tx_initialize_low_level: /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers + MOV r1, #0 // Build value for SysTick reset + STR r1, [r0, #0x10] // Reset SysTick Control + STR r1, [r0, #0x18] // Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] // Setup SysTick Reload Value MOV r1, #0x7 // Build SysTick Control Enable Value diff --git a/ports_arch/ARMv8-M/threadx/iar/src/tx_initialize_low_level.s b/ports_arch/ARMv8-M/threadx/iar/src/tx_initialize_low_level.s index 6d8e07e83..a79f1963a 100644 --- a/ports_arch/ARMv8-M/threadx/iar/src/tx_initialize_low_level.s +++ b/ports_arch/ARMv8-M/threadx/iar/src/tx_initialize_low_level.s @@ -108,6 +108,9 @@ _tx_initialize_low_level: /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers + MOV r1, #0 // Build value for SysTick reset + STR r1, [r0, #0x10] // Reset SysTick Control + STR r1, [r0, #0x18] // Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] // Setup SysTick Reload Value MOV r1, #0x7 // Build SysTick Control Enable Value diff --git a/ports_module/cortex_m0+/ac6/example_build/sample_threadx/tx_initialize_low_level.S b/ports_module/cortex_m0+/ac6/example_build/sample_threadx/tx_initialize_low_level.S index 0c6c1e742..a5de014ac 100644 --- a/ports_module/cortex_m0+/ac6/example_build/sample_threadx/tx_initialize_low_level.S +++ b/ports_module/cortex_m0+/ac6/example_build/sample_threadx/tx_initialize_low_level.S @@ -117,6 +117,9 @@ _tx_initialize_low_level: /* Configure SysTick for 100Hz clock, or 16384 cycles if no reference. */ LDR r0, =0xE000E000 // Build address of NVIC registers + LDR r1, =0 + STR r1, [r0, #0x10] // Reset SysTick Control + STR r1, [r0, #0x18] // Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES MOVS r2, #0x14 STR r1, [r0, r2] // Setup SysTick Reload Value diff --git a/ports_module/cortex_m0+/ac6/example_build/sample_threadx_module_manager/tx_initialize_low_level.S b/ports_module/cortex_m0+/ac6/example_build/sample_threadx_module_manager/tx_initialize_low_level.S index dcc369ae8..da703cce3 100644 --- a/ports_module/cortex_m0+/ac6/example_build/sample_threadx_module_manager/tx_initialize_low_level.S +++ b/ports_module/cortex_m0+/ac6/example_build/sample_threadx_module_manager/tx_initialize_low_level.S @@ -118,6 +118,9 @@ _tx_initialize_low_level: /* Configure SysTick for 100Hz clock, or 16384 cycles if no reference. */ LDR r0, =0xE000E000 // Build address of NVIC registers + LDR r1, =0 + STR r1, [r0, #0x10] // Reset SysTick Control + STR r1, [r0, #0x18] // Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES MOVS r2, #0x14 STR r1, [r0, r2] // Setup SysTick Reload Value diff --git a/ports_module/cortex_m0+/gnu/example_build/sample_threadx/tx_initialize_low_level.S b/ports_module/cortex_m0+/gnu/example_build/sample_threadx/tx_initialize_low_level.S index 445f77cf5..436ee0496 100644 --- a/ports_module/cortex_m0+/gnu/example_build/sample_threadx/tx_initialize_low_level.S +++ b/ports_module/cortex_m0+/gnu/example_build/sample_threadx/tx_initialize_low_level.S @@ -119,6 +119,9 @@ _tx_initialize_low_level: /* Configure SysTick for 100Hz clock, or 16384 cycles if no reference. */ LDR r0, =0xE000E000 // Build address of NVIC registers + LDR r1, =0 + STR r1, [r0, #0x10] // Reset SysTick Control + STR r1, [r0, #0x18] // Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES MOVS r2, #0x14 STR r1, [r0, r2] // Setup SysTick Reload Value diff --git a/ports_module/cortex_m0+/gnu/example_build/sample_threadx_module_manager/tx_initialize_low_level.S b/ports_module/cortex_m0+/gnu/example_build/sample_threadx_module_manager/tx_initialize_low_level.S index 4928d5965..667452cfd 100644 --- a/ports_module/cortex_m0+/gnu/example_build/sample_threadx_module_manager/tx_initialize_low_level.S +++ b/ports_module/cortex_m0+/gnu/example_build/sample_threadx_module_manager/tx_initialize_low_level.S @@ -119,6 +119,9 @@ _tx_initialize_low_level: /* Configure SysTick for 100Hz clock, or 16384 cycles if no reference. */ LDR r0, =0xE000E000 // Build address of NVIC registers + LDR r1, =0 + STR r1, [r0, #0x10] // Reset SysTick Control + STR r1, [r0, #0x18] // Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES MOVS r2, #0x14 STR r1, [r0, r2] // Setup SysTick Reload Value diff --git a/ports_module/cortex_m0+/iar/example_build/tx_initialize_low_level.s b/ports_module/cortex_m0+/iar/example_build/tx_initialize_low_level.s index 16404d63a..44be0ae66 100644 --- a/ports_module/cortex_m0+/iar/example_build/tx_initialize_low_level.s +++ b/ports_module/cortex_m0+/iar/example_build/tx_initialize_low_level.s @@ -123,6 +123,9 @@ _tx_initialize_low_level: /* Configure SysTick for 100Hz clock, or 16384 cycles if no reference. */ LDR r0, =0xE000E000 // Build address of NVIC registers + LDR r1, =0 + STR r1, [r0, #0x10] // Reset SysTick Control + STR r1, [r0, #0x18] // Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES MOVS r2, #0x14 STR r1, [r0, r2] // Setup SysTick Reload Value diff --git a/ports_module/cortex_m23/ac6/example_build/tx_initialize_low_level.S b/ports_module/cortex_m23/ac6/example_build/tx_initialize_low_level.S index 00d7b3251..2bc0c4602 100644 --- a/ports_module/cortex_m23/ac6/example_build/tx_initialize_low_level.S +++ b/ports_module/cortex_m23/ac6/example_build/tx_initialize_low_level.S @@ -103,6 +103,9 @@ _tx_initialize_low_level: /* Configure SysTick. */ LDR r0, =0xE000E000 // Build address of NVIC registers + MOV r1, #0 // Build value for SysTick reset + STR r1, [r0, #0x10] // Reset SysTick Control + STR r1, [r0, #0x18] // Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] // Setup SysTick Reload Value MOVW r1, #0x7 // Build SysTick Control Enable Value diff --git a/ports_module/cortex_m23/gnu/module_manager/src/tx_initialize_low_level.S b/ports_module/cortex_m23/gnu/module_manager/src/tx_initialize_low_level.S index d38525bf0..28c37f367 100644 --- a/ports_module/cortex_m23/gnu/module_manager/src/tx_initialize_low_level.S +++ b/ports_module/cortex_m23/gnu/module_manager/src/tx_initialize_low_level.S @@ -105,6 +105,9 @@ _tx_initialize_low_level: /* Configure SysTick. */ LDR r0, =0xE000E000 // Build address of NVIC registers + MOV r1, #0 // Build value for SysTick reset + STR r1, [r0, #0x10] // Reset SysTick Control + STR r1, [r0, #0x18] // Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] // Setup SysTick Reload Value MOVW r1, #0x7 // Build SysTick Control Enable Value diff --git a/ports_module/cortex_m23/iar/example_build/tx_initialize_low_level.s b/ports_module/cortex_m23/iar/example_build/tx_initialize_low_level.s index fb6a109f1..90849145d 100644 --- a/ports_module/cortex_m23/iar/example_build/tx_initialize_low_level.s +++ b/ports_module/cortex_m23/iar/example_build/tx_initialize_low_level.s @@ -104,6 +104,9 @@ _tx_initialize_low_level: /* Configure SysTick. */ LDR r0, =0xE000E000 // Build address of NVIC registers + MOV r1, #0 // Build value for SysTick reset + STR r1, [r0, #0x10] // Reset SysTick Control + STR r1, [r0, #0x18] // Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] // Setup SysTick Reload Value MOV r1, #0x7 // Build SysTick Control Enable Value diff --git a/ports_module/cortex_m3/ac5/example_build/tx_initialize_low_level.S b/ports_module/cortex_m3/ac5/example_build/tx_initialize_low_level.S index 057ccc9af..0d415dc59 100644 --- a/ports_module/cortex_m3/ac5/example_build/tx_initialize_low_level.S +++ b/ports_module/cortex_m3/ac5/example_build/tx_initialize_low_level.S @@ -185,6 +185,9 @@ _tx_initialize_low_level ; /* Configure SysTick. */ ; MOV r0, #0xE000E000 ; Build address of NVIC registers + MOV r1, #0 ; Build value for SysTick reset + STR r1, [r0, #0x10] ; Reset SysTick Control + STR r1, [r0, #0x18] ; Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] ; Setup SysTick Reload Value MOV r1, #0x7 ; Build SysTick Control Enable Value diff --git a/ports_module/cortex_m3/ac6/example_build/sample_threadx/tx_initialize_low_level.S b/ports_module/cortex_m3/ac6/example_build/sample_threadx/tx_initialize_low_level.S index 72f446436..5cf5b418d 100644 --- a/ports_module/cortex_m3/ac6/example_build/sample_threadx/tx_initialize_low_level.S +++ b/ports_module/cortex_m3/ac6/example_build/sample_threadx/tx_initialize_low_level.S @@ -116,6 +116,9 @@ _tx_initialize_low_level: /* Configure SysTick for 100Hz clock, or 16384 cycles if no reference. */ MOV r0, #0xE000E000 // Build address of NVIC registers + MOV r1, #0 // Build value for SysTick reset + STR r1, [r0, #0x10] // Reset SysTick Control + STR r1, [r0, #0x18] // Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] // Setup SysTick Reload Value MOV r1, #0x7 // Build SysTick Control Enable Value diff --git a/ports_module/cortex_m3/ac6/example_build/sample_threadx_module_manager/tx_initialize_low_level.S b/ports_module/cortex_m3/ac6/example_build/sample_threadx_module_manager/tx_initialize_low_level.S index 5f263caee..376b15c02 100644 --- a/ports_module/cortex_m3/ac6/example_build/sample_threadx_module_manager/tx_initialize_low_level.S +++ b/ports_module/cortex_m3/ac6/example_build/sample_threadx_module_manager/tx_initialize_low_level.S @@ -116,6 +116,9 @@ _tx_initialize_low_level: /* Configure SysTick for 100Hz clock, or 16384 cycles if no reference. */ MOV r0, #0xE000E000 // Build address of NVIC registers + MOV r1, #0 // Build value for SysTick reset + STR r1, [r0, #0x10] // Reset SysTick Control + STR r1, [r0, #0x18] // Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] // Setup SysTick Reload Value MOV r1, #0x7 // Build SysTick Control Enable Value diff --git a/ports_module/cortex_m3/gnu/example_build/tx_initialize_low_level.S b/ports_module/cortex_m3/gnu/example_build/tx_initialize_low_level.S index edc1eef39..278dd9b39 100644 --- a/ports_module/cortex_m3/gnu/example_build/tx_initialize_low_level.S +++ b/ports_module/cortex_m3/gnu/example_build/tx_initialize_low_level.S @@ -109,6 +109,9 @@ _tx_initialize_low_level: /* Configure SysTick for 100Hz clock, or 16384 cycles if no reference. */ MOV r0, #0xE000E000 @ Build address of NVIC registers + MOV r1, #0 @ Build value for SysTick reset + STR r1, [r0, #0x10] @ Reset SysTick Control + STR r1, [r0, #0x18] @ Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] @ Setup SysTick Reload Value MOV r1, #0x7 @ Build SysTick Control Enable Value diff --git a/ports_module/cortex_m3/iar/example_build/tx_initialize_low_level.s b/ports_module/cortex_m3/iar/example_build/tx_initialize_low_level.s index f3262e151..d31fbb338 100644 --- a/ports_module/cortex_m3/iar/example_build/tx_initialize_low_level.s +++ b/ports_module/cortex_m3/iar/example_build/tx_initialize_low_level.s @@ -123,6 +123,9 @@ _tx_initialize_low_level: ; /* Configure SysTick. */ ; MOV r0, #0xE000E000 ; Build address of NVIC registers + MOV r1, #0 ; Build value for SysTick reset + STR r1, [r0, #0x10] ; Reset SysTick Control + STR r1, [r0, #0x18] ; Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] ; Setup SysTick Reload Value MOV r1, #0x7 ; Build SysTick Control Enable Value diff --git a/ports_module/cortex_m33/ac6/example_build/tx_initialize_low_level.S b/ports_module/cortex_m33/ac6/example_build/tx_initialize_low_level.S index 9e6fa804a..4043e1103 100644 --- a/ports_module/cortex_m33/ac6/example_build/tx_initialize_low_level.S +++ b/ports_module/cortex_m33/ac6/example_build/tx_initialize_low_level.S @@ -103,6 +103,9 @@ _tx_initialize_low_level: /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers + MOV r1, #0 // Build value for SysTick reset + STR r1, [r0, #0x10] // Reset SysTick Control + STR r1, [r0, #0x18] // Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] // Setup SysTick Reload Value MOV r1, #0x7 // Build SysTick Control Enable Value diff --git a/ports_module/cortex_m33/gnu/module_manager/src/tx_initialize_low_level.S b/ports_module/cortex_m33/gnu/module_manager/src/tx_initialize_low_level.S index c89394c25..dd10aeffd 100644 --- a/ports_module/cortex_m33/gnu/module_manager/src/tx_initialize_low_level.S +++ b/ports_module/cortex_m33/gnu/module_manager/src/tx_initialize_low_level.S @@ -103,6 +103,9 @@ _tx_initialize_low_level: /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers + MOV r1, #0 // Build value for SysTick reset + STR r1, [r0, #0x10] // Reset SysTick Control + STR r1, [r0, #0x18] // Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] // Setup SysTick Reload Value MOV r1, #0x7 // Build SysTick Control Enable Value diff --git a/ports_module/cortex_m33/iar/example_build/tx_initialize_low_level.s b/ports_module/cortex_m33/iar/example_build/tx_initialize_low_level.s index 43467f185..048e0a8b1 100644 --- a/ports_module/cortex_m33/iar/example_build/tx_initialize_low_level.s +++ b/ports_module/cortex_m33/iar/example_build/tx_initialize_low_level.s @@ -104,6 +104,9 @@ _tx_initialize_low_level: /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers + MOV r1, #0 // Build value for SysTick reset + STR r1, [r0, #0x10] // Reset SysTick Control + STR r1, [r0, #0x18] // Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] // Setup SysTick Reload Value MOV r1, #0x7 // Build SysTick Control Enable Value diff --git a/ports_module/cortex_m4/ac5/example_build/tx_initialize_low_level.S b/ports_module/cortex_m4/ac5/example_build/tx_initialize_low_level.S index fb4615365..49b4f75c5 100644 --- a/ports_module/cortex_m4/ac5/example_build/tx_initialize_low_level.S +++ b/ports_module/cortex_m4/ac5/example_build/tx_initialize_low_level.S @@ -171,6 +171,9 @@ _tx_initialize_low_level /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers + MOV r1, #0 // Build value for SysTick reset + STR r1, [r0, #0x10] // Reset SysTick Control + STR r1, [r0, #0x18] // Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] // Setup SysTick Reload Value MOV r1, #0x7 // Build SysTick Control Enable Value diff --git a/ports_module/cortex_m4/ac6/example_build/sample_threadx/tx_initialize_low_level.S b/ports_module/cortex_m4/ac6/example_build/sample_threadx/tx_initialize_low_level.S index ccd76ffbf..fdf439916 100644 --- a/ports_module/cortex_m4/ac6/example_build/sample_threadx/tx_initialize_low_level.S +++ b/ports_module/cortex_m4/ac6/example_build/sample_threadx/tx_initialize_low_level.S @@ -116,6 +116,9 @@ _tx_initialize_low_level: /* Configure SysTick for 100Hz clock, or 16384 cycles if no reference. */ MOV r0, #0xE000E000 // Build address of NVIC registers + MOV r1, #0 // Build value for SysTick reset + STR r1, [r0, #0x10] // Reset SysTick Control + STR r1, [r0, #0x18] // Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] // Setup SysTick Reload Value MOV r1, #0x7 // Build SysTick Control Enable Value diff --git a/ports_module/cortex_m4/ac6/example_build/sample_threadx_module_manager/tx_initialize_low_level.S b/ports_module/cortex_m4/ac6/example_build/sample_threadx_module_manager/tx_initialize_low_level.S index 4e457588c..61e40d2ec 100644 --- a/ports_module/cortex_m4/ac6/example_build/sample_threadx_module_manager/tx_initialize_low_level.S +++ b/ports_module/cortex_m4/ac6/example_build/sample_threadx_module_manager/tx_initialize_low_level.S @@ -116,6 +116,9 @@ _tx_initialize_low_level: /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers + MOV r1, #0 // Build value for SysTick reset + STR r1, [r0, #0x10] // Reset SysTick Control + STR r1, [r0, #0x18] // Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] // Setup SysTick Reload Value MOV r1, #0x7 // Build SysTick Control Enable Value diff --git a/ports_module/cortex_m4/gnu/example_build/tx_initialize_low_level.S b/ports_module/cortex_m4/gnu/example_build/tx_initialize_low_level.S index e922a5b5a..85a88c699 100644 --- a/ports_module/cortex_m4/gnu/example_build/tx_initialize_low_level.S +++ b/ports_module/cortex_m4/gnu/example_build/tx_initialize_low_level.S @@ -115,6 +115,9 @@ _tx_initialize_low_level: /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers + MOV r1, #0 // Build value for SysTick reset + STR r1, [r0, #0x10] // Reset SysTick Control + STR r1, [r0, #0x18] // Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] // Setup SysTick Reload Value MOV r1, #0x7 // Build SysTick Control Enable Value diff --git a/ports_module/cortex_m4/iar/example_build/tx_initialize_low_level.s b/ports_module/cortex_m4/iar/example_build/tx_initialize_low_level.s index 07afc829a..55e9fc409 100644 --- a/ports_module/cortex_m4/iar/example_build/tx_initialize_low_level.s +++ b/ports_module/cortex_m4/iar/example_build/tx_initialize_low_level.s @@ -110,6 +110,9 @@ _tx_initialize_low_level: /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers + MOV r1, #0 // Build value for SysTick reset + STR r1, [r0, #0x10] // Reset SysTick Control + STR r1, [r0, #0x18] // Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] // Setup SysTick Reload Value MOV r1, #0x7 // Build SysTick Control Enable Value diff --git a/ports_module/cortex_m7/ac5/example_build/tx_initialize_low_level.S b/ports_module/cortex_m7/ac5/example_build/tx_initialize_low_level.S index 62d7eb938..7ab4b4509 100644 --- a/ports_module/cortex_m7/ac5/example_build/tx_initialize_low_level.S +++ b/ports_module/cortex_m7/ac5/example_build/tx_initialize_low_level.S @@ -171,6 +171,9 @@ _tx_initialize_low_level /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers + MOV r1, #0 // Build value for SysTick reset + STR r1, [r0, #0x10] // Reset SysTick Control + STR r1, [r0, #0x18] // Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] // Setup SysTick Reload Value MOV r1, #0x7 // Build SysTick Control Enable Value diff --git a/ports_module/cortex_m7/ac6/example_build/sample_threadx/tx_initialize_low_level.S b/ports_module/cortex_m7/ac6/example_build/sample_threadx/tx_initialize_low_level.S index 2837a1424..813d25770 100644 --- a/ports_module/cortex_m7/ac6/example_build/sample_threadx/tx_initialize_low_level.S +++ b/ports_module/cortex_m7/ac6/example_build/sample_threadx/tx_initialize_low_level.S @@ -116,6 +116,9 @@ _tx_initialize_low_level: /* Configure SysTick for 100Hz clock, or 16384 cycles if no reference. */ MOV r0, #0xE000E000 // Build address of NVIC registers + MOV r1, #0 // Build value for SysTick reset + STR r1, [r0, #0x10] // Reset SysTick Control + STR r1, [r0, #0x18] // Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] // Setup SysTick Reload Value MOV r1, #0x7 // Build SysTick Control Enable Value diff --git a/ports_module/cortex_m7/ac6/example_build/sample_threadx_module_manager/tx_initialize_low_level.S b/ports_module/cortex_m7/ac6/example_build/sample_threadx_module_manager/tx_initialize_low_level.S index 2df350e5b..c5715b945 100644 --- a/ports_module/cortex_m7/ac6/example_build/sample_threadx_module_manager/tx_initialize_low_level.S +++ b/ports_module/cortex_m7/ac6/example_build/sample_threadx_module_manager/tx_initialize_low_level.S @@ -116,6 +116,9 @@ _tx_initialize_low_level: /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers + MOV r1, #0 // Build value for SysTick reset + STR r1, [r0, #0x10] // Reset SysTick Control + STR r1, [r0, #0x18] // Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] // Setup SysTick Reload Value MOV r1, #0x7 // Build SysTick Control Enable Value diff --git a/ports_module/cortex_m7/gnu/example_build/tx_initialize_low_level.S b/ports_module/cortex_m7/gnu/example_build/tx_initialize_low_level.S index e9273cbd9..01c8814be 100644 --- a/ports_module/cortex_m7/gnu/example_build/tx_initialize_low_level.S +++ b/ports_module/cortex_m7/gnu/example_build/tx_initialize_low_level.S @@ -115,6 +115,9 @@ _tx_initialize_low_level: /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers + MOV r1, #0 // Build value for SysTick reset + STR r1, [r0, #0x10] // Reset SysTick Control + STR r1, [r0, #0x18] // Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] // Setup SysTick Reload Value MOV r1, #0x7 // Build SysTick Control Enable Value diff --git a/ports_module/cortex_m7/iar/example_build/tx_initialize_low_level.s b/ports_module/cortex_m7/iar/example_build/tx_initialize_low_level.s index 2df2d19f6..6919b6e10 100644 --- a/ports_module/cortex_m7/iar/example_build/tx_initialize_low_level.s +++ b/ports_module/cortex_m7/iar/example_build/tx_initialize_low_level.s @@ -110,6 +110,9 @@ _tx_initialize_low_level: /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers + MOV r1, #0 // Build value for SysTick reset + STR r1, [r0, #0x10] // Reset SysTick Control + STR r1, [r0, #0x18] // Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES STR r1, [r0, #0x14] // Setup SysTick Reload Value MOV r1, #0x7 // Build SysTick Control Enable Value From 3fcfb4e4c984c66eaeaafcff908afb7e2dfb72fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 29 Jun 2026 16:07:12 -0400 Subject: [PATCH 006/181] Updated Cortex-M BASEPRI zero immediates (#564) Use explicit immediate syntax when clearing BASEPRI in GNU and AC6 Cortex-M scheduler assembly. Co-authored-by: Codex --- ports/cortex_m3/ac6/src/tx_thread_schedule.S | 3 ++- ports/cortex_m3/gnu/src/tx_thread_schedule.S | 3 ++- ports/cortex_m33/ac6/src/tx_thread_schedule.S | 3 ++- ports/cortex_m33/gnu/src/tx_thread_schedule.S | 3 ++- ports/cortex_m4/ac6/src/tx_thread_schedule.S | 3 ++- ports/cortex_m4/gnu/src/tx_thread_schedule.S | 3 ++- ports/cortex_m55/ac6/src/tx_thread_schedule.S | 3 ++- ports/cortex_m55/gnu/src/tx_thread_schedule.S | 3 ++- ports/cortex_m7/ac6/src/tx_thread_schedule.S | 3 ++- ports/cortex_m7/gnu/src/tx_thread_schedule.S | 3 ++- ports/cortex_m85/ac6/src/tx_thread_schedule.S | 3 ++- ports/cortex_m85/gnu/src/tx_thread_schedule.S | 3 ++- ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_schedule.S | 3 ++- ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_schedule.S | 3 ++- .../ac6/module_manager/src/tx_thread_schedule.S | 5 +++-- .../gnu/module_manager/src/tx_thread_schedule.S | 5 +++-- ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_schedule.S | 3 ++- ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_schedule.S | 3 ++- .../cortex_m3/ac6/module_manager/src/tx_thread_schedule.S | 5 +++-- .../cortex_m3/gnu/module_manager/src/tx_thread_schedule.S | 5 +++-- .../cortex_m33/ac6/module_manager/src/tx_thread_schedule.S | 5 +++-- .../cortex_m33/gnu/module_manager/src/tx_thread_schedule.S | 5 +++-- .../cortex_m4/ac6/module_manager/src/tx_thread_schedule.S | 5 +++-- .../cortex_m4/gnu/module_manager/src/tx_thread_schedule.S | 5 +++-- .../cortex_m7/ac6/module_manager/src/tx_thread_schedule.S | 5 +++-- .../cortex_m7/gnu/module_manager/src/tx_thread_schedule.S | 5 +++-- 26 files changed, 62 insertions(+), 36 deletions(-) diff --git a/ports/cortex_m3/ac6/src/tx_thread_schedule.S b/ports/cortex_m3/ac6/src/tx_thread_schedule.S index 98d21f36c..f1a6deed6 100644 --- a/ports/cortex_m3/ac6/src/tx_thread_schedule.S +++ b/ports/cortex_m3/ac6/src/tx_thread_schedule.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ @@ -139,7 +140,7 @@ __tx_ts_handler: BL _tx_execution_thread_exit // Call the thread exit function POP {r0, lr} // Recover LR #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts diff --git a/ports/cortex_m3/gnu/src/tx_thread_schedule.S b/ports/cortex_m3/gnu/src/tx_thread_schedule.S index 9581ec389..7a7126c95 100644 --- a/ports/cortex_m3/gnu/src/tx_thread_schedule.S +++ b/ports/cortex_m3/gnu/src/tx_thread_schedule.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ @@ -137,7 +138,7 @@ __tx_ts_handler: BL _tx_execution_thread_exit // Call the thread exit function POP {r0, lr} // Recover LR #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts diff --git a/ports/cortex_m33/ac6/src/tx_thread_schedule.S b/ports/cortex_m33/ac6/src/tx_thread_schedule.S index 5aec68b6d..365f228fc 100644 --- a/ports/cortex_m33/ac6/src/tx_thread_schedule.S +++ b/ports/cortex_m33/ac6/src/tx_thread_schedule.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ @@ -129,7 +130,7 @@ __tx_ts_handler: BL _tx_execution_thread_exit // Call the thread exit function POP {r0, lr} // Recover LR #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts diff --git a/ports/cortex_m33/gnu/src/tx_thread_schedule.S b/ports/cortex_m33/gnu/src/tx_thread_schedule.S index 601d89da3..dcc35afb2 100644 --- a/ports/cortex_m33/gnu/src/tx_thread_schedule.S +++ b/ports/cortex_m33/gnu/src/tx_thread_schedule.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ @@ -125,7 +126,7 @@ __tx_ts_handler: BL _tx_execution_thread_exit // Call the thread exit function POP {r0, lr} // Recover LR #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts diff --git a/ports/cortex_m4/ac6/src/tx_thread_schedule.S b/ports/cortex_m4/ac6/src/tx_thread_schedule.S index 0b15b4de7..0ff44a1df 100644 --- a/ports/cortex_m4/ac6/src/tx_thread_schedule.S +++ b/ports/cortex_m4/ac6/src/tx_thread_schedule.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ @@ -139,7 +140,7 @@ __tx_ts_handler: BL _tx_execution_thread_exit // Call the thread exit function POP {r0, lr} // Recover LR #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts diff --git a/ports/cortex_m4/gnu/src/tx_thread_schedule.S b/ports/cortex_m4/gnu/src/tx_thread_schedule.S index 5b6fb5345..ebd149729 100644 --- a/ports/cortex_m4/gnu/src/tx_thread_schedule.S +++ b/ports/cortex_m4/gnu/src/tx_thread_schedule.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ @@ -137,7 +138,7 @@ __tx_ts_handler: BL _tx_execution_thread_exit // Call the thread exit function POP {r0, lr} // Recover LR #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts diff --git a/ports/cortex_m55/ac6/src/tx_thread_schedule.S b/ports/cortex_m55/ac6/src/tx_thread_schedule.S index a1f38fbc4..3665179aa 100644 --- a/ports/cortex_m55/ac6/src/tx_thread_schedule.S +++ b/ports/cortex_m55/ac6/src/tx_thread_schedule.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ @@ -129,7 +130,7 @@ __tx_ts_handler: BL _tx_execution_thread_exit // Call the thread exit function POP {r0, lr} // Recover LR #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts diff --git a/ports/cortex_m55/gnu/src/tx_thread_schedule.S b/ports/cortex_m55/gnu/src/tx_thread_schedule.S index 2bcc96f65..e70b44c8e 100644 --- a/ports/cortex_m55/gnu/src/tx_thread_schedule.S +++ b/ports/cortex_m55/gnu/src/tx_thread_schedule.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ @@ -125,7 +126,7 @@ __tx_ts_handler: BL _tx_execution_thread_exit // Call the thread exit function POP {r0, lr} // Recover LR #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts diff --git a/ports/cortex_m7/ac6/src/tx_thread_schedule.S b/ports/cortex_m7/ac6/src/tx_thread_schedule.S index e411198e1..beb6e0bb5 100644 --- a/ports/cortex_m7/ac6/src/tx_thread_schedule.S +++ b/ports/cortex_m7/ac6/src/tx_thread_schedule.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ @@ -139,7 +140,7 @@ __tx_ts_handler: BL _tx_execution_thread_exit // Call the thread exit function POP {r0, lr} // Recover LR #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts diff --git a/ports/cortex_m7/gnu/src/tx_thread_schedule.S b/ports/cortex_m7/gnu/src/tx_thread_schedule.S index 6700fd976..999970c2d 100644 --- a/ports/cortex_m7/gnu/src/tx_thread_schedule.S +++ b/ports/cortex_m7/gnu/src/tx_thread_schedule.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ @@ -137,7 +138,7 @@ __tx_ts_handler: BL _tx_execution_thread_exit // Call the thread exit function POP {r0, lr} // Recover LR #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts diff --git a/ports/cortex_m85/ac6/src/tx_thread_schedule.S b/ports/cortex_m85/ac6/src/tx_thread_schedule.S index 62412fffe..57e1c10f4 100644 --- a/ports/cortex_m85/ac6/src/tx_thread_schedule.S +++ b/ports/cortex_m85/ac6/src/tx_thread_schedule.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ @@ -129,7 +130,7 @@ __tx_ts_handler: BL _tx_execution_thread_exit // Call the thread exit function POP {r0, lr} // Recover LR #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts diff --git a/ports/cortex_m85/gnu/src/tx_thread_schedule.S b/ports/cortex_m85/gnu/src/tx_thread_schedule.S index f46f57379..57123f9b8 100644 --- a/ports/cortex_m85/gnu/src/tx_thread_schedule.S +++ b/ports/cortex_m85/gnu/src/tx_thread_schedule.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ @@ -125,7 +126,7 @@ __tx_ts_handler: BL _tx_execution_thread_exit // Call the thread exit function POP {r0, lr} // Recover LR #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts diff --git a/ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_schedule.S b/ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_schedule.S index 1aade9e5e..a368f5d6c 100644 --- a/ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_schedule.S +++ b/ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_schedule.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ @@ -139,7 +140,7 @@ __tx_ts_handler: BL _tx_execution_thread_exit // Call the thread exit function POP {r0, lr} // Recover LR #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts diff --git a/ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_schedule.S b/ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_schedule.S index 65c5ad509..d70a7b00c 100644 --- a/ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_schedule.S +++ b/ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_schedule.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ @@ -137,7 +138,7 @@ __tx_ts_handler: BL _tx_execution_thread_exit // Call the thread exit function POP {r0, lr} // Recover LR #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts diff --git a/ports_arch/ARMv7-M/threadx_modules/ac6/module_manager/src/tx_thread_schedule.S b/ports_arch/ARMv7-M/threadx_modules/ac6/module_manager/src/tx_thread_schedule.S index 1330dde38..715055592 100644 --- a/ports_arch/ARMv7-M/threadx_modules/ac6/module_manager/src/tx_thread_schedule.S +++ b/ports_arch/ARMv7-M/threadx_modules/ac6/module_manager/src/tx_thread_schedule.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ @@ -217,7 +218,7 @@ UsageFault_Handler: STR r1, [r0] // Store ICSR DSB // Wait for memory access to complete #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts @@ -252,7 +253,7 @@ __tx_ts_handler: BL _tx_execution_thread_exit // Call the thread exit function POP {r0, lr} // Recover LR #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts diff --git a/ports_arch/ARMv7-M/threadx_modules/gnu/module_manager/src/tx_thread_schedule.S b/ports_arch/ARMv7-M/threadx_modules/gnu/module_manager/src/tx_thread_schedule.S index dffca713f..92d557d5f 100644 --- a/ports_arch/ARMv7-M/threadx_modules/gnu/module_manager/src/tx_thread_schedule.S +++ b/ports_arch/ARMv7-M/threadx_modules/gnu/module_manager/src/tx_thread_schedule.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ @@ -215,7 +216,7 @@ UsageFault_Handler: STR r1, [r0] // Store ICSR DSB // Wait for memory access to complete #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts @@ -250,7 +251,7 @@ __tx_ts_handler: BL _tx_execution_thread_exit // Call the thread exit function POP {r0, lr} // Recover LR #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts diff --git a/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_schedule.S b/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_schedule.S index 40d3282bb..40c86d71c 100644 --- a/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_schedule.S +++ b/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_schedule.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ @@ -129,7 +130,7 @@ __tx_ts_handler: BL _tx_execution_thread_exit // Call the thread exit function POP {r0, lr} // Recover LR #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts diff --git a/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_schedule.S b/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_schedule.S index 0a30ab360..b69e50455 100644 --- a/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_schedule.S +++ b/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_schedule.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ @@ -125,7 +126,7 @@ __tx_ts_handler: BL _tx_execution_thread_exit // Call the thread exit function POP {r0, lr} // Recover LR #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts diff --git a/ports_module/cortex_m3/ac6/module_manager/src/tx_thread_schedule.S b/ports_module/cortex_m3/ac6/module_manager/src/tx_thread_schedule.S index 56187f4c2..0850b7081 100644 --- a/ports_module/cortex_m3/ac6/module_manager/src/tx_thread_schedule.S +++ b/ports_module/cortex_m3/ac6/module_manager/src/tx_thread_schedule.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ @@ -217,7 +218,7 @@ UsageFault_Handler: STR r1, [r0] // Store ICSR DSB // Wait for memory access to complete #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts @@ -252,7 +253,7 @@ __tx_ts_handler: BL _tx_execution_thread_exit // Call the thread exit function POP {r0, lr} // Recover LR #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts diff --git a/ports_module/cortex_m3/gnu/module_manager/src/tx_thread_schedule.S b/ports_module/cortex_m3/gnu/module_manager/src/tx_thread_schedule.S index 8336214b2..83210ac73 100644 --- a/ports_module/cortex_m3/gnu/module_manager/src/tx_thread_schedule.S +++ b/ports_module/cortex_m3/gnu/module_manager/src/tx_thread_schedule.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ @@ -215,7 +216,7 @@ UsageFault_Handler: STR r1, [r0] // Store ICSR DSB // Wait for memory access to complete #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts @@ -250,7 +251,7 @@ __tx_ts_handler: BL _tx_execution_thread_exit // Call the thread exit function POP {r0, lr} // Recover LR #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts diff --git a/ports_module/cortex_m33/ac6/module_manager/src/tx_thread_schedule.S b/ports_module/cortex_m33/ac6/module_manager/src/tx_thread_schedule.S index 707ad4de1..30357a854 100644 --- a/ports_module/cortex_m33/ac6/module_manager/src/tx_thread_schedule.S +++ b/ports_module/cortex_m33/ac6/module_manager/src/tx_thread_schedule.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ @@ -205,7 +206,7 @@ BusFault_Handler: STR r1, [r0] // Store ICSR DSB // Wait for memory access to complete #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts @@ -243,7 +244,7 @@ __tx_ts_handler: BL _tx_execution_thread_exit // Call the thread exit function POP {r0, lr} // Recover LR #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts diff --git a/ports_module/cortex_m33/gnu/module_manager/src/tx_thread_schedule.S b/ports_module/cortex_m33/gnu/module_manager/src/tx_thread_schedule.S index 16913f570..e2ec1edcd 100644 --- a/ports_module/cortex_m33/gnu/module_manager/src/tx_thread_schedule.S +++ b/ports_module/cortex_m33/gnu/module_manager/src/tx_thread_schedule.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ @@ -204,7 +205,7 @@ BusFault_Handler: STR r1, [r0] // Store ICSR DSB // Wait for memory access to complete #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts @@ -242,7 +243,7 @@ __tx_ts_handler: BL _tx_execution_thread_exit // Call the thread exit function POP {r0, lr} // Recover LR #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts diff --git a/ports_module/cortex_m4/ac6/module_manager/src/tx_thread_schedule.S b/ports_module/cortex_m4/ac6/module_manager/src/tx_thread_schedule.S index 02431092d..83ea99abd 100644 --- a/ports_module/cortex_m4/ac6/module_manager/src/tx_thread_schedule.S +++ b/ports_module/cortex_m4/ac6/module_manager/src/tx_thread_schedule.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ @@ -217,7 +218,7 @@ UsageFault_Handler: STR r1, [r0] // Store ICSR DSB // Wait for memory access to complete #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts @@ -252,7 +253,7 @@ __tx_ts_handler: BL _tx_execution_thread_exit // Call the thread exit function POP {r0, lr} // Recover LR #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts diff --git a/ports_module/cortex_m4/gnu/module_manager/src/tx_thread_schedule.S b/ports_module/cortex_m4/gnu/module_manager/src/tx_thread_schedule.S index a5a80868a..e4ceee8ab 100644 --- a/ports_module/cortex_m4/gnu/module_manager/src/tx_thread_schedule.S +++ b/ports_module/cortex_m4/gnu/module_manager/src/tx_thread_schedule.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ @@ -215,7 +216,7 @@ UsageFault_Handler: STR r1, [r0] // Store ICSR DSB // Wait for memory access to complete #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts @@ -250,7 +251,7 @@ __tx_ts_handler: BL _tx_execution_thread_exit // Call the thread exit function POP {r0, lr} // Recover LR #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts diff --git a/ports_module/cortex_m7/ac6/module_manager/src/tx_thread_schedule.S b/ports_module/cortex_m7/ac6/module_manager/src/tx_thread_schedule.S index a3126bc73..f3af5f71a 100644 --- a/ports_module/cortex_m7/ac6/module_manager/src/tx_thread_schedule.S +++ b/ports_module/cortex_m7/ac6/module_manager/src/tx_thread_schedule.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ @@ -217,7 +218,7 @@ UsageFault_Handler: STR r1, [r0] // Store ICSR DSB // Wait for memory access to complete #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts @@ -252,7 +253,7 @@ __tx_ts_handler: BL _tx_execution_thread_exit // Call the thread exit function POP {r0, lr} // Recover LR #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts diff --git a/ports_module/cortex_m7/gnu/module_manager/src/tx_thread_schedule.S b/ports_module/cortex_m7/gnu/module_manager/src/tx_thread_schedule.S index 571af2ee3..e7284c639 100644 --- a/ports_module/cortex_m7/gnu/module_manager/src/tx_thread_schedule.S +++ b/ports_module/cortex_m7/gnu/module_manager/src/tx_thread_schedule.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ @@ -215,7 +216,7 @@ UsageFault_Handler: STR r1, [r0] // Store ICSR DSB // Wait for memory access to complete #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts @@ -250,7 +251,7 @@ __tx_ts_handler: BL _tx_execution_thread_exit // Call the thread exit function POP {r0, lr} // Recover LR #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts From a33f6efc483da9e49fa6598d07e02ec213ea04db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 29 Jun 2026 16:22:52 -0400 Subject: [PATCH 007/181] Updated Cortex-R4 Thumb bit immediates (#565) Use explicit immediate syntax when testing the Thumb bit in AC6 Cortex-R4 stack build assembly. Co-authored-by: Codex --- ports/cortex_r4/ac6/src/tx_thread_stack_build.S | 3 ++- .../cortex_r4/ac6/module_manager/src/tx_thread_stack_build.S | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/ports/cortex_r4/ac6/src/tx_thread_stack_build.S b/ports/cortex_r4/ac6/src/tx_thread_stack_build.S index a29931360..ff916007a 100644 --- a/ports/cortex_r4/ac6/src/tx_thread_stack_build.S +++ b/ports/cortex_r4/ac6/src/tx_thread_stack_build.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ @@ -143,7 +144,7 @@ _tx_thread_stack_build: MRS r3, CPSR // Pickup CPSR BIC r3, r3, #CPSR_MASK // Mask mode bits of CPSR ORR r3, r3, #SVC_MODE // Build CPSR, SVC mode, interrupts enabled - TST r1, 1 // Test if Thumb bit is set in entry function address + TST r1, #1 // Test if Thumb bit is set in entry function address ITE NE ORRNE r3, r3, #THUMB_BIT // Yes, set the Thumb bit BICEQ r3, r3, #THUMB_BIT // No, clear the Thumb bit diff --git a/ports_module/cortex_r4/ac6/module_manager/src/tx_thread_stack_build.S b/ports_module/cortex_r4/ac6/module_manager/src/tx_thread_stack_build.S index 8f122083e..e3142ec4d 100644 --- a/ports_module/cortex_r4/ac6/module_manager/src/tx_thread_stack_build.S +++ b/ports_module/cortex_r4/ac6/module_manager/src/tx_thread_stack_build.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). /**************************************************************************/ @@ -143,7 +144,7 @@ _tx_thread_stack_build: BIC r3, r3, #CPSR_MASK // Mask mode bits of CPSR ORR r3, r3, #SYS_MODE // Build CPSR, SYS mode, interrupts enabled - TST r1, 1 // Test if Thumb bit is set in entry function address + TST r1, #1 // Test if Thumb bit is set in entry function address ITE NE ORRNE r3, r3, #THUMB_BIT // Yes, set the Thumb bit BICEQ r3, r3, #THUMB_BIT // No, clear the Thumb bit From 92ce0754ed42f9d9d1121805057db5cc9c171d66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 27 Jul 2026 10:30:29 -0400 Subject: [PATCH 008/181] Marked txm_module_object_deallocate as deprecated (#559) Added a compile-time #pragma message warning to the module library source so that any module that includes or compiles this file receives an explicit deprecation notice at build time. Updated the internal documentation block in the manager-side implementation to explain that this function must not be called directly and that calling it on a live object causes a use-after-free. The Module Manager dispatch layer already releases pool memory automatically after a successful tx_*_delete() call. Module authors should remove any explicit call to txm_module_object_deallocate(). Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../src/txm_module_object_deallocate.c | 21 +++++++++++++++++++ .../txm_module_manager_object_deallocate.c | 12 ++++++++++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/common_modules/module_lib/src/txm_module_object_deallocate.c b/common_modules/module_lib/src/txm_module_object_deallocate.c index c0ffb097f..480c61005 100644 --- a/common_modules/module_lib/src/txm_module_object_deallocate.c +++ b/common_modules/module_lib/src/txm_module_object_deallocate.c @@ -23,6 +23,27 @@ #define TXM_MODULE #include "txm_module.h" #ifndef TXM_MODULE_OBJECT_DEALLOCATE_CALL_NOT_USED + +/* DEPRECATION NOTICE + * txm_module_object_deallocate() is deprecated and must not be used in new + * code. It is retained only for backward-compatibility with existing modules. + * + * WHY: when a module calls tx_timer_delete(), tx_semaphore_delete(), or any + * other tx_*_delete() service, the Module Manager dispatch layer automatically + * releases the associated object pool memory after the kernel cleanup + * completes. No separate deallocation call is required or expected. + * + * WHAT TO DO: remove any call to txm_module_object_deallocate() from your + * module. The corresponding tx_*_delete() call already handles everything. + * + * RISK: calling txm_module_object_deallocate() on a live kernel object (one + * whose tx_*_delete() has not yet been called) frees the backing pool memory + * while the object is still referenced by the kernel, which is undefined + * behaviour (use-after-free). + */ +#pragma message("txm_module_object_deallocate() is deprecated and must not be used. " \ + "Call tx_*_delete() instead; the Module Manager dispatch layer " \ + "releases pool memory automatically on success.") /**************************************************************************/ /* */ /* FUNCTION RELEASE */ diff --git a/common_modules/module_manager/src/txm_module_manager_object_deallocate.c b/common_modules/module_manager/src/txm_module_manager_object_deallocate.c index 2efc465b7..95e28e4d6 100644 --- a/common_modules/module_manager/src/txm_module_manager_object_deallocate.c +++ b/common_modules/module_manager/src/txm_module_manager_object_deallocate.c @@ -38,7 +38,17 @@ /* */ /* DESCRIPTION */ /* */ -/* This function deallocates a previously allocated object. */ +/* DEPRECATED. This function is called internally by the Module */ +/* Manager dispatch layer after a successful tx_*_delete() call from */ +/* a module. It must not be called directly by module or application */ +/* code. Calling it on a live kernel object (one whose tx_*_delete() */ +/* has not yet been called) frees the backing pool memory while the */ +/* object is still referenced by the kernel (use-after-free). */ +/* */ +/* Module authors: remove any explicit call to */ +/* txm_module_object_deallocate(). Calling the appropriate */ +/* tx_*_delete() service is sufficient; pool deallocation is handled */ +/* automatically by the dispatch layer. */ /* */ /* INPUT */ /* */ From 190c4d6be48ae2fcf555d282691f6dfd985323ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 27 Jul 2026 10:30:49 -0400 Subject: [PATCH 009/181] Flagged txm_module_object_pointer_get as deprecated (#562) Added #pragma message compile-time warning to the module library source and updated the DESCRIPTION blocks in both the library and manager implementations. Reason: this wrapper passes UINT_MAX as the name-buffer length to the underlying extended search. The comparison loop can therefore read past the end of a short name buffer, which is undefined behaviour. Callers should use txm_module_object_pointer_get_extended() and supply the actual buffer length. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../src/txm_module_object_pointer_get.c | 23 ++++++++++++++++--- .../txm_module_manager_object_pointer_get.c | 7 +++--- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/common_modules/module_lib/src/txm_module_object_pointer_get.c b/common_modules/module_lib/src/txm_module_object_pointer_get.c index 6417457a5..fcd7ab1f8 100644 --- a/common_modules/module_lib/src/txm_module_object_pointer_get.c +++ b/common_modules/module_lib/src/txm_module_object_pointer_get.c @@ -23,6 +23,22 @@ #define TXM_MODULE #include "txm_module.h" #ifndef TXM_MODULE_OBJECT_POINTER_GET_CALL_NOT_USED + +/* DEPRECATION NOTICE + * txm_module_object_pointer_get() is deprecated. Do not use it in new code. + * + * WHY: this function passes UINT_MAX as the name-buffer length to the + * underlying search. If the name pointer points to a buffer shorter than + * the searched string, the comparison can read past the end of the buffer, + * which is undefined behaviour. + * + * WHAT TO DO: replace calls with txm_module_object_pointer_get_extended(), + * passing the actual length of the name buffer as the third argument. + */ +#pragma message("txm_module_object_pointer_get() is deprecated. " \ + "Use txm_module_object_pointer_get_extended() and pass " \ + "the actual name buffer length.") + /**************************************************************************/ /* */ /* FUNCTION RELEASE */ @@ -35,9 +51,10 @@ /* */ /* DESCRIPTION */ /* */ -/* This function is deprecated and calls the secure version of this */ -/* function (_txm_module_manager_object_pointer_get_extended) with the */ -/* maximum possible name length since none was passed. */ +/* DEPRECATED. Use _txm_module_object_pointer_get_extended() instead, */ +/* passing the actual name-buffer length. This wrapper passes */ +/* UINT_MAX as the length, which can cause the name-comparison loop */ +/* to read past the end of a short buffer (undefined behaviour). */ /* */ /* INPUT */ /* */ diff --git a/common_modules/module_manager/src/txm_module_manager_object_pointer_get.c b/common_modules/module_manager/src/txm_module_manager_object_pointer_get.c index 84cf6c96e..8b24558ba 100644 --- a/common_modules/module_manager/src/txm_module_manager_object_pointer_get.c +++ b/common_modules/module_manager/src/txm_module_manager_object_pointer_get.c @@ -37,9 +37,10 @@ /* */ /* DESCRIPTION */ /* */ -/* This function is deprecated and calls the secure version of this */ -/* function (_txm_module_manager_object_pointer_get_extended) with the */ -/* maximum possible name length since none was passed. */ +/* DEPRECATED. Use _txm_module_manager_object_pointer_get_extended() */ +/* instead, passing the actual name-buffer length. This wrapper */ +/* passes UINT_MAX as the length, which can cause the name-comparison */ +/* loop to read past the end of a short buffer (undefined behaviour). */ /* */ /* INPUT */ /* */ From 2baae7c57fee937af86d8a6664b7acf9a9f95645 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Thu, 6 Aug 2026 10:05:33 -0400 Subject: [PATCH 010/181] Fixed VFP issues on Cortex-R4 and R5 ports (#578) * Fixed missing VFP thread extension on Cortex-R4 and R5 ports Building cortex_r4/gnu, cortex_r5/gnu or cortex_r5/ac6 with TX_ENABLE_VFP_SUPPORT corrupts memory. The assembly in tx_thread_schedule, tx_thread_system_return and tx_thread_context_restore reads and writes a per-thread VFP enable flag as [thread, #144], but every TX_THREAD_EXTENSION in these ports' tx_port.h was empty, so no such member existed. Offset 144 in the resulting TX_THREAD is tx_thread_filex_ptr, so the damage runs both ways: - tx_thread_vfp_enable() stores 1 into tx_thread_filex_ptr, after which FileX dereferences 0x1; - conversely, once FileX sets that pointer the context switch reads it as "floating point enabled" and starts pushing about 132 bytes of floating-point context onto a thread stack never sized for it, then restores unrelated data into the D registers. sizeof(TX_THREAD) is 180 on these ports, so 144 is a live member rather than padding past the end of the structure. What makes this dangerous is that it is silent. The defect was reproduced at runtime by reverting the Cortex-R52 port -- which inherited the same assembly and the same hard-coded 144 from the R5 port -- to this state and running its floating-point demo on the Armv8-R AEM FVP. Every floating-point value was still preserved exactly and no corruption was reported across interrupts, because a non-zero filex_ptr reads as "enabled" and the context switch dutifully saves and restores. The only visible damage was tx_thread_filex_ptr reading 0x00000001. In other words the feature you enabled appears to work, and what breaks is an unrelated pointer that nothing notices until FileX is introduced. With the field present the same demo reports the sentinel intact. This appears to be drift rather than a deliberate limitation. All fourteen Armv7-A port and toolchain combinations define the field and contain the VFP code paths. The R-profile family is inconsistent in both directions: these three have the code paths without the field, while cortex_r4/ac5, cortex_r4/ac6, cortex_r4/iar, cortex_r5/ghs, cortex_r5/iar, cortex_r7/ghs and cortex_r8_smp/ac5 define the field but contain no VFP code paths. The fix follows the Armv7-A ports exactly: TX_THREAD_EXTENSION_2 carries tx_thread_vfp_enable, and tx_thread_vfp_enable/disable are declared. The field is defined unconditionally rather than under TX_ENABLE_VFP_SUPPORT because the offset is hard-coded in assembly, so a conditional member would shift every following field and be correct in only one configuration. No assembly changes are needed: 144 is already correct once the member exists. Verified with GCC 14.3: on all three ports tx_thread_vfp_enable now lands at exactly offset 144, matching the assembly, with tx_thread_filex_ptr moved to 148. The library builds cleanly for cortex_r4/gnu and cortex_r5/gnu both with and without TX_ENABLE_VFP_SUPPORT, and the VFP save and restore instructions appear in the port assembly only when it is requested. cortex_r5/ac6 is verified by offset and inspection only, as that toolchain was not available here. Runtime verification was performed on Armv8-R as described above rather than on R4/R5 silicon; upstream QEMU's xlnx-zcu102 machine holds its Cortex-R5F cores in reset, so no R5 target was available. ABI note for release documentation: adding the member moves tx_thread_filex_ptr and everything after it by four bytes and grows TX_THREAD from 180 to 184 bytes. This is the layout the Armv7-A ports already have, so the change aligns R-profile with A-profile rather than introducing a new one, but kernel awareness and TraceX tooling that hard-codes offsets will need rebuilding. Follow-up worth considering separately: nothing in the toolchain ties the literal 144 in the assembly to the C structure, which is what allowed this to go unnoticed. A compile-time assertion per port turns any recurrence into a build failure -- when the experiment above reverted the field, that assertion failed the build before a corrupting binary could be produced. ports/cortex_r52/gnu/src/tx_port_offset_check.c is a working reference. * Added compile-time offset checks to the Cortex-R4 and R5 ports Nothing in the toolchain connects the structure offsets hard-coded in the port assembly to the C definition of TX_THREAD, which is what allowed the missing VFP thread extension to go unnoticed. These files assert the offsets that the context-switch path depends on, so a recurrence becomes a build failure instead of memory corruption discovered later at runtime. Three offsets are asserted: the VFP enable flag at 144, the thread stack pointer at 8 and the run counter at 4. The stack pointer and run counter precede every extension macro in TX_THREAD, so they are stable by construction. Offset 144 was checked against the build options that could plausibly move it -- stack checking, event trace, event logging, performance info and TX_NOT_INTERRUPTABLE -- and is unchanged by all of them, because the only conditional member nearby guards tx_thread_filex_ptr, which follows the extension, and TX_THREAD_USER_EXTENSION appears much later in the structure. The assertions therefore cannot misfire on a legitimate configuration. C99 has no _Static_assert, so a negative array dimension is used. Each file compiles clean under -std=c99 -pedantic -Wall -Wextra and emits zero bytes of code or data. Verified that the checks actually catch regressions rather than merely compiling: asserting a deliberately wrong offset is rejected on all three ports, and removing the VFP field again fails the build outright with a message naming the missing member. These ports have no CMake build of their own, so the files take effect only in builds that compile everything under src/. That is still worthwhile given they cost nothing and emit nothing. Extending the same technique to the remaining ports is deliberately left as separate work: it requires reading each port's assembly to attribute every hard-coded literal to the right structure, and copying assertions without that analysis would risk asserting wrong offsets. Assisted-by: Claude Code (Opus 5) --- ports/cortex_r4/gnu/inc/tx_port.h | 24 ++++- .../cortex_r4/gnu/src/tx_port_offset_check.c | 87 +++++++++++++++++++ ports/cortex_r5/ac6/inc/tx_port.h | 24 ++++- .../cortex_r5/ac6/src/tx_port_offset_check.c | 87 +++++++++++++++++++ ports/cortex_r5/gnu/inc/tx_port.h | 24 ++++- .../cortex_r5/gnu/src/tx_port_offset_check.c | 87 +++++++++++++++++++ 6 files changed, 330 insertions(+), 3 deletions(-) create mode 100644 ports/cortex_r4/gnu/src/tx_port_offset_check.c create mode 100644 ports/cortex_r5/ac6/src/tx_port_offset_check.c create mode 100644 ports/cortex_r5/gnu/src/tx_port_offset_check.c diff --git a/ports/cortex_r4/gnu/inc/tx_port.h b/ports/cortex_r4/gnu/inc/tx_port.h index d85c21486..44c6b8a41 100644 --- a/ports/cortex_r4/gnu/inc/tx_port.h +++ b/ports/cortex_r4/gnu/inc/tx_port.h @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Claude Code (Opus 5). /**************************************************************************/ @@ -183,7 +184,16 @@ typedef unsigned short USHORT; #define TX_THREAD_EXTENSION_0 #define TX_THREAD_EXTENSION_1 -#define TX_THREAD_EXTENSION_2 + +/* TX_THREAD_EXTENSION_2 carries the per-thread VFP enable flag that the lazy + floating-point save and restore in tx_thread_schedule, tx_thread_system_return + and tx_thread_context_restore reads and writes as [thread, #144]. Without it + a TX_ENABLE_VFP_SUPPORT build has no such member and those accesses land on + tx_thread_filex_ptr instead. Defined unconditionally, matching the Armv7-A + ports: the offset is hard-coded in assembly, so a conditional member would + move every following field and be correct in only one configuration. */ + +#define TX_THREAD_EXTENSION_2 ULONG tx_thread_vfp_enable; #define TX_THREAD_EXTENSION_3 @@ -238,6 +248,18 @@ typedef unsigned short USHORT; #define TX_TIMER_DELETE_EXTENSION(timer_ptr) +/* Per-thread floating-point control, implemented in tx_thread_schedule and + available only in a TX_ENABLE_VFP_SUPPORT build. Floating-point context is + saved lazily: only threads that ask for it pay the cost. Note these set a + software flag for the context switch; enabling the FPU itself (CPACR, FPEXC) + remains the board support package's responsibility. */ + +#ifdef TX_ENABLE_VFP_SUPPORT +void tx_thread_vfp_enable(void); +void tx_thread_vfp_disable(void); +#endif + + /* Determine if the ARM architecture has the CLZ instruction. This is available on architectures v5 and above. If available, redefine the macro for calculating the lowest bit set. */ diff --git a/ports/cortex_r4/gnu/src/tx_port_offset_check.c b/ports/cortex_r4/gnu/src/tx_port_offset_check.c new file mode 100644 index 000000000..5504d28f3 --- /dev/null +++ b/ports/cortex_r4/gnu/src/tx_port_offset_check.c @@ -0,0 +1,87 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Port Specific */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +/**************************************************************************/ +/* */ +/* PORT SPECIFIC C INFORMATION RELEASE */ +/* */ +/* tx_port_offset_check.c Cortex-R4/GNU */ +/* */ +/* DESCRIPTION */ +/* */ +/* Compile-time verification of the TX_THREAD structure offsets that */ +/* this port's assembly reaches by hard-coded displacement. The file */ +/* emits no code; it exists purely so that a layout change becomes a */ +/* build failure. */ +/* */ +/* Why this is needed: tx_thread_schedule.S, */ +/* tx_thread_system_return.S and tx_thread_context_restore.S read and */ +/* write the per-thread VFP enable flag as [thread, #144]. Nothing in */ +/* the toolchain connects that literal to the C structure, so adding a */ +/* member, enabling an option that adds one, or reordering the port */ +/* extensions would silently retarget those accesses at an unrelated */ +/* field -- corrupting thread state in a way that is extremely hard to */ +/* diagnose from the symptom. The offset was measured at 144 for the */ +/* default build and is asserted here. */ +/* */ +/* NOTE: this port has no CMake build of its own, so this file takes */ +/* effect only in builds that compile everything under src/. It is */ +/* still worthwhile: it emits no code, costs nothing, and protects every */ +/* build that does pick it up. */ +/* */ +/* A negative array dimension is used rather than _Static_assert */ +/* because this project targets C99, where _Static_assert does not */ +/* exist. If an assertion below fails, the compiler reports a negative */ +/* or zero-sized array for the named typedef. */ +/* */ +/**************************************************************************/ + +#include "tx_api.h" +#include + +/* Offset of the VFP enable flag as encoded in this port's assembly. + Overridable only so that the assertion itself can be tested. */ + +#ifndef TX_PORT_VFP_ENABLE_OFFSET +#define TX_PORT_VFP_ENABLE_OFFSET 144 +#endif + +typedef char +tx_port_assert_vfp_enable_offset_is_144[ + (offsetof(TX_THREAD, tx_thread_vfp_enable) == TX_PORT_VFP_ENABLE_OFFSET) + ? 1 : -1]; + +/* The stack pointer is read as [thread, #8] by tx_thread_schedule.S and + written by tx_thread_system_return.S, and the run counter as + [thread, #4]. Assert those too, since they are on the context-switch + critical path. */ + +typedef char +tx_port_assert_stack_ptr_offset_is_8[ + (offsetof(TX_THREAD, tx_thread_stack_ptr) == 8) ? 1 : -1]; + +typedef char +tx_port_assert_run_count_offset_is_4[ + (offsetof(TX_THREAD, tx_thread_run_count) == 4) ? 1 : -1]; diff --git a/ports/cortex_r5/ac6/inc/tx_port.h b/ports/cortex_r5/ac6/inc/tx_port.h index 9826ac6fd..8a905c9a7 100644 --- a/ports/cortex_r5/ac6/inc/tx_port.h +++ b/ports/cortex_r5/ac6/inc/tx_port.h @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Claude Code (Opus 5). /**************************************************************************/ @@ -183,7 +184,16 @@ typedef unsigned short USHORT; #define TX_THREAD_EXTENSION_0 #define TX_THREAD_EXTENSION_1 -#define TX_THREAD_EXTENSION_2 + +/* TX_THREAD_EXTENSION_2 carries the per-thread VFP enable flag that the lazy + floating-point save and restore in tx_thread_schedule, tx_thread_system_return + and tx_thread_context_restore reads and writes as [thread, #144]. Without it + a TX_ENABLE_VFP_SUPPORT build has no such member and those accesses land on + tx_thread_filex_ptr instead. Defined unconditionally, matching the Armv7-A + ports: the offset is hard-coded in assembly, so a conditional member would + move every following field and be correct in only one configuration. */ + +#define TX_THREAD_EXTENSION_2 ULONG tx_thread_vfp_enable; #define TX_THREAD_EXTENSION_3 @@ -238,6 +248,18 @@ typedef unsigned short USHORT; #define TX_TIMER_DELETE_EXTENSION(timer_ptr) +/* Per-thread floating-point control, implemented in tx_thread_schedule and + available only in a TX_ENABLE_VFP_SUPPORT build. Floating-point context is + saved lazily: only threads that ask for it pay the cost. Note these set a + software flag for the context switch; enabling the FPU itself (CPACR, FPEXC) + remains the board support package's responsibility. */ + +#ifdef TX_ENABLE_VFP_SUPPORT +void tx_thread_vfp_enable(void); +void tx_thread_vfp_disable(void); +#endif + + /* Determine if the ARM architecture has the CLZ instruction. This is available on architectures v5 and above. If available, redefine the macro for calculating the lowest bit set. */ diff --git a/ports/cortex_r5/ac6/src/tx_port_offset_check.c b/ports/cortex_r5/ac6/src/tx_port_offset_check.c new file mode 100644 index 000000000..d7432b6a1 --- /dev/null +++ b/ports/cortex_r5/ac6/src/tx_port_offset_check.c @@ -0,0 +1,87 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Port Specific */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +/**************************************************************************/ +/* */ +/* PORT SPECIFIC C INFORMATION RELEASE */ +/* */ +/* tx_port_offset_check.c Cortex-R5/AC6 */ +/* */ +/* DESCRIPTION */ +/* */ +/* Compile-time verification of the TX_THREAD structure offsets that */ +/* this port's assembly reaches by hard-coded displacement. The file */ +/* emits no code; it exists purely so that a layout change becomes a */ +/* build failure. */ +/* */ +/* Why this is needed: tx_thread_schedule.S, */ +/* tx_thread_system_return.S and tx_thread_context_restore.S read and */ +/* write the per-thread VFP enable flag as [thread, #144]. Nothing in */ +/* the toolchain connects that literal to the C structure, so adding a */ +/* member, enabling an option that adds one, or reordering the port */ +/* extensions would silently retarget those accesses at an unrelated */ +/* field -- corrupting thread state in a way that is extremely hard to */ +/* diagnose from the symptom. The offset was measured at 144 for the */ +/* default build and is asserted here. */ +/* */ +/* NOTE: this port has no CMake build of its own, so this file takes */ +/* effect only in builds that compile everything under src/. It is */ +/* still worthwhile: it emits no code, costs nothing, and protects every */ +/* build that does pick it up. */ +/* */ +/* A negative array dimension is used rather than _Static_assert */ +/* because this project targets C99, where _Static_assert does not */ +/* exist. If an assertion below fails, the compiler reports a negative */ +/* or zero-sized array for the named typedef. */ +/* */ +/**************************************************************************/ + +#include "tx_api.h" +#include + +/* Offset of the VFP enable flag as encoded in this port's assembly. + Overridable only so that the assertion itself can be tested. */ + +#ifndef TX_PORT_VFP_ENABLE_OFFSET +#define TX_PORT_VFP_ENABLE_OFFSET 144 +#endif + +typedef char +tx_port_assert_vfp_enable_offset_is_144[ + (offsetof(TX_THREAD, tx_thread_vfp_enable) == TX_PORT_VFP_ENABLE_OFFSET) + ? 1 : -1]; + +/* The stack pointer is read as [thread, #8] by tx_thread_schedule.S and + written by tx_thread_system_return.S, and the run counter as + [thread, #4]. Assert those too, since they are on the context-switch + critical path. */ + +typedef char +tx_port_assert_stack_ptr_offset_is_8[ + (offsetof(TX_THREAD, tx_thread_stack_ptr) == 8) ? 1 : -1]; + +typedef char +tx_port_assert_run_count_offset_is_4[ + (offsetof(TX_THREAD, tx_thread_run_count) == 4) ? 1 : -1]; diff --git a/ports/cortex_r5/gnu/inc/tx_port.h b/ports/cortex_r5/gnu/inc/tx_port.h index 41f60412a..b5f81474d 100644 --- a/ports/cortex_r5/gnu/inc/tx_port.h +++ b/ports/cortex_r5/gnu/inc/tx_port.h @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Claude Code (Opus 5). /**************************************************************************/ @@ -183,7 +184,16 @@ typedef unsigned short USHORT; #define TX_THREAD_EXTENSION_0 #define TX_THREAD_EXTENSION_1 -#define TX_THREAD_EXTENSION_2 + +/* TX_THREAD_EXTENSION_2 carries the per-thread VFP enable flag that the lazy + floating-point save and restore in tx_thread_schedule, tx_thread_system_return + and tx_thread_context_restore reads and writes as [thread, #144]. Without it + a TX_ENABLE_VFP_SUPPORT build has no such member and those accesses land on + tx_thread_filex_ptr instead. Defined unconditionally, matching the Armv7-A + ports: the offset is hard-coded in assembly, so a conditional member would + move every following field and be correct in only one configuration. */ + +#define TX_THREAD_EXTENSION_2 ULONG tx_thread_vfp_enable; #define TX_THREAD_EXTENSION_3 @@ -238,6 +248,18 @@ typedef unsigned short USHORT; #define TX_TIMER_DELETE_EXTENSION(timer_ptr) +/* Per-thread floating-point control, implemented in tx_thread_schedule and + available only in a TX_ENABLE_VFP_SUPPORT build. Floating-point context is + saved lazily: only threads that ask for it pay the cost. Note these set a + software flag for the context switch; enabling the FPU itself (CPACR, FPEXC) + remains the board support package's responsibility. */ + +#ifdef TX_ENABLE_VFP_SUPPORT +void tx_thread_vfp_enable(void); +void tx_thread_vfp_disable(void); +#endif + + /* Determine if the ARM architecture has the CLZ instruction. This is available on architectures v5 and above. If available, redefine the macro for calculating the lowest bit set. */ diff --git a/ports/cortex_r5/gnu/src/tx_port_offset_check.c b/ports/cortex_r5/gnu/src/tx_port_offset_check.c new file mode 100644 index 000000000..44dfd1a88 --- /dev/null +++ b/ports/cortex_r5/gnu/src/tx_port_offset_check.c @@ -0,0 +1,87 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Port Specific */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +/**************************************************************************/ +/* */ +/* PORT SPECIFIC C INFORMATION RELEASE */ +/* */ +/* tx_port_offset_check.c Cortex-R5/GNU */ +/* */ +/* DESCRIPTION */ +/* */ +/* Compile-time verification of the TX_THREAD structure offsets that */ +/* this port's assembly reaches by hard-coded displacement. The file */ +/* emits no code; it exists purely so that a layout change becomes a */ +/* build failure. */ +/* */ +/* Why this is needed: tx_thread_schedule.S, */ +/* tx_thread_system_return.S and tx_thread_context_restore.S read and */ +/* write the per-thread VFP enable flag as [thread, #144]. Nothing in */ +/* the toolchain connects that literal to the C structure, so adding a */ +/* member, enabling an option that adds one, or reordering the port */ +/* extensions would silently retarget those accesses at an unrelated */ +/* field -- corrupting thread state in a way that is extremely hard to */ +/* diagnose from the symptom. The offset was measured at 144 for the */ +/* default build and is asserted here. */ +/* */ +/* NOTE: this port has no CMake build of its own, so this file takes */ +/* effect only in builds that compile everything under src/. It is */ +/* still worthwhile: it emits no code, costs nothing, and protects every */ +/* build that does pick it up. */ +/* */ +/* A negative array dimension is used rather than _Static_assert */ +/* because this project targets C99, where _Static_assert does not */ +/* exist. If an assertion below fails, the compiler reports a negative */ +/* or zero-sized array for the named typedef. */ +/* */ +/**************************************************************************/ + +#include "tx_api.h" +#include + +/* Offset of the VFP enable flag as encoded in this port's assembly. + Overridable only so that the assertion itself can be tested. */ + +#ifndef TX_PORT_VFP_ENABLE_OFFSET +#define TX_PORT_VFP_ENABLE_OFFSET 144 +#endif + +typedef char +tx_port_assert_vfp_enable_offset_is_144[ + (offsetof(TX_THREAD, tx_thread_vfp_enable) == TX_PORT_VFP_ENABLE_OFFSET) + ? 1 : -1]; + +/* The stack pointer is read as [thread, #8] by tx_thread_schedule.S and + written by tx_thread_system_return.S, and the run counter as + [thread, #4]. Assert those too, since they are on the context-switch + critical path. */ + +typedef char +tx_port_assert_stack_ptr_offset_is_8[ + (offsetof(TX_THREAD, tx_thread_stack_ptr) == 8) ? 1 : -1]; + +typedef char +tx_port_assert_run_count_offset_is_4[ + (offsetof(TX_THREAD, tx_thread_run_count) == 4) ? 1 : -1]; From f84dd3d2aa51872cf5b642319a42d156a28ba1a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Sat, 8 Aug 2026 08:00:01 -0400 Subject: [PATCH 011/181] Added Cortex-R52 port with Armv8-R AEM FVP example build (#579) Added a ThreadX port for Arm Cortex-R52 with the GNU toolchain Adds ports/cortex_r52/gnu together with a CMake build, an example build for the freely available Armv8-R AEM FVP, and an automated test suite. The port is EL2-aware by construction. Cortex-R52 always implements EL2 and resets into it, so the reset path configures EL2, installs both the EL2 and EL1 vector tables, and only then drops to EL1 to run the kernel. Keeping that structure from the start lets partitioning work reuse the boot path rather than replace it; TX_R52_BOOT_AT_EL1 skips the EL2 stage where a vendor monitor has already dropped privilege. This is also the first R-profile port in the tree with a working CMake build. cmake/cortex_a9.cmake exists but ports/cortex_a9/gnu/CMakeLists.txt is empty, so no A- or R-profile port could be built this way before. Contents: - Kernel port: 16 assembly sources plus tx_port.h, seeded from the Cortex-R5/GNU port. - Build: cmake/cortex_r52.cmake and the port CMakeLists.txt, with soft/hard float, VFP, FIQ and IRQ/FIQ nesting options. - Example BSP: EL2 to EL1 boot, GICv3, generic timer, PMSAv8-R MPU, semihosting and PL011 consoles. - Tests: six images registered with CTest, each judging itself and terminating the model. - tx_port_offset_check.c: compile-time assertions on the TX_THREAD offsets the assembly reaches by hard-coded displacement. This is the same defect class fixed for Cortex-R4/R5 in #578; nothing in the toolchain ties those literals to the C structure. Two facts were established by experiment rather than taken from documentation, and are recorded in the code and the readme because both are traps: - PRBAR.AP bit order is reversed relative to th AArch64 macro set: the low bit is read-only and the high bit grants EL0 access. Programming four disjoint regions, one per encoding, and attempting a privileged write to each gave 0b and 0b10 allowed. Using the AArch64 ordering as read-only and silently accept writes, because region coverage is still enforced: an unmapped address faults while a "read-only" region does not. - The generic timer PPI is INTID 30, recorded from ICC_IAR1 after enabling the whole PPI range 25-31, rather than assume Model behaviour that a silicon port must revisit: the FVP leaves CNTFRQ at zero with the system counter stopped, so the BSP programs both; CNTHCTL.PL1PCTEN, CNTHCTL.PL1PCEN and ICC_HSRE must be set at EL2 or EL1 accesses trap; and tx_thread_vfp_enable() sets only a per-thread software flag, so enabling the FPU hardware (CPACR, FPEXC.EN) is the board support package's responsibility, not the kernel's. The FVP reports MIDR 0x410FD0F0, an architecture envelope model rather than a Cortex-R52, so it validates architecture and not implementation. Nothing in the port is gated on MIDR. Changes outside ports/cortex_r52, three and all small: cmake/cortex_r52.cmake is a new toolchain file; CMakeLists.txt gains enable_testing() at the top level, without which add_test() in a subdirectory generat the root never references, so ctest reports no tests from the build root; and .gitignore covers build directories and __pycache__. Verification: all six images build warning-free a FVP_BaseR_AEMv8R in three configurations -- protection off, protection and caches on, and both together with hard-float VFP. Six build-option combinations build clean and pass the tick-and-preemption demo at run time. The tests assert behaviour rather than configuration, which is what caught the problems above: the cooperative demo asserts the order of execution, because counting alone cannot distinguish working context switches from one thread running to completion, and the MPU test provokes real faults, because reading SCTLR back only proves a bit was set. The 96-test regression suite is host-side and pas configurations on the Linux port. It is not cross-run here: it validates portable kernel logic, while the port-specific risk is the assembly, which the FVP images exercise. Structural coverage is therefore not claimed. Deliberate deviations: passing a string literal to tx_thread_create reports a discarded const qualifier from common/inc/tx_api. CHAR *; demo_threadx.c keeps the shipped sample's int main() so the demo body stays byte-identical to it; and the floating-point test compares exactly on purpose, since a tolerance would mask a restored wrong. Not included: modules support, split-mode SMP and support. The example targets the FVP only, and NXP S32Z280 bring-up is separate work; the readme flags what to re-verify there. Assisted-by: Claude Code (Opus 5) --- .gitignore | 7 + CMakeLists.txt | 7 + cmake/cortex_r52.cmake | 45 ++ ports/cortex_r52/gnu/CMakeLists.txt | 77 +++ .../fvp_baser_aemv8r/CMakeLists.txt | 289 +++++++++++ .../example_build/fvp_baser_aemv8r/board.h | 76 +++ .../example_build/fvp_baser_aemv8r/bsp_boot.c | 170 ++++++ .../example_build/fvp_baser_aemv8r/console.c | 170 ++++++ .../example_build/fvp_baser_aemv8r/console.h | 51 ++ .../example_build/fvp_baser_aemv8r/demo_m2.c | 224 ++++++++ .../example_build/fvp_baser_aemv8r/demo_m3.c | 249 +++++++++ .../example_build/fvp_baser_aemv8r/demo_m5.c | 285 ++++++++++ .../example_build/fvp_baser_aemv8r/demo_mpu.c | 245 +++++++++ .../fvp_baser_aemv8r/demo_threadx.c | 393 ++++++++++++++ .../fvp_baser_aemv8r/demo_verify.c | 186 +++++++ .../fvp_baser_aemv8r/demo_verify.h | 41 ++ .../example_build/fvp_baser_aemv8r/entry.S | 486 ++++++++++++++++++ .../example_build/fvp_baser_aemv8r/gicv3.c | 215 ++++++++ .../example_build/fvp_baser_aemv8r/gicv3.h | 61 +++ .../fvp_baser_aemv8r/irq_dispatch.c | 113 ++++ .../example_build/fvp_baser_aemv8r/link.lds | 141 +++++ .../gnu/example_build/fvp_baser_aemv8r/mpu.c | 353 +++++++++++++ .../gnu/example_build/fvp_baser_aemv8r/mpu.h | 113 ++++ .../example_build/fvp_baser_aemv8r/platform.h | 82 +++ .../fvp_baser_aemv8r/test/run_fvp_test.py | 111 ++++ .../example_build/fvp_baser_aemv8r/timer.c | 174 +++++++ .../example_build/fvp_baser_aemv8r/timer.h | 67 +++ .../tx_initialize_low_level.S | 102 ++++ .../fvp_baser_aemv8r/uart_pl011.c | 127 +++++ .../fvp_baser_aemv8r/uart_pl011.h | 47 ++ ports/cortex_r52/gnu/inc/tx_port.h | 338 ++++++++++++ ports/cortex_r52/gnu/readme_threadx.txt | 172 +++++++ .../cortex_r52/gnu/src/tx_port_offset_check.c | 86 ++++ .../gnu/src/tx_thread_context_restore.S | 247 +++++++++ .../gnu/src/tx_thread_context_save.S | 193 +++++++ .../gnu/src/tx_thread_fiq_context_restore.S | 237 +++++++++ .../gnu/src/tx_thread_fiq_context_save.S | 195 +++++++ .../gnu/src/tx_thread_fiq_nesting_end.S | 107 ++++ .../gnu/src/tx_thread_fiq_nesting_start.S | 99 ++++ .../gnu/src/tx_thread_interrupt_control.S | 108 ++++ .../gnu/src/tx_thread_interrupt_disable.S | 105 ++++ .../gnu/src/tx_thread_interrupt_restore.S | 96 ++++ .../gnu/src/tx_thread_irq_nesting_end.S | 106 ++++ .../gnu/src/tx_thread_irq_nesting_start.S | 99 ++++ ports/cortex_r52/gnu/src/tx_thread_schedule.S | 240 +++++++++ .../gnu/src/tx_thread_stack_build.S | 170 ++++++ .../gnu/src/tx_thread_system_return.S | 169 ++++++ .../gnu/src/tx_thread_vectored_context_save.S | 181 +++++++ ports/cortex_r52/gnu/src/tx_timer_interrupt.S | 270 ++++++++++ 49 files changed, 7925 insertions(+) create mode 100644 cmake/cortex_r52.cmake create mode 100644 ports/cortex_r52/gnu/CMakeLists.txt create mode 100644 ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/CMakeLists.txt create mode 100644 ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/board.h create mode 100644 ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/bsp_boot.c create mode 100644 ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/console.c create mode 100644 ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/console.h create mode 100644 ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/demo_m2.c create mode 100644 ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/demo_m3.c create mode 100644 ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/demo_m5.c create mode 100644 ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/demo_mpu.c create mode 100644 ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/demo_threadx.c create mode 100644 ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/demo_verify.c create mode 100644 ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/demo_verify.h create mode 100644 ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/entry.S create mode 100644 ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/gicv3.c create mode 100644 ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/gicv3.h create mode 100644 ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/irq_dispatch.c create mode 100644 ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/link.lds create mode 100644 ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/mpu.c create mode 100644 ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/mpu.h create mode 100644 ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/platform.h create mode 100644 ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/test/run_fvp_test.py create mode 100644 ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/timer.c create mode 100644 ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/timer.h create mode 100644 ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/tx_initialize_low_level.S create mode 100644 ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/uart_pl011.c create mode 100644 ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/uart_pl011.h create mode 100644 ports/cortex_r52/gnu/inc/tx_port.h create mode 100644 ports/cortex_r52/gnu/readme_threadx.txt create mode 100644 ports/cortex_r52/gnu/src/tx_port_offset_check.c create mode 100644 ports/cortex_r52/gnu/src/tx_thread_context_restore.S create mode 100644 ports/cortex_r52/gnu/src/tx_thread_context_save.S create mode 100644 ports/cortex_r52/gnu/src/tx_thread_fiq_context_restore.S create mode 100644 ports/cortex_r52/gnu/src/tx_thread_fiq_context_save.S create mode 100644 ports/cortex_r52/gnu/src/tx_thread_fiq_nesting_end.S create mode 100644 ports/cortex_r52/gnu/src/tx_thread_fiq_nesting_start.S create mode 100644 ports/cortex_r52/gnu/src/tx_thread_interrupt_control.S create mode 100644 ports/cortex_r52/gnu/src/tx_thread_interrupt_disable.S create mode 100644 ports/cortex_r52/gnu/src/tx_thread_interrupt_restore.S create mode 100644 ports/cortex_r52/gnu/src/tx_thread_irq_nesting_end.S create mode 100644 ports/cortex_r52/gnu/src/tx_thread_irq_nesting_start.S create mode 100644 ports/cortex_r52/gnu/src/tx_thread_schedule.S create mode 100644 ports/cortex_r52/gnu/src/tx_thread_stack_build.S create mode 100644 ports/cortex_r52/gnu/src/tx_thread_system_return.S create mode 100644 ports/cortex_r52/gnu/src/tx_thread_vectored_context_save.S create mode 100644 ports/cortex_r52/gnu/src/tx_timer_interrupt.S diff --git a/.gitignore b/.gitignore index 47438c97a..6054dbead 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,10 @@ CTestTestfile.cmake # Local build artifacts build_m7/ .codex +build_r52/ +__pycache__/ +*.pyc +build_r52_vfp/ +build_r52_uart/ +build_r52_mpu/ +build_r52_all/ diff --git a/CMakeLists.txt b/CMakeLists.txt index 5f6be6d25..956f2f101 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,6 +24,13 @@ endif() option(THREADX_SMP "Build ThreadX SMP version" 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 +# build root. Without this, add_test() in a subdirectory still generates a +# CTestTestfile.cmake there, but the root does not reference it and +# "ctest --test-dir " reports no tests at all. +enable_testing() + if(THREADX_SMP) set(TX_PORT_DIR "ports_smp") set(TX_COMMON_DIR "common_smp") diff --git a/cmake/cortex_r52.cmake b/cmake/cortex_r52.cmake new file mode 100644 index 000000000..ea599c682 --- /dev/null +++ b/cmake/cortex_r52.cmake @@ -0,0 +1,45 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# Toolchain file for Arm Cortex-R52 (Armv8-R, AArch32) using GNU tools. + +# Name of the target +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR cortex-r52) + +set(THREADX_ARCH "cortex_r52") +set(THREADX_TOOLCHAIN "gnu") + +# Floating-point ABI. Cortex-R52 always implements at least a single-precision +# FPU -- GCC rejects "+nofp" for this core and offers only "+nofp.dp" (drop +# double precision). There is therefore no FPU-less R52, so the soft-float +# baseline selects the soft *ABI* rather than removing the FPU. The hard-float +# variant with lazy VFP context save arrives with AR1 milestone M5. +if(NOT DEFINED TX_R52_FLOAT_ABI) + set(TX_R52_FLOAT_ABI "soft" CACHE STRING "R52 float ABI: soft | hard") +endif() + +set(MCPU_FLAGS "-marm -mcpu=cortex-r52") +if(TX_R52_FLOAT_ABI STREQUAL "hard") + set(VFP_FLAGS "-mfpu=fpv5-d16 -mfloat-abi=hard") +else() + set(VFP_FLAGS "-mfloat-abi=soft") +endif() +set(SPEC_FLAGS "--specs=nosys.specs") + +include(${CMAKE_CURRENT_LIST_DIR}/arm-none-eabi.cmake) + +# Pin the reference cross toolchain (see AGENTS.md, "Compiler"). Absolute paths +# are used deliberately so the build does not depend on PATH ordering. Override +# with -DARM_TOOLCHAIN_PATH= to build with a +# different compiler -- for example the advisory newest-compiler lane. +if(NOT DEFINED ARM_TOOLCHAIN_PATH) + set(ARM_TOOLCHAIN_PATH + "$ENV{HOME}/toolchains/arm-gnu-toolchain-14.3.rel1-x86_64-arm-none-eabi/bin") +endif() +if(EXISTS "${ARM_TOOLCHAIN_PATH}/arm-none-eabi-gcc") + set(CMAKE_C_COMPILER "${ARM_TOOLCHAIN_PATH}/arm-none-eabi-gcc") + set(CMAKE_CXX_COMPILER "${ARM_TOOLCHAIN_PATH}/arm-none-eabi-g++") + set(CMAKE_ASM_COMPILER "${ARM_TOOLCHAIN_PATH}/arm-none-eabi-gcc") +endif() diff --git a/ports/cortex_r52/gnu/CMakeLists.txt b/ports/cortex_r52/gnu/CMakeLists.txt new file mode 100644 index 000000000..b821ceb43 --- /dev/null +++ b/ports/cortex_r52/gnu/CMakeLists.txt @@ -0,0 +1,77 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${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_fiq_context_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fiq_context_save.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fiq_nesting_end.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fiq_nesting_start.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_irq_nesting_end.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_irq_nesting_start.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_vectored_context_save.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_port_offset_check.c + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) + +# Lazy floating-point context save and restore. PUBLIC because the assembly +# in the library and the application must agree: the flag changes which +# registers the context switch saves, so a mismatched application would either +# lose floating-point state or misread the thread control block. Requires a +# floating-point ABI, so pair it with -DTX_R52_FLOAT_ABI=hard. +option(TX_R52_ENABLE_VFP "Build with lazy VFP context save/restore" OFF) + +# FIQ support and interrupt nesting. These change which registers the +# assembly saves and what tx_port.h reports in TX_PORT_SPECIFIC_BUILD_OPTIONS, +# so like the VFP flag they must be PUBLIC: library and application have to +# agree. FIQ nesting additionally requires FIQ support. +option(TX_R52_ENABLE_FIQ "Build with FIQ support" OFF) +option(TX_R52_ENABLE_IRQ_NESTING "Build with nested IRQ support" OFF) +option(TX_R52_ENABLE_FIQ_NESTING "Build with nested FIQ support" OFF) + +if(TX_R52_ENABLE_FIQ) + target_compile_definitions(${PROJECT_NAME} PUBLIC TX_ENABLE_FIQ_SUPPORT) +endif() +if(TX_R52_ENABLE_IRQ_NESTING) + target_compile_definitions(${PROJECT_NAME} PUBLIC TX_ENABLE_IRQ_NESTING) +endif() +if(TX_R52_ENABLE_FIQ_NESTING) + if(NOT TX_R52_ENABLE_FIQ) + message(FATAL_ERROR + "TX_R52_ENABLE_FIQ_NESTING requires TX_R52_ENABLE_FIQ: nested FIQ " + "handling is meaningless without FIQ support compiled in.") + endif() + target_compile_definitions(${PROJECT_NAME} PUBLIC TX_ENABLE_FIQ_NESTING) +endif() +if(TX_R52_ENABLE_VFP) + target_compile_definitions(${PROJECT_NAME} PUBLIC TX_ENABLE_VFP_SUPPORT) + if(NOT TX_R52_FLOAT_ABI STREQUAL "hard") + message(WARNING + "TX_R52_ENABLE_VFP is on but TX_R52_FLOAT_ABI is '${TX_R52_FLOAT_ABI}'. " + "The compiler will not emit floating-point instructions, so the VFP " + "context path will never be exercised. Use -DTX_R52_FLOAT_ABI=hard.") + endif() +endif() + +# Armv8-R AEM FVP example builds (boot check now, kernel demo from AR1/M2). +# Off by default so the default build stays a pure static-library build. +option(TX_R52_BUILD_FVP_EXAMPLE "Build the Armv8-R AEM FVP example targets" OFF) +if(TX_R52_BUILD_FVP_EXAMPLE) + add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/example_build/fvp_baser_aemv8r) +endif() diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/CMakeLists.txt b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/CMakeLists.txt new file mode 100644 index 000000000..dc451bd39 --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/CMakeLists.txt @@ -0,0 +1,289 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# Example builds for Cortex-R52 on the Armv8-R AEM FVP (FVP_BaseR_AEMv8R). + +set(FVP_DIR ${CMAKE_CURRENT_LIST_DIR}) + +# Console sources. Both backends are always compiled; console.c selects one at +# compile time and --gc-sections drops the unused one, which keeps every image +# building in either configuration without per-target source juggling. +set(R52_CONSOLE_SOURCES + ${FVP_DIR}/console.c + ${FVP_DIR}/uart_pl011.c + ${FVP_DIR}/mpu.c +) + +# AR1/M1 -- boot check. Verifies the EL2 configuration, the drop to EL1 and +# the EL2 HVC seam. Standalone by design: it does not link ThreadX, so a +# failure here is unambiguously a boot problem rather than a kernel problem. +add_executable(boot_check.elf EXCLUDE_FROM_ALL + ${FVP_DIR}/entry.S + ${R52_CONSOLE_SOURCES} + ${FVP_DIR}/bsp_boot.c +) + +target_include_directories(boot_check.elf PRIVATE ${FVP_DIR}) + +target_link_options(boot_check.elf PRIVATE + -T${FVP_DIR}/link.lds + -nostartfiles + -Wl,-Map=boot_check.map + # A bare-metal image has one flat DRAM region and no OS page permissions; + # access control belongs to the MPU, so the RWX-segment note is expected. + -Wl,--no-warn-rwx-segments +) + +# AR1/M2 -- cooperative two-thread demo. Links ThreadX and exercises the +# ported context-switch assembly with no interrupts and no timer tick. +add_executable(demo_m2.elf EXCLUDE_FROM_ALL + ${FVP_DIR}/entry.S + ${R52_CONSOLE_SOURCES} + ${FVP_DIR}/tx_initialize_low_level.S + ${FVP_DIR}/demo_m2.c +) + +target_link_libraries(demo_m2.elf PRIVATE threadx) + +target_include_directories(demo_m2.elf PRIVATE + ${FVP_DIR} + ${CMAKE_SOURCE_DIR}/common/inc + ${CMAKE_SOURCE_DIR}/ports/${THREADX_ARCH}/${THREADX_TOOLCHAIN}/inc +) + +target_link_options(demo_m2.elf PRIVATE + -T${FVP_DIR}/link.lds + -nostartfiles + -Wl,-Map=demo_m2.map + -Wl,--no-warn-rwx-segments +) + +# AR1/M3 -- periodic tick and preemptive scheduling. Adds GICv3, the generic +# timer and the ThreadX IRQ path. TX_R52_USE_THREADX_IRQ routes the EL1 IRQ +# vector into _tx_thread_context_save and has _tx_initialize_low_level bring up +# the interrupt controller; images without it keep the fault reporter. +add_executable(demo_m3.elf EXCLUDE_FROM_ALL + ${FVP_DIR}/entry.S + ${R52_CONSOLE_SOURCES} + ${FVP_DIR}/gicv3.c + ${FVP_DIR}/timer.c + ${FVP_DIR}/irq_dispatch.c + ${FVP_DIR}/tx_initialize_low_level.S + ${FVP_DIR}/demo_m3.c +) + +target_compile_definitions(demo_m3.elf PRIVATE TX_R52_USE_THREADX_IRQ) + +target_link_libraries(demo_m3.elf PRIVATE threadx) + +target_include_directories(demo_m3.elf PRIVATE + ${FVP_DIR} + ${CMAKE_SOURCE_DIR}/common/inc + ${CMAKE_SOURCE_DIR}/ports/${THREADX_ARCH}/${THREADX_TOOLCHAIN}/inc +) + +target_link_options(demo_m3.elf PRIVATE + -T${FVP_DIR}/link.lds + -nostartfiles + -Wl,-Map=demo_m3.map + -Wl,--no-warn-rwx-segments +) + +# AR1/M4 -- the standard eight-thread ThreadX demo. demo_threadx.c is the +# shipped sample kept byte-identical apart from its header note and one call +# into the verification harness, which lives in demo_verify.c. +add_executable(demo_threadx.elf EXCLUDE_FROM_ALL + ${FVP_DIR}/entry.S + ${R52_CONSOLE_SOURCES} + ${FVP_DIR}/gicv3.c + ${FVP_DIR}/timer.c + ${FVP_DIR}/irq_dispatch.c + ${FVP_DIR}/tx_initialize_low_level.S + ${FVP_DIR}/demo_threadx.c + ${FVP_DIR}/demo_verify.c +) + +target_compile_definitions(demo_threadx.elf PRIVATE TX_R52_USE_THREADX_IRQ) + +target_link_libraries(demo_threadx.elf PRIVATE threadx) + +target_include_directories(demo_threadx.elf PRIVATE + ${FVP_DIR} + ${CMAKE_SOURCE_DIR}/common/inc + ${CMAKE_SOURCE_DIR}/ports/${THREADX_ARCH}/${THREADX_TOOLCHAIN}/inc +) + +target_link_options(demo_threadx.elf PRIVATE + -T${FVP_DIR}/link.lds + -nostartfiles + -Wl,-Map=demo_threadx.map + -Wl,--no-warn-rwx-segments +) + +# AR1/M5 -- lazy VFP context save and restore. Only meaningful when the +# library was built with TX_R52_ENABLE_VFP and a floating-point ABI, so the +# target exists only in that configuration. +if(TX_R52_ENABLE_VFP) + add_executable(demo_m5.elf EXCLUDE_FROM_ALL + ${FVP_DIR}/entry.S + ${R52_CONSOLE_SOURCES} + ${FVP_DIR}/gicv3.c + ${FVP_DIR}/timer.c + ${FVP_DIR}/irq_dispatch.c + ${FVP_DIR}/tx_initialize_low_level.S + ${FVP_DIR}/demo_m5.c + ) + + target_compile_definitions(demo_m5.elf PRIVATE TX_R52_USE_THREADX_IRQ) + + target_link_libraries(demo_m5.elf PRIVATE threadx) + + target_include_directories(demo_m5.elf PRIVATE + ${FVP_DIR} + ${CMAKE_SOURCE_DIR}/common/inc + ${CMAKE_SOURCE_DIR}/ports/${THREADX_ARCH}/${THREADX_TOOLCHAIN}/inc + ) + + target_link_options(demo_m5.elf PRIVATE + -T${FVP_DIR}/link.lds + -nostartfiles + -Wl,-Map=demo_m5.map + -Wl,--no-warn-rwx-segments + ) +endif() + +# AR1/M5 -- PMSAv8-R protection and caches. Verifies enforcement, so it needs +# the recoverable data-abort path in entry.S (TX_R52_MPU_FAULT_TEST) and the +# protection itself (TX_R52_ENABLE_MPU), independently of the global option. +add_executable(demo_mpu.elf EXCLUDE_FROM_ALL + ${FVP_DIR}/entry.S + ${R52_CONSOLE_SOURCES} + ${FVP_DIR}/gicv3.c + ${FVP_DIR}/timer.c + ${FVP_DIR}/irq_dispatch.c + ${FVP_DIR}/tx_initialize_low_level.S + ${FVP_DIR}/demo_mpu.c +) + +target_compile_definitions(demo_mpu.elf PRIVATE + TX_R52_USE_THREADX_IRQ + TX_R52_ENABLE_MPU + TX_R52_MPU_FAULT_TEST +) + +target_link_libraries(demo_mpu.elf PRIVATE threadx) + +target_include_directories(demo_mpu.elf PRIVATE + ${FVP_DIR} + ${CMAKE_SOURCE_DIR}/common/inc + ${CMAKE_SOURCE_DIR}/ports/${THREADX_ARCH}/${THREADX_TOOLCHAIN}/inc +) + +target_link_options(demo_mpu.elf PRIVATE + -T${FVP_DIR}/link.lds + -nostartfiles + -Wl,-Map=demo_mpu.map + -Wl,--no-warn-rwx-segments +) + +# Every image built here, in the order they should be exercised. +set(R52_IMAGES boot_check.elf demo_m2.elf demo_m3.elf demo_threadx.elf demo_mpu.elf) + +# The linker script is passed with -T, which CMake does not treat as a +# dependency, so editing it would not trigger a relink and stale images would +# be tested against new region boundaries. Declare it explicitly. +foreach(image IN LISTS R52_IMAGES) + set_target_properties(${image} PROPERTIES LINK_DEPENDS ${FVP_DIR}/link.lds) +endforeach() +if(TX_R52_ENABLE_VFP) + list(APPEND R52_IMAGES demo_m5.elf) +endif() + +# Console backend. Semihosting is the default because it needs no peripheral +# and so cannot be broken by a wrong memory map; the PL011 path is what real +# silicon will use. +# Protection and caches for every image. Off by default so a bring-up failure +# can always be reproduced with the simplest possible memory configuration. +option(TX_R52_ENABLE_MPU + "Enable the PMSAv8-R MPU and caches in every image" OFF) +if(TX_R52_ENABLE_MPU) + foreach(image IN LISTS R52_IMAGES) + target_compile_definitions(${image} PRIVATE TX_R52_ENABLE_MPU) + endforeach() +endif() + +option(TX_R52_CONSOLE_PL011 + "Use the PL011 UART for console output instead of semihosting" OFF) +if(TX_R52_CONSOLE_PL011) + foreach(image IN LISTS R52_IMAGES) + target_compile_definitions(${image} PRIVATE TX_R52_CONSOLE_PL011) + endforeach() +endif() + +# Run a target on the FVP. Each image exits by itself through the +# semihosting SYS_EXIT call, so no host-side timeout is needed. UART0 is +# routed to stdout unconditionally so that PL011-console images are visible +# too; it is harmless for semihosting images. +find_program(FVP_BASER_AEMV8R FVP_BaseR_AEMv8R + HINTS $ENV{HOME}/FVP_Base_AEMv8R_11.32_19/bin +) +if(FVP_BASER_AEMV8R) + function(threadx_r52_add_fvp_run target_name run_target description) + add_custom_target(${run_target} + COMMAND ${FVP_BASER_AEMV8R} + -C cluster0.NUM_CORES=1 + -C bp.vis.disable_visualisation=1 + -C bp.terminal_0.start_telnet=0 + -C bp.pl011_uart0.out_file=- + -C bp.pl011_uart0.unbuffered_output=1 + -a $ + DEPENDS ${target_name} + USES_TERMINAL + COMMENT "${description}" + ) + endfunction() + + threadx_r52_add_fvp_run(boot_check.elf run-boot-check-r52 + "Running AR1/M1 boot check on FVP_BaseR_AEMv8R...") + threadx_r52_add_fvp_run(demo_m2.elf run-demo-m2-r52 + "Running AR1/M2 cooperative switch demo on FVP_BaseR_AEMv8R...") + threadx_r52_add_fvp_run(demo_m3.elf run-demo-m3-r52 + "Running AR1/M3 tick and preemption demo on FVP_BaseR_AEMv8R...") + threadx_r52_add_fvp_run(demo_threadx.elf run-demo-threadx-r52 + "Running the standard ThreadX demo on FVP_BaseR_AEMv8R...") + + # Automated checks. The runner judges each image by its self-reported + # result and treats a missing result line as failure, so a hang cannot + # pass. Registered with CTest when Python is available, plus a plain + # target so the suite is runnable without CTest. + find_package(Python3 COMPONENTS Interpreter) + if(Python3_FOUND) + set(R52_RUNNER ${FVP_DIR}/test/run_fvp_test.py) + set(R52_TEST_IMAGES ${R52_IMAGES}) + + enable_testing() + foreach(image IN LISTS R52_TEST_IMAGES) + add_test(NAME r52-fvp-${image} + COMMAND ${Python3_EXECUTABLE} ${R52_RUNNER} + --elf $ + --fvp ${FVP_BASER_AEMV8R}) + endforeach() + + add_custom_target(check-r52-fvp + COMMENT "Running every Cortex-R52 FVP image through the test runner..." + ) + foreach(image IN LISTS R52_TEST_IMAGES) + add_custom_command(TARGET check-r52-fvp POST_BUILD + COMMAND ${Python3_EXECUTABLE} ${R52_RUNNER} + --elf $ + --fvp ${FVP_BASER_AEMV8R} + ) + add_dependencies(check-r52-fvp ${image}) + endforeach() + else() + message(STATUS "Python3 not found; check-r52-fvp unavailable.") + endif() +else() + message(STATUS "FVP_BaseR_AEMv8R not found; FVP run targets unavailable.") +endif() diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/board.h b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/board.h new file mode 100644 index 000000000..b514d29cf --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/board.h @@ -0,0 +1,76 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* BOARD SUPPORT RELEASE */ +/* */ +/* board.h Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frédéric Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Declarations for the objects that cross the C/assembly boundary in */ +/* this board support package. */ +/* */ +/* These exist because assembly callers do not provide prototypes: */ +/* entry.S calls bsp_main, _tx_initialize_low_level calls board_init, */ +/* and __tx_irq_processing_return calls board_irq_handler. Without a */ +/* header the definitions have external linkage and no visible */ +/* declaration, which MISRA C:2012 Rule 8.4 prohibits and which */ +/* -Wmissing-prototypes reports. Declaring them in one place also */ +/* means a signature change cannot silently disagree with the assembly.*/ +/* */ +/**************************************************************************/ + +#ifndef BOARD_H +#define BOARD_H + +/* Application entry, called from entry.S after EL1 setup; never returns. */ + +void bsp_main(void); + +/* Interrupt controller and periodic tick bring-up, called from + _tx_initialize_low_level while interrupts are still masked. */ + +void board_init(void); + +/* Interrupt dispatch, called from __tx_irq_processing_return in entry.S + after the interrupted context has been saved. */ + +void board_irq_handler(void); + +/* Interrupt observability, maintained by board_irq_handler. */ + +extern volatile unsigned long board_irq_count; +extern volatile unsigned long board_timer_intid; +extern volatile unsigned long board_spurious_count; +extern volatile unsigned long board_unexpected_intid; + +/* Counted by the EL2 hyp-trap handler in entry.S; the ZoneX seam. */ + +extern volatile unsigned long _hvc_call_count; + +/* Recoverable data-abort support for the MPU enforcement self-test, handled + in entry.S. Setting mpu_expect_abort makes the next data abort resume at + the instruction following the faulting one instead of halting. */ + +extern volatile unsigned long mpu_expect_abort; +extern volatile unsigned long mpu_abort_count; + +#endif /* BOARD_H */ diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/bsp_boot.c b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/bsp_boot.c new file mode 100644 index 000000000..4c60de8c4 --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/bsp_boot.c @@ -0,0 +1,170 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* BOARD SUPPORT RELEASE */ +/* */ +/* bsp_boot.c Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frédéric Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* AR1 milestone M1 boot check. Verifies that the reset path really */ +/* configured EL2 and then dropped to EL1, and that the EL2 HVC seam */ +/* used by ZoneX (AR3) is reachable from EL1 and returns correctly. */ +/* */ +/* This deliberately asserts the resulting exception level rather than */ +/* merely printing a message: "it printed something" does not prove a */ +/* correct EL2-to-EL1 transition, and AR3 depends on that transition. */ +/* */ +/* MISRA C:2012 deviations (justified) */ +/* */ +/* Directive 4.3 -- the two asm statements below read CPSR and issue */ +/* HVC; neither has a standard C equivalent. Both are encapsulated */ +/* in dedicated one-line functions. */ +/* */ +/**************************************************************************/ + +#include "board.h" +#include "console.h" + +/* AArch32 CPSR mode field encodings. */ + +#define CPSR_MODE_MASK 0x1FUL +#define CPSR_MODE_SVC 0x13UL /* Supervisor -- an EL1 mode */ +#define CPSR_MODE_HYP 0x1AUL /* Hyp -- EL2 */ + +/* Incremented by the EL2 HVC handler in entry.S. */ + + + +/**************************************************************************/ +/* read_cpsr -- current program status, including the mode field. */ +/**************************************************************************/ + +static unsigned long read_cpsr(void) +{ + unsigned long value; + + __asm__ volatile("mrs %0, cpsr" : "=r"(value)); + + return value; +} + + +/**************************************************************************/ +/* issue_hvc -- call into EL2 through the ZoneX seam and return. */ +/**************************************************************************/ + +static void issue_hvc(void) +{ + __asm__ volatile("hvc #0" : : : "memory"); +} + + +/**************************************************************************/ +/* report -- print one labelled check result. */ +/**************************************************************************/ + +static void report(const char *label_ptr, unsigned int passed) +{ + console_puts(label_ptr); + console_puts(passed != 0U ? "PASS\n" : "FAIL\n"); +} + + +/**************************************************************************/ +/* bsp_main -- entered at EL1 from entry.S. Does not return. */ +/**************************************************************************/ + +void bsp_main(void) +{ + unsigned long cpsr; + unsigned long mode; + unsigned long hvc_before; + unsigned long hvc_after; + unsigned int failures = 0U; + + console_puts("\n=== ThreadX AR1/M1 boot check " + "(Cortex-R52, Armv8-R AArch32, Armv8-R AEM FVP) ===\n"); + + /* Check 1: we are executing at EL1, not still at EL2. */ + + cpsr = read_cpsr(); + mode = cpsr & CPSR_MODE_MASK; + + console_puts("[EL1] CPSR = "); + console_puthex(cpsr); + console_puts("\n[EL1] CPSR.M = "); + console_puthex(mode); + console_puts("\n"); + + if (mode == CPSR_MODE_SVC) + { + report("[EL1] running in Supervisor mode (EL1) ", 1U); + } + else + { + failures++; + if (mode == CPSR_MODE_HYP) + { + console_puts("[EL1] still in Hyp mode -- ERET to EL1 did not happen FAIL\n"); + } + else + { + report("[EL1] unexpected CPSR mode ", 0U); + } + } + + /* Check 2: the EL2 HVC seam is reachable from EL1 and returns. This is + what AR3 (ZoneX Phase-0) builds on, so it is verified from AR1. */ + + hvc_before = _hvc_call_count; + issue_hvc(); + hvc_after = _hvc_call_count; + + console_puts("[EL1] HVC count before/after = "); + console_puthex(hvc_before); + console_puts(" / "); + console_puthex(hvc_after); + console_puts("\n"); + + if (hvc_after == (hvc_before + 1UL)) + { + report("[EL1] EL2 HVC seam reachable and returns to EL1 ", 1U); + } + else + { + failures++; + report("[EL1] EL2 HVC seam did not take effect ", 0U); + } + + /* Summary. The exact strings are what the automated runner greps for. */ + + if (failures == 0U) + { + console_puts("\nM1 RESULT: ALL CHECKS PASSED\n"); + } + else + { + console_puts("\nM1 RESULT: FAILED\n"); + } + + console_exit(failures); +} diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/console.c b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/console.c new file mode 100644 index 000000000..2f75f605b --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/console.c @@ -0,0 +1,170 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* BOARD SUPPORT RELEASE */ +/* */ +/* console.c Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frédéric Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Semihosting console for the Armv8-R AEM FVP. Armv8 AArch32 uses */ +/* HLT 0xF000 as the semihosting trap; the model implements it with no */ +/* peripheral configuration, which keeps early bring-up independent of */ +/* the platform memory map. */ +/* */ +/* MISRA C:2012 deviations (justified) */ +/* */ +/* Directive 4.3 (assembly language shall be encapsulated and isolated)*/ +/* -- observed rather than violated: the single asm statement lives */ +/* in semihost_call() and nowhere else in the port. */ +/* Rule 1.1 / 1.2 (language extensions) */ +/* -- register-asm bindings and inline assembly are unavoidable to */ +/* invoke a semihosting trap; no standard C construct expresses it. */ +/* */ +/**************************************************************************/ + +#include "console.h" + +#ifdef TX_R52_CONSOLE_PL011 +#include "uart_pl011.h" +#endif + +/* Semihosting operation numbers (Arm semihosting specification). */ + +#define SYS_WRITE0 0x04U +#define SYS_EXIT 0x18U + +/* SYS_EXIT reason codes. On AArch32 the parameter is a reason, not an exit + status, so a failing run is reported by its printed result line. */ + +#define ADP_STOPPED_APPLICATION_EXIT 0x20026U +#define ADP_STOPPED_RUN_TIME_ERROR 0x20023U + +/* Number of hexadecimal digits in a 32-bit value. */ + +#define HEX_DIGITS 8U + + +/**************************************************************************/ +/* semihost_call */ +/* */ +/* Issues a single semihosting operation. This is the only assembly in */ +/* the console driver (MISRA C:2012 Dir 4.3). */ +/**************************************************************************/ + +static int semihost_call(int operation, const void *argument_ptr) +{ + register int result __asm__("r0") = operation; + register const void *argument __asm__("r1") = argument_ptr; + + __asm__ volatile("hlt 0xf000" + : "+r"(result) + : "r"(argument) + : "memory"); + + return result; +} + + +/**************************************************************************/ +/* console_puts */ +/**************************************************************************/ + +void console_puts(const char *string_ptr) +{ + if (string_ptr == 0) + { + return; + } + +#ifdef TX_R52_CONSOLE_PL011 + + /* Initialise on first use rather than from board_init, so that images + with no ThreadX initialisation path (the M1 boot check) also get a + working UART console. */ + + static unsigned int initialised = 0U; + + if (initialised == 0U) + { + pl011_init(); + initialised = 1U; + } + + pl011_puts(string_ptr); + +#else + + (void) semihost_call((int) SYS_WRITE0, string_ptr); + +#endif +} + + +/**************************************************************************/ +/* console_puthex */ +/**************************************************************************/ + +void console_puthex(unsigned long value) +{ + static const char digits[] = "0123456789abcdef"; + char buffer[3U + HEX_DIGITS]; /* "0x" + digits + NUL */ + unsigned int index; + + buffer[0] = '0'; + buffer[1] = 'x'; + + for (index = 0U; index < HEX_DIGITS; index++) + { + unsigned int shift = (HEX_DIGITS - 1U - index) * 4U; + + buffer[2U + index] = digits[(value >> shift) & 0xFUL]; + } + + buffer[2U + HEX_DIGITS] = '\0'; + + console_puts(buffer); +} + + +/**************************************************************************/ +/* console_exit */ +/**************************************************************************/ + +/* Note this always uses semihosting, even with the PL011 console selected: + SYS_EXIT is how the model is told to stop, which is a debug-channel + operation rather than console output. */ + +void console_exit(unsigned int status) +{ + unsigned int reason = (status == 0U) ? ADP_STOPPED_APPLICATION_EXIT + : ADP_STOPPED_RUN_TIME_ERROR; + + (void) semihost_call((int) SYS_EXIT, (const void *) reason); + + /* The model terminates on the call above; loop defensively in case a + host or debug configuration ignores semihosting exit. */ + + for (;;) + { + /* Intentionally empty. */ + } +} diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/console.h b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/console.h new file mode 100644 index 000000000..a9bc5ba0a --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/console.h @@ -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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* BOARD SUPPORT RELEASE */ +/* */ +/* console.h Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frédéric Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Minimal console for the Armv8-R AEM FVP. Backed by semihosting so */ +/* that early bring-up needs no peripheral base addresses; the PL011 */ +/* UART implementation arrives in AR1/M3 behind this same interface. */ +/* */ +/**************************************************************************/ + +#ifndef CONSOLE_H +#define CONSOLE_H + +/* Write a NUL-terminated string to the console. */ + +void console_puts(const char *string_ptr); + +/* Write value as 0x-prefixed, zero-padded 32-bit hexadecimal. */ + +void console_puthex(unsigned long value); + +/* Terminate the simulation (semihosting SYS_EXIT). Does not return. + Pass/fail is reported through the printed result line rather than a host + exit status, because the AArch32 SYS_EXIT reason code is not a status. */ + +void console_exit(unsigned int status); + +#endif /* CONSOLE_H */ diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/demo_m2.c b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/demo_m2.c new file mode 100644 index 000000000..e6b7da2cf --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/demo_m2.c @@ -0,0 +1,224 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* DEMONSTRATION RELEASE */ +/* */ +/* demo_m2.c Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frédéric Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* AR1 milestone M2: two threads switching cooperatively, with no */ +/* interrupts and no timer tick. This is the first real exercise of */ +/* the ported assembly -- _tx_thread_stack_build builds each thread's */ +/* initial frame, _tx_thread_schedule restores it, and */ +/* _tx_thread_system_return saves a solicited context on every */ +/* tx_thread_relinquish call. */ +/* */ +/* The threads record their execution order in a trace buffer, and the */ +/* expected alternating sequence is asserted at the end. Counting */ +/* iterations alone would not prove a context switch happened: if */ +/* switching were broken, one thread could run to completion by itself.*/ +/* */ +/* Only tx_thread_relinquish is used. tx_thread_sleep would hang */ +/* without a tick, which AR1/M3 adds. */ +/* */ +/**************************************************************************/ + +#include "tx_api.h" +#include "board.h" +#include "console.h" + +#define DEMO_STACK_SIZE 2048 +#define DEMO_ITERATIONS 5U +#define TRACE_LENGTH (2U * DEMO_ITERATIONS) + +static TX_THREAD thread_0; +static TX_THREAD thread_1; + +static ULONG thread_0_stack[DEMO_STACK_SIZE / sizeof(ULONG)]; +static ULONG thread_1_stack[DEMO_STACK_SIZE / sizeof(ULONG)]; + +static volatile ULONG thread_0_counter; +static volatile ULONG thread_1_counter; + +/* Execution order, one character per slice. */ + +static char trace[TRACE_LENGTH + 1U]; +static volatile UINT trace_index; + + +/**************************************************************************/ +/* trace_record -- append one thread's mark to the execution trace. */ +/**************************************************************************/ + +static void trace_record(char mark) +{ + if (trace_index < TRACE_LENGTH) + { + trace[trace_index] = mark; + trace_index++; + } +} + + +/**************************************************************************/ +/* report -- print one labelled check result. */ +/**************************************************************************/ + +static void report(const char *label_ptr, UINT passed) +{ + console_puts(label_ptr); + console_puts((passed != 0U) ? "PASS\n" : "FAIL\n"); +} + + +/**************************************************************************/ +/* thread_1_entry -- yields back to thread 0 on every slice. */ +/**************************************************************************/ + +static void thread_1_entry(ULONG thread_input) +{ + (void) thread_input; + + while (thread_1_counter < DEMO_ITERATIONS) + { + thread_1_counter++; + trace_record('1'); + + console_puts("[thread 1] slice "); + console_puthex(thread_1_counter); + console_puts("\n"); + + tx_thread_relinquish(); + } +} + + +/**************************************************************************/ +/* thread_0_entry -- yields to thread 1, then checks the outcome. */ +/**************************************************************************/ + +static void thread_0_entry(ULONG thread_input) +{ + UINT failures = 0U; + UINT index; + + (void) thread_input; + + while (thread_0_counter < DEMO_ITERATIONS) + { + thread_0_counter++; + trace_record('0'); + + console_puts("[thread 0] slice "); + console_puthex(thread_0_counter); + console_puts("\n"); + + tx_thread_relinquish(); + } + + /* Check 1: both threads ran the expected number of slices. A broken + context switch would leave thread 1 at zero. */ + + console_puts("\n[check] slices thread 0 / thread 1 = "); + console_puthex(thread_0_counter); + console_puts(" / "); + console_puthex(thread_1_counter); + console_puts("\n"); + + if ((thread_0_counter == (ULONG) DEMO_ITERATIONS) && + (thread_1_counter == (ULONG) DEMO_ITERATIONS)) + { + report("[check] both threads ran every slice ", 1U); + } + else + { + failures++; + report("[check] both threads ran every slice ", 0U); + } + + /* Check 2: execution strictly alternated, proving each relinquish + really switched context rather than returning to the same thread. */ + + trace[TRACE_LENGTH] = '\0'; + console_puts("[check] execution order = "); + console_puts(trace); + console_puts(" (expected 0101010101)\n"); + + for (index = 0U; index < TRACE_LENGTH; index++) + { + char expected = ((index % 2U) == 0U) ? '0' : '1'; + + if (trace[index] != expected) + { + failures++; + break; + } + } + + report("[check] threads alternated on every relinquish ", + (UINT) ((failures == 0U) ? 1U : 0U)); + + if (failures == 0U) + { + console_puts("\nM2 RESULT: ALL CHECKS PASSED\n"); + } + else + { + console_puts("\nM2 RESULT: FAILED\n"); + } + + console_exit(failures); +} + + +/**************************************************************************/ +/* tx_application_define -- create the demo threads. */ +/* */ +/* Static stacks are used rather than a byte pool so that M2 exercises */ +/* only the context-switch path, with no allocator in the way. */ +/**************************************************************************/ + +void tx_application_define(void *first_unused_memory) +{ + (void) first_unused_memory; + + (void) tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0UL, + thread_0_stack, sizeof(thread_0_stack), + 16U, 16U, TX_NO_TIME_SLICE, TX_AUTO_START); + + (void) tx_thread_create(&thread_1, "thread 1", thread_1_entry, 0UL, + thread_1_stack, sizeof(thread_1_stack), + 16U, 16U, TX_NO_TIME_SLICE, TX_AUTO_START); +} + + +/**************************************************************************/ +/* bsp_main -- entered at EL1 from entry.S. Does not return. */ +/**************************************************************************/ + +void bsp_main(void) +{ + console_puts("\n=== ThreadX AR1/M2 cooperative switch " + "(Cortex-R52, Armv8-R AArch32, Armv8-R AEM FVP) ===\n"); + + tx_kernel_enter(); +} diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/demo_m3.c b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/demo_m3.c new file mode 100644 index 000000000..96beac48a --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/demo_m3.c @@ -0,0 +1,249 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* DEMONSTRATION RELEASE */ +/* */ +/* demo_m3.c Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frédéric Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* AR1 milestone M3: periodic tick and preemptive scheduling. This */ +/* exercises the parts of the port that M2 could not reach -- */ +/* _tx_thread_context_save, _tx_timer_interrupt and */ +/* _tx_thread_context_restore -- by driving them from a real generic */ +/* timer interrupt routed through GICv3. */ +/* */ +/* The checks build on each other, so a failure localises the cause: */ +/* 1. CNTFRQ is non-zero -> entry.S programmed it at EL2 */ +/* 2. counter is enabled -> the control frame was started */ +/* 3. CNTPCT advances -> the counter really runs */ +/* 4. interrupts arrive -> GICv3 + PPI + vector wiring work */ +/* 5. tx_time_get advances -> _tx_timer_interrupt drives the tick*/ +/* 6. tx_thread_sleep returns -> timer-driven thread resumption */ +/* 7. a lower-priority thread ran while we slept -> preemption and */ +/* context save/restore across an interrupt */ +/* */ +/* The timer PPI INTID is reported, not assumed: the whole PPI range is*/ +/* enabled and whichever INTID the model drives is recorded. */ +/* */ +/**************************************************************************/ + +#include "tx_api.h" +#include "board.h" +#include "console.h" +#include "timer.h" + +#define DEMO_STACK_SIZE 2048 +#define SLEEP_TICKS 20UL +#define SLEEP_SLACK_TICKS 10UL + +static TX_THREAD thread_main; +static TX_THREAD thread_busy; + +static ULONG thread_main_stack[DEMO_STACK_SIZE / sizeof(ULONG)]; +static ULONG thread_busy_stack[DEMO_STACK_SIZE / sizeof(ULONG)]; + +static volatile ULONG busy_counter; + +/* Recorded by the interrupt dispatcher. */ + + + +/**************************************************************************/ +/* report -- print one labelled check result. */ +/**************************************************************************/ + +static UINT report(const char *label_ptr, UINT passed) +{ + console_puts(label_ptr); + console_puts((passed != 0U) ? "PASS\n" : "FAIL\n"); + + return (passed != 0U) ? 0U : 1U; +} + + +/**************************************************************************/ +/* thread_busy_entry -- lowest priority; only runs when nothing else can.*/ +/**************************************************************************/ + +static void thread_busy_entry(ULONG thread_input) +{ + (void) thread_input; + + for (;;) + { + busy_counter++; + } +} + + +/**************************************************************************/ +/* thread_main_entry -- runs the checks and terminates the simulation. */ +/**************************************************************************/ + +static void thread_main_entry(ULONG thread_input) +{ + UINT failures = 0U; + unsigned long frequency; + unsigned long long counter_first; + unsigned long long counter_second; + ULONG time_before; + ULONG time_after; + ULONG elapsed; + ULONG busy_before; + ULONG busy_after; + unsigned long irq_before; + + (void) thread_input; + + /* Check 1: CNTFRQ was programmed at EL2 (the model resets it to zero). */ + + frequency = timer_frequency(); + console_puts("[check] CNTFRQ = "); + console_puthex(frequency); + console_puts(" Hz\n"); + failures += report("[check] CNTFRQ programmed at EL2 (non-zero) ", + (frequency != 0UL) ? 1U : 0U); + + /* Check 2: the system counter was started (stopped at reset). */ + + failures += report("[check] system counter enabled by BSP ", + timer_counter_enabled()); + + /* Check 3: the counter actually advances. */ + + counter_first = timer_counter(); + { + volatile unsigned int spin; + for (spin = 0U; spin < 20000U; spin++) + { + /* Burn a little time. */ + } + } + counter_second = timer_counter(); + failures += report("[check] CNTPCT advancing ", + (counter_second > counter_first) ? 1U : 0U); + + /* Check 4: timer interrupts are being delivered through GICv3. */ + + irq_before = board_irq_count; + time_before = tx_time_get(); + busy_before = busy_counter; + + /* Check 6: a timer-driven sleep returns. While suspended, the only + runnable thread is the lower-priority busy thread. */ + + tx_thread_sleep(SLEEP_TICKS); + + time_after = tx_time_get(); + busy_after = busy_counter; + + console_puts("[check] timer PPI INTID observed = "); + console_puthex(board_timer_intid); + console_puts("\n[check] timer interrupts taken = "); + console_puthex(board_irq_count); + console_puts("\n"); + + failures += report("[check] timer interrupts delivered via GICv3 ", + (board_irq_count > irq_before) ? 1U : 0U); + + /* Check 5: the ThreadX clock is driven by those interrupts. */ + + elapsed = time_after - time_before; + console_puts("[check] tx_time_get elapsed = "); + console_puthex(elapsed); + console_puts(" ticks (slept "); + console_puthex(SLEEP_TICKS); + console_puts(")\n"); + + failures += report("[check] tx_time_get advancing ", + (elapsed >= SLEEP_TICKS) ? 1U : 0U); + + failures += report("[check] sleep lasted about the requested time ", + (elapsed <= (SLEEP_TICKS + SLEEP_SLACK_TICKS)) ? 1U : 0U); + + /* Check 7: the lower-priority thread ran while we were suspended, then + was preempted when the tick made this thread ready again. That + requires a correct context save and restore across the interrupt. */ + + console_puts("[check] busy-thread counter delta = "); + console_puthex(busy_after - busy_before); + console_puts("\n"); + + failures += report("[check] lower-priority thread ran, then preempted ", + (busy_after > busy_before) ? 1U : 0U); + + /* Nothing unexpected should have arrived on the interrupt path. */ + + if (board_unexpected_intid != 0UL) + { + console_puts("[check] unexpected INTID = "); + console_puthex(board_unexpected_intid); + console_puts("\n"); + } + failures += report("[check] no unexpected interrupt IDs ", + (board_unexpected_intid == 0UL) ? 1U : 0U); + + if (failures == 0U) + { + console_puts("\nM3 RESULT: ALL CHECKS PASSED\n"); + } + else + { + console_puts("\nM3 RESULT: FAILED\n"); + } + + console_exit(failures); +} + + +/**************************************************************************/ +/* tx_application_define */ +/**************************************************************************/ + +void tx_application_define(void *first_unused_memory) +{ + (void) first_unused_memory; + + /* Priority 10 runs the checks; priority 20 only gets the processor when + the checking thread is suspended. */ + + (void) tx_thread_create(&thread_main, "check thread", thread_main_entry, + 0UL, thread_main_stack, sizeof(thread_main_stack), + 10U, 10U, TX_NO_TIME_SLICE, TX_AUTO_START); + + (void) tx_thread_create(&thread_busy, "busy thread", thread_busy_entry, + 0UL, thread_busy_stack, sizeof(thread_busy_stack), + 20U, 20U, TX_NO_TIME_SLICE, TX_AUTO_START); +} + + +/**************************************************************************/ +/* bsp_main -- entered at EL1 from entry.S. Does not return. */ +/**************************************************************************/ + +void bsp_main(void) +{ + console_puts("\n=== ThreadX AR1/M3 tick and preemption " + "(Cortex-R52, Armv8-R AArch32, Armv8-R AEM FVP) ===\n"); + + tx_kernel_enter(); +} diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/demo_m5.c b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/demo_m5.c new file mode 100644 index 000000000..783bed06a --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/demo_m5.c @@ -0,0 +1,285 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* DEMONSTRATION RELEASE */ +/* */ +/* demo_m5.c Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frédéric Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* AR1 milestone M5: lazy floating-point context save and restore. */ +/* */ +/* Two paths must be covered, and they use different register sets: */ +/* */ +/* solicited tx_thread_system_return saves D8-D15 and FPSCR, because*/ +/* the callee-saved half is all a voluntary switch can */ +/* lose. Exercised by the checking thread, which keeps */ +/* eight doubles live across tx_thread_sleep. */ +/* interrupt tx_thread_context_restore restores D0-D15 and FPSCR, */ +/* because an asynchronous interrupt can land anywhere. */ +/* Exercised by a lower-priority thread doing continuous */ +/* floating-point work while the tick fires into it. */ +/* */ +/* Every constant is an exact binary fraction, so the comparisons are */ +/* exact and a single corrupted register shows up as a mismatch rather */ +/* than as rounding noise. The two threads use disjoint value ranges, */ +/* so leakage from one context into the other is also caught. */ +/* */ +/* Both threads call tx_thread_vfp_enable(): with lazy save/restore, a */ +/* thread that has not asked for floating-point support does not get */ +/* it, so forgetting the call would show up as corruption rather than */ +/* as a build error. */ +/* */ +/* MISRA C:2012 / warning deviations (justified) */ +/* */ +/* Rule 13.3 style equality on floating point (-Wfloat-equal) */ +/* -- exact comparison is the point of this test, not an oversight. */ +/* Every constant is an exact binary fraction and every operation is */ +/* an addition of 0.5, so the arithmetic is exact and the expected */ +/* results are representable. A tolerance-based comparison would */ +/* mask precisely the corruption being looked for: a restored */ +/* register that is close but wrong would pass. Confined to this */ +/* test file. */ +/* */ +/**************************************************************************/ + +#include "tx_api.h" +#include "board.h" +#include "console.h" + +#define DEMO_STACK_SIZE 2048 +#define FILEX_PTR_SENTINEL ((void *) 0xF11EF11EUL) +#define FP_ITERATIONS 50UL +#define FP_STEP 0.5 /* exactly representable */ + +static TX_THREAD thread_check; +static TX_THREAD thread_fp_busy; + +static ULONG thread_check_stack[DEMO_STACK_SIZE / sizeof(ULONG)]; +static ULONG thread_fp_busy_stack[DEMO_STACK_SIZE / sizeof(ULONG)]; + +/* Set by the busy thread if its floating-point state was ever seen wrong.*/ + +static volatile ULONG busy_iterations; +static volatile ULONG busy_corruptions; + + +/**************************************************************************/ +/* report */ +/**************************************************************************/ + +static UINT report(const char *label_ptr, UINT passed) +{ + console_puts(label_ptr); + console_puts((passed != 0U) ? "PASS\n" : "FAIL\n"); + + return (passed != 0U) ? 0U : 1U; +} + + +/**************************************************************************/ +/* thread_fp_busy_entry */ +/* */ +/* Lowest priority, never sleeps: the periodic tick therefore interrupts */ +/* it in the middle of floating-point work, which is what exercises the */ +/* interrupt half of the VFP context path (D0-D15 + FPSCR). Its values */ +/* are checked every iteration against exactly representable constants. */ +/**************************************************************************/ + +static void thread_fp_busy_entry(ULONG thread_input) +{ + (void) thread_input; + + tx_thread_vfp_enable(); + + for (;;) + { + /* Disjoint from the checking thread's range, so cross-contamination + between contexts is detectable. */ + + double v0 = 1024.5; + double v1 = 2048.25; + double v2 = 4096.125; + double v3 = 8192.0625; + + v0 = (v0 * 2.0) - 1024.5; /* 1024.5 */ + v1 = (v1 * 2.0) - 2048.25; /* 2048.25 */ + v2 = (v2 * 2.0) - 4096.125; /* 4096.125 */ + v3 = (v3 * 2.0) - 8192.0625; /* 8192.0625*/ + + if ((v0 != 1024.5) || (v1 != 2048.25) || + (v2 != 4096.125) || (v3 != 8192.0625)) + { + busy_corruptions++; + } + + busy_iterations++; + } +} + + +/**************************************************************************/ +/* thread_check_entry */ +/**************************************************************************/ + +static void thread_check_entry(ULONG thread_input) +{ + UINT failures = 0U; + ULONG iteration; + ULONG expected_steps; + TX_THREAD *self; + + /* Eight live doubles held across a blocking call. Eight is chosen so + the compiler must use the callee-saved bank D8-D15 (or spill), which + is exactly what a solicited context switch has to preserve. */ + + double a = 1.5; + double b = 2.25; + double c = 3.125; + double d = 4.0625; + double e = 5.03125; + double f = 6.015625; + double g = 7.0078125; + double h = 8.00390625; + + (void) thread_input; + + /* Guard against the VFP enable flag aliasing another thread member. The + flag is reached from assembly by hard-coded offset, and on the + Cortex-R4/R5 ports that offset lands on tx_thread_filex_ptr because + their TX_THREAD_EXTENSION_2 is empty. Planting a sentinel here turns + that class of mistake into a visible failure rather than corruption + that only surfaces once FileX is added. */ + + self = tx_thread_identify(); + self->tx_thread_filex_ptr = FILEX_PTR_SENTINEL; + + tx_thread_vfp_enable(); + + console_puts("[check] running floating-point work across "); + console_puthex(FP_ITERATIONS); + console_puts(" solicited switches...\n"); + + for (iteration = 0UL; iteration < FP_ITERATIONS; iteration++) + { + /* Suspend: the switch must preserve every one of these values, and + the lower-priority floating-point thread runs meanwhile. */ + + tx_thread_sleep(1); + + a += FP_STEP; + b += FP_STEP; + c += FP_STEP; + d += FP_STEP; + e += FP_STEP; + f += FP_STEP; + g += FP_STEP; + h += FP_STEP; + } + + expected_steps = FP_ITERATIONS; + + /* Exact comparisons: every value above is an exact binary fraction and + FP_STEP is 0.5, so no rounding is involved. */ + + failures += report("[check] D-register value a preserved exactly ", + (a == (1.5 + (0.5 * (double) expected_steps))) ? 1U : 0U); + failures += report("[check] D-register value b preserved exactly ", + (b == (2.25 + (0.5 * (double) expected_steps))) ? 1U : 0U); + failures += report("[check] D-register value c preserved exactly ", + (c == (3.125 + (0.5 * (double) expected_steps))) ? 1U : 0U); + failures += report("[check] D-register value d preserved exactly ", + (d == (4.0625 + (0.5 * (double) expected_steps))) ? 1U : 0U); + failures += report("[check] D-register value e preserved exactly ", + (e == (5.03125 + (0.5 * (double) expected_steps))) ? 1U : 0U); + failures += report("[check] D-register value f preserved exactly ", + (f == (6.015625 + (0.5 * (double) expected_steps))) ? 1U : 0U); + failures += report("[check] D-register value g preserved exactly ", + (g == (7.0078125 + (0.5 * (double) expected_steps))) ? 1U : 0U); + failures += report("[check] D-register value h preserved exactly ", + (h == (8.00390625 + (0.5 * (double) expected_steps))) ? 1U : 0U); + + /* The busy thread must have run, and never seen its own state damaged + by an interrupt landing inside its floating-point sequence. */ + + console_puts("[check] busy-thread iterations = "); + console_puthex(busy_iterations); + console_puts("\n[check] busy-thread corruptions = "); + console_puthex(busy_corruptions); + console_puts("\n"); + + failures += report("[check] interrupted FP thread made progress ", + (busy_iterations > 0UL) ? 1U : 0U); + failures += report("[check] no FP corruption across interrupts ", + (busy_corruptions == 0UL) ? 1U : 0U); + + /* The VFP flag must not have aliased tx_thread_filex_ptr. */ + + console_puts("[check] tx_thread_filex_ptr = "); + console_puthex((unsigned long) self->tx_thread_filex_ptr); + console_puts(" (expected 0xf11ef11e)\n"); + + failures += report("[check] VFP flag did not alias filex_ptr ", + (self->tx_thread_filex_ptr == FILEX_PTR_SENTINEL) ? 1U : 0U); + + if (failures == 0U) + { + console_puts("\nM5 RESULT: ALL CHECKS PASSED\n"); + } + else + { + console_puts("\nM5 RESULT: FAILED\n"); + } + + console_exit(failures); +} + + +/**************************************************************************/ +/* tx_application_define */ +/**************************************************************************/ + +void tx_application_define(void *first_unused_memory) +{ + (void) first_unused_memory; + + (void) tx_thread_create(&thread_check, "fp check", thread_check_entry, 0UL, + thread_check_stack, sizeof(thread_check_stack), + 10U, 10U, TX_NO_TIME_SLICE, TX_AUTO_START); + + (void) tx_thread_create(&thread_fp_busy, "fp busy", thread_fp_busy_entry, + 0UL, thread_fp_busy_stack, + sizeof(thread_fp_busy_stack), + 20U, 20U, TX_NO_TIME_SLICE, TX_AUTO_START); +} + + +/**************************************************************************/ +/* bsp_main -- entered at EL1 from entry.S. Does not return. */ +/**************************************************************************/ + +void bsp_main(void) +{ + console_puts("\n=== ThreadX AR1/M5 lazy VFP context switch " + "(Cortex-R52, Armv8-R AArch32, Armv8-R AEM FVP) ===\n"); + + tx_kernel_enter(); +} diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/demo_mpu.c b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/demo_mpu.c new file mode 100644 index 000000000..6d754d5ea --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/demo_mpu.c @@ -0,0 +1,245 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* DEMONSTRATION RELEASE */ +/* */ +/* demo_mpu.c Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frédéric Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* AR1 milestone M5: PMSAv8-R protection and caches. */ +/* */ +/* The important check here is enforcement, not configuration. Reading*/ +/* SCTLR back only proves a bit was set; it says nothing about whether */ +/* the region table actually describes memory correctly. So the test */ +/* provokes a real permission fault by writing to the read-only code */ +/* region and requires the abort to arrive, then confirms a legal write*/ +/* to the data region still succeeds. A region set that permitted */ +/* everything would pass the first kind of check and fail this one. */ +/* */ +/**************************************************************************/ + +#include "tx_api.h" +#include "board.h" +#include "console.h" +#include "mpu.h" + +#define DEMO_STACK_SIZE 2048 + +static TX_THREAD thread_check; +static ULONG thread_check_stack[DEMO_STACK_SIZE / sizeof(ULONG)]; + +/* Provided by entry.S and manipulated by its data-abort handler. */ + + +/* A known-writable location, used to show legal access still works. */ + +static volatile unsigned long writable_probe; + + +/**************************************************************************/ +/* report */ +/**************************************************************************/ + +static UINT report(const char *label_ptr, UINT passed) +{ + console_puts(label_ptr); + console_puts((passed != 0U) ? "PASS\n" : "FAIL\n"); + + return (passed != 0U) ? 0U : 1U; +} + + +/**************************************************************************/ +/* thread_check_entry */ +/**************************************************************************/ + +static void thread_check_entry(ULONG thread_input) +{ + UINT failures = 0U; + unsigned int available; + unsigned int used; + unsigned int index; + const MPU_REGION *table; + unsigned long aborts_before; + + (void) thread_input; + + /* What the implementation provides. */ + + available = mpu_region_count(); + console_puts("[check] MPUIR regions available = "); + console_puthex(available); + console_puts("\n"); + failures += report("[check] implementation reports MPU regions ", + (available > 0U) ? 1U : 0U); + + /* What this image programmed. */ + + table = mpu_region_table(&used); + console_puts("[check] regions programmed = "); + console_puthex(used); + console_puts("\n"); + + for (index = 0U; index < used; index++) + { + console_puts(" "); + console_puts(table[index].mpu_region_name); + console_puts(" base "); + console_puthex(table[index].mpu_region_base); + console_puts(" limit "); + console_puthex(table[index].mpu_region_limit); + console_puts("\n"); + } + + failures += report("[check] region table programmed ", + (used > 0U) ? 1U : 0U); + + /* Read the hardware back: if the register encodings were wrong the + writes would be silently discarded and a permissive background map + would make everything appear to work. */ + + for (index = 0U; index < used; index++) + { + unsigned long prbar = 0UL; + unsigned long prlar = 0UL; + + mpu_read_region(index, &prbar, &prlar); + console_puts(" region "); + console_puthex(index); + console_puts(" PRBAR="); + console_puthex(prbar); + console_puts(" PRLAR="); + console_puthex(prlar); + console_puts("\n"); + if ((prbar == 0UL) && (prlar == 0UL)) + { + failures++; + } + } + failures += report("[check] hardware holds the programmed regions ", + (failures == 0U) ? 1U : 0U); + + failures += report("[check] MPU enabled (SCTLR.M) ", + mpu_is_enabled()); + failures += report("[check] caches enabled (SCTLR.C and SCTLR.I) ", + mpu_caches_enabled()); + + /* Enforcement, part 1: a legal write to the data region must work. */ + + writable_probe = 0xA5A5A5A5UL; + failures += report("[check] legal write to data region succeeds ", + (writable_probe == 0xA5A5A5A5UL) ? 1U : 0U); + + /* Enforcement, part 1b: an address covered by NO region must fault. + This distinguishes "the MPU is not enforcing at all" from "the MPU + enforces coverage but not the access permission". 0x40000000 lies + between the end of the data region and the peripheral region. */ + + /* Enforcement, part 2: an address covered by no region must fault. This + distinguishes "not enforcing at all" from "enforcing coverage only". */ + + aborts_before = mpu_abort_count; + mpu_expect_abort = 1UL; + { + volatile unsigned long *gap_ptr = (volatile unsigned long *) 0x40000000UL; + + *gap_ptr = 0x11223344UL; + } + failures += report("[check] write to unmapped address faulted ", + (mpu_abort_count == (aborts_before + 1UL)) ? 1U : 0U); + mpu_expect_abort = 0UL; + + /* Enforcement, part 3: the read-only code region must reject a write. + This is the check that matters: region coverage is enforced even with a + wrong access-permission encoding, so only a write-permission test can + show that the permissions themselves are right. */ + + aborts_before = mpu_abort_count; + mpu_expect_abort = 1UL; + { + volatile unsigned long *code_ptr = + (volatile unsigned long *) table[0].mpu_region_base; + + *code_ptr = 0xDEADBEEFUL; + } + mpu_expect_abort = 0UL; + + console_puts("[check] aborts before/after write to code = "); + console_puthex(aborts_before); + console_puts(" / "); + console_puthex(mpu_abort_count); + console_puts("\n"); + + failures += report("[check] write to read-only code region faulted ", + (mpu_abort_count == (aborts_before + 1UL)) ? 1U : 0U); + + { + volatile unsigned long *code_ptr = + (volatile unsigned long *) table[0].mpu_region_base; + + failures += report("[check] code region contents unmodified ", + (*code_ptr != 0xDEADBEEFUL) ? 1U : 0U); + } + + /* And the kernel is still healthy afterwards. */ + + failures += report("[check] kernel still running after the fault ", + (tx_thread_identify() == &thread_check) ? 1U : 0U); + + if (failures == 0U) + { + console_puts("\nMPU RESULT: ALL CHECKS PASSED\n"); + } + else + { + console_puts("\nMPU RESULT: FAILED\n"); + } + + console_exit(failures); +} + + +/**************************************************************************/ +/* tx_application_define */ +/**************************************************************************/ + +void tx_application_define(void *first_unused_memory) +{ + (void) first_unused_memory; + + (void) tx_thread_create(&thread_check, "mpu check", thread_check_entry, + 0UL, thread_check_stack, sizeof(thread_check_stack), + 10U, 10U, TX_NO_TIME_SLICE, TX_AUTO_START); +} + + +/**************************************************************************/ +/* bsp_main -- entered at EL1 from entry.S. Does not return. */ +/**************************************************************************/ + +void bsp_main(void) +{ + console_puts("\n=== ThreadX AR1/M5 PMSAv8-R protection and caches " + "(Cortex-R52, Armv8-R AEM FVP) ===\n"); + + tx_kernel_enter(); +} diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/demo_threadx.c b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/demo_threadx.c new file mode 100644 index 000000000..19d976b3e --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/demo_threadx.c @@ -0,0 +1,393 @@ +/**************************************************************************/ +/* Copyright (c) 2024 Microsoft Corporation */ +/* 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 */ +/**************************************************************************/ +// Some portions generated by Claude Code (Opus 5). + +/* Copied unmodified from samples/demo_threadx.c for the Armv8-R AEM FVP + example build, then extended with a verification thread and a bsp_main + entry point. Keeping the demo body byte-identical to the shipped sample + is the point of AR1 milestone M4: it shows the standard ThreadX demo runs + on Cortex-R52 with no demo-side changes. The additions are confined to + the end of this file and one call in tx_application_define. */ + +/* This is a small demo of the high-performance ThreadX kernel. It includes examples of eight + threads of different priorities, using a message queue, semaphore, mutex, event flags group, + byte pool, and block pool. */ + +#include "tx_api.h" +#include "demo_verify.h" + +#define DEMO_STACK_SIZE 1024 +#define DEMO_BYTE_POOL_SIZE 9120 +#define DEMO_BLOCK_POOL_SIZE 100 +#define DEMO_QUEUE_SIZE 100 + + +/* Define the ThreadX object control blocks... */ + +TX_THREAD thread_0; +TX_THREAD thread_1; +TX_THREAD thread_2; +TX_THREAD thread_3; +TX_THREAD thread_4; +TX_THREAD thread_5; +TX_THREAD thread_6; +TX_THREAD thread_7; +TX_QUEUE queue_0; +TX_SEMAPHORE semaphore_0; +TX_MUTEX mutex_0; +TX_EVENT_FLAGS_GROUP event_flags_0; +TX_BYTE_POOL byte_pool_0; +TX_BLOCK_POOL block_pool_0; +UCHAR memory_area[DEMO_BYTE_POOL_SIZE]; + + +/* Define the counters used in the demo application... */ + +ULONG thread_0_counter; +ULONG thread_1_counter; +ULONG thread_1_messages_sent; +ULONG thread_2_counter; +ULONG thread_2_messages_received; +ULONG thread_3_counter; +ULONG thread_4_counter; +ULONG thread_5_counter; +ULONG thread_6_counter; +ULONG thread_7_counter; + + +/* Define thread prototypes. */ + +void thread_0_entry(ULONG thread_input); +void thread_1_entry(ULONG thread_input); +void thread_2_entry(ULONG thread_input); +void thread_3_and_4_entry(ULONG thread_input); +void thread_5_entry(ULONG thread_input); +void thread_6_and_7_entry(ULONG thread_input); + + +/* Define main entry point. */ + +int main() +{ + + /* Enter the ThreadX kernel. */ + tx_kernel_enter(); +} + + +/* Define what the initial system looks like. */ + +void tx_application_define(void *first_unused_memory) +{ + +CHAR *pointer = TX_NULL; + + + /* Create a byte memory pool from which to allocate the thread stacks. */ + tx_byte_pool_create(&byte_pool_0, "byte pool 0", memory_area, DEMO_BYTE_POOL_SIZE); + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + /* Allocate the stack for thread 0. */ + tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); + + /* Create the main thread. */ + tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0, + pointer, DEMO_STACK_SIZE, + 1, 1, TX_NO_TIME_SLICE, TX_AUTO_START); + + + /* Allocate the stack for thread 1. */ + tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); + + /* Create threads 1 and 2. These threads pass information through a ThreadX + message queue. It is also interesting to note that these threads have a time + slice. */ + tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, DEMO_STACK_SIZE, + 16, 16, 4, TX_AUTO_START); + + /* Allocate the stack for thread 2. */ + tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); + + tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2, + pointer, DEMO_STACK_SIZE, + 16, 16, 4, TX_AUTO_START); + + /* Allocate the stack for thread 3. */ + tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); + + /* Create threads 3 and 4. These threads compete for a ThreadX counting semaphore. + An interesting thing here is that both threads share the same instruction area. */ + tx_thread_create(&thread_3, "thread 3", thread_3_and_4_entry, 3, + pointer, DEMO_STACK_SIZE, + 8, 8, TX_NO_TIME_SLICE, TX_AUTO_START); + + /* Allocate the stack for thread 4. */ + tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); + + tx_thread_create(&thread_4, "thread 4", thread_3_and_4_entry, 4, + pointer, DEMO_STACK_SIZE, + 8, 8, TX_NO_TIME_SLICE, TX_AUTO_START); + + /* Allocate the stack for thread 5. */ + tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); + + /* Create thread 5. This thread simply pends on an event flag which will be set + by thread_0. */ + tx_thread_create(&thread_5, "thread 5", thread_5_entry, 5, + pointer, DEMO_STACK_SIZE, + 4, 4, TX_NO_TIME_SLICE, TX_AUTO_START); + + /* Allocate the stack for thread 6. */ + tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); + + /* Create threads 6 and 7. These threads compete for a ThreadX mutex. */ + tx_thread_create(&thread_6, "thread 6", thread_6_and_7_entry, 6, + pointer, DEMO_STACK_SIZE, + 8, 8, TX_NO_TIME_SLICE, TX_AUTO_START); + + /* Allocate the stack for thread 7. */ + tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); + + tx_thread_create(&thread_7, "thread 7", thread_6_and_7_entry, 7, + pointer, DEMO_STACK_SIZE, + 8, 8, TX_NO_TIME_SLICE, TX_AUTO_START); + + /* Allocate the message queue. */ + tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_QUEUE_SIZE*sizeof(ULONG), TX_NO_WAIT); + + /* Create the message queue shared by threads 1 and 2. */ + tx_queue_create(&queue_0, "queue 0", TX_1_ULONG, pointer, DEMO_QUEUE_SIZE*sizeof(ULONG)); + + /* Create the semaphore used by threads 3 and 4. */ + tx_semaphore_create(&semaphore_0, "semaphore 0", 1); + + /* Create the event flags group used by threads 1 and 5. */ + tx_event_flags_create(&event_flags_0, "event flags 0"); + + /* Create the mutex used by thread 6 and 7 without priority inheritance. */ + tx_mutex_create(&mutex_0, "mutex 0", TX_NO_INHERIT); + + /* Allocate the memory for a small block pool. */ + tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_BLOCK_POOL_SIZE, TX_NO_WAIT); + + /* Create a block memory pool to allocate a message buffer from. */ + tx_block_pool_create(&block_pool_0, "block pool 0", sizeof(ULONG), pointer, DEMO_BLOCK_POOL_SIZE); + + /* Allocate a block and release the block memory. */ + tx_block_allocate(&block_pool_0, (VOID **) &pointer, TX_NO_WAIT); + + /* Release the block back to the pool. */ + tx_block_release(pointer); + + /* AR1/M4 addition: create the verification thread. */ + demo_verify_create(); +} + + + +/* Define the test threads. */ + +void thread_0_entry(ULONG thread_input) +{ + +UINT status; + + + /* This thread simply sits in while-forever-sleep loop. */ + while(1) + { + + /* Increment the thread counter. */ + thread_0_counter++; + + /* Sleep for 10 ticks. */ + tx_thread_sleep(10); + + /* Set event flag 0 to wakeup thread 5. */ + status = tx_event_flags_set(&event_flags_0, 0x1, TX_OR); + + /* Check status. */ + if (status != TX_SUCCESS) + break; + } +} + + +void thread_1_entry(ULONG thread_input) +{ + +UINT status; + + + /* This thread simply sends messages to a queue shared by thread 2. */ + while(1) + { + + /* Increment the thread counter. */ + thread_1_counter++; + + /* Send message to queue 0. */ + status = tx_queue_send(&queue_0, &thread_1_messages_sent, TX_WAIT_FOREVER); + + /* Check completion status. */ + if (status != TX_SUCCESS) + break; + + /* Increment the message sent. */ + thread_1_messages_sent++; + } +} + + +void thread_2_entry(ULONG thread_input) +{ + +ULONG received_message; +UINT status; + + /* This thread retrieves messages placed on the queue by thread 1. */ + while(1) + { + + /* Increment the thread counter. */ + thread_2_counter++; + + /* Retrieve a message from the queue. */ + status = tx_queue_receive(&queue_0, &received_message, TX_WAIT_FOREVER); + + /* Check completion status and make sure the message is what we + expected. */ + if ((status != TX_SUCCESS) || (received_message != thread_2_messages_received)) + break; + + /* Otherwise, all is okay. Increment the received message count. */ + thread_2_messages_received++; + } +} + + +void thread_3_and_4_entry(ULONG thread_input) +{ + +UINT status; + + + /* This function is executed from thread 3 and thread 4. As the loop + below shows, these function compete for ownership of semaphore_0. */ + while(1) + { + + /* Increment the thread counter. */ + if (thread_input == 3) + thread_3_counter++; + else + thread_4_counter++; + + /* Get the semaphore with suspension. */ + status = tx_semaphore_get(&semaphore_0, TX_WAIT_FOREVER); + + /* Check status. */ + if (status != TX_SUCCESS) + break; + + /* Sleep for 2 ticks to hold the semaphore. */ + tx_thread_sleep(2); + + /* Release the semaphore. */ + status = tx_semaphore_put(&semaphore_0); + + /* Check status. */ + if (status != TX_SUCCESS) + break; + } +} + + +void thread_5_entry(ULONG thread_input) +{ + +UINT status; +ULONG actual_flags; + + + /* This thread simply waits for an event in a forever loop. */ + while(1) + { + + /* Increment the thread counter. */ + thread_5_counter++; + + /* Wait for event flag 0. */ + status = tx_event_flags_get(&event_flags_0, 0x1, TX_OR_CLEAR, + &actual_flags, TX_WAIT_FOREVER); + + /* Check status. */ + if ((status != TX_SUCCESS) || (actual_flags != 0x1)) + break; + } +} + + +void thread_6_and_7_entry(ULONG thread_input) +{ + +UINT status; + + + /* This function is executed from thread 6 and thread 7. As the loop + below shows, these function compete for ownership of mutex_0. */ + while(1) + { + + /* Increment the thread counter. */ + if (thread_input == 6) + thread_6_counter++; + else + thread_7_counter++; + + /* Get the mutex with suspension. */ + status = tx_mutex_get(&mutex_0, TX_WAIT_FOREVER); + + /* Check status. */ + if (status != TX_SUCCESS) + break; + + /* Get the mutex again with suspension. This shows + that an owning thread may retrieve the mutex it + owns multiple times. */ + status = tx_mutex_get(&mutex_0, TX_WAIT_FOREVER); + + /* Check status. */ + if (status != TX_SUCCESS) + break; + + /* Sleep for 2 ticks to hold the mutex. */ + tx_thread_sleep(2); + + /* Release the mutex. */ + status = tx_mutex_put(&mutex_0); + + /* Check status. */ + if (status != TX_SUCCESS) + break; + + /* Release the mutex again. This will actually + release ownership since it was obtained twice. */ + status = tx_mutex_put(&mutex_0); + + /* Check status. */ + if (status != TX_SUCCESS) + break; + } +} diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/demo_verify.c b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/demo_verify.c new file mode 100644 index 000000000..a22c7e135 --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/demo_verify.c @@ -0,0 +1,186 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* DEMONSTRATION RELEASE */ +/* */ +/* demo_verify.c Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frédéric Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* AR1 milestone M4: verifies that the standard eight-thread ThreadX */ +/* demo makes progress on Cortex-R52, then terminates the simulation */ +/* so the run can be automated. */ +/* */ +/* Where M3 proved the tick and a single preemption, this exercises */ +/* the demo's full object set -- queue, semaphore, mutex, event flags, */ +/* byte pool and block pool -- across eight threads at five priorities.*/ +/* Each of the ten demo counters is required to have advanced: a */ +/* stalled thread (a lost wakeup, a mishandled priority inversion) */ +/* shows up as a counter still at zero rather than as a plausible- */ +/* looking run. */ +/* */ +/* The verification thread runs at priority 0 so it can always preempt */ +/* the demo, and spends nearly all its life suspended. */ +/* */ +/**************************************************************************/ + +#include "tx_api.h" +#include "board.h" +#include "console.h" +#include "demo_verify.h" + +#define VERIFY_STACK_SIZE 2048 + +/* Ticks to let the demo run before checking. thread_0 sleeps 10 ticks per + iteration and thread_5 waits on the event flag it sets, so these two are + the slowest; 300 ticks (3 s at 100 Hz) gives them ~30 iterations each. */ + +#define VERIFY_SETTLE_TICKS 300UL + +/* Counters defined by the standard demo. */ + +extern ULONG thread_0_counter; +extern ULONG thread_1_counter; +extern ULONG thread_1_messages_sent; +extern ULONG thread_2_counter; +extern ULONG thread_2_messages_received; +extern ULONG thread_3_counter; +extern ULONG thread_4_counter; +extern ULONG thread_5_counter; +extern ULONG thread_6_counter; +extern ULONG thread_7_counter; + +static TX_THREAD verify_thread; +static ULONG verify_stack[VERIFY_STACK_SIZE / sizeof(ULONG)]; + + +/**************************************************************************/ +/* check_counter -- report one counter and whether it advanced. */ +/**************************************************************************/ + +static UINT check_counter(const char *label_ptr, ULONG value) +{ + console_puts(label_ptr); + console_puthex(value); + console_puts((value > 0UL) ? " PASS\n" : " FAIL\n"); + + return (value > 0UL) ? 0U : 1U; +} + + +/**************************************************************************/ +/* verify_thread_entry */ +/**************************************************************************/ + +static void verify_thread_entry(ULONG thread_input) +{ + UINT failures = 0U; + ULONG elapsed; + + (void) thread_input; + + console_puts("[verify] letting the standard demo run for "); + console_puthex(VERIFY_SETTLE_TICKS); + console_puts(" ticks...\n"); + + tx_thread_sleep(VERIFY_SETTLE_TICKS); + + elapsed = tx_time_get(); + + console_puts("\n[verify] demo counters after settling:\n"); + + failures += check_counter(" thread 0 counter = ", thread_0_counter); + failures += check_counter(" thread 1 counter = ", thread_1_counter); + failures += check_counter(" thread 1 messages sent = ", thread_1_messages_sent); + failures += check_counter(" thread 2 counter = ", thread_2_counter); + failures += check_counter(" thread 2 messages received = ", thread_2_messages_received); + failures += check_counter(" thread 3 counter = ", thread_3_counter); + failures += check_counter(" thread 4 counter = ", thread_4_counter); + failures += check_counter(" thread 5 counter = ", thread_5_counter); + failures += check_counter(" thread 6 counter = ", thread_6_counter); + failures += check_counter(" thread 7 counter = ", thread_7_counter); + + /* The queue must not have silently dropped or duplicated messages. */ + + console_puts("\n[verify] queue balance (sent >= received) "); + if (thread_1_messages_sent >= thread_2_messages_received) + { + console_puts("PASS\n"); + } + else + { + failures++; + console_puts("FAIL\n"); + } + + console_puts("[verify] elapsed ticks = "); + console_puthex(elapsed); + console_puts("\n[verify] tick advanced past the settle period "); + if (elapsed >= VERIFY_SETTLE_TICKS) + { + console_puts("PASS\n"); + } + else + { + failures++; + console_puts("FAIL\n"); + } + + if (failures == 0U) + { + console_puts("\nM4 RESULT: ALL CHECKS PASSED\n"); + } + else + { + console_puts("\nM4 RESULT: FAILED\n"); + } + + console_exit(failures); +} + + +/**************************************************************************/ +/* demo_verify_create */ +/**************************************************************************/ + +void demo_verify_create(void) +{ + /* Priority 0 and its own static stack: the verification thread must be + able to preempt every demo thread, and must not perturb the demo's + byte-pool allocations. */ + + (void) tx_thread_create(&verify_thread, "verify", verify_thread_entry, 0UL, + verify_stack, sizeof(verify_stack), + 0U, 0U, TX_NO_TIME_SLICE, TX_AUTO_START); +} + + +/**************************************************************************/ +/* bsp_main -- entered at EL1 from entry.S. Does not return. */ +/**************************************************************************/ + +void bsp_main(void) +{ + console_puts("\n=== ThreadX AR1/M4 standard eight-thread demo " + "(Cortex-R52, Armv8-R AArch32, Armv8-R AEM FVP) ===\n"); + + tx_kernel_enter(); +} diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/demo_verify.h b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/demo_verify.h new file mode 100644 index 000000000..71ebe6be0 --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/demo_verify.h @@ -0,0 +1,41 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* DEMONSTRATION RELEASE */ +/* */ +/* demo_verify.h Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frédéric Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Verification harness for the standard ThreadX demo, kept separate */ +/* so demo_threadx.c stays byte-identical to the shipped sample apart */ +/* from its header note and a single call to demo_verify_create(). */ +/* */ +/**************************************************************************/ + +#ifndef DEMO_VERIFY_H +#define DEMO_VERIFY_H + +/* Create the verification thread. Called from tx_application_define. */ + +void demo_verify_create(void); + +#endif /* DEMO_VERIFY_H */ diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/entry.S b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/entry.S new file mode 100644 index 000000000..0b89ee82c --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/entry.S @@ -0,0 +1,486 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* BOARD SUPPORT RELEASE */ +/* */ +/* entry.S Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frédéric Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Reset entry for Cortex-R52 (Armv8-R, AArch32) on the Armv8-R AEM */ +/* FVP. The R52 always implements EL2 and resets into it, so this */ +/* file configures EL2 first, installs both the EL2 and EL1 vector */ +/* tables, and only then drops to EL1 (Supervisor mode) to run the */ +/* kernel. The HVC entry in the EL2 table is the seam that ZoneX */ +/* (roadmap AR3) grows into -- it is deliberately present from AR1 so */ +/* that partitioning does not require re-architecting the boot path. */ +/* */ +/* Define TX_R52_BOOT_AT_EL1 to skip EL2 configuration, for targets */ +/* where an earlier boot stage or a vendor EL2 monitor (for example */ +/* NXP's EL2M on S32Z2) has already dropped privilege to EL1. */ +/* */ +/**************************************************************************/ + +#include "platform.h" + + .arch armv8-r + .syntax unified + .arm + +/* AArch32 CPSR mode encodings and interrupt mask bits. */ + + .equ MODE_USR, 0x10 + .equ MODE_FIQ, 0x11 + .equ MODE_IRQ, 0x12 + .equ MODE_SVC, 0x13 + .equ MODE_ABT, 0x17 + .equ MODE_HYP, 0x1A + .equ MODE_UND, 0x1B + .equ MODE_SYS, 0x1F + .equ PSR_A, 0x100 /* asynchronous abort mask */ + .equ PSR_I, 0x80 /* IRQ mask */ + .equ PSR_F, 0x40 /* FIQ mask */ + +/* HCR (Hyp Configuration Register) bits used here. */ + + .equ HCR_VM, (1 << 0) /* stage-2 MPU enable */ + .equ HCR_AMO, (1 << 3) /* route aborts to EL2 */ + .equ HCR_IMO, (1 << 4) /* route IRQ to EL2 */ + .equ HCR_FMO, (1 << 5) /* route FIQ to EL2 */ + .equ HCR_TGE, (1 << 27) /* trap general exceptions to EL2 */ + .equ HCR_HCD, (1 << 29) /* HVC disable -- must be clear */ + + .equ HCPTR_TCP, (3 << 10) /* trap EL1 access to CP10/CP11 */ + +/* CNTHCTL: permit EL1/EL0 use of the physical counter and timer. */ + + .equ CNTHCTL_PL1PCTEN, (1 << 0) + .equ CNTHCTL_PL1PCEN, (1 << 1) + +/* ICC_HSRE: enable the GICv3 system-register interface for EL1. */ + + .equ ICC_HSRE_SRE, (1 << 0) + .equ ICC_HSRE_ENABLE, (1 << 3) + +/* CPACR grants EL1/EL0 access to CP10 and CP11 (the floating-point unit); + FPEXC.EN then enables floating-point execution. */ + + .equ CPACR_CP10, (3 << 20) + .equ CPACR_CP11, (3 << 22) + .equ FPEXC_EN, (1 << 30) + + .equ SYS_WRITE0, 0x04 /* semihosting: write NUL-string */ + +/* HSR (Hyp Syndrome Register) exception classes. Every exception taken to + EL2 from EL1/EL0 arrives at the single Hyp Trap Entry vector, so the cause + must be decoded from HSR.EC (bits [31:26]). */ + + .equ HSR_EC_SHIFT, 26 + .equ HSR_EC_HVC, 0x12 /* HVC executed in AArch32 */ + +/* Report which vector was taken, then halt. The FVP offers no GDB stub + (Iris only), so a self-identifying fault is the primary debugging tool + for this port. Uses no stack: only r0/r1 and a semihosting call. */ + + .macro FAULT_REPORT msglabel + ldr r1, =\msglabel + mov r0, #SYS_WRITE0 + hlt 0xf000 + b fault_halt + .endm + +/**************************************************************************/ +/* EL2 (Hyp) vector table. Must be 32-byte aligned for HVBAR. */ +/**************************************************************************/ + + .section .vectors_el2, "ax" + .balign 32 + .global el2_vectors +el2_vectors: +/* Offsets 0x04-0x10 are exceptions taken *from* Hyp mode itself. Offset + 0x14 is the Hyp Trap Entry: every exception routed to EL2 from EL1/EL0 -- + HVC, stage-2 faults, trapped register accesses -- funnels through it and + is decoded from HSR. That single funnel is the ZoneX (AR3) seam. */ + + b el2_trap_reset /* 0x00 reset (unused at EL2) */ + b el2_trap_undef /* 0x04 undef, from Hyp */ + b el2_trap_svc /* 0x08 SVC, from Hyp */ + b el2_trap_pabt /* 0x0C prefetch abort, Hyp */ + b el2_trap_dabt /* 0x10 data abort, from Hyp */ + b el2_hyp_trap_entry /* 0x14 from EL1/EL0 <-- seam */ + b el2_trap_irq /* 0x18 IRQ */ + b el2_trap_fiq /* 0x1C FIQ */ + +/**************************************************************************/ +/* EL1 vector table. Must be 32-byte aligned for VBAR. */ +/**************************************************************************/ + + .section .vectors_el1, "ax" + .balign 32 + .global el1_vectors +el1_vectors: + b el1_trap_reset /* 0x00 reset */ + b el1_trap_undef /* 0x04 undefined instruction */ + b el1_trap_svc /* 0x08 supervisor call */ + b el1_trap_pabt /* 0x0C prefetch abort */ + b el1_trap_dabt /* 0x10 data abort */ + b el1_trap_reserved /* 0x14 reserved */ + b el1_irq_entry /* 0x18 IRQ */ + b el1_trap_fiq /* 0x1C FIQ */ + + .text + .balign 4 + +/**************************************************************************/ +/* _start -- reset entry. Entered at EL2 (Hyp mode) on Cortex-R52. */ +/**************************************************************************/ + + .global _start + .type _start, %function +_start: +#ifndef TX_R52_BOOT_AT_EL1 + + /* Hyp-mode stack must exist before anything can be pushed at EL2. */ + + ldr sp, =__hyp_stack_top + + /* Install the EL2 vector table (HVBAR). */ + + ldr r0, =el2_vectors + mcr p15, 4, r0, c12, c0, 0 + isb + + /* Configure EL2: keep exceptions and interrupts routed to EL1, and + leave the stage-2 MPU disabled for AR1 (the FVP background memory + map already permits execution and data access in low DRAM). ZoneX + enables HCR_VM and programs stage 2 in AR3. + + HCR_HCD is cleared explicitly so HVC is enabled from EL1 rather than + relying on its reset value -- the ZoneX seam depends on it. */ + + mrc p15, 4, r0, c1, c1, 0 /* HCR */ + ldr r1, =(HCR_TGE | HCR_AMO | HCR_IMO | HCR_FMO | HCR_VM | HCR_HCD) + bic r0, r0, r1 + mcr p15, 4, r0, c1, c1, 0 + isb + + /* Let EL1 use the FPU: clear HCPTR.TCP11/TCP10. R52 always implements + at least a single-precision FPU, so these traps must be cleared even + for a soft-float kernel build if application code uses the FPU. */ + + mrc p15, 4, r0, c1, c1, 2 /* HCPTR */ + ldr r1, =HCPTR_TCP + bic r0, r0, r1 + mcr p15, 4, r0, c1, c1, 2 + isb + + /* Generic timer, part 1 of 2 (part 2 is timer_init at EL1). + + CNTFRQ resets to ZERO on this model and is writable only at the + highest implemented exception level, so it must be programmed here at + EL2. The value is CNTFID0 read back from the counter control frame. + Software that derived a tick interval from CNTFRQ without this would + divide by zero. */ + + ldr r0, =SYSTEM_COUNTER_HZ + mcr p15, 0, r0, c14, c0, 0 /* CNTFRQ */ + + /* Permit EL1/EL0 to use the physical counter and the physical timer. + CNTHCTL.PL1PCTEN/PL1PCEN reset disabled, so without this every EL1 + access to CNTPCT or CNTP_* would trap to EL2. */ + + mrc p15, 4, r0, c14, c1, 0 /* CNTHCTL */ + orr r0, r0, #(CNTHCTL_PL1PCTEN | CNTHCTL_PL1PCEN) + mcr p15, 4, r0, c14, c1, 0 + isb + + /* Permit EL1 to reach the GICv3 CPU interface through its system + registers (ICC_*), which is how the R52 acknowledges interrupts. */ + + mrc p15, 4, r0, c12, c9, 5 /* ICC_HSRE */ + orr r0, r0, #(ICC_HSRE_SRE | ICC_HSRE_ENABLE) + mcr p15, 4, r0, c12, c9, 5 + isb + + /* Progress marker: proves we reached EL2 and semihosting works. */ + + ldr r1, =msg_el2 + mov r0, #SYS_WRITE0 + hlt 0xf000 + + /* Drop to EL1 (Supervisor), interrupts still masked. */ + + ldr r0, =el1_entry + msr ELR_hyp, r0 + ldr r0, =(PSR_A | PSR_I | PSR_F | MODE_SVC) + msr SPSR_hyp, r0 + isb + eret + +#else + b el1_entry +#endif + +/**************************************************************************/ +/* el1_entry -- first instruction executed at EL1. */ +/**************************************************************************/ + + .global el1_entry + .type el1_entry, %function +el1_entry: + + /* Install the EL1 vector table (VBAR). */ + + ldr r0, =el1_vectors + mcr p15, 0, r0, c12, c0, 0 + isb + + /* Give every EL1 mode its own stack. Interrupts stay masked: CPS + changes mode only. System mode shares SP_usr, so it is set last + before returning to Supervisor mode. */ + + cps #MODE_IRQ + ldr sp, =__irq_stack_top + cps #MODE_FIQ + ldr sp, =__fiq_stack_top + cps #MODE_ABT + ldr sp, =__abt_stack_top + cps #MODE_UND + ldr sp, =__und_stack_top + cps #MODE_SYS + ldr sp, =__sys_stack_top + cps #MODE_SVC + ldr sp, =__svc_stack_top + +#ifdef __ARM_FP + + /* Enable the floating-point unit for EL1. + * + * Two separate gates must be opened and both reset closed: + * CPACR grants EL1/EL0 access to CP10/CP11. It reads 0 out of reset, + * so the first floating-point instruction would otherwise raise + * an Undefined Instruction exception. + * FPEXC .EN enables floating-point execution itself. + * EL2 has already cleared HCPTR.TCP10/TCP11 so neither access traps to EL2. + * + * This is a BSP responsibility, not the kernel's: tx_thread_vfp_enable() + * only sets the per-thread software flag that makes the context switch + * save and restore floating-point state. It does not turn the hardware + * on, so without the code below a VFP-enabled build faults on its first + * context switch that touches D-registers. + * + * Guarded by __ARM_FP, which the compiler defines exactly when the build + * can emit floating-point instructions. In a soft-float build "vmsr + * fpexc" is not even assemblable for this target. + */ + + mrc p15, 0, r0, c1, c0, 2 /* CPACR */ + orr r0, r0, #(CPACR_CP10 | CPACR_CP11) + mcr p15, 0, r0, c1, c0, 2 + isb + + mov r0, #FPEXC_EN + vmsr fpexc, r0 + isb + +#endif + + /* Zero .bss before any C code runs. */ + + ldr r0, =__bss_start__ + ldr r1, =__bss_end__ + mov r2, #0 +bss_zero_loop: + cmp r0, r1 + bhs bss_zero_done + str r2, [r0], #4 + b bss_zero_loop +bss_zero_done: + +#ifdef TX_R52_ENABLE_MPU + + /* Protection and caches on before any application code runs. This is + after .bss is cleared because mpu_init keeps its region table there. */ + + bl mpu_init + +#endif + + bl bsp_main + + /* bsp_main is not expected to return. */ +_start_hang: + b _start_hang + +/**************************************************************************/ +/* el1_irq_entry -- IRQ vector. */ +/* */ +/* With ThreadX linked in, the IRQ vector branches straight into */ +/* _tx_thread_context_save, which saves the interrupted context and */ +/* branches back to __tx_irq_processing_return. The branch must be a */ +/* plain B: context save adjusts lr itself to find the point of */ +/* interrupt. Interrupts are still disabled on return from it. */ +/* */ +/* Images that do not link ThreadX (the M1 boot check) keep the */ +/* self-identifying fault reporter instead. */ +/**************************************************************************/ + + .global el1_irq_entry + .type el1_irq_entry, %function +el1_irq_entry: +#ifdef TX_R52_USE_THREADX_IRQ + b _tx_thread_context_save + + .global __tx_irq_processing_return +__tx_irq_processing_return: + bl board_irq_handler + b _tx_thread_context_restore +#else + FAULT_REPORT msg_el1_irq +#endif + +/**************************************************************************/ +/* el2_hyp_trap_entry -- the ZoneX (AR3) seam. */ +/* */ +/* Reached for every exception routed to EL2 from EL1/EL0, so the cause */ +/* is decoded from HSR.EC before dispatch. AR1 handles only HVC, which */ +/* it counts before returning to EL1; that proves EL2 is live and */ +/* reachable without the boot path changing later. AR3 grows the */ +/* dispatch table here (stage-2 faults, trapped accesses, IRQ paravirt). */ +/* */ +/* EL1's registers must be preserved -- this runs on the Hyp stack. */ +/**************************************************************************/ + + .global el2_hyp_trap_entry + .type el2_hyp_trap_entry, %function +el2_hyp_trap_entry: + push {r0, r1} + mrc p15, 4, r0, c5, c2, 0 /* HSR */ + lsr r1, r0, #HSR_EC_SHIFT + cmp r1, #HSR_EC_HVC + bne el2_hyp_trap_unhandled + + /* HVC from EL1: AR1 placeholder for the ZoneX hypercall dispatch. */ + + ldr r0, =_hvc_call_count + ldr r1, [r0] + add r1, r1, #1 + str r1, [r0] + pop {r0, r1} + eret + +el2_hyp_trap_unhandled: + pop {r0, r1} + FAULT_REPORT msg_el2_hyp + +/**************************************************************************/ +/* Unhandled exceptions. Each records a distinct code in r12 so a halted*/ +/* model or a later fault dump (AR1/M5) can identify the cause. Real */ +/* handlers arrive with the interrupt work in M3. */ +/**************************************************************************/ + +/* Unhandled exceptions. Real handlers arrive with the interrupt work in + AR1/M3; until then each vector identifies itself and halts. */ + +el2_trap_reset: FAULT_REPORT msg_el2_reset +el2_trap_undef: FAULT_REPORT msg_el2_undef +el2_trap_svc: FAULT_REPORT msg_el2_svc +el2_trap_pabt: FAULT_REPORT msg_el2_pabt +el2_trap_dabt: FAULT_REPORT msg_el2_dabt +el2_trap_irq: FAULT_REPORT msg_el2_irq +el2_trap_fiq: FAULT_REPORT msg_el2_fiq + +el1_trap_reset: FAULT_REPORT msg_el1_reset +el1_trap_undef: FAULT_REPORT msg_el1_undef +el1_trap_svc: FAULT_REPORT msg_el1_svc +el1_trap_pabt: FAULT_REPORT msg_el1_pabt + +/* Data abort. Normally fatal and self-reporting, but the MPU self-test + needs to provoke a permission fault and carry on: without that, "the MPU + is enabled" is an unverified claim. When mpu_expect_abort is non-zero the + fault is counted and execution resumes at the instruction *after* the one + that faulted. On a data abort LR_abt holds the faulting address plus 8, + so returning to LR_abt-4 skips it, where LR_abt-8 would retry it forever. + Runs on the Abort-mode stack set up above. */ + +el1_trap_dabt: +#ifdef TX_R52_MPU_FAULT_TEST + push {r0, r1} + ldr r0, =mpu_expect_abort + ldr r1, [r0] + cmp r1, #0 + beq el1_dabt_fatal + mov r1, #0 + str r1, [r0] /* consume the expectation */ + ldr r0, =mpu_abort_count + ldr r1, [r0] + add r1, r1, #1 + str r1, [r0] + dsb + pop {r0, r1} + subs pc, lr, #4 /* resume after the fault */ +el1_dabt_fatal: + pop {r0, r1} +#endif + FAULT_REPORT msg_el1_dabt +el1_trap_reserved: FAULT_REPORT msg_el1_reserved +el1_trap_fiq: FAULT_REPORT msg_el1_fiq + +fault_halt: b fault_halt + + .section .rodata + .balign 4 +msg_el2: + .asciz "[EL2] reset entry reached; configuring EL2 and dropping to EL1\n" + +msg_el2_reset: .asciz "[FAULT] EL2 reset vector\n" +msg_el2_undef: .asciz "[FAULT] EL2 undefined instruction\n" +msg_el2_svc: .asciz "[FAULT] EL2 supervisor call from Hyp mode\n" +msg_el2_pabt: .asciz "[FAULT] EL2 prefetch abort\n" +msg_el2_dabt: .asciz "[FAULT] EL2 data abort\n" +msg_el2_hyp: .asciz "[FAULT] EL2 hyp trap with unhandled HSR.EC\n" +msg_el2_irq: .asciz "[FAULT] EL2 IRQ (unexpected: IRQs route to EL1)\n" +msg_el2_fiq: .asciz "[FAULT] EL2 FIQ (unexpected: FIQs route to EL1)\n" + +msg_el1_reset: .asciz "[FAULT] EL1 reset vector\n" +msg_el1_undef: .asciz "[FAULT] EL1 undefined instruction\n" +msg_el1_svc: .asciz "[FAULT] EL1 supervisor call (no handler yet)\n" +msg_el1_pabt: .asciz "[FAULT] EL1 prefetch abort\n" +msg_el1_dabt: .asciz "[FAULT] EL1 data abort\n" +msg_el1_reserved: .asciz "[FAULT] EL1 reserved vector\n" +msg_el1_irq: .asciz "[FAULT] EL1 IRQ (no handler yet)\n" +msg_el1_fiq: .asciz "[FAULT] EL1 FIQ (no handler yet)\n" + + .section .data + .balign 4 + .global _hvc_call_count +_hvc_call_count: + .word 0 + +/* Used by the MPU enforcement self-test (see el1_trap_dabt). */ + + .global mpu_expect_abort +mpu_expect_abort: + .word 0 + + .global mpu_abort_count +mpu_abort_count: + .word 0 diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/gicv3.c b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/gicv3.c new file mode 100644 index 000000000..4a1925094 --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/gicv3.c @@ -0,0 +1,215 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* BOARD SUPPORT RELEASE */ +/* */ +/* gicv3.c Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frédéric Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* GICv3 bring-up for Cortex-R52 on the Armv8-R AEM FVP. */ +/* */ +/* Model characteristics that shape this code, taken from its own */ +/* parameters rather than assumed: */ +/* */ +/* has-two-security-states=0 single security state, so GICD_CTLR.DS */ +/* reads 1 and the Group 1 enable is bit 1*/ +/* ARE-fixed-to-one=1 affinity routing cannot be turned off */ +/* priority-bits=5 only the top 5 priority bits exist, so */ +/* priorities must be multiples of 8 */ +/* */ +/* MISRA C:2012 deviations (justified) */ +/* */ +/* Directive 4.3 -- the CPU interface is only reachable through CP15 */ +/* system registers, so inline assembly is unavoidable. Every such */ +/* access is encapsulated in a one-line accessor below and appears */ +/* nowhere else. */ +/* Rule 11.4/11.6 -- casting integer addresses to volatile pointers is */ +/* inherent to memory-mapped device access; confined to REG32. */ +/* */ +/**************************************************************************/ + +#include "platform.h" +#include "gicv3.h" + +/* Distributor registers. */ + +#define GICD_CTLR 0x0000U +#define GICD_CTLR_ENABLE_GRP1 (1UL << 1) +#define GICD_CTLR_ARE (1UL << 4) + +/* Redistributor RD frame. */ + +#define GICR_WAKER 0x0014U +#define GICR_WAKER_PROC_SLEEP (1UL << 1) +#define GICR_WAKER_CHILD_ASLEEP (1UL << 2) + +/* Redistributor SGI frame (SGIs and PPIs, INTID 0-31). */ + +#define GICR_IGROUPR0 0x0080U +#define GICR_ISENABLER0 0x0100U +#define GICR_IPRIORITYR 0x0400U +#define GICR_ICFGR1 0x0C04U + +#define ICC_PMR_UNMASK_ALL 0xFFUL +#define ICC_SRE_SRE (1UL << 0) +#define ICC_IGRPEN1_ENABLE (1UL << 0) + +#define PPI_FIRST_INTID 16U + + +/**************************************************************************/ +/* CPU interface accessors (AArch32 ICC_* system registers). */ +/**************************************************************************/ + +static unsigned long read_icc_sre(void) +{ + unsigned long value; + __asm__ volatile("mrc p15, 0, %0, c12, c12, 5" : "=r"(value)); + return value; +} + +static void write_icc_sre(unsigned long value) +{ + __asm__ volatile("mcr p15, 0, %0, c12, c12, 5" : : "r"(value) : "memory"); +} + +static void write_icc_pmr(unsigned long value) +{ + __asm__ volatile("mcr p15, 0, %0, c4, c6, 0" : : "r"(value) : "memory"); +} + +static void write_icc_bpr1(unsigned long value) +{ + __asm__ volatile("mcr p15, 0, %0, c12, c12, 3" : : "r"(value) : "memory"); +} + +static void write_icc_igrpen1(unsigned long value) +{ + __asm__ volatile("mcr p15, 0, %0, c12, c12, 7" : : "r"(value) : "memory"); +} + +static void instruction_barrier(void) +{ + __asm__ volatile("isb" : : : "memory"); +} + + +/**************************************************************************/ +/* gicv3_init */ +/**************************************************************************/ + +void gicv3_init(void) +{ + unsigned long waker; + + /* Distributor: affinity routing first, then the Group 1 enable. With a + single security state Group 1 is bit 1 of GICD_CTLR. */ + + REG32(GICD_BASE + GICD_CTLR) |= GICD_CTLR_ARE; + REG32(GICD_BASE + GICD_CTLR) |= GICD_CTLR_ENABLE_GRP1; + + /* Redistributor: clear ProcessorSleep and wait for the redistributor to + report that its children are awake, otherwise no interrupt can be + delivered to this core. */ + + waker = REG32(GICR_RD_BASE + GICR_WAKER); + waker &= ~GICR_WAKER_PROC_SLEEP; + REG32(GICR_RD_BASE + GICR_WAKER) = waker; + + while ((REG32(GICR_RD_BASE + GICR_WAKER) & GICR_WAKER_CHILD_ASLEEP) != 0UL) + { + /* Wait for the redistributor to wake. */ + } + + /* CPU interface: system-register access, then unmask all priorities and + enable Group 1. EL2 has already permitted EL1 system-register access + via ICC_HSRE in entry.S. */ + + write_icc_sre(read_icc_sre() | ICC_SRE_SRE); + instruction_barrier(); + + write_icc_pmr(ICC_PMR_UNMASK_ALL); + write_icc_bpr1(0UL); + write_icc_igrpen1(ICC_IGRPEN1_ENABLE); + instruction_barrier(); +} + + +/**************************************************************************/ +/* gicv3_enable_ppi */ +/**************************************************************************/ + +void gicv3_enable_ppi(unsigned int intid, unsigned int priority) +{ + unsigned long shift; + + if ((intid < PPI_FIRST_INTID) || (intid > 31U)) + { + return; + } + + /* Group 1. */ + + REG32(GICR_SGI_BASE + GICR_IGROUPR0) |= (1UL << intid); + + /* Priority is a byte per INTID. Only the top 5 bits are implemented on + this model, so callers pass multiples of 8. */ + + REG32(GICR_SGI_BASE + GICR_IPRIORITYR + (intid & ~3U)) &= + ~(0xFFUL << ((intid & 3U) * 8U)); + REG32(GICR_SGI_BASE + GICR_IPRIORITYR + (intid & ~3U)) |= + ((unsigned long) priority & 0xFFUL) << ((intid & 3U) * 8U); + + /* Level-sensitive: two configuration bits per INTID, 00 = level. The + generic timer asserts a level, not an edge. */ + + shift = ((unsigned long) intid - PPI_FIRST_INTID) * 2UL; + REG32(GICR_SGI_BASE + GICR_ICFGR1) &= ~(3UL << shift); + + /* Enable. */ + + REG32(GICR_SGI_BASE + GICR_ISENABLER0) = (1UL << intid); +} + + +/**************************************************************************/ +/* gicv3_acknowledge */ +/**************************************************************************/ + +unsigned long gicv3_acknowledge(void) +{ + unsigned long intid; + + __asm__ volatile("mrc p15, 0, %0, c12, c12, 0" : "=r"(intid)); + + return intid; +} + + +/**************************************************************************/ +/* gicv3_end_of_interrupt */ +/**************************************************************************/ + +void gicv3_end_of_interrupt(unsigned long intid) +{ + __asm__ volatile("mcr p15, 0, %0, c12, c12, 1" : : "r"(intid) : "memory"); +} diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/gicv3.h b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/gicv3.h new file mode 100644 index 000000000..cc35639c0 --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/gicv3.h @@ -0,0 +1,61 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* BOARD SUPPORT RELEASE */ +/* */ +/* gicv3.h Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frédéric Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* GICv3 interrupt controller for Cortex-R52. The CPU interface is */ +/* reached through AArch32 ICC_* system registers; the Distributor and */ +/* Redistributor are memory mapped. */ +/* */ +/**************************************************************************/ + +#ifndef GICV3_H +#define GICV3_H + +/* Spurious interrupt ID returned by the CPU interface when no interrupt is + pending. It must be neither dispatched nor acknowledged with EOI. */ + +#define GICV3_SPURIOUS_INTID 1023UL + +/* Bring up the Distributor, this core's Redistributor and the CPU + interface. Interrupts remain masked at the PSTATE level. */ + +void gicv3_init(void); + +/* Enable one private peripheral interrupt (PPI, INTID 16-31) as a + level-sensitive Group 1 interrupt at the given priority. */ + +void gicv3_enable_ppi(unsigned int intid, unsigned int priority); + +/* Acknowledge the highest-priority pending Group 1 interrupt, returning its + INTID (possibly GICV3_SPURIOUS_INTID). */ + +unsigned long gicv3_acknowledge(void); + +/* Signal completion of the interrupt previously acknowledged. */ + +void gicv3_end_of_interrupt(unsigned long intid); + +#endif /* GICV3_H */ diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/irq_dispatch.c b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/irq_dispatch.c new file mode 100644 index 000000000..0028dddbd --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/irq_dispatch.c @@ -0,0 +1,113 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* BOARD SUPPORT RELEASE */ +/* */ +/* irq_dispatch.c Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frédéric Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Interrupt dispatch for Cortex-R52 on the Armv8-R AEM FVP. Called */ +/* from __tx_irq_processing_return in entry.S, that is after */ +/* _tx_thread_context_save has saved the interrupted context and with */ +/* interrupts still disabled. */ +/* */ +/* _tx_timer_interrupt is safe to call from C: it uses only r0-r3 and */ +/* returns through lr like an ordinary function. */ +/* */ +/**************************************************************************/ + +#include "board.h" +#include "gicv3.h" +#include "timer.h" + +/* ThreadX periodic timer entry point (assembly, AAPCS-compatible). */ + +extern void _tx_timer_interrupt(void); + +/* Observability for the M3 checks. board_timer_intid records the INTID that + actually arrived -- this is how the timer PPI was identified during bring-up + (see TIMER_PPI_INTID) and it keeps reporting it, so a platform that assigns + the timer elsewhere shows up as an unexpected INTID rather than a silent + absence of ticks. */ + +volatile unsigned long board_irq_count; +volatile unsigned long board_timer_intid; +volatile unsigned long board_spurious_count; +volatile unsigned long board_unexpected_intid; + + +/* Timer PPI priority. Only the top 5 priority bits are implemented on this + model, so the value is a multiple of 8. */ + +#define TIMER_PPI_PRIORITY 0xA0U + + +/**************************************************************************/ +/* board_init */ +/* */ +/* Called from _tx_initialize_low_level. Interrupts are still masked at */ +/* this point, so the tick cannot be delivered before the kernel is */ +/* ready for it. */ +/**************************************************************************/ + +void board_init(void) +{ + gicv3_init(); + gicv3_enable_ppi(TIMER_PPI_INTID, TIMER_PPI_PRIORITY); + timer_init(); +} + + +/**************************************************************************/ +/* board_irq_handler */ +/**************************************************************************/ + +void board_irq_handler(void) +{ + unsigned long intid = gicv3_acknowledge(); + + if (intid == GICV3_SPURIOUS_INTID) + { + /* No interrupt was actually pending; must not be acknowledged. */ + + board_spurious_count++; + return; + } + + if (intid == (unsigned long) TIMER_PPI_INTID) + { + board_timer_intid = intid; + board_irq_count++; + + /* Re-arm before servicing so the next interval starts immediately; + this also deasserts the level-sensitive timer output. */ + + timer_reload(); + _tx_timer_interrupt(); + } + else + { + board_unexpected_intid = intid; + } + + gicv3_end_of_interrupt(intid); +} diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/link.lds b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/link.lds new file mode 100644 index 000000000..b7aac5c88 --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/link.lds @@ -0,0 +1,141 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/* Linker script for Cortex-R52 on the Armv8-R AEM FVP (BaseR platform). + * + * The BaseR memory map is the Base platform map with its two 2 GB halves + * swapped: Base DRAM at 0x80000000 appears at 0x00000000 here, and the + * 0x80000000-0xFFFFFFFF half holds peripherals and is NOT executable by + * default. Code must therefore be linked into low DRAM -- linking at + * 0x80000000 produces a silent fault loop with no output. + */ + +ENTRY(_start) + +__hyp_stack_size__ = 0x0800; +__svc_stack_size__ = 0x1000; +__irq_stack_size__ = 0x0800; +__fiq_stack_size__ = 0x0400; +__abt_stack_size__ = 0x0400; +__und_stack_size__ = 0x0400; +__sys_stack_size__ = 0x0800; + +MEMORY +{ + DRAM (rwx) : ORIGIN = 0x00000000, LENGTH = 0x08000000 /* 128 MB */ +} + +SECTIONS +{ + /* PMSAv8-R regions have a 64-byte granule and their limits are inclusive, + so the code and data areas are separated on a 64-byte boundary. Without + this a single region would have to span both, forcing writable code or + executable data. */ + + . = ALIGN(64); + __code_start__ = .; + + .text : + { + KEEP(*(.vectors_el2)) + KEEP(*(.vectors_el1)) + *(.text*) + *(.glue_7) + *(.glue_7t) + } > DRAM + + .rodata : + { + . = ALIGN(4); + *(.rodata*) + . = ALIGN(4); + } > DRAM + + /* Start the writable area on a protection-region granule. + * + * The alignment belongs on the output section itself. Two things that + * look equivalent do not work: an assignment such as ". = ALIGN(64);" + * between sections does not advance a MEMORY region's allocation + * pointer, and ". = ALIGN(64);" at the end of .rodata does not extend + * that section when no data follows it. In both cases .data keeps its + * unaligned address while __data_start__ reports the aligned one, so the + * first bytes of .data fall inside the read-only code region. The MPU + * caught precisely that: writes to the two variables at the start of + * .data faulted, and since one of them is the flag the abort handler + * consults, the fault turned itself fatal. + */ + + .data ALIGN(64) : + { + __code_end__ = .; /* code region ends where writable data begins */ + __data_start__ = .; + *(.data*) + . = ALIGN(4); + } > DRAM + + .bss (NOLOAD) : + { + . = ALIGN(4); + __bss_start__ = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > DRAM + + /* One stack per AArch32 processor mode. SP must stay 8-byte aligned + (AAPCS), so each region is aligned before its top symbol is taken. */ + + .stacks (NOLOAD) : + { + . = ALIGN(8); + . = . + __hyp_stack_size__; + __hyp_stack_top = .; + + . = ALIGN(8); + . = . + __svc_stack_size__; + __svc_stack_top = .; + + . = ALIGN(8); + . = . + __irq_stack_size__; + __irq_stack_top = .; + + . = ALIGN(8); + . = . + __fiq_stack_size__; + __fiq_stack_top = .; + + . = ALIGN(8); + . = . + __abt_stack_size__; + __abt_stack_top = .; + + . = ALIGN(8); + . = . + __und_stack_size__; + __und_stack_top = .; + + . = ALIGN(8); + . = . + __sys_stack_size__; + __sys_stack_top = .; + } > DRAM + + . = ALIGN(8); + _end = .; + PROVIDE(end = .); + + /* Writable area for the MPU: data, bss, stacks and the heap that + tx_application_define carves out of everything above _end. */ + + . = ALIGN(64); + __data_end__ = . + 0x00100000; /* 1 MB of heap beyond the image */ +} diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/mpu.c b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/mpu.c new file mode 100644 index 000000000..21e1cf126 --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/mpu.c @@ -0,0 +1,353 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* BOARD SUPPORT RELEASE */ +/* */ +/* mpu.c Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frédéric Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* PMSAv8-R memory protection and cache enable for Cortex-R52. */ +/* */ +/* Register model (AArch32): a region is selected through PRSELR and */ +/* then described by PRBAR (base, shareability, access permission, */ +/* execute-never) and PRLAR (inclusive limit, attribute index, enable).*/ +/* Both addresses have a 64-byte granule, so the low six bits of each */ +/* register hold attributes rather than address. Memory types come */ +/* from MAIR through the attribute index, not from the region itself. */ +/* */ +/* Caches are invalidated before being enabled. On this model they */ +/* come out of reset invalid, but silicon does not guarantee that, and */ +/* this code is meant to be the template the S32Z280 port starts from. */ +/* */ +/* MISRA C:2012 deviations (justified) */ +/* */ +/* Directive 4.3 -- the MPU, MAIR, SCTLR and cache maintenance are only*/ +/* reachable through CP15; every access is encapsulated in a one-line*/ +/* accessor below. */ +/* */ +/**************************************************************************/ + +#include "platform.h" +#include "mpu.h" + +/* SCTLR bits. */ + +#define SCTLR_M (1UL << 0) /* MPU enable */ +#define SCTLR_C (1UL << 2) /* data cache enable */ +#define SCTLR_I (1UL << 12) /* instruction cache enable */ + +/* MAIR attribute bytes. Index 0 is Normal write-back read/write-allocate, + index 1 is Device-nGnRnE, matching MPU_ATTR_* in the header. */ + +#define MAIR_ATTR_NORMAL_WB 0xFFUL +#define MAIR_ATTR_DEVICE 0x00UL + +/* Boundaries supplied by the linker script, all 64-byte aligned. */ + +extern char __code_start__; +extern char __code_end__; +extern char __data_start__; +extern char __data_end__; + + +/**************************************************************************/ +/* The region table. */ +/* */ +/* Deliberately minimal and readable: code is read-only and executable, */ +/* everything writable is non-executable, and the peripheral half of the */ +/* address map is Device. A write-protected code region is the point -- */ +/* it is what makes the MPU do something observable, and AR2 extends the */ +/* same table with per-module regions. */ +/**************************************************************************/ + +static MPU_REGION mpu_regions[3]; +static unsigned int mpu_regions_used; + + +/**************************************************************************/ +/* CP15 accessors. */ +/**************************************************************************/ + +static unsigned long read_mpuir(void) +{ + unsigned long value; + __asm__ volatile("mrc p15, 0, %0, c0, c0, 4" : "=r"(value)); + return value; +} + +static unsigned long read_sctlr(void) +{ + unsigned long value; + __asm__ volatile("mrc p15, 0, %0, c1, c0, 0" : "=r"(value)); + return value; +} + +static void write_sctlr(unsigned long value) +{ + __asm__ volatile("mcr p15, 0, %0, c1, c0, 0" : : "r"(value) : "memory"); +} + +static void write_prselr(unsigned long value) +{ + __asm__ volatile("mcr p15, 0, %0, c6, c2, 1" : : "r"(value) : "memory"); +} + +static void write_prbar(unsigned long value) +{ + __asm__ volatile("mcr p15, 0, %0, c6, c3, 0" : : "r"(value) : "memory"); +} + +static void write_prlar(unsigned long value) +{ + __asm__ volatile("mcr p15, 0, %0, c6, c3, 1" : : "r"(value) : "memory"); +} + +static unsigned long read_prbar(void) +{ + unsigned long value; + __asm__ volatile("mrc p15, 0, %0, c6, c3, 0" : "=r"(value)); + return value; +} + +static unsigned long read_prlar(void) +{ + unsigned long value; + __asm__ volatile("mrc p15, 0, %0, c6, c3, 1" : "=r"(value)); + return value; +} + +static void write_mair0(unsigned long value) +{ + __asm__ volatile("mcr p15, 0, %0, c10, c2, 0" : : "r"(value) : "memory"); +} + +static void write_mair1(unsigned long value) +{ + __asm__ volatile("mcr p15, 0, %0, c10, c2, 1" : : "r"(value) : "memory"); +} + +static void invalidate_icache_all(void) +{ + __asm__ volatile("mcr p15, 0, r0, c7, c5, 0" : : : "memory"); /* ICIALLU */ +} + +static void data_sync_barrier(void) +{ + __asm__ volatile("dsb" : : : "memory"); +} + +static void instruction_barrier(void) +{ + __asm__ volatile("isb" : : : "memory"); +} + + +/**************************************************************************/ +/* mpu_region_count */ +/**************************************************************************/ + +unsigned int mpu_region_count(void) +{ + /* MPUIR.REGION occupies bits [15:8]. */ + + return (unsigned int) ((read_mpuir() >> 8) & 0xFFUL); +} + + +/**************************************************************************/ +/* mpu_is_enabled / mpu_caches_enabled */ +/**************************************************************************/ + +unsigned int mpu_is_enabled(void) +{ + return ((read_sctlr() & SCTLR_M) != 0UL) ? 1U : 0U; +} + +unsigned int mpu_caches_enabled(void) +{ + unsigned long sctlr = read_sctlr(); + + return (((sctlr & SCTLR_C) != 0UL) && ((sctlr & SCTLR_I) != 0UL)) ? 1U : 0U; +} + + +/**************************************************************************/ +/* mpu_region_table */ +/**************************************************************************/ + +const MPU_REGION *mpu_region_table(unsigned int *count_ptr) +{ + if (count_ptr != 0) + { + *count_ptr = mpu_regions_used; + } + + return mpu_regions; +} + + +/**************************************************************************/ +/* mpu_read_region */ +/**************************************************************************/ + +void mpu_read_region(unsigned int index, unsigned long *prbar_ptr, + unsigned long *prlar_ptr) +{ + write_prselr((unsigned long) index); + instruction_barrier(); + + if (prbar_ptr != 0) + { + *prbar_ptr = read_prbar(); + } + if (prlar_ptr != 0) + { + *prlar_ptr = read_prlar(); + } +} + + +/**************************************************************************/ +/* build_table -- describe this image's memory. */ +/**************************************************************************/ + +static void build_table(void) +{ + /* Code: read-only and executable. */ + + mpu_regions[0].mpu_region_base = (unsigned long) &__code_start__; + mpu_regions[0].mpu_region_limit = (unsigned long) &__code_end__ - 1UL; + mpu_regions[0].mpu_region_ap = MPU_AP_RO_EL1; + mpu_regions[0].mpu_region_execute_never = 0U; + mpu_regions[0].mpu_region_shareability = MPU_SH_NON; + mpu_regions[0].mpu_region_attr_index = MPU_ATTR_NORMAL_WB; + mpu_regions[0].mpu_region_name = "code RO X normal-wb"; + + /* Data, bss, stacks and heap: writable, never executable. */ + + mpu_regions[1].mpu_region_base = (unsigned long) &__data_start__; + mpu_regions[1].mpu_region_limit = (unsigned long) &__data_end__ - 1UL; + mpu_regions[1].mpu_region_ap = MPU_AP_RW_EL1; + mpu_regions[1].mpu_region_execute_never = 1U; + mpu_regions[1].mpu_region_shareability = MPU_SH_NON; + mpu_regions[1].mpu_region_attr_index = MPU_ATTR_NORMAL_WB; + mpu_regions[1].mpu_region_name = "data RW NX normal-wb"; + + /* Peripherals occupy the upper half of the BaseR map. */ + + mpu_regions[2].mpu_region_base = 0x80000000UL; + mpu_regions[2].mpu_region_limit = 0xFFFFFFFFUL; + mpu_regions[2].mpu_region_ap = MPU_AP_RW_EL1; + mpu_regions[2].mpu_region_execute_never = 1U; + mpu_regions[2].mpu_region_shareability = MPU_SH_NON; + mpu_regions[2].mpu_region_attr_index = MPU_ATTR_DEVICE; + mpu_regions[2].mpu_region_name = "dev RW NX device"; + + mpu_regions_used = 3U; +} + + +/**************************************************************************/ +/* program_region */ +/**************************************************************************/ + +static void program_region(unsigned int index, const MPU_REGION *region_ptr) +{ + unsigned long prbar; + unsigned long prlar; + + /* PRBAR: BASE[31:6], SH[5:4], AP[3:2], XN[1]. */ + + prbar = (region_ptr->mpu_region_base & 0xFFFFFFC0UL) + | (((unsigned long) region_ptr->mpu_region_shareability & 0x3UL) << 4) + | (((unsigned long) region_ptr->mpu_region_ap & 0x3UL) << 2) + | (((unsigned long) region_ptr->mpu_region_execute_never & 0x1UL) << 1); + + prlar = (region_ptr->mpu_region_limit & 0xFFFFFFC0UL) + | (((unsigned long) region_ptr->mpu_region_attr_index & 0x7UL) << 1) + | 1UL; /* region enable */ + + write_prselr((unsigned long) index); + instruction_barrier(); + write_prbar(prbar); + write_prlar(prlar); +} + + +/**************************************************************************/ +/* mpu_init */ +/**************************************************************************/ + +unsigned int mpu_init(void) +{ + unsigned long sctlr; + unsigned int index; + unsigned int available = mpu_region_count(); + + build_table(); + + if (available < mpu_regions_used) + { + return 0U; + } + + /* Memory types first: a region's attribute index is meaningless until + MAIR is populated. */ + + write_mair0((MAIR_ATTR_DEVICE << 8) | MAIR_ATTR_NORMAL_WB); + write_mair1(0UL); + + for (index = 0U; index < mpu_regions_used; index++) + { + program_region(index, &mpu_regions[index]); + } + + /* Disable any regions this image does not use, so that stale enables + cannot grant access we did not intend. */ + + for (index = mpu_regions_used; index < available; index++) + { + write_prselr((unsigned long) index); + instruction_barrier(); + write_prlar(0UL); + } + + data_sync_barrier(); + + /* Caches are invalidated before enabling. The instruction cache has a + single invalidate-all; the data cache is left to the model's reset + state, which is invalid, because a set/way sweep belongs with the + silicon bring-up where it can be verified against the real cache + geometry. */ + + invalidate_icache_all(); + data_sync_barrier(); + instruction_barrier(); + + sctlr = read_sctlr(); + sctlr |= SCTLR_M | SCTLR_C | SCTLR_I; + write_sctlr(sctlr); + data_sync_barrier(); + instruction_barrier(); + + return mpu_regions_used; +} diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/mpu.h b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/mpu.h new file mode 100644 index 000000000..e90690e9c --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/mpu.h @@ -0,0 +1,113 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* BOARD SUPPORT RELEASE */ +/* */ +/* mpu.h Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frédéric Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* PMSAv8-R memory protection and cache enable for Cortex-R52. */ +/* */ +/* The region set is described by a table rather than a sequence of */ +/* register writes. That is deliberate and is a roadmap decision, not */ +/* a style preference: AR2 programs a Stage-1 region set per ThreadX */ +/* module and AR3 programs Stage-2 regions per ZoneX partition, and */ +/* both reuse this shape. A table can be swapped at a partition */ +/* switch; open-coded register writes cannot. */ +/* */ +/**************************************************************************/ + +#ifndef MPU_H +#define MPU_H + +/* Access permissions, PRBAR.AP (bits [3:2]). + * + * These values were CALIBRATED AGAINST THE HARDWARE, not copied from a + * reference, because the widely-published Armv8-R AArch64 macro set has the + * two bits the other way round (its "read-only, no EL0 access" is 0x2). + * Programming four disjoint regions, one per encoding, and attempting a + * privileged write to each gave: + * + * AP=0b00 write allowed AP=0b01 write faulted + * AP=0b10 write allowed AP=0b11 write faulted + * + * so the low bit is read-only and the high bit grants EL0 access. Using the + * AArch64 ordering here silently produces writable "read-only" regions: the + * MPU still enforces region coverage, so everything appears to work and only + * an explicit write-permission test exposes it. Re-calibrate on S32Z280 + * silicon before trusting these values there. + */ + +#define MPU_AP_RW_EL1 0U /* EL1 read/write, EL0 no access */ +#define MPU_AP_RO_EL1 1U /* EL1 read-only, EL0 no access */ +#define MPU_AP_RW_EL1_EL0 2U /* EL1 read/write, EL0 read/write */ +#define MPU_AP_RO_EL1_EL0 3U /* EL1 read-only, EL0 read-only */ + +/* Shareability, PRBAR.SH. */ + +#define MPU_SH_NON 0U +#define MPU_SH_OUTER 2U +#define MPU_SH_INNER 3U + +/* Attribute indices into MAIR, PRLAR.AttrIndx. */ + +#define MPU_ATTR_NORMAL_WB 0U /* Normal, inner/outer write-back */ +#define MPU_ATTR_DEVICE 1U /* Device-nGnRnE */ + +/* One protection region. The limit is inclusive, matching the hardware. */ + +typedef struct MPU_REGION_STRUCT +{ + unsigned long mpu_region_base; + unsigned long mpu_region_limit; + unsigned char mpu_region_ap; + unsigned char mpu_region_execute_never; + unsigned char mpu_region_shareability; + unsigned char mpu_region_attr_index; + const char *mpu_region_name; +} MPU_REGION; + +/* Number of regions this implementation provides, from MPUIR. */ + +unsigned int mpu_region_count(void); + +/* Program the region table, then enable the MPU and the caches. Returns + the number of regions programmed, or 0 if the table does not fit. */ + +unsigned int mpu_init(void); + +/* True once SCTLR reports the MPU and both caches enabled. */ + +unsigned int mpu_is_enabled(void); +unsigned int mpu_caches_enabled(void); + +/* The active table, for reporting. */ + +const MPU_REGION *mpu_region_table(unsigned int *count_ptr); + +/* Read back what the hardware holds for one region, so that programming can + be verified rather than assumed. */ + +void mpu_read_region(unsigned int index, unsigned long *prbar_ptr, + unsigned long *prlar_ptr); + +#endif /* MPU_H */ diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/platform.h b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/platform.h new file mode 100644 index 000000000..913befdb8 --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/platform.h @@ -0,0 +1,82 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* BOARD SUPPORT RELEASE */ +/* */ +/* platform.h Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frédéric Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Memory map for the Armv8-R AEM FVP (BaseR platform). */ +/* */ +/* Every address here was VERIFIED IN-MODEL, not taken from */ +/* documentation or recollection. The BaseR map is the Base platform */ +/* map with its two 2 GB halves swapped (so a Base peripheral at X */ +/* below 0x80000000 appears at X + 0x80000000), and each base was then */ +/* confirmed by reading its identification register: */ +/* */ +/* PL011 UART0 peripheral ID 0x11,0x10,0x24,0x00, and a marker */ +/* written to it appeared on the host console */ +/* GIC GICD_PIDR2 = 0x3B and GICR_PIDR2 = 0x3B, i.e. */ +/* architecture revision 3 = GICv3 */ +/* Counter CNTFID0 = 0x05F5E100 = 100 MHz, matching the */ +/* model's bp.refcounter.base_frequency parameter */ +/* */ +/* Values are written without integer suffixes so that this header can */ +/* also be included from preprocessed assembly. */ +/* */ +/**************************************************************************/ + +#ifndef PLATFORM_H +#define PLATFORM_H + +/* PL011 UART0. */ + +#define PL011_UART0_BASE 0x9C090000 + +/* GICv3. A redistributor is two consecutive 64 KB frames per core: the RD + frame carries the identification and wake-up registers, the SGI frame the + per-interrupt enable, priority and configuration registers for SGIs/PPIs. */ + +#define GICD_BASE 0xAF000000 +#define GICR_RD_BASE 0xAF100000 +#define GICR_SGI_BASE 0xAF110000 + +/* System counter control frame (CNTControlBase). */ + +#define CNT_CONTROL_BASE 0xAA430000 + +/* The model resets CNTFRQ to zero and leaves the system counter stopped -- + bp.refcounter.non_arch_start_at_default=0, documented as "firmware is + expected to enable the timer at boot time". This BSP therefore programs + both. The value is CNTFID0 read back from the counter control frame. */ + +#define SYSTEM_COUNTER_HZ 100000000 + +#ifndef __ASSEMBLER__ + +/* 32-bit device register access. */ + +#define REG32(address) (*(volatile unsigned long *)(unsigned long)(address)) + +#endif /* __ASSEMBLER__ */ + +#endif /* PLATFORM_H */ diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/test/run_fvp_test.py b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/test/run_fvp_test.py new file mode 100644 index 000000000..356a6a102 --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/test/run_fvp_test.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +"""Run a Cortex-R52 image on the Armv8-R AEM FVP and assert its result. + +This runner is deliberately much simpler than the RISC-V/QEMU one, because +the platform allows it: the FVP exposes only an Iris server and no GDB stub, +so there is nothing to script through a debugger, and every image terminates +itself with a semihosting SYS_EXIT. The runner therefore just launches the +model, captures its console, and judges the self-reported result. + +A missing result line is treated as FAILURE, never as success: a silent hang +or a crash before the first check must not be able to masquerade as a pass. +""" + +import argparse +import subprocess +import sys + +PASS_MARK = "ALL CHECKS PASSED" +FAIL_MARK = "RESULT: FAILED" +FAULT_MARK = "[FAULT]" + + +def as_text(stream): + """Normalise a captured stream to str. + + subprocess.TimeoutExpired carries its partial output undecoded even when + the call used text=True, so the timeout path can hand us bytes where the + normal path hands us str. Decoding defensively here keeps the hang + report readable instead of raising TypeError inside the error handler. + """ + if stream is None: + return "" + if isinstance(stream, bytes): + return stream.decode(errors="replace") + return stream + + +def run(elf, fvp, timeout): + command = [ + fvp, + "-C", "cluster0.NUM_CORES=1", + "-C", "bp.vis.disable_visualisation=1", + "-C", "bp.terminal_0.start_telnet=0", + # Route UART0 to stdout so PL011-console images are captured too. + # Harmless for semihosting images, which do not touch the UART. + "-C", "bp.pl011_uart0.out_file=-", + "-C", "bp.pl011_uart0.unbuffered_output=1", + "-a", elf, + ] + + print("Running:", " ".join(command), flush=True) + + try: + completed = subprocess.run( + command, capture_output=True, text=True, timeout=timeout + ) + output = as_text(completed.stdout) + as_text(completed.stderr) + except subprocess.TimeoutExpired as expired: + print(as_text(expired.stdout) + as_text(expired.stderr)) + print( + f"FAIL: the simulation did not terminate within {timeout}s. " + "Every image is expected to exit through semihosting SYS_EXIT, " + "so this is a hang, not a slow run.", + file=sys.stderr, + ) + return 1 + + print(output) + + if FAULT_MARK in output: + faults = [line for line in output.splitlines() if FAULT_MARK in line] + print("FAIL: unhandled exception reported:", file=sys.stderr) + for line in faults: + print(" " + line.strip(), file=sys.stderr) + return 1 + + if FAIL_MARK in output: + print("FAIL: the image reported failing checks.", file=sys.stderr) + return 1 + + if PASS_MARK not in output: + print( + "FAIL: no result line found. The image neither passed nor " + "reported failure, so it did not reach its checks.", + file=sys.stderr, + ) + return 1 + + print("PASS") + return 0 + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--elf", required=True, help="image to run") + parser.add_argument("--fvp", default="FVP_BaseR_AEMv8R", help="model binary") + parser.add_argument( + "--timeout", type=int, default=180, help="seconds before declaring a hang" + ) + arguments = parser.parse_args() + + return run(arguments.elf, arguments.fvp, arguments.timeout) + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/timer.c b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/timer.c new file mode 100644 index 000000000..eac0b3dc1 --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/timer.c @@ -0,0 +1,174 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* BOARD SUPPORT RELEASE */ +/* */ +/* timer.c Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frédéric Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Arm generic timer tick for Cortex-R52 on the Armv8-R AEM FVP. */ +/* */ +/* Two model behaviours make this longer than a bare timer setup, both */ +/* confirmed by reading the hardware rather than assumed: */ +/* */ +/* 1. The system counter is STOPPED at reset (CNTCR = 0, CNTCV = 0). */ +/* The model documents that firmware is expected to start it, so */ +/* the counter control frame is enabled here. Without this the */ +/* timer never counts and no tick is ever delivered. */ +/* 2. CNTFRQ resets to ZERO. It is writable only at the highest */ +/* implemented exception level, so entry.S programs it at EL2; */ +/* this file only reads it. Deriving the tick interval from an */ +/* unprogrammed CNTFRQ would divide by zero. */ +/* */ +/* EL1 access to the physical timer and counter also depends on */ +/* CNTHCTL.PL1PCEN/PL1PCTEN, which reset disabled and are set by */ +/* entry.S at EL2; otherwise these accesses would trap to EL2. */ +/* */ +/* MISRA C:2012 deviations (justified) */ +/* */ +/* Directive 4.3 -- the generic timer is only reachable through CP15 */ +/* registers; every such access is encapsulated in an accessor below.*/ +/* */ +/**************************************************************************/ + +#include "tx_api.h" +#include "platform.h" +#include "timer.h" + +/* Counter control frame (CNTControlBase). */ + +#define CNTCR 0x0000U +#define CNTCR_EN (1UL << 0) +#define CNTSR 0x0004U + +/* CNTP_CTL bits. */ + +#define CNTP_CTL_ENABLE (1UL << 0) +#define CNTP_CTL_IMASK (1UL << 1) + +static unsigned long tick_interval; + + +/**************************************************************************/ +/* Generic timer accessors (AArch32 CP15). */ +/**************************************************************************/ + +static unsigned long read_cntfrq(void) +{ + unsigned long value; + __asm__ volatile("mrc p15, 0, %0, c14, c0, 0" : "=r"(value)); + return value; +} + +static void write_cntp_tval(unsigned long value) +{ + __asm__ volatile("mcr p15, 0, %0, c14, c2, 0" : : "r"(value) : "memory"); +} + +static void write_cntp_ctl(unsigned long value) +{ + __asm__ volatile("mcr p15, 0, %0, c14, c2, 1" : : "r"(value) : "memory"); +} + +static unsigned long long read_cntpct(void) +{ + unsigned long low; + unsigned long high; + + __asm__ volatile("mrrc p15, 0, %0, %1, c14" : "=r"(low), "=r"(high)); + + return ((unsigned long long) high << 32) | (unsigned long long) low; +} + + +/**************************************************************************/ +/* timer_frequency */ +/**************************************************************************/ + +unsigned long timer_frequency(void) +{ + return read_cntfrq(); +} + + +/**************************************************************************/ +/* timer_counter */ +/**************************************************************************/ + +unsigned long long timer_counter(void) +{ + return read_cntpct(); +} + + +/**************************************************************************/ +/* timer_counter_enabled */ +/**************************************************************************/ + +unsigned int timer_counter_enabled(void) +{ + return ((REG32(CNT_CONTROL_BASE + CNTCR) & CNTCR_EN) != 0UL) ? 1U : 0U; +} + + +/**************************************************************************/ +/* timer_reload */ +/**************************************************************************/ + +void timer_reload(void) +{ + /* Writing CNTP_TVAL restarts the down-count, which also deasserts the + level-sensitive timer output. */ + + write_cntp_tval(tick_interval); +} + + +/**************************************************************************/ +/* timer_init */ +/**************************************************************************/ + +void timer_init(void) +{ + unsigned long frequency; + + /* Start the system counter -- it is stopped at reset on this model. */ + + REG32(CNT_CONTROL_BASE + CNTCR) |= CNTCR_EN; + + /* Derive the tick interval. CNTFRQ was programmed at EL2; fall back to + the known counter frequency rather than dividing by zero should that + ever not have happened. */ + + frequency = read_cntfrq(); + if (frequency == 0UL) + { + frequency = (unsigned long) SYSTEM_COUNTER_HZ; + } + + tick_interval = frequency / TX_TIMER_TICKS_PER_SECOND; + + /* Enable the timer, unmasked, and arm the first interval. */ + + write_cntp_tval(tick_interval); + write_cntp_ctl(CNTP_CTL_ENABLE); +} diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/timer.h b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/timer.h new file mode 100644 index 000000000..5b7968a3b --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/timer.h @@ -0,0 +1,67 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* BOARD SUPPORT RELEASE */ +/* */ +/* timer.h Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frédéric Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Arm generic timer tick for Cortex-R52. */ +/* */ +/**************************************************************************/ + +#ifndef TIMER_H +#define TIMER_H + +/* PPI driven by the EL1 physical timer. + * + * This was not assumed. Bring-up enabled the entire PPI range 25-31 and + * recorded whichever INTID came back from ICC_IAR1; the model drove 30, which + * matches the architectural assignment for the EL1 physical timer. Only that + * line is enabled now, and irq_dispatch.c still records any other INTID so a + * different platform assignment would be reported rather than silently + * mishandled. Re-verify when moving to S32Z2 silicon. */ + +#define TIMER_PPI_INTID 30U + +/* Enable the system counter, then start the periodic tick at + TX_TIMER_TICKS_PER_SECOND. gicv3_init() must have run first. */ + +void timer_init(void); + +/* Re-arm the timer for the next tick. Called from the interrupt path. */ + +void timer_reload(void); + +/* CNTFRQ as programmed by entry.S at EL2. */ + +unsigned long timer_frequency(void); + +/* Current 64-bit physical counter value, for verifying the counter runs. */ + +unsigned long long timer_counter(void); + +/* True once the counter control frame reports the counter enabled. */ + +unsigned int timer_counter_enabled(void); + +#endif /* TIMER_H */ diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/tx_initialize_low_level.S b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/tx_initialize_low_level.S new file mode 100644 index 000000000..cb473a43e --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/tx_initialize_low_level.S @@ -0,0 +1,102 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Initialize */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .arch armv8-r + .syntax unified + .arm + + .global _tx_thread_system_stack_ptr + .global _tx_initialize_unused_memory + + .text + .balign 4 + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_initialize_low_level Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frédéric Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Low-level initialization for Cortex-R52 on the Armv8-R AEM FVP. */ +/* Called by _tx_initialize_kernel_enter with the processor already in */ +/* Supervisor mode at EL1. */ +/* */ +/* This is deliberately shorter than the A-profile reference ports: */ +/* entry.S has already given every AArch32 mode its own stack from */ +/* dedicated linker-script regions, so there is no stack carving to do */ +/* here and no run-time stack-overlap check to perform -- the linker */ +/* guarantees the regions do not overlap. */ +/* */ +/* When built with TX_R52_USE_THREADX_IRQ, board_init() brings up GICv3*/ +/* and the generic timer tick here. That is safe this early because */ +/* interrupts stay masked until _tx_thread_schedule enables them, so no*/ +/* tick can be delivered before the kernel is ready to take one. */ +/* Without that symbol (the M2 cooperative demo) no tick is created, */ +/* which keeps M2 free of any interrupt dependency. */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_initialize_kernel_enter ThreadX entry function */ +/* */ +/**************************************************************************/ + + .global _tx_initialize_low_level + .type _tx_initialize_low_level, %function +_tx_initialize_low_level: + + /* Record the system stack. The interrupt path uses it when an + exception arrives while no thread is running. */ + + ldr r0, =__sys_stack_top + ldr r1, =_tx_thread_system_stack_ptr + str r0, [r1] + + /* Publish the first free memory address for tx_application_define. + _end sits above the image, .bss and every per-mode stack. Round up + to an 8-byte boundary so pool control blocks are aligned. */ + + ldr r0, =_end + add r0, r0, #7 + bic r0, r0, #7 + ldr r1, =_tx_initialize_unused_memory + str r0, [r1] + +#ifdef TX_R52_USE_THREADX_IRQ + + /* Bring up the interrupt controller and the periodic tick. */ + + push {lr} + bl board_init + pop {lr} + +#endif + + bx lr diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/uart_pl011.c b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/uart_pl011.c new file mode 100644 index 000000000..b4c78127d --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/uart_pl011.c @@ -0,0 +1,127 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* BOARD SUPPORT RELEASE */ +/* */ +/* uart_pl011.c Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frédéric Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* PL011 UART output for the Armv8-R AEM FVP, used as the console when */ +/* the image is built with TX_R52_CONSOLE_PL011. */ +/* */ +/* Semihosting remains the default because it needs no peripheral at */ +/* all, which keeps early bring-up independent of the memory map. The */ +/* UART matters because it is what real silicon will use: exercising it*/ +/* here means the S32Z280 console differs only in its base address and */ +/* clocking, not in structure. */ +/* */ +/* The model leaves UART0 disabled at reset */ +/* (bp.pl011_uart0.uart_enable=0), so the control register must be */ +/* written before the first character. Baud rate is left alone: the */ +/* model does not emulate serial timing, and inventing a divisor here */ +/* would only be misleading. */ +/* */ +/* MISRA C:2012 deviations (justified) */ +/* */ +/* Rule 11.4/11.6 -- casting integer addresses to volatile pointers is */ +/* inherent to memory-mapped device access; confined to REG32. */ +/* */ +/**************************************************************************/ + +#include "platform.h" +#include "uart_pl011.h" + +/* PL011 register offsets. */ + +#define UART_DR 0x000U /* data */ +#define UART_FR 0x018U /* flags */ +#define UART_LCR_H 0x02CU /* line control */ +#define UART_CR 0x030U /* control */ + +#define UART_FR_TXFF (1UL << 5) /* transmit FIFO full */ + +#define UART_LCR_H_WLEN_8 (3UL << 5) /* 8 data bits */ +#define UART_LCR_H_FEN (1UL << 4) /* enable FIFOs */ + +#define UART_CR_UARTEN (1UL << 0) /* UART enable */ +#define UART_CR_TXE (1UL << 8) /* transmit enable */ +#define UART_CR_RXE (1UL << 9) /* receive enable */ + + +/**************************************************************************/ +/* pl011_init */ +/**************************************************************************/ + +void pl011_init(void) +{ + /* Disable while reconfiguring, as the programming model requires. */ + + REG32(PL011_UART0_BASE + UART_CR) = 0UL; + + REG32(PL011_UART0_BASE + UART_LCR_H) = UART_LCR_H_WLEN_8 | UART_LCR_H_FEN; + + REG32(PL011_UART0_BASE + UART_CR) = + UART_CR_UARTEN | UART_CR_TXE | UART_CR_RXE; +} + + +/**************************************************************************/ +/* pl011_putc */ +/**************************************************************************/ + +void pl011_putc(char character) +{ + /* Expand newlines so the host console shows discrete lines. */ + + if (character == '\n') + { + pl011_putc('\r'); + } + + while ((REG32(PL011_UART0_BASE + UART_FR) & UART_FR_TXFF) != 0UL) + { + /* Wait for room in the transmit FIFO. */ + } + + REG32(PL011_UART0_BASE + UART_DR) = (unsigned long) (unsigned char) character; +} + + +/**************************************************************************/ +/* pl011_puts */ +/**************************************************************************/ + +void pl011_puts(const char *string_ptr) +{ + const char *cursor = string_ptr; + + if (cursor == 0) + { + return; + } + + while (*cursor != '\0') + { + pl011_putc(*cursor); + cursor++; + } +} diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/uart_pl011.h b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/uart_pl011.h new file mode 100644 index 000000000..89e416ce8 --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/uart_pl011.h @@ -0,0 +1,47 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* BOARD SUPPORT RELEASE */ +/* */ +/* uart_pl011.h Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frédéric Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* PL011 UART console backend for the Armv8-R AEM FVP. */ +/* */ +/**************************************************************************/ + +#ifndef UART_PL011_H +#define UART_PL011_H + +/* Configure and enable UART0. The model leaves it disabled at reset. */ + +void pl011_init(void); + +/* Send one character, expanding a newline into CR LF. */ + +void pl011_putc(char character); + +/* Send a NUL-terminated string. */ + +void pl011_puts(const char *string_ptr); + +#endif /* UART_PL011_H */ diff --git a/ports/cortex_r52/gnu/inc/tx_port.h b/ports/cortex_r52/gnu/inc/tx_port.h new file mode 100644 index 000000000..7feb2300a --- /dev/null +++ b/ports/cortex_r52/gnu/inc/tx_port.h @@ -0,0 +1,338 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * 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 + **************************************************************************/ +// Some portions generated by Claude Code (Opus 5). + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Port Specific */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* PORT SPECIFIC C INFORMATION RELEASE */ +/* */ +/* tx_port.h Cortex-R52/GNU */ +/* 6.5.2 */ +/* */ +/* AUTHOR */ +/* */ +/* Frédéric Desbiens, Eclipse Foundation */ +/* */ +/* Derived from the Cortex-R5/GNU port originally written by */ +/* William E. Lamie, Microsoft Corporation. */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains data type definitions that make the ThreadX */ +/* real-time kernel function identically on a variety of different */ +/* processor architectures. For example, the size or number of bits */ +/* in an "int" data type vary between microprocessor architectures and */ +/* even C compilers for the same microprocessor. ThreadX does not */ +/* directly use native C data types. Instead, ThreadX creates its */ +/* own special types that can be mapped to actual data types by this */ +/* file to guarantee consistency in the interface and functionality. */ +/* */ +/**************************************************************************/ + +#ifndef TX_PORT_H +#define TX_PORT_H + + +/* Determine if the optional ThreadX user define file should be used. */ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE + + +/* Yes, include the user defines in tx_user.h. The defines in this file may + alternately be defined on the command line. */ + +#include "tx_user.h" +#endif + + +/* Define compiler library include files. */ + +#include +#include + + +/* Define ThreadX basic types for this port. */ + +#define VOID void +typedef char CHAR; +typedef unsigned char UCHAR; +typedef int INT; +typedef unsigned int UINT; +typedef long LONG; +typedef unsigned long ULONG; +typedef short SHORT; +typedef unsigned short USHORT; + + +/* Define the priority levels for ThreadX. Legal values range + from 32 to 1024 and MUST be evenly divisible by 32. */ + +#ifndef TX_MAX_PRIORITIES +#define TX_MAX_PRIORITIES 32 +#endif + + +/* Define the minimum stack for a ThreadX thread on this processor. If the size supplied during + thread creation is less than this value, the thread create call will return an error. */ + +#ifndef TX_MINIMUM_STACK +#define TX_MINIMUM_STACK 200 /* Minimum stack size for this port */ +#endif + + +/* Define the system timer thread's default stack size and priority. These are only applicable + if TX_TIMER_PROCESS_IN_ISR is not defined. */ + +#ifndef TX_TIMER_THREAD_STACK_SIZE +#define TX_TIMER_THREAD_STACK_SIZE 1024 /* Default timer thread stack size */ +#endif + +#ifndef TX_TIMER_THREAD_PRIORITY +#define TX_TIMER_THREAD_PRIORITY 0 /* Default timer thread priority */ +#endif + + +/* Define various constants for the ThreadX ARM port. */ + +#ifdef TX_ENABLE_FIQ_SUPPORT +#define TX_INT_DISABLE 0xC0 /* Disable IRQ & FIQ interrupts */ +#else +#define TX_INT_DISABLE 0x80 /* Disable IRQ interrupts */ +#endif +#define TX_INT_ENABLE 0x00 /* Enable IRQ interrupts */ + + +/* Define the clock source for trace event entry time stamp. The following two item are port specific. + For example, if the time source is at the address 0x0a800024 and is 16-bits in size, the clock + source constants would be: + +#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024) +#define TX_TRACE_TIME_MASK 0x0000FFFFUL + +*/ + +#ifndef TX_TRACE_TIME_SOURCE +#define TX_TRACE_TIME_SOURCE ++_tx_trace_simulated_time +#endif +#ifndef TX_TRACE_TIME_MASK +#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL +#endif + + +/* Define the port specific options for the _tx_build_options variable. This variable indicates + how the ThreadX library was built. */ + +#ifdef TX_ENABLE_FIQ_SUPPORT +#define TX_FIQ_ENABLED 1 +#else +#define TX_FIQ_ENABLED 0 +#endif + +#ifdef TX_ENABLE_IRQ_NESTING +#define TX_IRQ_NESTING_ENABLED 2 +#else +#define TX_IRQ_NESTING_ENABLED 0 +#endif + +#ifdef TX_ENABLE_FIQ_NESTING +#define TX_FIQ_NESTING_ENABLED 4 +#else +#define TX_FIQ_NESTING_ENABLED 0 +#endif + +#define TX_PORT_SPECIFIC_BUILD_OPTIONS TX_FIQ_ENABLED | TX_IRQ_NESTING_ENABLED | TX_FIQ_NESTING_ENABLED + + +/* Define the in-line initialization constant so that modules with in-line + initialization capabilities can prevent their initialization from being + a function call. */ + +#define TX_INLINE_INITIALIZATION + + +/* Determine whether or not stack checking is enabled. By default, ThreadX stack checking is + disabled. When the following is defined, ThreadX thread stack checking is enabled. If stack + checking is enabled (TX_ENABLE_STACK_CHECKING is defined), the TX_DISABLE_STACK_FILLING + define is negated, thereby forcing the stack fill which is necessary for the stack checking + logic. */ + +#ifdef TX_ENABLE_STACK_CHECKING +#undef TX_DISABLE_STACK_FILLING +#endif + + +/* Define the TX_THREAD control block extensions for this port. The main reason + for the multiple macros is so that backward compatibility can be maintained with + existing ThreadX kernel awareness modules. */ + +/* TX_THREAD_EXTENSION_2 carries the per-thread VFP enable flag used by the + lazy floating-point save and restore in tx_thread_schedule.S, + tx_thread_system_return.S and tx_thread_context_restore.S. + + It is defined UNCONDITIONALLY, not under TX_ENABLE_VFP_SUPPORT, and that is + deliberate: the assembly reaches this field through a hard-coded structure + offset, so making the field conditional would move every following member + between build configurations and leave the offset correct in only one of + them. Keeping it always present makes the layout independent of the + floating-point build options. The offset is checked at compile time in + tx_port_offset_check.c, which turns a wrong offset into a build failure + instead of silent corruption of an unrelated thread field. */ + +#define TX_THREAD_EXTENSION_0 +#define TX_THREAD_EXTENSION_1 +#define TX_THREAD_EXTENSION_2 ULONG tx_thread_vfp_enable; +#define TX_THREAD_EXTENSION_3 + + +/* Define the port extensions of the remaining ThreadX objects. */ + +#define TX_BLOCK_POOL_EXTENSION +#define TX_BYTE_POOL_EXTENSION +#define TX_EVENT_FLAGS_GROUP_EXTENSION +#define TX_MUTEX_EXTENSION +#define TX_QUEUE_EXTENSION +#define TX_SEMAPHORE_EXTENSION +#define TX_TIMER_EXTENSION + + +/* Define the user extension field of the thread control block. Nothing + additional is needed for this port so it is defined as white space. */ + +#ifndef TX_THREAD_USER_EXTENSION +#define TX_THREAD_USER_EXTENSION +#endif + + +/* Define the macros for processing extensions in tx_thread_create, tx_thread_delete, + tx_thread_shell_entry, and tx_thread_terminate. */ + + +#define TX_THREAD_CREATE_EXTENSION(thread_ptr) +#define TX_THREAD_DELETE_EXTENSION(thread_ptr) +#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) +#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) + + +/* Define the ThreadX object creation extensions for remaining objects. */ + +#define TX_BLOCK_POOL_CREATE_EXTENSION(pool_ptr) +#define TX_BYTE_POOL_CREATE_EXTENSION(pool_ptr) +#define TX_EVENT_FLAGS_GROUP_CREATE_EXTENSION(group_ptr) +#define TX_MUTEX_CREATE_EXTENSION(mutex_ptr) +#define TX_QUEUE_CREATE_EXTENSION(queue_ptr) +#define TX_SEMAPHORE_CREATE_EXTENSION(semaphore_ptr) +#define TX_TIMER_CREATE_EXTENSION(timer_ptr) + + +/* Define the ThreadX object deletion extensions for remaining objects. */ + +#define TX_BLOCK_POOL_DELETE_EXTENSION(pool_ptr) +#define TX_BYTE_POOL_DELETE_EXTENSION(pool_ptr) +#define TX_EVENT_FLAGS_GROUP_DELETE_EXTENSION(group_ptr) +#define TX_MUTEX_DELETE_EXTENSION(mutex_ptr) +#define TX_QUEUE_DELETE_EXTENSION(queue_ptr) +#define TX_SEMAPHORE_DELETE_EXTENSION(semaphore_ptr) +#define TX_TIMER_DELETE_EXTENSION(timer_ptr) + + +/* Determine if the ARM architecture has the CLZ instruction. This is available on + architectures v5 and above. If available, redefine the macro for calculating the + lowest bit set. */ + +#if __TARGET_ARCH_ARM > 4 + +#ifndef __thumb__ + +#define TX_LOWEST_SET_BIT_CALCULATE(m, b) m = m & ((ULONG) (-((LONG) m))); \ + asm volatile (" CLZ %0,%1 ": "=r" (b) : "r" (m) ); \ + b = 31 - b; +#endif +#endif + + +/* Define ThreadX interrupt lockout and restore macros for protection on + access of critical kernel information. The restore interrupt macro must + restore the interrupt posture of the running thread prior to the value + present prior to the disable macro. In most cases, the save area macro + is used to define a local function save area for the disable and restore + macros. */ + +/* Per-thread floating-point control. Implemented in tx_thread_schedule.S and + available only when the library is built with TX_ENABLE_VFP_SUPPORT. A + thread's floating-point context is saved and restored lazily: only threads + that have called tx_thread_vfp_enable() pay for it. */ + +#ifdef TX_ENABLE_VFP_SUPPORT +void tx_thread_vfp_enable(void); +void tx_thread_vfp_disable(void); +#endif + + +#ifdef __thumb__ + +unsigned int _tx_thread_interrupt_disable(void); +unsigned int _tx_thread_interrupt_restore(UINT old_posture); + + +#define TX_INTERRUPT_SAVE_AREA UINT interrupt_save; + +#define TX_DISABLE interrupt_save = _tx_thread_interrupt_disable(); +#define TX_RESTORE _tx_thread_interrupt_restore(interrupt_save); + +#else + +#define TX_INTERRUPT_SAVE_AREA UINT interrupt_save; + +#ifdef TX_ENABLE_FIQ_SUPPORT +#define TX_DISABLE asm volatile (" MRS %0,CPSR; CPSID if ": "=r" (interrupt_save) ); +#else +#define TX_DISABLE asm volatile (" MRS %0,CPSR; CPSID i ": "=r" (interrupt_save) ); +#endif + +#define TX_RESTORE asm volatile (" MSR CPSR_c,%0 "::"r" (interrupt_save) ); + +#endif + + +/* Define the interrupt lockout macros for each ThreadX object. */ + +#define TX_BLOCK_POOL_DISABLE TX_DISABLE +#define TX_BYTE_POOL_DISABLE TX_DISABLE +#define TX_EVENT_FLAGS_GROUP_DISABLE TX_DISABLE +#define TX_MUTEX_DISABLE TX_DISABLE +#define TX_QUEUE_DISABLE TX_DISABLE +#define TX_SEMAPHORE_DISABLE TX_DISABLE + + +/* Define the version ID of ThreadX. This may be used by the application.*/ + +#ifdef TX_THREAD_INIT +CHAR _tx_version_id[] = + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadXCortex-R52/GNU Version 6.5.1.202602a *"; +#else +extern CHAR _tx_version_id[]; +#endif + + +#endif + diff --git a/ports/cortex_r52/gnu/readme_threadx.txt b/ports/cortex_r52/gnu/readme_threadx.txt new file mode 100644 index 000000000..ccc2c8d60 --- /dev/null +++ b/ports/cortex_r52/gnu/readme_threadx.txt @@ -0,0 +1,172 @@ + Eclipse ThreadX for Cortex-R52 + Using GNU Tools + + +1. Building the ThreadX run-time Library + +The port is built with CMake and Ninja. From the repository root: + + cmake -B build_r52 -G Ninja \ + -DCMAKE_TOOLCHAIN_FILE=cmake/cortex_r52.cmake . + ninja -C build_r52 + +This produces libthreadx.a for Cortex-R52 in AArch32 state. The toolchain +file pins the reference cross compiler by absolute path so that the build +does not depend on PATH ordering; override it with + + -DARM_TOOLCHAIN_PATH= + +Note this is the first R-profile port in the tree with a working CMake +build. cmake/cortex_a9.cmake exists but ports/cortex_a9/gnu/CMakeLists.txt +is empty, so no A- or R-profile port could previously be built this way. + + +2. Build options + + -DTX_R52_FLOAT_ABI=soft|hard floating-point ABI, default soft + -DTX_R52_ENABLE_VFP=ON lazy VFP context save and restore + -DTX_R52_ENABLE_FIQ=ON FIQ support + -DTX_R52_ENABLE_IRQ_NESTING=ON nested IRQ support + -DTX_R52_ENABLE_FIQ_NESTING=ON nested FIQ support (requires the above) + -DTX_R52_BUILD_FVP_EXAMPLE=ON build the Armv8-R AEM FVP examples + -DTX_R52_ENABLE_MPU=ON PMSAv8-R protection and caches + -DTX_R52_CONSOLE_PL011=ON console on the PL011 UART, not semihosting + +TX_R52_ENABLE_VFP is PUBLIC: it changes which registers the context switch +saves, so the library and the application must agree. Pair it with +TX_R52_FLOAT_ABI=hard, otherwise the compiler emits no floating-point +instructions and the VFP path is never exercised. + +Cortex-R52 always implements at least a single-precision FPU. GCC rejects +"-mcpu=cortex-r52+nofp" and offers only "+nofp.dp", so the soft-float +baseline selects the soft ABI rather than removing the FPU. + + +3. Example builds and tests + + cmake -B build_r52 -G Ninja \ + -DCMAKE_TOOLCHAIN_FILE=cmake/cortex_r52.cmake \ + -DTX_R52_BUILD_FVP_EXAMPLE=ON . + ninja -C build_r52 boot_check.elf demo_m2.elf demo_m3.elf \ + demo_threadx.elf demo_mpu.elf + ctest --test-dir build_r52 + +The images target the free Armv8-R AEM FVP (FVP_BaseR_AEMv8R): + + boot_check.elf EL2 configuration, the drop to EL1 and the EL2 seam + demo_m2.elf cooperative context switching, no interrupts + demo_m3.elf generic timer tick, GICv3 and preemption + demo_threadx.elf the standard eight-thread demo plus verification + demo_mpu.elf PMSAv8-R protection and cache enable + demo_m5.elf lazy VFP context save (needs TX_R52_ENABLE_VFP) + +Each image reports its own result and terminates the model through the +semihosting SYS_EXIT call, so no host-side timeout is needed. The test +runner treats a missing result line as failure, so a hang cannot pass. + + +4. System Initialization + +The entry point is _start in the example build's entry.S. Cortex-R52 +always implements EL2 and resets into it, so the reset path configures EL2 +first, installs both the EL2 and EL1 vector tables, and only then drops to +EL1 (Supervisor mode) to run the kernel. Define TX_R52_BOOT_AT_EL1 to skip +the EL2 stage where an earlier boot stage or a vendor EL2 monitor has +already dropped privilege. + +Work that must happen at EL2, because the registers are inaccessible or +read-only later: + + CNTFRQ the model resets it to zero and it is writable + only at the highest implemented exception level + CNTHCTL.PL1PCTEN/PL1PCEN otherwise every EL1 access to CNTPCT or CNTP_* + traps to EL2 + ICC_HSRE.SRE/Enable lets EL1 reach the GICv3 CPU interface through + its system registers + HCR.HCD cleared enables HVC, which the EL2 seam depends on + HCPTR.TCP10/TCP11 cleared lets EL1 use the FPU + +_tx_initialize_low_level records the system stack and publishes the first +free memory address. It is shorter than the A-profile equivalents because +entry.S has already given every AArch32 mode its own stack from dedicated +linker-script regions, so there is no stack carving and no run-time overlap +check to perform. With TX_R52_USE_THREADX_IRQ it also calls board_init to +bring up GICv3 and the periodic tick; that is safe this early because +interrupts stay masked until _tx_thread_schedule enables them. + + +5. Interrupt Handling + +The EL1 IRQ vector branches directly into _tx_thread_context_save, which +returns to __tx_irq_processing_return. A C dispatcher acknowledges the +interrupt, re-arms the timer, calls _tx_timer_interrupt and finishes with +_tx_thread_context_restore. The branch must be a plain B: context save +adjusts lr itself to locate the point of interrupt. + +Exceptions routed to EL2 from EL1 or EL0 all arrive at the Hyp Trap Entry, +vector offset 0x14, not at 0x08. Offsets 0x04 to 0x10 are exceptions taken +from Hyp mode itself, and 0x08 is specifically SVC from Hyp. The handler +therefore decodes HSR.EC and dispatches; it services HVC (EC 0x12) and +reports anything else. That single funnel is the seam that partitioning +work extends. + +Every unhandled vector identifies itself over the console. The FVP exposes +only an Iris server and no GDB stub, which makes a self-identifying fault +the primary debugging tool for this port. + + +6. Floating Point + +Floating-point context is saved lazily: only threads that call +tx_thread_vfp_enable() pay for it. Note that function sets a per-thread +software flag for the context switch; it does not enable the FPU. Enabling +the hardware is the board support package's responsibility -- CPACR grants +CP10/CP11 access and FPEXC.EN enables execution, both of which reset +disabled. The example build does this in entry.S under __ARM_FP. + +The flag lives in TX_THREAD_EXTENSION_2 and is reached from assembly by the +hard-coded offset 144. It is defined unconditionally rather than under +TX_ENABLE_VFP_SUPPORT so that the structure layout does not change with the +floating-point build options. tx_port_offset_check.c asserts that offset, +and the thread stack pointer and run counter offsets, at compile time: a +layout change becomes a build failure instead of silent corruption. + + +7. Memory Protection + +PMSAv8-R regions are described by a table rather than a sequence of +register writes, so that a region set can be swapped wholesale. The +example programs three regions -- code read-only and executable, all +writable memory non-executable, peripherals as Device -- and explicitly +disables the regions it does not use. + +Two cautions for anyone reusing this code on silicon: + + - The PRBAR.AP encoding used here was calibrated against the hardware. + The low bit is read-only and the high bit grants EL0 access, which is + the reverse of the widely-published Armv8-R AArch64 macro set. Getting + it wrong produces regions that report as read-only and accept writes, + because region coverage is still enforced: an unmapped address faults + while a "read-only" region does not. Re-calibrate before trusting + these values on a different implementation. + + - The code and data regions must not share a 64-byte granule. The + linker script separates them with ".data ALIGN(64) :" on the output + section. An assignment to the location counter between sections does + not advance a MEMORY region's allocation pointer, and an ALIGN at the + end of the preceding section does not extend it when no data follows, + so both of those leave writable data inside the read-only region. + + +8. Validation + +Functional validation is performed on the Armv8-R AEM FVP through the +images listed in section 3. Structural coverage is not claimed from this +port: the platform-agnostic regression suite runs on the host, which is +where the coverage instrumentation and the certification evidence live. + +The FVP is an architecture envelope model, not a Cortex-R52 +implementation -- it reports MIDR 0x410FD0F0, part number 0xD0F. It +validates architecture; implementation details such as MPU region count, +TCM, lockstep and RAS must be validated on silicon. Nothing in this port +is gated on MIDR. diff --git a/ports/cortex_r52/gnu/src/tx_port_offset_check.c b/ports/cortex_r52/gnu/src/tx_port_offset_check.c new file mode 100644 index 000000000..5e853fca6 --- /dev/null +++ b/ports/cortex_r52/gnu/src/tx_port_offset_check.c @@ -0,0 +1,86 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Port Specific */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +/**************************************************************************/ +/* */ +/* PORT SPECIFIC C INFORMATION RELEASE */ +/* */ +/* tx_port_offset_check.c Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frédéric Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Compile-time verification of the TX_THREAD structure offsets that */ +/* this port's assembly reaches by hard-coded displacement. The file */ +/* emits no code; it exists purely so that a layout change becomes a */ +/* build failure. */ +/* */ +/* Why this is needed: tx_thread_schedule.S, */ +/* tx_thread_system_return.S and tx_thread_context_restore.S read and */ +/* write the per-thread VFP enable flag as [thread, #144]. Nothing in */ +/* the toolchain connects that literal to the C structure, so adding a */ +/* member, enabling an option that adds one, or reordering the port */ +/* extensions would silently retarget those accesses at an unrelated */ +/* field -- corrupting thread state in a way that is extremely hard to */ +/* diagnose from the symptom. The offset was measured at 144 for the */ +/* default build and is asserted here. */ +/* */ +/* A negative array dimension is used rather than _Static_assert */ +/* because this project targets C99, where _Static_assert does not */ +/* exist. If an assertion below fails, the compiler reports a negative*/ +/* or zero-sized array for the named typedef. */ +/* */ +/**************************************************************************/ + +#include "tx_api.h" +#include + +/* Offset of the VFP enable flag as encoded in this port's assembly. + Overridable only so that the assertion itself can be tested. */ + +#ifndef TX_PORT_VFP_ENABLE_OFFSET +#define TX_PORT_VFP_ENABLE_OFFSET 144 +#endif + +typedef char +tx_port_assert_vfp_enable_offset_is_144[ + (offsetof(TX_THREAD, tx_thread_vfp_enable) == TX_PORT_VFP_ENABLE_OFFSET) + ? 1 : -1]; + +/* The stack pointer is read as [thread, #8] by tx_thread_schedule.S and + written by tx_thread_system_return.S, and the run counter as + [thread, #4]. Assert those too, since they are on the context-switch + critical path. */ + +typedef char +tx_port_assert_stack_ptr_offset_is_8[ + (offsetof(TX_THREAD, tx_thread_stack_ptr) == 8) ? 1 : -1]; + +typedef char +tx_port_assert_run_count_offset_is_4[ + (offsetof(TX_THREAD, tx_thread_run_count) == 4) ? 1 : -1]; diff --git a/ports/cortex_r52/gnu/src/tx_thread_context_restore.S b/ports/cortex_r52/gnu/src/tx_thread_context_restore.S new file mode 100644 index 000000000..ed6230714 --- /dev/null +++ b/ports/cortex_r52/gnu/src/tx_thread_context_restore.S @@ -0,0 +1,247 @@ +@/*************************************************************************** +@ * Copyright (c) 2024 Microsoft Corporation +@ * 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 +@ **************************************************************************/ +@ Some portions generated by Claude Code (Opus 5). +@ +@ +@/**************************************************************************/ +@/**************************************************************************/ +@/** */ +@/** ThreadX Component */ +@/** */ +@/** Thread */ +@/** */ +@/**************************************************************************/ +@/**************************************************************************/ +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + + .arm + +#ifdef TX_ENABLE_FIQ_SUPPORT +SVC_MODE = 0xD3 @ Disable IRQ/FIQ, SVC mode +IRQ_MODE = 0xD2 @ Disable IRQ/FIQ, IRQ mode +#else +SVC_MODE = 0x93 @ Disable IRQ, SVC mode +IRQ_MODE = 0x92 @ Disable IRQ, IRQ mode +#endif +@ + .global _tx_thread_system_state + .global _tx_thread_current_ptr + .global _tx_thread_execute_ptr + .global _tx_timer_time_slice + .global _tx_thread_schedule + .global _tx_thread_preempt_disable + .global _tx_execution_isr_exit +@ +@ +@/* No 16-bit Thumb mode veneer code is needed for _tx_thread_context_restore +@ since it will never be called 16-bit mode. */ +@ + .arm + .text + .align 2 +@/**************************************************************************/ +@/* */ +@/* FUNCTION RELEASE */ +@/* */ +@/* _tx_thread_context_restore Cortex-R52/GNU */ +@/* 6.5.2 */ +@/* AUTHOR */ +@/* */ +@/* Frédéric Desbiens, Eclipse Foundation */ +@/* */ +@/* Derived from the Cortex-R5/GNU port originally written by */ +@/* William E. Lamie, Microsoft Corporation. */ +@/* */ +@/* DESCRIPTION */ +@/* */ +@/* This function restores the interrupt context if it is processing a */ +@/* nested interrupt. If not, it returns to the interrupt thread if no */ +@/* preemption is necessary. Otherwise, if preemption is necessary or */ +@/* if no thread was running, the function returns to the scheduler. */ +@/* */ +@/* INPUT */ +@/* */ +@/* None */ +@/* */ +@/* OUTPUT */ +@/* */ +@/* None */ +@/* */ +@/* CALLS */ +@/* */ +@/* _tx_thread_schedule Thread scheduling routine */ +@/* */ +@/* CALLED BY */ +@/* */ +@/* ISRs Interrupt Service Routines */ +@/* */ +@/**************************************************************************/ +@VOID _tx_thread_context_restore(VOID) +@{ + .global _tx_thread_context_restore + .type _tx_thread_context_restore,function +_tx_thread_context_restore: +@ +@ /* Lockout interrupts. */ +@ +#ifdef TX_ENABLE_FIQ_SUPPORT + CPSID if @ Disable IRQ and FIQ interrupts +#else + CPSID i @ Disable IRQ interrupts +#endif + +#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +@ +@ /* Call the ISR exit function to indicate an ISR is complete. */ +@ + BL _tx_execution_isr_exit @ Call the ISR exit function +#endif +@ +@ /* Determine if interrupts are nested. */ +@ if (--_tx_thread_system_state) +@ { +@ + LDR r3, =_tx_thread_system_state @ Pickup address of system state variable + LDR r2, [r3] @ Pickup system state + SUB r2, r2, #1 @ Decrement the counter + STR r2, [r3] @ Store the counter + CMP r2, #0 @ Was this the first interrupt? + BEQ __tx_thread_not_nested_restore @ If so, not a nested restore +@ +@ /* Interrupts are nested. */ +@ +@ /* Just recover the saved registers and return to the point of +@ interrupt. */ +@ + LDMIA sp!, {r0, r10, r12, lr} @ Recover SPSR, POI, and scratch regs + MSR SPSR_cxsf, r0 @ Put SPSR back + LDMIA sp!, {r0-r3} @ Recover r0-r3 + MOVS pc, lr @ Return to point of interrupt +@ +@ } +__tx_thread_not_nested_restore: +@ +@ /* Determine if a thread was interrupted and no preemption is required. */ +@ else if (((_tx_thread_current_ptr) && (_tx_thread_current_ptr == _tx_thread_execute_ptr)) +@ || (_tx_thread_preempt_disable)) +@ { +@ + LDR r1, =_tx_thread_current_ptr @ Pickup address of current thread ptr + LDR r0, [r1] @ Pickup actual current thread pointer + CMP r0, #0 @ Is it NULL? + BEQ __tx_thread_idle_system_restore @ Yes, idle system was interrupted +@ + LDR r3, =_tx_thread_preempt_disable @ Pickup preempt disable address + LDR r2, [r3] @ Pickup actual preempt disable flag + CMP r2, #0 @ Is it set? + BNE __tx_thread_no_preempt_restore @ Yes, don't preempt this thread + LDR r3, =_tx_thread_execute_ptr @ Pickup address of execute thread ptr + LDR r2, [r3] @ Pickup actual execute thread pointer + CMP r0, r2 @ Is the same thread highest priority? + BNE __tx_thread_preempt_restore @ No, preemption needs to happen +@ +@ +__tx_thread_no_preempt_restore: +@ +@ /* Restore interrupted thread or ISR. */ +@ +@ /* Pickup the saved stack pointer. */ +@ tmp_ptr = _tx_thread_current_ptr -> tx_thread_stack_ptr; +@ +@ /* Recover the saved context and return to the point of interrupt. */ +@ + LDMIA sp!, {r0, r10, r12, lr} @ Recover SPSR, POI, and scratch regs + MSR SPSR_cxsf, r0 @ Put SPSR back + LDMIA sp!, {r0-r3} @ Recover r0-r3 + MOVS pc, lr @ Return to point of interrupt +@ +@ } +@ else +@ { +__tx_thread_preempt_restore: +@ + LDMIA sp!, {r3, r10, r12, lr} @ Recover temporarily saved registers + MOV r1, lr @ Save lr (point of interrupt) + MOV r2, #SVC_MODE @ Build SVC mode CPSR + MSR CPSR_c, r2 @ Enter SVC mode + STR r1, [sp, #-4]! @ Save point of interrupt + STMDB sp!, {r4-r12, lr} @ Save upper half of registers + MOV r4, r3 @ Save SPSR in r4 + MOV r2, #IRQ_MODE @ Build IRQ mode CPSR + MSR CPSR_c, r2 @ Enter IRQ mode + LDMIA sp!, {r0-r3} @ Recover r0-r3 + MOV r5, #SVC_MODE @ Build SVC mode CPSR + MSR CPSR_c, r5 @ Enter SVC mode + STMDB sp!, {r0-r3} @ Save r0-r3 on thread's stack +@ + LDR r1, =_tx_thread_current_ptr @ Pickup address of current thread ptr + LDR r0, [r1] @ Pickup current thread pointer +@ +#ifdef TX_ENABLE_VFP_SUPPORT + LDR r2, [r0, #144] @ Pickup the VFP enabled flag + CMP r2, #0 @ Is the VFP enabled? + BEQ _tx_skip_irq_vfp_save @ No, skip VFP IRQ save + VMRS r2, FPSCR @ Pickup the FPSCR + STR r2, [sp, #-4]! @ Save FPSCR + VSTMDB sp!, {D0-D15} @ Save D0-D15 +_tx_skip_irq_vfp_save: +#endif +@ + MOV r3, #1 @ Build interrupt stack type + STMDB sp!, {r3, r4} @ Save interrupt stack type and SPSR + STR sp, [r0, #8] @ Save stack pointer in thread control + @ block +@ +@ /* Save the remaining time-slice and disable it. */ +@ if (_tx_timer_time_slice) +@ { +@ + LDR r3, =_tx_timer_time_slice @ Pickup time-slice variable address + LDR r2, [r3] @ Pickup time-slice + CMP r2, #0 @ Is it active? + BEQ __tx_thread_dont_save_ts @ No, don't save it +@ +@ _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice; +@ _tx_timer_time_slice = 0; +@ + STR r2, [r0, #24] @ Save thread's time-slice + MOV r2, #0 @ Clear value + STR r2, [r3] @ Disable global time-slice flag +@ +@ } +__tx_thread_dont_save_ts: +@ +@ +@ /* Clear the current task pointer. */ +@ _tx_thread_current_ptr = TX_NULL; +@ + MOV r0, #0 @ NULL value + STR r0, [r1] @ Clear current thread pointer +@ +@ /* Return to the scheduler. */ +@ _tx_thread_schedule(); +@ + B _tx_thread_schedule @ Return to scheduler +@ } +@ +__tx_thread_idle_system_restore: +@ +@ /* Just return back to the scheduler! */ +@ + MOV r0, #SVC_MODE @ Build SVC mode CPSR + MSR CPSR_c, r0 @ Enter SVC mode + B _tx_thread_schedule @ Return to scheduler +@} + + + diff --git a/ports/cortex_r52/gnu/src/tx_thread_context_save.S b/ports/cortex_r52/gnu/src/tx_thread_context_save.S new file mode 100644 index 000000000..9b61077e4 --- /dev/null +++ b/ports/cortex_r52/gnu/src/tx_thread_context_save.S @@ -0,0 +1,193 @@ +@/*************************************************************************** +@ * Copyright (c) 2024 Microsoft Corporation +@ * 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 +@ **************************************************************************/ +@ Some portions generated by Claude Code (Opus 5). +@ +@ +@/**************************************************************************/ +@/**************************************************************************/ +@/** */ +@/** ThreadX Component */ +@/** */ +@/** Thread */ +@/** */ +@/**************************************************************************/ +@/**************************************************************************/ +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + + .global _tx_thread_system_state + .global _tx_thread_current_ptr + .global _tx_irq_processing_return + .global _tx_execution_isr_enter +@ +@ +@/* No 16-bit Thumb mode veneer code is needed for _tx_thread_context_save +@ since it will never be called 16-bit mode. */ +@ + .arm + .text + .align 2 +@/**************************************************************************/ +@/* */ +@/* FUNCTION RELEASE */ +@/* */ +@/* _tx_thread_context_save Cortex-R52/GNU */ +@/* 6.5.2 */ +@/* AUTHOR */ +@/* */ +@/* Frédéric Desbiens, Eclipse Foundation */ +@/* */ +@/* Derived from the Cortex-R5/GNU port originally written by */ +@/* William E. Lamie, Microsoft Corporation. */ +@/* */ +@/* DESCRIPTION */ +@/* */ +@/* This function saves the context of an executing thread in the */ +@/* beginning of interrupt processing. The function also ensures that */ +@/* the system stack is used upon return to the calling ISR. */ +@/* */ +@/* INPUT */ +@/* */ +@/* None */ +@/* */ +@/* OUTPUT */ +@/* */ +@/* None */ +@/* */ +@/* CALLS */ +@/* */ +@/* None */ +@/* */ +@/* CALLED BY */ +@/* */ +@/* ISRs */ +@/* */ +@/**************************************************************************/ +@VOID _tx_thread_context_save(VOID) +@{ + .global _tx_thread_context_save + .type _tx_thread_context_save,function +_tx_thread_context_save: +@ +@ /* Upon entry to this routine, it is assumed that IRQ interrupts are locked +@ out, we are in IRQ mode, and all registers are intact. */ +@ +@ /* Check for a nested interrupt condition. */ +@ if (_tx_thread_system_state++) +@ { +@ + STMDB sp!, {r0-r3} @ Save some working registers +#ifdef TX_ENABLE_FIQ_SUPPORT + CPSID if @ Disable FIQ interrupts +#endif + LDR r3, =_tx_thread_system_state @ Pickup address of system state variable + LDR r2, [r3] @ Pickup system state + CMP r2, #0 @ Is this the first interrupt? + BEQ __tx_thread_not_nested_save @ Yes, not a nested context save +@ +@ /* Nested interrupt condition. */ +@ + ADD r2, r2, #1 @ Increment the interrupt counter + STR r2, [r3] @ Store it back in the variable +@ +@ /* Save the rest of the scratch registers on the stack and return to the +@ calling ISR. */ +@ + MRS r0, SPSR @ Pickup saved SPSR + SUB lr, lr, #4 @ Adjust point of interrupt + STMDB sp!, {r0, r10, r12, lr} @ Store other registers +@ +@ /* Return to the ISR. */ +@ + MOV r10, #0 @ Clear stack limit + +#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +@ +@ /* Call the ISR enter function to indicate an ISR is executing. */ +@ + PUSH {lr} @ Save ISR lr + BL _tx_execution_isr_enter @ Call the ISR enter function + POP {lr} @ Recover ISR lr +#endif + + B __tx_irq_processing_return @ Continue IRQ processing +@ +__tx_thread_not_nested_save: +@ } +@ +@ /* Otherwise, not nested, check to see if a thread was running. */ +@ else if (_tx_thread_current_ptr) +@ { +@ + ADD r2, r2, #1 @ Increment the interrupt counter + STR r2, [r3] @ Store it back in the variable + LDR r1, =_tx_thread_current_ptr @ Pickup address of current thread ptr + LDR r0, [r1] @ Pickup current thread pointer + CMP r0, #0 @ Is it NULL? + BEQ __tx_thread_idle_system_save @ If so, interrupt occurred in + @ scheduling loop - nothing needs saving! +@ +@ /* Save minimal context of interrupted thread. */ +@ + MRS r2, SPSR @ Pickup saved SPSR + SUB lr, lr, #4 @ Adjust point of interrupt + STMDB sp!, {r2, r10, r12, lr} @ Store other registers +@ +@ /* Save the current stack pointer in the thread's control block. */ +@ _tx_thread_current_ptr -> tx_thread_stack_ptr = sp; +@ +@ /* Switch to the system stack. */ +@ sp = _tx_thread_system_stack_ptr@ +@ + MOV r10, #0 @ Clear stack limit + +#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +@ +@ /* Call the ISR enter function to indicate an ISR is executing. */ +@ + PUSH {lr} @ Save ISR lr + BL _tx_execution_isr_enter @ Call the ISR enter function + POP {lr} @ Recover ISR lr +#endif + + B __tx_irq_processing_return @ Continue IRQ processing +@ +@ } +@ else +@ { +@ +__tx_thread_idle_system_save: +@ +@ /* Interrupt occurred in the scheduling loop. */ +@ +@ /* Not much to do here, just adjust the stack pointer, and return to IRQ +@ processing. */ +@ + MOV r10, #0 @ Clear stack limit + +#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +@ +@ /* Call the ISR enter function to indicate an ISR is executing. */ +@ + PUSH {lr} @ Save ISR lr + BL _tx_execution_isr_enter @ Call the ISR enter function + POP {lr} @ Recover ISR lr +#endif + + ADD sp, sp, #16 @ Recover saved registers + B __tx_irq_processing_return @ Continue IRQ processing +@ +@ } +@} + + + diff --git a/ports/cortex_r52/gnu/src/tx_thread_fiq_context_restore.S b/ports/cortex_r52/gnu/src/tx_thread_fiq_context_restore.S new file mode 100644 index 000000000..1d576f901 --- /dev/null +++ b/ports/cortex_r52/gnu/src/tx_thread_fiq_context_restore.S @@ -0,0 +1,237 @@ +@/*************************************************************************** +@ * Copyright (c) 2024 Microsoft Corporation +@ * 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 +@ **************************************************************************/ +@ Some portions generated by Claude Code (Opus 5). +@ +@ +@/**************************************************************************/ +@/**************************************************************************/ +@/** */ +@/** ThreadX Component */ +@/** */ +@/** Thread */ +@/** */ +@/**************************************************************************/ +@/**************************************************************************/ +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + +SVC_MODE = 0xD3 @ SVC mode +FIQ_MODE = 0xD1 @ FIQ mode +MODE_MASK = 0x1F @ Mode mask +THUMB_MASK = 0x20 @ Thumb bit mask +IRQ_MODE_BITS = 0x12 @ IRQ mode bits +@ +@ + .global _tx_thread_system_state + .global _tx_thread_current_ptr + .global _tx_thread_system_stack_ptr + .global _tx_thread_execute_ptr + .global _tx_timer_time_slice + .global _tx_thread_schedule + .global _tx_thread_preempt_disable + .global _tx_execution_isr_exit +@ +@ +@/* No 16-bit Thumb mode veneer code is needed for _tx_thread_fiq_context_restore +@ since it will never be called 16-bit mode. */ +@ + .arm + .text + .align 2 +@/**************************************************************************/ +@/* */ +@/* FUNCTION RELEASE */ +@/* */ +@/* _tx_thread_fiq_context_restore Cortex-R52/GNU */ +@/* 6.5.2 */ +@/* AUTHOR */ +@/* */ +@/* Frédéric Desbiens, Eclipse Foundation */ +@/* */ +@/* Derived from the Cortex-R5/GNU port originally written by */ +@/* William E. Lamie, Microsoft Corporation. */ +@/* */ +@/* DESCRIPTION */ +@/* */ +@/* This function restores the fiq interrupt context when processing a */ +@/* nested interrupt. If not, it returns to the interrupt thread if no */ +@/* preemption is necessary. Otherwise, if preemption is necessary or */ +@/* if no thread was running, the function returns to the scheduler. */ +@/* */ +@/* INPUT */ +@/* */ +@/* None */ +@/* */ +@/* OUTPUT */ +@/* */ +@/* None */ +@/* */ +@/* CALLS */ +@/* */ +@/* _tx_thread_schedule Thread scheduling routine */ +@/* */ +@/* CALLED BY */ +@/* */ +@/* FIQ ISR Interrupt Service Routines */ +@/* */ +@/**************************************************************************/ +@VOID _tx_thread_fiq_context_restore(VOID) +@{ + .global _tx_thread_fiq_context_restore + .type _tx_thread_fiq_context_restore,function +_tx_thread_fiq_context_restore: +@ +@ /* Lockout interrupts. */ +@ + CPSID if @ Disable IRQ and FIQ interrupts + +#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +@ +@ /* Call the ISR exit function to indicate an ISR is complete. */ +@ + BL _tx_execution_isr_exit @ Call the ISR exit function +#endif +@ +@ /* Determine if interrupts are nested. */ +@ if (--_tx_thread_system_state) +@ { +@ + LDR r3, =_tx_thread_system_state @ Pickup address of system state variable + LDR r2, [r3] @ Pickup system state + SUB r2, r2, #1 @ Decrement the counter + STR r2, [r3] @ Store the counter + CMP r2, #0 @ Was this the first interrupt? + BEQ __tx_thread_fiq_not_nested_restore @ If so, not a nested restore +@ +@ /* Interrupts are nested. */ +@ +@ /* Just recover the saved registers and return to the point of +@ interrupt. */ +@ + LDMIA sp!, {r0, r10, r12, lr} @ Recover SPSR, POI, and scratch regs + MSR SPSR_cxsf, r0 @ Put SPSR back + LDMIA sp!, {r0-r3} @ Recover r0-r3 + MOVS pc, lr @ Return to point of interrupt +@ +@ } +__tx_thread_fiq_not_nested_restore: +@ +@ /* Determine if a thread was interrupted and no preemption is required. */ +@ else if (((_tx_thread_current_ptr) && (_tx_thread_current_ptr == _tx_thread_execute_ptr)) +@ || (_tx_thread_preempt_disable)) +@ { +@ + LDR r1, [sp] @ Pickup the saved SPSR + MOV r2, #MODE_MASK @ Build mask to isolate the interrupted mode + AND r1, r1, r2 @ Isolate mode bits + CMP r1, #IRQ_MODE_BITS @ Was an interrupt taken in IRQ mode before we + @ got to context save? */ + BEQ __tx_thread_fiq_no_preempt_restore @ Yes, just go back to point of interrupt + + + LDR r1, =_tx_thread_current_ptr @ Pickup address of current thread ptr + LDR r0, [r1] @ Pickup actual current thread pointer + CMP r0, #0 @ Is it NULL? + BEQ __tx_thread_fiq_idle_system_restore @ Yes, idle system was interrupted + + LDR r3, =_tx_thread_preempt_disable @ Pickup preempt disable address + LDR r2, [r3] @ Pickup actual preempt disable flag + CMP r2, #0 @ Is it set? + BNE __tx_thread_fiq_no_preempt_restore @ Yes, don't preempt this thread + LDR r3, =_tx_thread_execute_ptr @ Pickup address of execute thread ptr + LDR r2, [r3] @ Pickup actual execute thread pointer + CMP r0, r2 @ Is the same thread highest priority? + BNE __tx_thread_fiq_preempt_restore @ No, preemption needs to happen + + +__tx_thread_fiq_no_preempt_restore: +@ +@ /* Restore interrupted thread or ISR. */ +@ +@ /* Pickup the saved stack pointer. */ +@ tmp_ptr = _tx_thread_current_ptr -> tx_thread_stack_ptr; +@ +@ /* Recover the saved context and return to the point of interrupt. */ +@ + LDMIA sp!, {r0, lr} @ Recover SPSR, POI, and scratch regs + MSR SPSR_cxsf, r0 @ Put SPSR back + LDMIA sp!, {r0-r3} @ Recover r0-r3 + MOVS pc, lr @ Return to point of interrupt +@ +@ } +@ else +@ { +__tx_thread_fiq_preempt_restore: +@ + LDMIA sp!, {r3, lr} @ Recover temporarily saved registers + MOV r1, lr @ Save lr (point of interrupt) + MOV r2, #SVC_MODE @ Build SVC mode CPSR + MSR CPSR_c, r2 @ Enter SVC mode + STR r1, [sp, #-4]! @ Save point of interrupt + STMDB sp!, {r4-r12, lr} @ Save upper half of registers + MOV r4, r3 @ Save SPSR in r4 + MOV r2, #FIQ_MODE @ Build FIQ mode CPSR + MSR CPSR_c, r2 @ Reenter FIQ mode + LDMIA sp!, {r0-r3} @ Recover r0-r3 + MOV r5, #SVC_MODE @ Build SVC mode CPSR + MSR CPSR_c, r5 @ Enter SVC mode + STMDB sp!, {r0-r3} @ Save r0-r3 on thread's stack + MOV r3, #1 @ Build interrupt stack type + STMDB sp!, {r3, r4} @ Save interrupt stack type and SPSR + LDR r1, =_tx_thread_current_ptr @ Pickup address of current thread ptr + LDR r0, [r1] @ Pickup current thread pointer + STR sp, [r0, #8] @ Save stack pointer in thread control + @ block */ +@ +@ /* Save the remaining time-slice and disable it. */ +@ if (_tx_timer_time_slice) +@ { +@ + LDR r3, =_tx_timer_time_slice @ Pickup time-slice variable address + LDR r2, [r3] @ Pickup time-slice + CMP r2, #0 @ Is it active? + BEQ __tx_thread_fiq_dont_save_ts @ No, don't save it +@ +@ _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice; +@ _tx_timer_time_slice = 0; +@ + STR r2, [r0, #24] @ Save thread's time-slice + MOV r2, #0 @ Clear value + STR r2, [r3] @ Disable global time-slice flag +@ +@ } +__tx_thread_fiq_dont_save_ts: +@ +@ +@ /* Clear the current task pointer. */ +@ _tx_thread_current_ptr = TX_NULL; +@ + MOV r0, #0 @ NULL value + STR r0, [r1] @ Clear current thread pointer +@ +@ /* Return to the scheduler. */ +@ _tx_thread_schedule(); +@ + B _tx_thread_schedule @ Return to scheduler +@ } +@ +__tx_thread_fiq_idle_system_restore: +@ +@ /* Just return back to the scheduler! */ +@ + ADD sp, sp, #24 @ Recover FIQ stack space + MOV r3, #SVC_MODE @ Build SVC mode CPSR + MSR CPSR_c, r3 @ Lockout interrupts + B _tx_thread_schedule @ Return to scheduler +@ +@} + diff --git a/ports/cortex_r52/gnu/src/tx_thread_fiq_context_save.S b/ports/cortex_r52/gnu/src/tx_thread_fiq_context_save.S new file mode 100644 index 000000000..9a4ec94bf --- /dev/null +++ b/ports/cortex_r52/gnu/src/tx_thread_fiq_context_save.S @@ -0,0 +1,195 @@ +@/*************************************************************************** +@ * Copyright (c) 2024 Microsoft Corporation +@ * 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 +@ **************************************************************************/ +@ Some portions generated by Claude Code (Opus 5). +@ +@ +@/**************************************************************************/ +@/**************************************************************************/ +@/** */ +@/** ThreadX Component */ +@/** */ +@/** Thread */ +@/** */ +@/**************************************************************************/ +@/**************************************************************************/ +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + + .global _tx_thread_system_state + .global _tx_thread_current_ptr + .global __tx_fiq_processing_return + .global _tx_execution_isr_enter +@ +@ +@/* No 16-bit Thumb mode veneer code is needed for _tx_thread_fiq_context_save +@ since it will never be called 16-bit mode. */ +@ + .arm + .text + .align 2 +@/**************************************************************************/ +@/* */ +@/* FUNCTION RELEASE */ +@/* */ +@/* _tx_thread_fiq_context_save Cortex-R52/GNU */ +@/* 6.5.2 */ +@/* AUTHOR */ +@/* */ +@/* Frédéric Desbiens, Eclipse Foundation */ +@/* */ +@/* Derived from the Cortex-R5/GNU port originally written by */ +@/* William E. Lamie, Microsoft Corporation. */ +@/* */ +@/* DESCRIPTION */ +@/* */ +@/* This function saves the context of an executing thread in the */ +@/* beginning of interrupt processing. The function also ensures that */ +@/* the system stack is used upon return to the calling ISR. */ +@/* */ +@/* INPUT */ +@/* */ +@/* None */ +@/* */ +@/* OUTPUT */ +@/* */ +@/* None */ +@/* */ +@/* CALLS */ +@/* */ +@/* None */ +@/* */ +@/* CALLED BY */ +@/* */ +@/* ISRs */ +@/* */ +@/**************************************************************************/ +@ VOID _tx_thread_fiq_context_save(VOID) +@{ + .global _tx_thread_fiq_context_save + .type _tx_thread_fiq_context_save,function +_tx_thread_fiq_context_save: +@ +@ /* Upon entry to this routine, it is assumed that IRQ interrupts are locked +@ out, we are in IRQ mode, and all registers are intact. */ +@ +@ /* Check for a nested interrupt condition. */ +@ if (_tx_thread_system_state++) +@ { +@ + STMDB sp!, {r0-r3} @ Save some working registers + LDR r3, =_tx_thread_system_state @ Pickup address of system state variable + LDR r2, [r3] @ Pickup system state + CMP r2, #0 @ Is this the first interrupt? + BEQ __tx_thread_fiq_not_nested_save @ Yes, not a nested context save +@ +@ /* Nested interrupt condition. */ +@ + ADD r2, r2, #1 @ Increment the interrupt counter + STR r2, [r3] @ Store it back in the variable +@ +@ /* Save the rest of the scratch registers on the stack and return to the +@ calling ISR. */ +@ + MRS r0, SPSR @ Pickup saved SPSR + SUB lr, lr, #4 @ Adjust point of interrupt + STMDB sp!, {r0, r10, r12, lr} @ Store other registers +@ +@ /* Return to the ISR. */ +@ + MOV r10, #0 @ Clear stack limit + +#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +@ +@ /* Call the ISR enter function to indicate an ISR is executing. */ +@ + PUSH {lr} @ Save ISR lr + BL _tx_execution_isr_enter @ Call the ISR enter function + POP {lr} @ Recover ISR lr +#endif + + B __tx_fiq_processing_return @ Continue FIQ processing +@ +__tx_thread_fiq_not_nested_save: +@ } +@ +@ /* Otherwise, not nested, check to see if a thread was running. */ +@ else if (_tx_thread_current_ptr) +@ { +@ + ADD r2, r2, #1 @ Increment the interrupt counter + STR r2, [r3] @ Store it back in the variable + LDR r1, =_tx_thread_current_ptr @ Pickup address of current thread ptr + LDR r0, [r1] @ Pickup current thread pointer + CMP r0, #0 @ Is it NULL? + BEQ __tx_thread_fiq_idle_system_save @ If so, interrupt occurred in +@ @ scheduling loop - nothing needs saving! +@ +@ /* Save minimal context of interrupted thread. */ +@ + MRS r2, SPSR @ Pickup saved SPSR + SUB lr, lr, #4 @ Adjust point of interrupt + STMDB sp!, {r2, lr} @ Store other registers, Note that we don't +@ @ need to save sl and ip since FIQ has +@ @ copies of these registers. Nested +@ @ interrupt processing does need to save +@ @ these registers. +@ +@ /* Save the current stack pointer in the thread's control block. */ +@ _tx_thread_current_ptr -> tx_thread_stack_ptr = sp; +@ +@ /* Switch to the system stack. */ +@ sp = _tx_thread_system_stack_ptr; +@ + MOV r10, #0 @ Clear stack limit + +#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +@ +@ /* Call the ISR enter function to indicate an ISR is executing. */ +@ + PUSH {lr} @ Save ISR lr + BL _tx_execution_isr_enter @ Call the ISR enter function + POP {lr} @ Recover ISR lr +#endif + + B __tx_fiq_processing_return @ Continue FIQ processing +@ +@ } +@ else +@ { +@ +__tx_thread_fiq_idle_system_save: +@ +@ /* Interrupt occurred in the scheduling loop. */ +@ +#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +@ +@ /* Call the ISR enter function to indicate an ISR is executing. */ +@ + PUSH {lr} @ Save ISR lr + BL _tx_execution_isr_enter @ Call the ISR enter function + POP {lr} @ Recover ISR lr +#endif +@ +@ /* Not much to do here, save the current SPSR and LR for possible +@ use in IRQ interrupted in idle system conditions, and return to +@ FIQ interrupt processing. */ +@ + MRS r0, SPSR @ Pickup saved SPSR + SUB lr, lr, #4 @ Adjust point of interrupt + STMDB sp!, {r0, lr} @ Store other registers that will get used +@ @ or stripped off the stack in context +@ @ restore + B __tx_fiq_processing_return @ Continue FIQ processing +@ +@ } +@} + diff --git a/ports/cortex_r52/gnu/src/tx_thread_fiq_nesting_end.S b/ports/cortex_r52/gnu/src/tx_thread_fiq_nesting_end.S new file mode 100644 index 000000000..927f6307c --- /dev/null +++ b/ports/cortex_r52/gnu/src/tx_thread_fiq_nesting_end.S @@ -0,0 +1,107 @@ +@/*************************************************************************** +@ * Copyright (c) 2024 Microsoft Corporation +@ * 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 +@ **************************************************************************/ +@ Some portions generated by Claude Code (Opus 5). +@ +@ +@/**************************************************************************/ +@/**************************************************************************/ +@/** */ +@/** ThreadX Component */ +@/** */ +@/** Thread */ +@/** */ +@/**************************************************************************/ +@/**************************************************************************/ +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + +#ifdef TX_ENABLE_FIQ_SUPPORT +DISABLE_INTS = 0xC0 @ Disable IRQ/FIQ interrupts +#else +DISABLE_INTS = 0x80 @ Disable IRQ interrupts +#endif +MODE_MASK = 0x1F @ Mode mask +FIQ_MODE_BITS = 0x11 @ FIQ mode bits +@ +@ +@/* No 16-bit Thumb mode veneer code is needed for _tx_thread_fiq_nesting_end +@ since it will never be called 16-bit mode. */ +@ + .arm + .text + .align 2 +@/**************************************************************************/ +@/* */ +@/* FUNCTION RELEASE */ +@/* */ +@/* _tx_thread_fiq_nesting_end Cortex-R52/GNU */ +@/* 6.5.2 */ +@/* AUTHOR */ +@/* */ +@/* Frédéric Desbiens, Eclipse Foundation */ +@/* */ +@/* Derived from the Cortex-R5/GNU port originally written by */ +@/* William E. Lamie, Microsoft Corporation. */ +@/* */ +@/* DESCRIPTION */ +@/* */ +@/* This function is called by the application from FIQ mode after */ +@/* _tx_thread_fiq_nesting_start has been called and switches the FIQ */ +@/* processing from system mode back to FIQ mode prior to the ISR */ +@/* calling _tx_thread_fiq_context_restore. Note that this function */ +@/* assumes the system stack pointer is in the same position after */ +@/* nesting start function was called. */ +@/* */ +@/* This function assumes that the system mode stack pointer was setup */ +@/* during low-level initialization (tx_initialize_low_level.s). */ +@/* */ +@/* This function returns with FIQ interrupts disabled. */ +@/* */ +@/* INPUT */ +@/* */ +@/* None */ +@/* */ +@/* OUTPUT */ +@/* */ +@/* None */ +@/* */ +@/* CALLS */ +@/* */ +@/* None */ +@/* */ +@/* CALLED BY */ +@/* */ +@/* ISRs */ +@/* */ +@/**************************************************************************/ +@VOID _tx_thread_fiq_nesting_end(VOID) +@{ + .global _tx_thread_fiq_nesting_end + .type _tx_thread_fiq_nesting_end,function +_tx_thread_fiq_nesting_end: + MOV r3,lr @ Save ISR return address + MRS r0, CPSR @ Pickup the CPSR + ORR r0, r0, #DISABLE_INTS @ Build disable interrupt value + MSR CPSR_c, r0 @ Disable interrupts + LDMIA sp!, {r1, lr} @ Pickup saved lr (and r1 throw-away for + @ 8-byte alignment logic) + BIC r0, r0, #MODE_MASK @ Clear mode bits + ORR r0, r0, #FIQ_MODE_BITS @ Build IRQ mode CPSR + MSR CPSR_c, r0 @ Reenter IRQ mode + +#ifdef __THUMB_INTERWORK + BX r3 @ Return to caller +#else + MOV pc, r3 @ Return to caller +#endif +@} + diff --git a/ports/cortex_r52/gnu/src/tx_thread_fiq_nesting_start.S b/ports/cortex_r52/gnu/src/tx_thread_fiq_nesting_start.S new file mode 100644 index 000000000..7c9be8d31 --- /dev/null +++ b/ports/cortex_r52/gnu/src/tx_thread_fiq_nesting_start.S @@ -0,0 +1,99 @@ +@/*************************************************************************** +@ * Copyright (c) 2024 Microsoft Corporation +@ * 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 +@ **************************************************************************/ +@ Some portions generated by Claude Code (Opus 5). +@ +@ +@/**************************************************************************/ +@/**************************************************************************/ +@/** */ +@/** ThreadX Component */ +@/** */ +@/** Thread */ +@/** */ +@/**************************************************************************/ +@/**************************************************************************/ +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + +FIQ_DISABLE = 0x40 @ FIQ disable bit +MODE_MASK = 0x1F @ Mode mask +SYS_MODE_BITS = 0x1F @ System mode bits +@ +@ +@/* No 16-bit Thumb mode veneer code is needed for _tx_thread_fiq_nesting_start +@ since it will never be called 16-bit mode. */ +@ + .arm + .text + .align 2 +@/**************************************************************************/ +@/* */ +@/* FUNCTION RELEASE */ +@/* */ +@/* _tx_thread_fiq_nesting_start Cortex-R52/GNU */ +@/* 6.5.2 */ +@/* AUTHOR */ +@/* */ +@/* Frédéric Desbiens, Eclipse Foundation */ +@/* */ +@/* Derived from the Cortex-R5/GNU port originally written by */ +@/* William E. Lamie, Microsoft Corporation. */ +@/* */ +@/* DESCRIPTION */ +@/* */ +@/* This function is called by the application from FIQ mode after */ +@/* _tx_thread_fiq_context_save has been called and switches the FIQ */ +@/* processing to the system mode so nested FIQ interrupt processing */ +@/* is possible (system mode has its own "lr" register). Note that */ +@/* this function assumes that the system mode stack pointer was setup */ +@/* during low-level initialization (tx_initialize_low_level.s). */ +@/* */ +@/* This function returns with FIQ interrupts enabled. */ +@/* */ +@/* INPUT */ +@/* */ +@/* None */ +@/* */ +@/* OUTPUT */ +@/* */ +@/* None */ +@/* */ +@/* CALLS */ +@/* */ +@/* None */ +@/* */ +@/* CALLED BY */ +@/* */ +@/* ISRs */ +@/* */ +@/**************************************************************************/ +@VOID _tx_thread_fiq_nesting_start(VOID) +@{ + .global _tx_thread_fiq_nesting_start + .type _tx_thread_fiq_nesting_start,function +_tx_thread_fiq_nesting_start: + MOV r3,lr @ Save ISR return address + MRS r0, CPSR @ Pickup the CPSR + BIC r0, r0, #MODE_MASK @ Clear the mode bits + ORR r0, r0, #SYS_MODE_BITS @ Build system mode CPSR + MSR CPSR_c, r0 @ Enter system mode + STMDB sp!, {r1, lr} @ Push the system mode lr on the system mode stack + @ and push r1 just to keep 8-byte alignment + BIC r0, r0, #FIQ_DISABLE @ Build enable FIQ CPSR + MSR CPSR_c, r0 @ Enter system mode +#ifdef __THUMB_INTERWORK + BX r3 @ Return to caller +#else + MOV pc, r3 @ Return to caller +#endif +@} + diff --git a/ports/cortex_r52/gnu/src/tx_thread_interrupt_control.S b/ports/cortex_r52/gnu/src/tx_thread_interrupt_control.S new file mode 100644 index 000000000..430f6ea28 --- /dev/null +++ b/ports/cortex_r52/gnu/src/tx_thread_interrupt_control.S @@ -0,0 +1,108 @@ +@/*************************************************************************** +@ * Copyright (c) 2024 Microsoft Corporation +@ * 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 +@ **************************************************************************/ +@ Some portions generated by Claude Code (Opus 5). +@ +@ +@/**************************************************************************/ +@/**************************************************************************/ +@/** */ +@/** ThreadX Component */ +@/** */ +@/** Thread */ +@/** */ +@/**************************************************************************/ +@/**************************************************************************/ +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + + +INT_MASK = 0x03F + +@ +@/* Define the 16-bit Thumb mode veneer for _tx_thread_interrupt_control for +@ applications calling this function from to 16-bit Thumb mode. */ +@ + .text + .align 2 + .global $_tx_thread_interrupt_control +$_tx_thread_interrupt_control: + .thumb + BX pc @ Switch to 32-bit mode + NOP @ + .arm + STMFD sp!, {lr} @ Save return address + BL _tx_thread_interrupt_control @ Call _tx_thread_interrupt_control function + LDMFD sp!, {lr} @ Recover saved return address + BX lr @ Return to 16-bit caller +@ +@ + .text + .align 2 +@/**************************************************************************/ +@/* */ +@/* FUNCTION RELEASE */ +@/* */ +@/* _tx_thread_interrupt_control Cortex-R52/GNU */ +@/* 6.5.2 */ +@/* AUTHOR */ +@/* */ +@/* Frédéric Desbiens, Eclipse Foundation */ +@/* */ +@/* Derived from the Cortex-R5/GNU port originally written by */ +@/* William E. Lamie, Microsoft Corporation. */ +@/* */ +@/* DESCRIPTION */ +@/* */ +@/* This function is responsible for changing the interrupt lockout */ +@/* posture of the system. */ +@/* */ +@/* INPUT */ +@/* */ +@/* new_posture New interrupt lockout posture */ +@/* */ +@/* OUTPUT */ +@/* */ +@/* old_posture Old interrupt lockout posture */ +@/* */ +@/* CALLS */ +@/* */ +@/* None */ +@/* */ +@/* CALLED BY */ +@/* */ +@/* Application Code */ +@/* */ +@/**************************************************************************/ +@UINT _tx_thread_interrupt_control(UINT new_posture) +@{ + .global _tx_thread_interrupt_control + .type _tx_thread_interrupt_control,function +_tx_thread_interrupt_control: +@ +@ /* Pickup current interrupt lockout posture. */ +@ + MRS r3, CPSR @ Pickup current CPSR + MOV r2, #INT_MASK @ Build interrupt mask + AND r1, r3, r2 @ Clear interrupt lockout bits + ORR r1, r1, r0 @ Or-in new interrupt lockout bits +@ +@ /* Apply the new interrupt posture. */ +@ + MSR CPSR_c, r1 @ Setup new CPSR + BIC r0, r3, r2 @ Return previous interrupt mask +#ifdef __THUMB_INTERWORK + BX lr @ Return to caller +#else + MOV pc, lr @ Return to caller +#endif +@} + diff --git a/ports/cortex_r52/gnu/src/tx_thread_interrupt_disable.S b/ports/cortex_r52/gnu/src/tx_thread_interrupt_disable.S new file mode 100644 index 000000000..1e10b9582 --- /dev/null +++ b/ports/cortex_r52/gnu/src/tx_thread_interrupt_disable.S @@ -0,0 +1,105 @@ +@/*************************************************************************** +@ * Copyright (c) 2024 Microsoft Corporation +@ * 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 +@ **************************************************************************/ +@ Some portions generated by Claude Code (Opus 5). +@ +@ +@/**************************************************************************/ +@/**************************************************************************/ +@/** */ +@/** ThreadX Component */ +@/** */ +@/** Thread */ +@/** */ +@/**************************************************************************/ +@/**************************************************************************/ +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + +@/* Define the 16-bit Thumb mode veneer for _tx_thread_interrupt_disable for +@ applications calling this function from to 16-bit Thumb mode. */ +@ + .text + .align 2 + .global $_tx_thread_interrupt_disable +$_tx_thread_interrupt_disable: + .thumb + BX pc @ Switch to 32-bit mode + NOP @ + .arm + STMFD sp!, {lr} @ Save return address + BL _tx_thread_interrupt_disable @ Call _tx_thread_interrupt_disable function + LDMFD sp!, {lr} @ Recover saved return address + BX lr @ Return to 16-bit caller +@ +@ + .text + .align 2 +@/**************************************************************************/ +@/* */ +@/* FUNCTION RELEASE */ +@/* */ +@/* _tx_thread_interrupt_disable Cortex-R52/GNU */ +@/* 6.5.2 */ +@/* AUTHOR */ +@/* */ +@/* Frédéric Desbiens, Eclipse Foundation */ +@/* */ +@/* Derived from the Cortex-R5/GNU port originally written by */ +@/* William E. Lamie, Microsoft Corporation. */ +@/* */ +@/* DESCRIPTION */ +@/* */ +@/* This function is responsible for disabling interrupts */ +@/* */ +@/* INPUT */ +@/* */ +@/* None */ +@/* */ +@/* OUTPUT */ +@/* */ +@/* old_posture Old interrupt lockout posture */ +@/* */ +@/* CALLS */ +@/* */ +@/* None */ +@/* */ +@/* CALLED BY */ +@/* */ +@/* Application Code */ +@/* */ +@/**************************************************************************/ +@UINT _tx_thread_interrupt_disable(void) +@{ + .global _tx_thread_interrupt_disable + .type _tx_thread_interrupt_disable,function +_tx_thread_interrupt_disable: +@ +@ /* Pickup current interrupt lockout posture. */ +@ + MRS r0, CPSR @ Pickup current CPSR +@ +@ /* Mask interrupts. */ +@ +#ifdef TX_ENABLE_FIQ_SUPPORT + CPSID if @ Disable IRQ and FIQ +#else + CPSID i @ Disable IRQ +#endif + +#ifdef __THUMB_INTERWORK + BX lr @ Return to caller +#else + MOV pc, lr @ Return to caller +#endif +@} + + diff --git a/ports/cortex_r52/gnu/src/tx_thread_interrupt_restore.S b/ports/cortex_r52/gnu/src/tx_thread_interrupt_restore.S new file mode 100644 index 000000000..ea95e57cb --- /dev/null +++ b/ports/cortex_r52/gnu/src/tx_thread_interrupt_restore.S @@ -0,0 +1,96 @@ +@/*************************************************************************** +@ * Copyright (c) 2024 Microsoft Corporation +@ * 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 +@ **************************************************************************/ +@ Some portions generated by Claude Code (Opus 5). +@ +@ +@/**************************************************************************/ +@/**************************************************************************/ +@/** */ +@/** ThreadX Component */ +@/** */ +@/** Thread */ +@/** */ +@/**************************************************************************/ +@/**************************************************************************/ +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + +@/* Define the 16-bit Thumb mode veneer for _tx_thread_interrupt_restore for +@ applications calling this function from to 16-bit Thumb mode. */ +@ + .text + .align 2 + .global $_tx_thread_interrupt_restore +$_tx_thread_interrupt_restore: + .thumb + BX pc @ Switch to 32-bit mode + NOP @ + .arm + STMFD sp!, {lr} @ Save return address + BL _tx_thread_interrupt_restore @ Call _tx_thread_interrupt_restore function + LDMFD sp!, {lr} @ Recover saved return address + BX lr @ Return to 16-bit caller +@ +@ + .text + .align 2 +@/**************************************************************************/ +@/* */ +@/* FUNCTION RELEASE */ +@/* */ +@/* _tx_thread_interrupt_restore Cortex-R52/GNU */ +@/* 6.5.2 */ +@/* AUTHOR */ +@/* */ +@/* Frédéric Desbiens, Eclipse Foundation */ +@/* */ +@/* Derived from the Cortex-R5/GNU port originally written by */ +@/* William E. Lamie, Microsoft Corporation. */ +@/* */ +@/* DESCRIPTION */ +@/* */ +@/* This function is responsible for restoring interrupts to the state */ +@/* returned by a previous _tx_thread_interrupt_disable call. */ +@/* */ +@/* INPUT */ +@/* */ +@/* old_posture Old interrupt lockout posture */ +@/* */ +@/* OUTPUT */ +@/* */ +@/* None */ +@/* */ +@/* CALLS */ +@/* */ +@/* None */ +@/* */ +@/* CALLED BY */ +@/* */ +@/* Application Code */ +@/* */ +@/**************************************************************************/ +@UINT _tx_thread_interrupt_restore(UINT old_posture) +@{ + .global _tx_thread_interrupt_restore + .type _tx_thread_interrupt_restore,function +_tx_thread_interrupt_restore: +@ +@ /* Apply the new interrupt posture. */ +@ + MSR CPSR_c, r0 @ Setup new CPSR +#ifdef __THUMB_INTERWORK + BX lr @ Return to caller +#else + MOV pc, lr @ Return to caller +#endif +@} + diff --git a/ports/cortex_r52/gnu/src/tx_thread_irq_nesting_end.S b/ports/cortex_r52/gnu/src/tx_thread_irq_nesting_end.S new file mode 100644 index 000000000..6e34d110c --- /dev/null +++ b/ports/cortex_r52/gnu/src/tx_thread_irq_nesting_end.S @@ -0,0 +1,106 @@ +@/*************************************************************************** +@ * Copyright (c) 2024 Microsoft Corporation +@ * 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 +@ **************************************************************************/ +@ Some portions generated by Claude Code (Opus 5). +@ +@ +@/**************************************************************************/ +@/**************************************************************************/ +@/** */ +@/** ThreadX Component */ +@/** */ +@/** Thread */ +@/** */ +@/**************************************************************************/ +@/**************************************************************************/ +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + +#ifdef TX_ENABLE_FIQ_SUPPORT +DISABLE_INTS = 0xC0 @ Disable IRQ/FIQ interrupts +#else +DISABLE_INTS = 0x80 @ Disable IRQ interrupts +#endif +MODE_MASK = 0x1F @ Mode mask +IRQ_MODE_BITS = 0x12 @ IRQ mode bits +@ +@ +@/* No 16-bit Thumb mode veneer code is needed for _tx_thread_irq_nesting_end +@ since it will never be called 16-bit mode. */ +@ + .arm + .text + .align 2 +@/**************************************************************************/ +@/* */ +@/* FUNCTION RELEASE */ +@/* */ +@/* _tx_thread_irq_nesting_end Cortex-R52/GNU */ +@/* 6.5.2 */ +@/* AUTHOR */ +@/* */ +@/* Frédéric Desbiens, Eclipse Foundation */ +@/* */ +@/* Derived from the Cortex-R5/GNU port originally written by */ +@/* William E. Lamie, Microsoft Corporation. */ +@/* */ +@/* DESCRIPTION */ +@/* */ +@/* This function is called by the application from IRQ mode after */ +@/* _tx_thread_irq_nesting_start has been called and switches the IRQ */ +@/* processing from system mode back to IRQ mode prior to the ISR */ +@/* calling _tx_thread_context_restore. Note that this function */ +@/* assumes the system stack pointer is in the same position after */ +@/* nesting start function was called. */ +@/* */ +@/* This function assumes that the system mode stack pointer was setup */ +@/* during low-level initialization (tx_initialize_low_level.s). */ +@/* */ +@/* This function returns with IRQ interrupts disabled. */ +@/* */ +@/* INPUT */ +@/* */ +@/* None */ +@/* */ +@/* OUTPUT */ +@/* */ +@/* None */ +@/* */ +@/* CALLS */ +@/* */ +@/* None */ +@/* */ +@/* CALLED BY */ +@/* */ +@/* ISRs */ +@/* */ +@/**************************************************************************/ +@VOID _tx_thread_irq_nesting_end(VOID) +@{ + .global _tx_thread_irq_nesting_end + .type _tx_thread_irq_nesting_end,function +_tx_thread_irq_nesting_end: + MOV r3,lr @ Save ISR return address + MRS r0, CPSR @ Pickup the CPSR + ORR r0, r0, #DISABLE_INTS @ Build disable interrupt value + MSR CPSR_c, r0 @ Disable interrupts + LDMIA sp!, {r1, lr} @ Pickup saved lr (and r1 throw-away for + @ 8-byte alignment logic) + BIC r0, r0, #MODE_MASK @ Clear mode bits + ORR r0, r0, #IRQ_MODE_BITS @ Build IRQ mode CPSR + MSR CPSR_c, r0 @ Reenter IRQ mode +#ifdef __THUMB_INTERWORK + BX r3 @ Return to caller +#else + MOV pc, r3 @ Return to caller +#endif +@} + diff --git a/ports/cortex_r52/gnu/src/tx_thread_irq_nesting_start.S b/ports/cortex_r52/gnu/src/tx_thread_irq_nesting_start.S new file mode 100644 index 000000000..38134b7da --- /dev/null +++ b/ports/cortex_r52/gnu/src/tx_thread_irq_nesting_start.S @@ -0,0 +1,99 @@ +@/*************************************************************************** +@ * Copyright (c) 2024 Microsoft Corporation +@ * 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 +@ **************************************************************************/ +@ Some portions generated by Claude Code (Opus 5). +@ +@ +@/**************************************************************************/ +@/**************************************************************************/ +@/** */ +@/** ThreadX Component */ +@/** */ +@/** Thread */ +@/** */ +@/**************************************************************************/ +@/**************************************************************************/ +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + +IRQ_DISABLE = 0x80 @ IRQ disable bit +MODE_MASK = 0x1F @ Mode mask +SYS_MODE_BITS = 0x1F @ System mode bits +@ +@ +@/* No 16-bit Thumb mode veneer code is needed for _tx_thread_irq_nesting_start +@ since it will never be called 16-bit mode. */ +@ + .arm + .text + .align 2 +@/**************************************************************************/ +@/* */ +@/* FUNCTION RELEASE */ +@/* */ +@/* _tx_thread_irq_nesting_start Cortex-R52/GNU */ +@/* 6.5.2 */ +@/* AUTHOR */ +@/* */ +@/* Frédéric Desbiens, Eclipse Foundation */ +@/* */ +@/* Derived from the Cortex-R5/GNU port originally written by */ +@/* William E. Lamie, Microsoft Corporation. */ +@/* */ +@/* DESCRIPTION */ +@/* */ +@/* This function is called by the application from IRQ mode after */ +@/* _tx_thread_context_save has been called and switches the IRQ */ +@/* processing to the system mode so nested IRQ interrupt processing */ +@/* is possible (system mode has its own "lr" register). Note that */ +@/* this function assumes that the system mode stack pointer was setup */ +@/* during low-level initialization (tx_initialize_low_level.s). */ +@/* */ +@/* This function returns with IRQ interrupts enabled. */ +@/* */ +@/* INPUT */ +@/* */ +@/* None */ +@/* */ +@/* OUTPUT */ +@/* */ +@/* None */ +@/* */ +@/* CALLS */ +@/* */ +@/* None */ +@/* */ +@/* CALLED BY */ +@/* */ +@/* ISRs */ +@/* */ +@/**************************************************************************/ +@VOID _tx_thread_irq_nesting_start(VOID) +@{ + .global _tx_thread_irq_nesting_start + .type _tx_thread_irq_nesting_start,function +_tx_thread_irq_nesting_start: + MOV r3,lr @ Save ISR return address + MRS r0, CPSR @ Pickup the CPSR + BIC r0, r0, #MODE_MASK @ Clear the mode bits + ORR r0, r0, #SYS_MODE_BITS @ Build system mode CPSR + MSR CPSR_c, r0 @ Enter system mode + STMDB sp!, {r1, lr} @ Push the system mode lr on the system mode stack + @ and push r1 just to keep 8-byte alignment + BIC r0, r0, #IRQ_DISABLE @ Build enable IRQ CPSR + MSR CPSR_c, r0 @ Enter system mode +#ifdef __THUMB_INTERWORK + BX r3 @ Return to caller +#else + MOV pc, r3 @ Return to caller +#endif +@} + diff --git a/ports/cortex_r52/gnu/src/tx_thread_schedule.S b/ports/cortex_r52/gnu/src/tx_thread_schedule.S new file mode 100644 index 000000000..271667fb7 --- /dev/null +++ b/ports/cortex_r52/gnu/src/tx_thread_schedule.S @@ -0,0 +1,240 @@ +@/*************************************************************************** +@ * Copyright (c) 2024 Microsoft Corporation +@ * 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 +@ **************************************************************************/ +@ Some portions generated by Claude Code (Opus 5). +@ +@ +@/**************************************************************************/ +@/**************************************************************************/ +@/** */ +@/** ThreadX Component */ +@/** */ +@/** Thread */ +@/** */ +@/**************************************************************************/ +@/**************************************************************************/ +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + + .global _tx_thread_execute_ptr + .global _tx_thread_current_ptr + .global _tx_timer_time_slice + .global _tx_execution_thread_enter +@ +@ +@/* Define the 16-bit Thumb mode veneer for _tx_thread_schedule for +@ applications calling this function from to 16-bit Thumb mode. */ +@ + .text + .align 2 + .global $_tx_thread_schedule + .type $_tx_thread_schedule,function +$_tx_thread_schedule: + .thumb + BX pc @ Switch to 32-bit mode + NOP @ + .arm + STMFD sp!, {lr} @ Save return address + BL _tx_thread_schedule @ Call _tx_thread_schedule function + LDMFD sp!, {lr} @ Recover saved return address + BX lr @ Return to 16-bit caller +@ +@ + .text + .align 2 +@/**************************************************************************/ +@/* */ +@/* FUNCTION RELEASE */ +@/* */ +@/* _tx_thread_schedule Cortex-R52/GNU */ +@/* 6.5.2 */ +@/* AUTHOR */ +@/* */ +@/* Frédéric Desbiens, Eclipse Foundation */ +@/* */ +@/* Derived from the Cortex-R5/GNU port originally written by */ +@/* William E. Lamie, Microsoft Corporation. */ +@/* */ +@/* DESCRIPTION */ +@/* */ +@/* This function waits for a thread control block pointer to appear in */ +@/* the _tx_thread_execute_ptr variable. Once a thread pointer appears */ +@/* in the variable, the corresponding thread is resumed. */ +@/* */ +@/* INPUT */ +@/* */ +@/* None */ +@/* */ +@/* OUTPUT */ +@/* */ +@/* None */ +@/* */ +@/* CALLS */ +@/* */ +@/* None */ +@/* */ +@/* CALLED BY */ +@/* */ +@/* _tx_initialize_kernel_enter ThreadX entry function */ +@/* _tx_thread_system_return Return to system from thread */ +@/* _tx_thread_context_restore Restore thread's context */ +@/* */ +@/**************************************************************************/ +@VOID _tx_thread_schedule(VOID) +@{ + .global _tx_thread_schedule + .type _tx_thread_schedule,function +_tx_thread_schedule: +@ +@ /* Enable interrupts. */ +@ +#ifdef TX_ENABLE_FIQ_SUPPORT + CPSIE if @ Enable IRQ and FIQ interrupts +#else + CPSIE i @ Enable IRQ interrupts +#endif +@ +@ /* Wait for a thread to execute. */ +@ do +@ { + LDR r1, =_tx_thread_execute_ptr @ Address of thread execute ptr +@ +__tx_thread_schedule_loop: +@ + LDR r0, [r1] @ Pickup next thread to execute + CMP r0, #0 @ Is it NULL? + BEQ __tx_thread_schedule_loop @ If so, keep looking for a thread +@ +@ } +@ while(_tx_thread_execute_ptr == TX_NULL); +@ +@ /* Yes! We have a thread to execute. Lockout interrupts and +@ transfer control to it. */ +@ +#ifdef TX_ENABLE_FIQ_SUPPORT + CPSID if @ Disable IRQ and FIQ interrupts +#else + CPSID i @ Disable IRQ interrupts +#endif +@ +@ /* Setup the current thread pointer. */ +@ _tx_thread_current_ptr = _tx_thread_execute_ptr; +@ + LDR r1, =_tx_thread_current_ptr @ Pickup address of current thread + STR r0, [r1] @ Setup current thread pointer +@ +@ /* Increment the run count for this thread. */ +@ _tx_thread_current_ptr -> tx_thread_run_count++; +@ + LDR r2, [r0, #4] @ Pickup run counter + LDR r3, [r0, #24] @ Pickup time-slice for this thread + ADD r2, r2, #1 @ Increment thread run-counter + STR r2, [r0, #4] @ Store the new run counter +@ +@ /* Setup time-slice, if present. */ +@ _tx_timer_time_slice = _tx_thread_current_ptr -> tx_thread_time_slice; +@ + LDR r2, =_tx_timer_time_slice @ Pickup address of time-slice + @ variable + LDR sp, [r0, #8] @ Switch stack pointers + STR r3, [r2] @ Setup time-slice +@ +@ /* Switch to the thread's stack. */ +@ sp = _tx_thread_execute_ptr -> tx_thread_stack_ptr; +@ +#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +@ +@ /* Call the thread entry function to indicate the thread is executing. */ +@ + BL _tx_execution_thread_enter @ Call the thread execution enter function +#endif +@ +@ /* Determine if an interrupt frame or a synchronous task suspension frame +@ is present. */ +@ + LDMIA sp!, {r4, r5} @ Pickup the stack type and saved CPSR + CMP r4, #0 @ Check for synchronous context switch + BEQ _tx_solicited_return + MSR SPSR_cxsf, r5 @ Setup SPSR for return +#ifdef TX_ENABLE_VFP_SUPPORT + LDR r1, [r0, #144] @ Pickup the VFP enabled flag + CMP r1, #0 @ Is the VFP enabled? + BEQ _tx_skip_interrupt_vfp_restore @ No, skip VFP interrupt restore + VLDMIA sp!, {D0-D15} @ Recover D0-D15 + LDR r4, [sp], #4 @ Pickup FPSCR + VMSR FPSCR, r4 @ Restore FPSCR +_tx_skip_interrupt_vfp_restore: +#endif + LDMIA sp!, {r0-r12, lr, pc}^ @ Return to point of thread interrupt +@ +_tx_solicited_return: +#ifdef TX_ENABLE_VFP_SUPPORT + LDR r1, [r0, #144] @ Pickup the VFP enabled flag + CMP r1, #0 @ Is the VFP enabled? + BEQ _tx_skip_solicited_vfp_restore @ No, skip VFP solicited restore + VLDMIA sp!, {D8-D15} @ Recover D8-D15 + LDR r4, [sp], #4 @ Pickup FPSCR + VMSR FPSCR, r4 @ Restore FPSCR +_tx_skip_solicited_vfp_restore: +#endif + MOV r0, r5 @ Move CPSR to scratch register + LDMIA sp!, {r4-r11, lr} @ Return to thread synchronously + MSR CPSR_cxsf, r0 @ Recover CPSR +@ +#ifdef __THUMB_INTERWORK + BX lr @ Return to caller +#else + MOV pc, lr @ Return to caller +#endif +@ +@} +@ +@ +#ifdef TX_ENABLE_VFP_SUPPORT + .global tx_thread_vfp_enable + .type tx_thread_vfp_enable,function +tx_thread_vfp_enable: + MRS r2, CPSR @ Pickup the CPSR +#ifdef TX_ENABLE_FIQ_SUPPORT + CPSID if @ Disable IRQ and FIQ interrupts +#else + CPSID i @ Disable IRQ interrupts +#endif + LDR r0, =_tx_thread_current_ptr @ Build current thread pointer address + LDR r1, [r0] @ Pickup current thread pointer + CMP r1, #0 @ Check for NULL thread pointer + BEQ __tx_no_thread_to_enable @ If NULL, skip VFP enable + MOV r0, #1 @ Build enable value + STR r0, [r1, #144] @ Set the VFP enable flag (tx_thread_vfp_enable field in TX_THREAD) +__tx_no_thread_to_enable: + MSR CPSR_cxsf, r2 @ Recover CPSR + BX LR @ Return to caller +@ + .global tx_thread_vfp_disable + .type tx_thread_vfp_disable,function +tx_thread_vfp_disable: + MRS r2, CPSR @ Pickup the CPSR +#ifdef TX_ENABLE_FIQ_SUPPORT + CPSID if @ Disable IRQ and FIQ interrupts +#else + CPSID i @ Disable IRQ interrupts +#endif + LDR r0, =_tx_thread_current_ptr @ Build current thread pointer address + LDR r1, [r0] @ Pickup current thread pointer + CMP r1, #0 @ Check for NULL thread pointer + BEQ __tx_no_thread_to_disable @ If NULL, skip VFP disable + MOV r0, #0 @ Build disable value + STR r0, [r1, #144] @ Clear the VFP enable flag (tx_thread_vfp_enable field in TX_THREAD) +__tx_no_thread_to_disable: + MSR CPSR_cxsf, r2 @ Recover CPSR + BX LR @ Return to caller +#endif + diff --git a/ports/cortex_r52/gnu/src/tx_thread_stack_build.S b/ports/cortex_r52/gnu/src/tx_thread_stack_build.S new file mode 100644 index 000000000..dc9238c43 --- /dev/null +++ b/ports/cortex_r52/gnu/src/tx_thread_stack_build.S @@ -0,0 +1,170 @@ +@/*************************************************************************** +@ * Copyright (c) 2024 Microsoft Corporation +@ * 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 +@ **************************************************************************/ +@ Some portions generated by Claude Code (Opus 5). +@ +@ +@/**************************************************************************/ +@/**************************************************************************/ +@/** */ +@/** ThreadX Component */ +@/** */ +@/** Thread */ +@/** */ +@/**************************************************************************/ +@/**************************************************************************/ +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + + .arm + +SVC_MODE = 0x13 @ SVC mode +#ifdef TX_ENABLE_FIQ_SUPPORT +CPSR_MASK = 0xDF @ Mask initial CPSR, IRQ & FIQ interrupts enabled +#else +CPSR_MASK = 0x9F @ Mask initial CPSR, IRQ interrupts enabled +#endif +@ +@ +@/* Define the 16-bit Thumb mode veneer for _tx_thread_stack_build for +@ applications calling this function from to 16-bit Thumb mode. */ +@ + .text + .align 2 + .thumb + .global $_tx_thread_stack_build + .type $_tx_thread_stack_build,function +$_tx_thread_stack_build: + BX pc @ Switch to 32-bit mode + NOP @ + .arm + STMFD sp!, {lr} @ Save return address + BL _tx_thread_stack_build @ Call _tx_thread_stack_build function + LDMFD sp!, {lr} @ Recover saved return address + BX lr @ Return to 16-bit caller +@ +@ + .text + .align 2 +@/**************************************************************************/ +@/* */ +@/* FUNCTION RELEASE */ +@/* */ +@/* _tx_thread_stack_build Cortex-R52/GNU */ +@/* 6.5.2 */ +@/* AUTHOR */ +@/* */ +@/* Frédéric Desbiens, Eclipse Foundation */ +@/* */ +@/* Derived from the Cortex-R5/GNU port originally written by */ +@/* William E. Lamie, Microsoft Corporation. */ +@/* */ +@/* DESCRIPTION */ +@/* */ +@/* This function builds a stack frame on the supplied thread's stack. */ +@/* The stack frame results in a fake interrupt return to the supplied */ +@/* function pointer. */ +@/* */ +@/* INPUT */ +@/* */ +@/* thread_ptr Pointer to thread control blk */ +@/* function_ptr Pointer to return function */ +@/* */ +@/* OUTPUT */ +@/* */ +@/* None */ +@/* */ +@/* CALLS */ +@/* */ +@/* None */ +@/* */ +@/* CALLED BY */ +@/* */ +@/* _tx_thread_create Create thread service */ +@/* */ +@/**************************************************************************/ +@VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID)) +@{ + .global _tx_thread_stack_build + .type _tx_thread_stack_build,function +_tx_thread_stack_build: +@ +@ +@ /* Build a fake interrupt frame. The form of the fake interrupt stack +@ on the ARM9 should look like the following after it is built: +@ +@ Stack Top: 1 Interrupt stack frame type +@ CPSR Initial value for CPSR +@ a1 (r0) Initial value for a1 +@ a2 (r1) Initial value for a2 +@ a3 (r2) Initial value for a3 +@ a4 (r3) Initial value for a4 +@ v1 (r4) Initial value for v1 +@ v2 (r5) Initial value for v2 +@ v3 (r6) Initial value for v3 +@ v4 (r7) Initial value for v4 +@ v5 (r8) Initial value for v5 +@ sb (r9) Initial value for sb +@ sl (r10) Initial value for sl +@ fp (r11) Initial value for fp +@ ip (r12) Initial value for ip +@ lr (r14) Initial value for lr +@ pc (r15) Initial value for pc +@ 0 For stack backtracing +@ +@ Stack Bottom: (higher memory address) */ +@ + LDR r2, [r0, #16] @ Pickup end of stack area + BIC r2, r2, #7 @ Ensure 8-byte alignment + SUB r2, r2, #76 @ Allocate space for the stack frame +@ +@ /* Actually build the stack frame. */ +@ + MOV r3, #1 @ Build interrupt stack type + STR r3, [r2, #0] @ Store stack type + MOV r3, #0 @ Build initial register value + STR r3, [r2, #8] @ Store initial r0 + STR r3, [r2, #12] @ Store initial r1 + STR r3, [r2, #16] @ Store initial r2 + STR r3, [r2, #20] @ Store initial r3 + STR r3, [r2, #24] @ Store initial r4 + STR r3, [r2, #28] @ Store initial r5 + STR r3, [r2, #32] @ Store initial r6 + STR r3, [r2, #36] @ Store initial r7 + STR r3, [r2, #40] @ Store initial r8 + STR r3, [r2, #44] @ Store initial r9 + LDR r3, [r0, #12] @ Pickup stack starting address + STR r3, [r2, #48] @ Store initial r10 (sl) + LDR r3,=_tx_thread_schedule @ Pickup address of _tx_thread_schedule for GDB backtrace + STR r3, [r2, #60] @ Store initial r14 (lr) + MOV r3, #0 @ Build initial register value + STR r3, [r2, #52] @ Store initial r11 + STR r3, [r2, #56] @ Store initial r12 + STR r1, [r2, #64] @ Store initial pc + STR r3, [r2, #68] @ 0 for back-trace + MRS r1, CPSR @ Pickup CPSR + BIC r1, r1, #CPSR_MASK @ Mask mode bits of CPSR + ORR r3, r1, #SVC_MODE @ Build CPSR, SVC mode, interrupts enabled + STR r3, [r2, #4] @ Store initial CPSR +@ +@ /* Setup stack pointer. */ +@ thread_ptr -> tx_thread_stack_ptr = r2; +@ + STR r2, [r0, #8] @ Save stack pointer in thread's + @ control block +#ifdef __THUMB_INTERWORK + BX lr @ Return to caller +#else + MOV pc, lr @ Return to caller +#endif +@} + + diff --git a/ports/cortex_r52/gnu/src/tx_thread_system_return.S b/ports/cortex_r52/gnu/src/tx_thread_system_return.S new file mode 100644 index 000000000..c0ab615b4 --- /dev/null +++ b/ports/cortex_r52/gnu/src/tx_thread_system_return.S @@ -0,0 +1,169 @@ +@/*************************************************************************** +@ * Copyright (c) 2024 Microsoft Corporation +@ * 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 +@ **************************************************************************/ +@ Some portions generated by Claude Code (Opus 5). +@ +@ +@/**************************************************************************/ +@/**************************************************************************/ +@/** */ +@/** ThreadX Component */ +@/** */ +@/** Thread */ +@/** */ +@/**************************************************************************/ +@/**************************************************************************/ +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + + .arm +@ +@ + .global _tx_thread_current_ptr + .global _tx_timer_time_slice + .global _tx_thread_schedule + .global _tx_execution_thread_exit +@ +@ +@ +@/* Define the 16-bit Thumb mode veneer for _tx_thread_system_return for +@ applications calling this function from to 16-bit Thumb mode. */ +@ + .text + .align 2 + .global $_tx_thread_system_return + .type $_tx_thread_system_return,function +$_tx_thread_system_return: + .thumb + BX pc @ Switch to 32-bit mode + NOP @ + .arm + STMFD sp!, {lr} @ Save return address + BL _tx_thread_system_return @ Call _tx_thread_system_return function + LDMFD sp!, {lr} @ Recover saved return address + BX lr @ Return to 16-bit caller +@ +@ + .text + .align 2 +@/**************************************************************************/ +@/* */ +@/* FUNCTION RELEASE */ +@/* */ +@/* _tx_thread_system_return Cortex-R52/GNU */ +@/* 6.5.2 */ +@/* AUTHOR */ +@/* */ +@/* Frédéric Desbiens, Eclipse Foundation */ +@/* */ +@/* Derived from the Cortex-R5/GNU port originally written by */ +@/* William E. Lamie, Microsoft Corporation. */ +@/* */ +@/* DESCRIPTION */ +@/* */ +@/* This function is target processor specific. It is used to transfer */ +@/* control from a thread back to the ThreadX system. Only a */ +@/* minimal context is saved since the compiler assumes temp registers */ +@/* are going to get slicked by a function call anyway. */ +@/* */ +@/* INPUT */ +@/* */ +@/* None */ +@/* */ +@/* OUTPUT */ +@/* */ +@/* None */ +@/* */ +@/* CALLS */ +@/* */ +@/* _tx_thread_schedule Thread scheduling loop */ +@/* */ +@/* CALLED BY */ +@/* */ +@/* ThreadX components */ +@/* */ +@/**************************************************************************/ +@VOID _tx_thread_system_return(VOID) +@{ + .global _tx_thread_system_return + .type _tx_thread_system_return,function +_tx_thread_system_return: +@ +@ /* Lockout interrupts. */ +@ + MRS r1, CPSR @ Pickup the CPSR +#ifdef TX_ENABLE_FIQ_SUPPORT + CPSID if @ Disable IRQ and FIQ interrupts +#else + CPSID i @ Disable IRQ interrupts +#endif +@ /* Save minimal context on the stack. */ +@ + STMDB sp!, {r4-r11, lr} @ Save minimal context + LDR r5, =_tx_thread_current_ptr @ Pickup address of current ptr + LDR r6, [r5, #0] @ Pickup current thread pointer +@ +#ifdef TX_ENABLE_VFP_SUPPORT + LDR r0, [r6, #144] @ Pickup the VFP enabled flag + CMP r0, #0 @ Is the VFP enabled? + BEQ _tx_skip_solicited_vfp_save @ No, skip VFP solicited save + VMRS r4, FPSCR @ Pickup the FPSCR + STR r4, [sp, #-4]! @ Save FPSCR + VSTMDB sp!, {D8-D15} @ Save D8-D15 +_tx_skip_solicited_vfp_save: +#endif +@ + MOV r0, #0 @ Build a solicited stack type + STMDB sp!, {r0-r1} @ Save type and CPSR +@ +@ +#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +@ +@ /* Call the thread exit function to indicate the thread is no longer executing. */ +@ + BL _tx_execution_thread_exit @ Call the thread exit function +#endif +@ + LDR r2, =_tx_timer_time_slice @ Pickup address of time slice + LDR r1, [r2, #0] @ Pickup current time slice +@ +@ /* Save current stack and switch to system stack. */ +@ _tx_thread_current_ptr -> tx_thread_stack_ptr = sp; +@ sp = _tx_thread_system_stack_ptr; +@ + STR sp, [r6, #8] @ Save thread stack pointer +@ +@ /* Determine if the time-slice is active. */ +@ if (_tx_timer_time_slice) +@ { +@ + MOV r4, #0 @ Build clear value + CMP r1, #0 @ Is a time-slice active? + BEQ __tx_thread_dont_save_ts @ No, don't save the time-slice +@ +@ /* Save time-slice for the thread and clear the current time-slice. */ +@ _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice; +@ _tx_timer_time_slice = 0; +@ + STR r4, [r2, #0] @ Clear time-slice + STR r1, [r6, #24] @ Save current time-slice +@ +@ } +__tx_thread_dont_save_ts: +@ +@ /* Clear the current thread pointer. */ +@ _tx_thread_current_ptr = TX_NULL; +@ + STR r4, [r5, #0] @ Clear current thread pointer + B _tx_thread_schedule @ Jump to scheduler! +@ +@} + diff --git a/ports/cortex_r52/gnu/src/tx_thread_vectored_context_save.S b/ports/cortex_r52/gnu/src/tx_thread_vectored_context_save.S new file mode 100644 index 000000000..68e945e06 --- /dev/null +++ b/ports/cortex_r52/gnu/src/tx_thread_vectored_context_save.S @@ -0,0 +1,181 @@ +@/*************************************************************************** +@ * Copyright (c) 2024 Microsoft Corporation +@ * 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 +@ **************************************************************************/ +@ Some portions generated by Claude Code (Opus 5). +@ +@ +@/**************************************************************************/ +@/**************************************************************************/ +@/** */ +@/** ThreadX Component */ +@/** */ +@/** Thread */ +@/** */ +@/**************************************************************************/ +@/**************************************************************************/ +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + + .global _tx_thread_system_state + .global _tx_thread_current_ptr + .global _tx_execution_isr_enter +@ +@ +@ +@/* No 16-bit Thumb mode veneer code is needed for _tx_thread_vectored_context_save +@ since it will never be called 16-bit mode. */ +@ + .arm + .text + .align 2 +@/**************************************************************************/ +@/* */ +@/* FUNCTION RELEASE */ +@/* */ +@/* _tx_thread_vectored_context_save Cortex-R52/GNU */ +@/* 6.5.2 */ +@/* AUTHOR */ +@/* */ +@/* Frédéric Desbiens, Eclipse Foundation */ +@/* */ +@/* Derived from the Cortex-R5/GNU port originally written by */ +@/* William E. Lamie, Microsoft Corporation. */ +@/* */ +@/* DESCRIPTION */ +@/* */ +@/* This function saves the context of an executing thread in the */ +@/* beginning of interrupt processing. The function also ensures that */ +@/* the system stack is used upon return to the calling ISR. */ +@/* */ +@/* INPUT */ +@/* */ +@/* None */ +@/* */ +@/* OUTPUT */ +@/* */ +@/* None */ +@/* */ +@/* CALLS */ +@/* */ +@/* None */ +@/* */ +@/* CALLED BY */ +@/* */ +@/* ISRs */ +@/* */ +@/**************************************************************************/ +@VOID _tx_thread_vectored_context_save(VOID) +@{ + .global _tx_thread_vectored_context_save + .type _tx_thread_vectored_context_save,function +_tx_thread_vectored_context_save: +@ +@ /* Upon entry to this routine, it is assumed that IRQ interrupts are locked +@ out, we are in IRQ mode, and all registers are intact. */ +@ +@ /* Check for a nested interrupt condition. */ +@ if (_tx_thread_system_state++) +@ { +@ +#ifdef TX_ENABLE_FIQ_SUPPORT + CPSID if @ Disable IRQ and FIQ interrupts +#endif + LDR r3, =_tx_thread_system_state @ Pickup address of system state variable + LDR r2, [r3, #0] @ Pickup system state + CMP r2, #0 @ Is this the first interrupt? + BEQ __tx_thread_not_nested_save @ Yes, not a nested context save +@ +@ /* Nested interrupt condition. */ +@ + ADD r2, r2, #1 @ Increment the interrupt counter + STR r2, [r3, #0] @ Store it back in the variable +@ +@ /* Note: Minimal context of interrupted thread is already saved. */ +@ +@ /* Return to the ISR. */ +@ + MOV r10, #0 @ Clear stack limit + +#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +@ +@ /* Call the ISR enter function to indicate an ISR is executing. */ +@ + PUSH {lr} @ Save ISR lr + BL _tx_execution_isr_enter @ Call the ISR enter function + POP {lr} @ Recover ISR lr +#endif + + MOV pc, lr @ Return to caller +@ +__tx_thread_not_nested_save: +@ } +@ +@ /* Otherwise, not nested, check to see if a thread was running. */ +@ else if (_tx_thread_current_ptr) +@ { +@ + ADD r2, r2, #1 @ Increment the interrupt counter + STR r2, [r3, #0] @ Store it back in the variable + LDR r1, =_tx_thread_current_ptr @ Pickup address of current thread ptr + LDR r0, [r1, #0] @ Pickup current thread pointer + CMP r0, #0 @ Is it NULL? + BEQ __tx_thread_idle_system_save @ If so, interrupt occurred in + @ scheduling loop - nothing needs saving! +@ +@ /* Note: Minimal context of interrupted thread is already saved. */ +@ +@ /* Save the current stack pointer in the thread's control block. */ +@ _tx_thread_current_ptr -> tx_thread_stack_ptr = sp; +@ +@ /* Switch to the system stack. */ +@ sp = _tx_thread_system_stack_ptr; +@ + MOV r10, #0 @ Clear stack limit + +#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +@ +@ /* Call the ISR enter function to indicate an ISR is executing. */ +@ + PUSH {lr} @ Save ISR lr + BL _tx_execution_isr_enter @ Call the ISR enter function + POP {lr} @ Recover ISR lr +#endif + + MOV pc, lr @ Return to caller +@ +@ } +@ else +@ { +@ +__tx_thread_idle_system_save: +@ +@ /* Interrupt occurred in the scheduling loop. */ +@ +@ /* Not much to do here, just adjust the stack pointer, and return to IRQ +@ processing. */ +@ + MOV r10, #0 @ Clear stack limit + +#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +@ +@ /* Call the ISR enter function to indicate an ISR is executing. */ +@ + PUSH {lr} @ Save ISR lr + BL _tx_execution_isr_enter @ Call the ISR enter function + POP {lr} @ Recover ISR lr +#endif + + ADD sp, sp, #32 @ Recover saved registers + MOV pc, lr @ Return to caller +@ +@ } +@} + diff --git a/ports/cortex_r52/gnu/src/tx_timer_interrupt.S b/ports/cortex_r52/gnu/src/tx_timer_interrupt.S new file mode 100644 index 000000000..7d45de601 --- /dev/null +++ b/ports/cortex_r52/gnu/src/tx_timer_interrupt.S @@ -0,0 +1,270 @@ +@/*************************************************************************** +@ * Copyright (c) 2024 Microsoft Corporation +@ * 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 +@ **************************************************************************/ +@ Some portions generated by Claude Code (Opus 5). +@ +@ +@/**************************************************************************/ +@/**************************************************************************/ +@/** */ +@/** ThreadX Component */ +@/** */ +@/** Timer */ +@/** */ +@/**************************************************************************/ +@/**************************************************************************/ +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + + .arm + +@ +@/* Define Assembly language external references... */ +@ + .global _tx_timer_time_slice + .global _tx_timer_system_clock + .global _tx_timer_current_ptr + .global _tx_timer_list_start + .global _tx_timer_list_end + .global _tx_timer_expired_time_slice + .global _tx_timer_expired + .global _tx_thread_time_slice +@ +@ +@ +@/* Define the 16-bit Thumb mode veneer for _tx_timer_interrupt for +@ applications calling this function from to 16-bit Thumb mode. */ +@ + .text + .align 2 + .thumb + .global $_tx_timer_interrupt + .type $_tx_timer_interrupt,function +$_tx_timer_interrupt: + BX pc @ Switch to 32-bit mode + NOP @ + .arm + STMFD sp!, {lr} @ Save return address + BL _tx_timer_interrupt @ Call _tx_timer_interrupt function + LDMFD sp!, {lr} @ Recover saved return address + BX lr @ Return to 16-bit caller +@ +@ + .text + .align 2 +@/**************************************************************************/ +@/* */ +@/* FUNCTION RELEASE */ +@/* */ +@/* _tx_timer_interrupt Cortex-R52/GNU */ +@/* 6.5.2 */ +@/* AUTHOR */ +@/* */ +@/* Frédéric Desbiens, Eclipse Foundation */ +@/* */ +@/* Derived from the Cortex-R5/GNU port originally written by */ +@/* William E. Lamie, Microsoft Corporation. */ +@/* */ +@/* DESCRIPTION */ +@/* */ +@/* This function processes the hardware timer interrupt. This */ +@/* processing includes incrementing the system clock and checking for */ +@/* time slice and/or timer expiration. If either is found, the */ +@/* interrupt context save/restore functions are called along with the */ +@/* expiration functions. */ +@/* */ +@/* INPUT */ +@/* */ +@/* None */ +@/* */ +@/* OUTPUT */ +@/* */ +@/* None */ +@/* */ +@/* CALLS */ +@/* */ +@/* _tx_thread_time_slice Time slice interrupted thread */ +@/* _tx_timer_expiration_process Timer expiration processing */ +@/* */ +@/* CALLED BY */ +@/* */ +@/* interrupt vector */ +@/* */ +@/**************************************************************************/ +@VOID _tx_timer_interrupt(VOID) +@{ + .global _tx_timer_interrupt + .type _tx_timer_interrupt,function +_tx_timer_interrupt: +@ +@ /* Upon entry to this routine, it is assumed that context save has already +@ been called, and therefore the compiler scratch registers are available +@ for use. */ +@ +@ /* Increment the system clock. */ +@ _tx_timer_system_clock++; +@ + LDR r1, =_tx_timer_system_clock @ Pickup address of system clock + LDR r0, [r1] @ Pickup system clock + ADD r0, r0, #1 @ Increment system clock + STR r0, [r1] @ Store new system clock +@ +@ /* Test for time-slice expiration. */ +@ if (_tx_timer_time_slice) +@ { +@ + LDR r3, =_tx_timer_time_slice @ Pickup address of time-slice + LDR r2, [r3] @ Pickup time-slice + CMP r2, #0 @ Is it non-active? + BEQ __tx_timer_no_time_slice @ Yes, skip time-slice processing +@ +@ /* Decrement the time_slice. */ +@ _tx_timer_time_slice--; +@ + SUB r2, r2, #1 @ Decrement the time-slice + STR r2, [r3] @ Store new time-slice value +@ +@ /* Check for expiration. */ +@ if (__tx_timer_time_slice == 0) +@ + CMP r2, #0 @ Has it expired? + BNE __tx_timer_no_time_slice @ No, skip expiration processing +@ +@ /* Set the time-slice expired flag. */ +@ _tx_timer_expired_time_slice = TX_TRUE; +@ + LDR r3, =_tx_timer_expired_time_slice @ Pickup address of expired flag + MOV r0, #1 @ Build expired value + STR r0, [r3] @ Set time-slice expiration flag +@ +@ } +@ +__tx_timer_no_time_slice: +@ +@ /* Test for timer expiration. */ +@ if (*_tx_timer_current_ptr) +@ { +@ + LDR r1, =_tx_timer_current_ptr @ Pickup current timer pointer address + LDR r0, [r1] @ Pickup current timer + LDR r2, [r0] @ Pickup timer list entry + CMP r2, #0 @ Is there anything in the list? + BEQ __tx_timer_no_timer @ No, just increment the timer +@ +@ /* Set expiration flag. */ +@ _tx_timer_expired = TX_TRUE; +@ + LDR r3, =_tx_timer_expired @ Pickup expiration flag address + MOV r2, #1 @ Build expired value + STR r2, [r3] @ Set expired flag + B __tx_timer_done @ Finished timer processing +@ +@ } +@ else +@ { +__tx_timer_no_timer: +@ +@ /* No timer expired, increment the timer pointer. */ +@ _tx_timer_current_ptr++; +@ + ADD r0, r0, #4 @ Move to next timer +@ +@ /* Check for wraparound. */ +@ if (_tx_timer_current_ptr == _tx_timer_list_end) +@ + LDR r3, =_tx_timer_list_end @ Pickup address of timer list end + LDR r2, [r3] @ Pickup list end + CMP r0, r2 @ Are we at list end? + BNE __tx_timer_skip_wrap @ No, skip wraparound logic +@ +@ /* Wrap to beginning of list. */ +@ _tx_timer_current_ptr = _tx_timer_list_start; +@ + LDR r3, =_tx_timer_list_start @ Pickup address of timer list start + LDR r0, [r3] @ Set current pointer to list start +@ +__tx_timer_skip_wrap: +@ + STR r0, [r1] @ Store new current timer pointer +@ } +@ +__tx_timer_done: +@ +@ +@ /* See if anything has expired. */ +@ if ((_tx_timer_expired_time_slice) || (_tx_timer_expired)) +@ { +@ + LDR r3, =_tx_timer_expired_time_slice @ Pickup address of expired flag + LDR r2, [r3] @ Pickup time-slice expired flag + CMP r2, #0 @ Did a time-slice expire? + BNE __tx_something_expired @ If non-zero, time-slice expired + LDR r1, =_tx_timer_expired @ Pickup address of other expired flag + LDR r0, [r1] @ Pickup timer expired flag + CMP r0, #0 @ Did a timer expire? + BEQ __tx_timer_nothing_expired @ No, nothing expired +@ +__tx_something_expired: +@ +@ + STMDB sp!, {r0, lr} @ Save the lr register on the stack + @ and save r0 just to keep 8-byte alignment +@ +@ /* Did a timer expire? */ +@ if (_tx_timer_expired) +@ { +@ + LDR r1, =_tx_timer_expired @ Pickup address of expired flag + LDR r0, [r1] @ Pickup timer expired flag + CMP r0, #0 @ Check for timer expiration + BEQ __tx_timer_dont_activate @ If not set, skip timer activation +@ +@ /* Process timer expiration. */ +@ _tx_timer_expiration_process(); +@ + BL _tx_timer_expiration_process @ Call the timer expiration handling routine +@ +@ } +__tx_timer_dont_activate: +@ +@ /* Did time slice expire? */ +@ if (_tx_timer_expired_time_slice) +@ { +@ + LDR r3, =_tx_timer_expired_time_slice @ Pickup address of time-slice expired + LDR r2, [r3] @ Pickup the actual flag + CMP r2, #0 @ See if the flag is set + BEQ __tx_timer_not_ts_expiration @ No, skip time-slice processing +@ +@ /* Time slice interrupted thread. */ +@ _tx_thread_time_slice(); +@ + BL _tx_thread_time_slice @ Call time-slice processing +@ +@ } +@ +__tx_timer_not_ts_expiration: +@ + LDMIA sp!, {r0, lr} @ Recover lr register (r0 is just there for + @ the 8-byte stack alignment +@ +@ } +@ +__tx_timer_nothing_expired: +@ +#ifdef __THUMB_INTERWORK + BX lr @ Return to caller +#else + MOV pc, lr @ Return to caller +#endif +@ +@} + From bd8d30f23b2f968da052092f59a7298fdc073c4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Sat, 8 Aug 2026 08:01:38 -0400 Subject: [PATCH 012/181] Fixed code_buffer leak in the module converter utilities (#581) The host-side module converter utilities allocated code_buffer inside the loop over the ELF code sections and never released it, so every code section in the input ELF leaked one buffer. The malloc() result was also unchecked, so a failed allocation passed a null pointer on to elf_object_read() and crashed the tool. Release the buffer at the end of each iteration and report a clean failure with exit code 5 when the allocation does not succeed. Verified with AddressSanitizer on a two-code-section input: 128 bytes leaked in 2 allocations before, none after, with byte-identical output. Fixes https://github.com/eclipse-threadx/threadx/issues/571 Assisted-by: Claude Code (Opus 5) --- .../utilities/module_to_binary.c | 27 +++++++++++++++++++ .../utilities/module_to_c_array.c | 27 +++++++++++++++++++ 2 files changed, 54 insertions(+) diff --git a/common_modules/module_manager/utilities/module_to_binary.c b/common_modules/module_manager/utilities/module_to_binary.c index bb4f294d0..66657fcc6 100644 --- a/common_modules/module_manager/utilities/module_to_binary.c +++ b/common_modules/module_manager/utilities/module_to_binary.c @@ -9,11 +9,20 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ +// Some portions generated by Claude Code (Opus 5) + #include #include #include +/* MISRA C:2012 Rule 21.3 and Dir 4.12 deviation: dynamic memory is used in this + file. This is a host-side conversion utility executed on the development + machine, not ThreadX runtime code, and the ELF areas being read have sizes + that are only known at run time. Every allocation result is checked for NULL + and every buffer is released before its pointer is reused. */ + + /* Define the file handles. */ FILE *source_file; @@ -310,6 +319,20 @@ unsigned char zero_value; /* Now allocate memory for the code section. */ code_buffer = malloc(code_section_array[i].code_section_size); + /* Determine if the memory allocation was successful. */ + if (code_buffer == NULL) + { + + /* Print an error message out. */ + printf("**** Error: memory allocation failed for code section **** \n"); + + /* Close files. */ + fclose(source_file); + fclose(binary_file); + + return(5); + } + /* Read in the code area. */ j = code_section_array[i].code_section_index; elf_object_read(section_header[j].elf_section_header_offset, code_buffer, code_section_array[i].code_section_size); @@ -333,6 +356,10 @@ unsigned char zero_value; /* Move index into buffer. */ j++; } + + /* Release the code section buffer before the next section is read. */ + free(code_buffer); + code_buffer = NULL; } /* Close files. */ diff --git a/common_modules/module_manager/utilities/module_to_c_array.c b/common_modules/module_manager/utilities/module_to_c_array.c index d34724164..72461e273 100644 --- a/common_modules/module_manager/utilities/module_to_c_array.c +++ b/common_modules/module_manager/utilities/module_to_c_array.c @@ -9,11 +9,20 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ +// Some portions generated by Claude Code (Opus 5) + #include #include #include +/* MISRA C:2012 Rule 21.3 and Dir 4.12 deviation: dynamic memory is used in this + file. This is a host-side conversion utility executed on the development + machine, not ThreadX runtime code, and the ELF areas being read have sizes + that are only known at run time. Every allocation result is checked for NULL + and every buffer is released before its pointer is reused. */ + + /* Define the file handles. */ FILE *source_file; @@ -342,6 +351,20 @@ CODE_SECTION_ENTRY code_section_temp; /* Now allocate memory for the code section. */ code_buffer = malloc(code_section_array[i].code_section_size); + /* Determine if the memory allocation was successful. */ + if (code_buffer == NULL) + { + + /* Print an error message out. */ + printf("**** Error: memory allocation failed for code section **** \n"); + + /* Close files. */ + fclose(source_file); + fclose(array_file); + + return(5); + } + /* Read in the code area. */ j = code_section_array[i].code_section_index; elf_object_read(section_header[j].elf_section_header_offset, code_buffer, code_section_array[i].code_section_size); @@ -390,6 +413,10 @@ CODE_SECTION_ENTRY code_section_temp; /* Move index into buffer. */ j++; } + + /* Release the code section buffer before the next section is read. */ + free(code_buffer); + code_buffer = NULL; } /* Finally, finish the C array containing the module code. */ From 2b0e4e44b94a4edcdf838912731e4c971e8f34c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Sat, 8 Aug 2026 08:09:06 -0400 Subject: [PATCH 013/181] Hardened the module converter utilities against malformed input (#580) * Hardened the module converter utilities against malformed input While reviewing the code_buffer leak reported in issue 571, three further pre-existing defects turned up in the same host-side utilities. The four ELF area allocations in module_to_binary.c and module_to_c_array.c were unchecked, and every elf_object_read() return value was discarded, so a truncated or crafted ELF file was read into whatever the allocation and the reads happened to leave behind. Check each allocation, distinguishing a NULL return for an empty area from a genuine failure, and abandon the conversion with exit code 5 on an allocation failure and exit code 6 on a read failure. Validate the section string table index taken from the ELF header before it is used to subscript the section header area. AddressSanitizer confirms that an out-of-range index produced a heap buffer overflow in both tools. Correct the address format specifiers in module_to_c_array.c and module_binary_to_c_array.c, which passed an unsigned long to %08X, and close the source file on the invalid format path of module_binary_to_c_array.c. The unused current_total local is removed. All three utilities now build warning free with gcc -std=c99 -Wall -Wextra, and the code they emit is unchanged byte for byte on valid input. Refresh the version banners of all three tools, on the console and in the header written into the generated C arrays, to the 2024 Microsoft Corp and 2026 Eclipse ThreadX contributors copyrights and version v6.5.2.202603. The banners still advertised v5.8 and v5.4 with a 2018 build date. The .exe suffix is dropped from the tool names, since these tools build on Linux too. Related to https://github.com/eclipse-threadx/threadx/issues/571 Assisted-by: Claude Code (Opus 5) * Added the missing licence header to module_binary_to_c_array.c The file carried no copyright or licence header at all, unlike the two other converter utilities in the same directory. Use the same MIT header they carry, since the three tools share an origin. Assisted-by: Claude Code (Opus 5) --- .../utilities/module_binary_to_c_array.c | 30 ++- .../utilities/module_to_binary.c | 209 +++++++++++++++-- .../utilities/module_to_c_array.c | 217 ++++++++++++++++-- 3 files changed, 407 insertions(+), 49 deletions(-) diff --git a/common_modules/module_manager/utilities/module_binary_to_c_array.c b/common_modules/module_manager/utilities/module_binary_to_c_array.c index da0cf97c6..38b38c327 100644 --- a/common_modules/module_manager/utilities/module_binary_to_c_array.c +++ b/common_modules/module_manager/utilities/module_binary_to_c_array.c @@ -1,3 +1,16 @@ +/***************************************************************************/ +/* Copyright (c) 2024 Microsoft Corporation */ +/* 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 */ +/***************************************************************************/ + +// Some portions generated by Claude Code (Opus 5) + #include #include #include @@ -25,8 +38,11 @@ unsigned long column; { /* Print an error message out and wait for user key hit. */ - printf("module_binary_to_c_array.exe - Copyright (c) Microsoft Corporation v5.8\n"); - printf("**** Error: invalid input parameter for module_binary_to_c_array.exe **** \n"); + printf("module_binary_to_c_array\n"); + printf("(c) 2024 Microsoft Corp\n"); + printf("(c) 2026 Eclipse ThreadX contributors\n"); + printf("v6.5.2.202603\n"); + printf("**** Error: invalid input parameter for module_binary_to_c_array **** \n"); printf(" Command Line Should be:\n\n"); printf(" > module_binary_to_c_array source_binary_file c_array_file \n\n"); return(1); @@ -57,6 +73,10 @@ unsigned long column; /* Print an error message out and wait for user key hit. */ printf("**** Error: invalid format of binary input file **** \n"); printf(" File: %s ", argv[1]); + + /* Close the source file. */ + fclose(source_file); + return(3); } @@ -75,7 +95,9 @@ unsigned long column; fprintf(array_file, "/**************************** Module-Binary-to-C-array Utility **********************************/\n"); fprintf(array_file, "/* */\n"); - fprintf(array_file, "/* Copyright (c) Microsoft Corporation Version 5.4, build date: 03-01-2018 */\n"); + fprintf(array_file, "/* Copyright (c) 2024 Microsoft Corp */\n"); + fprintf(array_file, "/* Copyright (c) 2026 Eclipse ThreadX contributors */\n"); + fprintf(array_file, "/* v6.5.2.202603 */\n"); fprintf(array_file, "/* */\n"); fprintf(array_file, "/************************************************************************************************/\n\n"); fprintf(array_file, "/* \n"); @@ -109,7 +131,7 @@ unsigned long column; { if (address != 0) fprintf(array_file, ",\n"); - fprintf(array_file, "/* 0x%08X */ 0x%02X", address, (unsigned int) alpha); + fprintf(array_file, "/* 0x%08lX */ 0x%02X", address, (unsigned int) alpha); } else fprintf(array_file, ", 0x%02X", (unsigned int) alpha); diff --git a/common_modules/module_manager/utilities/module_to_binary.c b/common_modules/module_manager/utilities/module_to_binary.c index 66657fcc6..b691d9e40 100644 --- a/common_modules/module_manager/utilities/module_to_binary.c +++ b/common_modules/module_manager/utilities/module_to_binary.c @@ -22,6 +22,11 @@ that are only known at run time. Every allocation result is checked for NULL and every buffer is released before its pointer is reused. */ +/* MISRA C:2012 Rule 15.5 (advisory) deviation: main() returns from several + error paths instead of having a single point of exit. The project forbids + goto, so an early return is the only way to abandon the conversion, and this + matches the style already used by the parameter and file open checks. */ + /* Define the file handles. */ @@ -146,13 +151,52 @@ unsigned char *buffer; } +/* Close the files and release the ELF areas allocated by main(). This is called + from every exit path taken after the files have been opened, so it must + tolerate being called with resources that were never acquired. The areas it + releases are the file scope pointers declared above. */ + +static void converter_cleanup(void) +{ + + /* Determine if the source file is open. */ + if (source_file != NULL) + { + + /* Close it. */ + fclose(source_file); + source_file = NULL; + } + + /* Determine if the binary output file is open. */ + if (binary_file != NULL) + { + + /* Close it. */ + fclose(binary_file); + binary_file = NULL; + } + + /* Release the ELF areas. Note that free() is defined to do nothing when it + is supplied a NULL pointer, so no test is required here. */ + free(program_header); + program_header = NULL; + free(section_header); + section_header = NULL; + free(section_string_table); + section_string_table = NULL; + free(code_section_array); + code_section_array = NULL; +} + + int main(int argc, char* argv[]) { unsigned long i, j; -unsigned long current_total; unsigned long address; unsigned long size; +unsigned long allocation_size; unsigned char *code_buffer; unsigned long code_section_index; CODE_SECTION_ENTRY code_section_temp; @@ -164,8 +208,11 @@ unsigned char zero_value; { /* Print an error message out and wait for user key hit. */ - printf("module_to_binary.exe - Copyright (c) Microsoft Corporation v5.8\n"); - printf("**** Error: invalid input parameter for module_to_binary.exe **** \n"); + printf("module_to_binary\n"); + printf("(c) 2024 Microsoft Corp\n"); + printf("(c) 2026 Eclipse ThreadX contributors\n"); + printf("v6.5.2.202603\n"); + printf("**** Error: invalid input parameter for module_to_binary **** \n"); printf(" Command Line Should be:\n\n"); printf(" > module_to_binary source_elf_file c_binary_file \n\n"); return(1); @@ -198,29 +245,140 @@ unsigned char zero_value; } /* Read the ELF header. */ - elf_object_read(0, &header, sizeof(header)); + if (elf_object_read(0, &header, sizeof(header)) != 0) + { + + /* Print an error message out. */ + printf("**** Error: read failed on the ELF header **** \n"); + + /* Close the files and release the ELF areas. */ + converter_cleanup(); + + return(6); + } /* Allocate memory for the program header(s). */ - program_header = malloc(sizeof(ELF_PROGRAM_HEADER)*header.elf_header_program_header_entries); + allocation_size = sizeof(ELF_PROGRAM_HEADER)*header.elf_header_program_header_entries; + program_header = malloc(allocation_size); + + /* Determine if the memory allocation was successful. Note that an empty area + is not an error, since malloc() is permitted to return NULL for it. */ + if ((program_header == NULL) && (allocation_size != 0)) + { + + /* Print an error message out. */ + printf("**** Error: memory allocation failed for the program header(s) **** \n"); + + /* Close the files and release the ELF areas. */ + converter_cleanup(); + + return(5); + } /* Read the program header(s). */ - elf_object_read(header.elf_header_program_header_offset, program_header, (sizeof(ELF_PROGRAM_HEADER)*header.elf_header_program_header_entries)); + if (elf_object_read(header.elf_header_program_header_offset, program_header, allocation_size) != 0) + { + + /* Print an error message out. */ + printf("**** Error: read failed on the program header(s) **** \n"); + + /* Close the files and release the ELF areas. */ + converter_cleanup(); + + return(6); + } /* Allocate memory for the section header(s). */ - section_header = malloc(sizeof(ELF_SECTION_HEADER)*header.elf_header_section_header_entries); + allocation_size = sizeof(ELF_SECTION_HEADER)*header.elf_header_section_header_entries; + section_header = malloc(allocation_size); + + /* Determine if the memory allocation was successful. */ + if ((section_header == NULL) && (allocation_size != 0)) + { + + /* Print an error message out. */ + printf("**** Error: memory allocation failed for the section header(s) **** \n"); + + /* Close the files and release the ELF areas. */ + converter_cleanup(); + + return(5); + } /* Read the section header(s). */ - elf_object_read(header.elf_header_section_header_offset, section_header, (sizeof(ELF_SECTION_HEADER)*header.elf_header_section_header_entries)); + if (elf_object_read(header.elf_header_section_header_offset, section_header, allocation_size) != 0) + { + + /* Print an error message out. */ + printf("**** Error: read failed on the section header(s) **** \n"); + + /* Close the files and release the ELF areas. */ + converter_cleanup(); + + return(6); + } + + /* Determine if the section string table index supplied by the ELF header is + inside the section header area that was just read. */ + if (header.elf_header_section_string_index >= header.elf_header_section_header_entries) + { + + /* Print an error message out. */ + printf("**** Error: invalid section string table index in the ELF header **** \n"); + + /* Close the files and release the ELF areas. */ + converter_cleanup(); + return(6); + } /* Alocate memory for the section string table. */ - section_string_table = malloc(section_header[header.elf_header_section_string_index].elf_section_header_size); + allocation_size = section_header[header.elf_header_section_string_index].elf_section_header_size; + section_string_table = malloc(allocation_size); + + /* Determine if the memory allocation was successful. */ + if ((section_string_table == NULL) && (allocation_size != 0)) + { + + /* Print an error message out. */ + printf("**** Error: memory allocation failed for the section string table **** \n"); + + /* Close the files and release the ELF areas. */ + converter_cleanup(); + + return(5); + } /* Read the section string table. */ - elf_object_read(section_header[header.elf_header_section_string_index].elf_section_header_offset, section_string_table, section_header[header.elf_header_section_string_index].elf_section_header_size); + if (elf_object_read(section_header[header.elf_header_section_string_index].elf_section_header_offset, section_string_table, allocation_size) != 0) + { + + /* Print an error message out. */ + printf("**** Error: read failed on the section string table **** \n"); + + /* Close the files and release the ELF areas. */ + converter_cleanup(); + + return(6); + } /* Allocate memory for the code section array. */ - code_section_array = malloc(sizeof(CODE_SECTION_ENTRY)*header.elf_header_section_header_entries); + allocation_size = sizeof(CODE_SECTION_ENTRY)*header.elf_header_section_header_entries; + code_section_array = malloc(allocation_size); + + /* Determine if the memory allocation was successful. */ + if ((code_section_array == NULL) && (allocation_size != 0)) + { + + /* Print an error message out. */ + printf("**** Error: memory allocation failed for the code section array **** \n"); + + /* Close the files and release the ELF areas. */ + converter_cleanup(); + + return(5); + } + code_section_index = 0; /* Print out the section header(s). */ @@ -267,9 +425,8 @@ unsigned char zero_value; if (code_section_index == 0) { - /* Close files. */ - fclose(source_file); - fclose(binary_file); + /* Close the files and release the ELF areas. */ + converter_cleanup(); return(4); } @@ -326,16 +483,27 @@ unsigned char zero_value; /* Print an error message out. */ printf("**** Error: memory allocation failed for code section **** \n"); - /* Close files. */ - fclose(source_file); - fclose(binary_file); + /* Close the files and release the ELF areas. */ + converter_cleanup(); return(5); } /* Read in the code area. */ j = code_section_array[i].code_section_index; - elf_object_read(section_header[j].elf_section_header_offset, code_buffer, code_section_array[i].code_section_size); + if (elf_object_read(section_header[j].elf_section_header_offset, code_buffer, code_section_array[i].code_section_size) != 0) + { + + /* Print an error message out. */ + printf("**** Error: read failed on a code section **** \n"); + + /* Release the code section buffer, then close the files and release + the ELF areas. */ + free(code_buffer); + converter_cleanup(); + + return(6); + } /* Write out the contents of this program area. */ size = code_section_array[i].code_section_size; @@ -362,9 +530,8 @@ unsigned char zero_value; code_buffer = NULL; } - /* Close files. */ - fclose(source_file); - fclose(binary_file); + /* Close the files and release the ELF areas. */ + converter_cleanup(); return 0; } diff --git a/common_modules/module_manager/utilities/module_to_c_array.c b/common_modules/module_manager/utilities/module_to_c_array.c index 72461e273..554d13ba8 100644 --- a/common_modules/module_manager/utilities/module_to_c_array.c +++ b/common_modules/module_manager/utilities/module_to_c_array.c @@ -22,6 +22,11 @@ that are only known at run time. Every allocation result is checked for NULL and every buffer is released before its pointer is reused. */ +/* MISRA C:2012 Rule 15.5 (advisory) deviation: main() returns from several + error paths instead of having a single point of exit. The project forbids + goto, so an early return is the only way to abandon the conversion, and this + matches the style already used by the parameter and file open checks. */ + /* Define the file handles. */ @@ -146,13 +151,52 @@ unsigned char *buffer; } +/* Close the files and release the ELF areas allocated by main(). This is called + from every exit path taken after the files have been opened, so it must + tolerate being called with resources that were never acquired. The areas it + releases are the file scope pointers declared above. */ + +static void converter_cleanup(void) +{ + + /* Determine if the source file is open. */ + if (source_file != NULL) + { + + /* Close it. */ + fclose(source_file); + source_file = NULL; + } + + /* Determine if the C array output file is open. */ + if (array_file != NULL) + { + + /* Close it. */ + fclose(array_file); + array_file = NULL; + } + + /* Release the ELF areas. Note that free() is defined to do nothing when it + is supplied a NULL pointer, so no test is required here. */ + free(program_header); + program_header = NULL; + free(section_header); + section_header = NULL; + free(section_string_table); + section_string_table = NULL; + free(code_section_array); + code_section_array = NULL; +} + + int main(int argc, char* argv[]) { unsigned long i, j, k; -unsigned long current_total; unsigned long address; unsigned long size; +unsigned long allocation_size; unsigned long column; unsigned char *code_buffer; unsigned long code_section_index; @@ -164,8 +208,11 @@ CODE_SECTION_ENTRY code_section_temp; { /* Print an error message out and wait for user key hit. */ - printf("module_to_c_array.exe - Copyright (c) Microsoft Corporation v5.8\n"); - printf("**** Error: invalid input parameter for module_to_c_array.exe **** \n"); + printf("module_to_c_array\n"); + printf("(c) 2024 Microsoft Corp\n"); + printf("(c) 2026 Eclipse ThreadX contributors\n"); + printf("v6.5.2.202603\n"); + printf("**** Error: invalid input parameter for module_to_c_array **** \n"); printf(" Command Line Should be:\n\n"); printf(" > module_to_c_array source_elf_file c_array_file \n\n"); return(1); @@ -198,11 +245,23 @@ CODE_SECTION_ENTRY code_section_temp; } /* Read the ELF header. */ - elf_object_read(0, &header, sizeof(header)); + if (elf_object_read(0, &header, sizeof(header)) != 0) + { + + /* Print an error message out. */ + printf("**** Error: read failed on the ELF header **** \n"); + + /* Close the files and release the ELF areas. */ + converter_cleanup(); + + return(6); + } fprintf(array_file, "/**************************** Module-to-C-array Utility *****************************************/\n"); fprintf(array_file, "/* */\n"); - fprintf(array_file, "/* Copyright (c) Microsoft Corporation Version 5.8, build date: 03-01-2018 */\n"); + fprintf(array_file, "/* Copyright (c) 2024 Microsoft Corp */\n"); + fprintf(array_file, "/* Copyright (c) 2026 Eclipse ThreadX contributors */\n"); + fprintf(array_file, "/* v6.5.2.202603 */\n"); fprintf(array_file, "/* */\n"); fprintf(array_file, "/************************************************************************************************/\n\n"); fprintf(array_file, "/* \n"); @@ -211,26 +270,127 @@ CODE_SECTION_ENTRY code_section_temp; fprintf(array_file, "*/\n\n"); /* Allocate memory for the program header(s). */ - program_header = malloc(sizeof(ELF_PROGRAM_HEADER)*header.elf_header_program_header_entries); + allocation_size = sizeof(ELF_PROGRAM_HEADER)*header.elf_header_program_header_entries; + program_header = malloc(allocation_size); + + /* Determine if the memory allocation was successful. Note that an empty area + is not an error, since malloc() is permitted to return NULL for it. */ + if ((program_header == NULL) && (allocation_size != 0)) + { + + /* Print an error message out. */ + printf("**** Error: memory allocation failed for the program header(s) **** \n"); + + /* Close the files and release the ELF areas. */ + converter_cleanup(); + + return(5); + } /* Read the program header(s). */ - elf_object_read(header.elf_header_program_header_offset, program_header, (sizeof(ELF_PROGRAM_HEADER)*header.elf_header_program_header_entries)); + if (elf_object_read(header.elf_header_program_header_offset, program_header, allocation_size) != 0) + { + + /* Print an error message out. */ + printf("**** Error: read failed on the program header(s) **** \n"); + + /* Close the files and release the ELF areas. */ + converter_cleanup(); + + return(6); + } /* Allocate memory for the section header(s). */ - section_header = malloc(sizeof(ELF_SECTION_HEADER)*header.elf_header_section_header_entries); + allocation_size = sizeof(ELF_SECTION_HEADER)*header.elf_header_section_header_entries; + section_header = malloc(allocation_size); + + /* Determine if the memory allocation was successful. */ + if ((section_header == NULL) && (allocation_size != 0)) + { + + /* Print an error message out. */ + printf("**** Error: memory allocation failed for the section header(s) **** \n"); + + /* Close the files and release the ELF areas. */ + converter_cleanup(); + + return(5); + } /* Read the section header(s). */ - elf_object_read(header.elf_header_section_header_offset, section_header, (sizeof(ELF_SECTION_HEADER)*header.elf_header_section_header_entries)); + if (elf_object_read(header.elf_header_section_header_offset, section_header, allocation_size) != 0) + { + + /* Print an error message out. */ + printf("**** Error: read failed on the section header(s) **** \n"); + + /* Close the files and release the ELF areas. */ + converter_cleanup(); + + return(6); + } + + /* Determine if the section string table index supplied by the ELF header is + inside the section header area that was just read. */ + if (header.elf_header_section_string_index >= header.elf_header_section_header_entries) + { + + /* Print an error message out. */ + printf("**** Error: invalid section string table index in the ELF header **** \n"); + + /* Close the files and release the ELF areas. */ + converter_cleanup(); + return(6); + } /* Alocate memory for the section string table. */ - section_string_table = malloc(section_header[header.elf_header_section_string_index].elf_section_header_size); + allocation_size = section_header[header.elf_header_section_string_index].elf_section_header_size; + section_string_table = malloc(allocation_size); + + /* Determine if the memory allocation was successful. */ + if ((section_string_table == NULL) && (allocation_size != 0)) + { + + /* Print an error message out. */ + printf("**** Error: memory allocation failed for the section string table **** \n"); + + /* Close the files and release the ELF areas. */ + converter_cleanup(); + + return(5); + } /* Read the section string table. */ - elf_object_read(section_header[header.elf_header_section_string_index].elf_section_header_offset, section_string_table, section_header[header.elf_header_section_string_index].elf_section_header_size); + if (elf_object_read(section_header[header.elf_header_section_string_index].elf_section_header_offset, section_string_table, allocation_size) != 0) + { + + /* Print an error message out. */ + printf("**** Error: read failed on the section string table **** \n"); + + /* Close the files and release the ELF areas. */ + converter_cleanup(); + + return(6); + } /* Allocate memory for the code section array. */ - code_section_array = malloc(sizeof(CODE_SECTION_ENTRY)*header.elf_header_section_header_entries); + allocation_size = sizeof(CODE_SECTION_ENTRY)*header.elf_header_section_header_entries; + code_section_array = malloc(allocation_size); + + /* Determine if the memory allocation was successful. */ + if ((code_section_array == NULL) && (allocation_size != 0)) + { + + /* Print an error message out. */ + printf("**** Error: memory allocation failed for the code section array **** \n"); + + /* Close the files and release the ELF areas. */ + converter_cleanup(); + + return(5); + } + code_section_index = 0; /* Print out the section header(s). */ @@ -281,9 +441,8 @@ CODE_SECTION_ENTRY code_section_temp; fprintf(array_file, "unsigned char module_code[] = {0x00};\n\n"); - /* Close files. */ - fclose(source_file); - fclose(array_file); + /* Close the files and release the ELF areas. */ + converter_cleanup(); return(4); } @@ -330,7 +489,7 @@ CODE_SECTION_ENTRY code_section_temp; /* Print out a character with a leading comma, except on the first character. */ if (column == 0) - fprintf(array_file, "/* 0x%08X */ 0x00", address); + fprintf(array_file, "/* 0x%08lX */ 0x00", address); else fprintf(array_file, ", 0x00"); @@ -358,16 +517,27 @@ CODE_SECTION_ENTRY code_section_temp; /* Print an error message out. */ printf("**** Error: memory allocation failed for code section **** \n"); - /* Close files. */ - fclose(source_file); - fclose(array_file); + /* Close the files and release the ELF areas. */ + converter_cleanup(); return(5); } /* Read in the code area. */ j = code_section_array[i].code_section_index; - elf_object_read(section_header[j].elf_section_header_offset, code_buffer, code_section_array[i].code_section_size); + if (elf_object_read(section_header[j].elf_section_header_offset, code_buffer, code_section_array[i].code_section_size) != 0) + { + + /* Print an error message out. */ + printf("**** Error: read failed on a code section **** \n"); + + /* Release the code section buffer, then close the files and release + the ELF areas. */ + free(code_buffer); + converter_cleanup(); + + return(6); + } /* Write out the contents of this program area. */ size = code_section_array[i].code_section_size; @@ -379,7 +549,7 @@ CODE_SECTION_ENTRY code_section_temp; /* Print out a character with a leading comma, except on the first character. */ if (column == 0) - fprintf(array_file, "/* 0x%08X */ 0x%02X", address, (unsigned int) code_buffer[j]); + fprintf(array_file, "/* 0x%08lX */ 0x%02X", address, (unsigned int) code_buffer[j]); else fprintf(array_file, ", 0x%02X", (unsigned int) code_buffer[j]); @@ -422,9 +592,8 @@ CODE_SECTION_ENTRY code_section_temp; /* Finally, finish the C array containing the module code. */ fprintf(array_file, "};\n\n"); - /* Close files. */ - fclose(source_file); - fclose(array_file); + /* Close the files and release the ELF areas. */ + converter_cleanup(); return 0; } From 5481fc75a0f182b29e64e55bfe4afb8a830d065c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Sun, 9 Aug 2026 07:28:19 -0400 Subject: [PATCH 014/181] Fixed the resource leaks on the xQueueCreate error paths (#582) xQueueCreate() allocated the queue descriptor and its backing memory, then created two ThreadX semaphores, and returned NULL on either semaphore failure without releasing anything. Since no handle reached the caller, vQueueDelete() could not be used to recover, so both allocations were lost. A failure on the second semaphore additionally abandoned the read semaphore it had already created, leaving a live ThreadX control block inside freed memory. Release the backing memory and the descriptor on both paths, and delete the read semaphore before returning when the write semaphore cannot be created. This is the teardown order vQueueDelete() already uses, and it matches the cleanup xTaskCreate() performs on its own error paths. Verified with a fault injection harness that intercepts the ThreadX byte pool and semaphore entry points to force tx_semaphore_create() to fail on a chosen call. On a read semaphore failure the layer previously performed 2 allocations and 0 releases, and on a write semaphore failure 2 allocations, 0 releases and 0 semaphore deletions. It now performs 2 releases in both cases and deletes the read semaphore in the second, with the byte pool restored to its prior state. Fixes https://github.com/eclipse-threadx/threadx/issues/570 Assisted-by: Claude Code (Opus 5) --- utility/rtos_compatibility_layers/FreeRTOS/tx_freertos.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/utility/rtos_compatibility_layers/FreeRTOS/tx_freertos.c b/utility/rtos_compatibility_layers/FreeRTOS/tx_freertos.c index acac53ccd..8d55586dd 100644 --- a/utility/rtos_compatibility_layers/FreeRTOS/tx_freertos.c +++ b/utility/rtos_compatibility_layers/FreeRTOS/tx_freertos.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Claude Code (Opus 5) + /**************************************************************************/ /**************************************************************************/ /** */ @@ -1543,11 +1545,16 @@ QueueHandle_t xQueueCreate(UBaseType_t uxQueueLength, UBaseType_t uxItemSize) ret = tx_semaphore_create(&p_queue->read_sem, "", 0u); if(ret != TX_SUCCESS) { + txfr_free(p_mem); + txfr_free(p_queue); return NULL; } ret = tx_semaphore_create(&p_queue->write_sem, "", uxQueueLength); if(ret != TX_SUCCESS) { + (void)tx_semaphore_delete(&p_queue->read_sem); + txfr_free(p_mem); + txfr_free(p_queue); return NULL; } From f3df5f9ddeedce76b7b0dd35a390a5924ec3d481 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Sun, 9 Aug 2026 08:03:16 -0400 Subject: [PATCH 015/181] Added a regression suite for the FreeRTOS compatibility layer (#583) * Fixed the resource leaks on the xQueueCreate error paths xQueueCreate() allocated the queue descriptor and its backing memory, then created two ThreadX semaphores, and returned NULL on either semaphore failure without releasing anything. Since no handle reached the caller, vQueueDelete() could not be used to recover, so both allocations were lost. A failure on the second semaphore additionally abandoned the read semaphore it had already created, leaving a live ThreadX control block inside freed memory. Release the backing memory and the descriptor on both paths, and delete the read semaphore before returning when the write semaphore cannot be created. This is the teardown order vQueueDelete() already uses, and it matches the cleanup xTaskCreate() performs on its own error paths. Verified with a fault injection harness that intercepts the ThreadX byte pool and semaphore entry points to force tx_semaphore_create() to fail on a chosen call. On a read semaphore failure the layer previously performed 2 allocations and 0 releases, and on a write semaphore failure 2 allocations, 0 releases and 0 semaphore deletions. It now performs 2 releases in both cases and deletes the read semaphore in the second, with the byte pool restored to its prior state. Fixes https://github.com/eclipse-threadx/threadx/issues/570 Assisted-by: Claude Code (Opus 5) * Added a regression suite for the FreeRTOS compatibility layer The compatibility layer had no tests in this repository, which is awkward for its creation functions in particular. Each of them takes one or two byte pool allocations for its bookkeeping and then creates ThreadX kernel objects, and each returns NULL when a kernel object cannot be created. The caller is left without a handle, so it cannot call the matching delete function, and anything the layer failed to release is gone until the system restarts. A leaking version and a correct version are indistinguishable from the outside, which is how the leak in issue 570 went unnoticed. Add a suite that counts what the layer takes and gives back. A test asks the harness to fail a chosen kernel creation call, then checks the number of byte pool allocations, releases, object creations and object deletions performed. The ThreadX entry points are intercepted with the linker's --wrap so that tx_freertos.c is compiled exactly as it ships, with no test hooks in it. Note that tx_api.h maps the public API onto the error checking entry points, so the _txe_ symbols are the ones wrapped. Coverage is the creation and teardown paths of queues, tasks, semaphores, mutexes, event groups and timers, including a regression test for the two paths fixed for issue 570. The suite follows the layout of the existing ThreadX and SMP suites, is registered with ctest, and runs in CI through the shared regression template. It is built 32 bit because the Linux port defines ULONG as unsigned int on x86_64 while the layer passes pointers through ULONG arguments, so a 64 bit build truncates them. It is Linux only because --wrap has no MSVC equivalent, and the CMake configuration says so rather than failing at link time. Validated by building the suite against the layer as it stands before the issue 570 fix, where the two expected checks fail with the leaked counts, and against the fixed layer, where all three tests pass. Assisted-by: Claude Code (Opus 5) --- .github/workflows/regression_test.yml | 18 + scripts/build_freertos.sh | 17 + scripts/test_freertos.sh | 17 + test/freertos/cmake/CMakeLists.txt | 78 ++++ test/freertos/cmake/regression/CMakeLists.txt | 83 ++++ test/freertos/cmake/run.sh | 112 ++++++ test/freertos/fixtures/FreeRTOSConfig.h | 66 ++++ test/freertos/fixtures/tx_user.h | 35 ++ test/freertos/readme.md | 86 ++++ .../regression/txfr_queue_create_test.c | 116 ++++++ .../regression/txfr_sync_create_test.c | 129 ++++++ .../regression/txfr_task_create_test.c | 105 +++++ test/freertos/regression/txfr_test_harness.c | 366 ++++++++++++++++++ test/freertos/regression/txfr_test_harness.h | 98 +++++ 14 files changed, 1326 insertions(+) create mode 100755 scripts/build_freertos.sh create mode 100755 scripts/test_freertos.sh create mode 100644 test/freertos/cmake/CMakeLists.txt create mode 100644 test/freertos/cmake/regression/CMakeLists.txt create mode 100755 test/freertos/cmake/run.sh create mode 100644 test/freertos/fixtures/FreeRTOSConfig.h create mode 100644 test/freertos/fixtures/tx_user.h create mode 100644 test/freertos/readme.md create mode 100644 test/freertos/regression/txfr_queue_create_test.c create mode 100644 test/freertos/regression/txfr_sync_create_test.c create mode 100644 test/freertos/regression/txfr_task_create_test.c create mode 100644 test/freertos/regression/txfr_test_harness.c create mode 100644 test/freertos/regression/txfr_test_harness.h diff --git a/.github/workflows/regression_test.yml b/.github/workflows/regression_test.yml index ee5519fdb..8fa974743 100644 --- a/.github/workflows/regression_test.yml +++ b/.github/workflows/regression_test.yml @@ -41,6 +41,24 @@ jobs: cmake_path: ./test/smp/cmake result_affix: SMP skip_deploy: true + freertos: + permissions: + contents: read + issues: read + checks: write + pull-requests: write + pages: write + id-token: write + uses: ./.github/workflows/regression_template.yml + with: + build_script: ./scripts/build_freertos.sh + test_script: ./scripts/test_freertos.sh + cmake_path: ./test/freertos/cmake + result_affix: FreeRTOS + skip_deploy: true + # No coverage build configuration yet; the suite covers the creation + # paths of the layer rather than all of it. + skip_coverage: true # riscv: disabled — re-enable when RISC-V CI is ready # riscv: # permissions: diff --git a/scripts/build_freertos.sh b/scripts/build_freertos.sh new file mode 100755 index 000000000..c3058b110 --- /dev/null +++ b/scripts/build_freertos.sh @@ -0,0 +1,17 @@ +#!/bin/bash +############################################################################## +# 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. +# +# AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +# The AI-generated portions may be considered public domain (CC0-1.0) +# and not subject to the project's licence. The human contributor has +# reviewed and verified that the code is correct. +# +# SPDX-License-Identifier: MIT and CC0-1.0 +############################################################################## + +$(dirname `realpath $0`)/../test/freertos/cmake/run.sh build all diff --git a/scripts/test_freertos.sh b/scripts/test_freertos.sh new file mode 100755 index 000000000..9edd20be7 --- /dev/null +++ b/scripts/test_freertos.sh @@ -0,0 +1,17 @@ +#!/bin/bash +############################################################################## +# 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. +# +# AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +# The AI-generated portions may be considered public domain (CC0-1.0) +# and not subject to the project's licence. The human contributor has +# reviewed and verified that the code is correct. +# +# SPDX-License-Identifier: MIT and CC0-1.0 +############################################################################## + +CTEST_PARALLEL_LEVEL=4 $(dirname `realpath $0`)/../test/freertos/cmake/run.sh test all diff --git a/test/freertos/cmake/CMakeLists.txt b/test/freertos/cmake/CMakeLists.txt new file mode 100644 index 000000000..a8c07d8d0 --- /dev/null +++ b/test/freertos/cmake/CMakeLists.txt @@ -0,0 +1,78 @@ +############################################################################## +# 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. +# +# AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +# The AI-generated portions may be considered public domain (CC0-1.0) +# and not subject to the project's licence. The human contributor has +# reviewed and verified that the code is correct. +# +# SPDX-License-Identifier: MIT and CC0-1.0 +############################################################################## + +cmake_minimum_required(VERSION 3.13 FATAL_ERROR) +cmake_policy(SET CMP0054 NEW) +cmake_policy(SET CMP0057 NEW) + +project(threadx_freertos_test LANGUAGES C) + +set(CMAKE_C_STANDARD 99) +set(CMAKE_C_STANDARD_REQUIRED ON) +set(CMAKE_C_EXTENSIONS OFF) + +# The suite intercepts the ThreadX entry points with the linker's --wrap, which +# is a GNU ld and lld feature. There is no MSVC equivalent, so the suite is +# built on Linux only and the build stops early elsewhere rather than failing +# later with confusing link errors. +if(NOT CMAKE_C_COMPILER_ID MATCHES "GNU|Clang") + message(FATAL_ERROR + "The FreeRTOS compatibility layer tests require GNU ld or lld for " + "--wrap support and are supported on Linux only.") +endif() + +set(BUILD_CONFIGURATIONS default_build) +set(CMAKE_CONFIGURATION_TYPES + ${BUILD_CONFIGURATIONS} + CACHE STRING "list of supported configuration types" FORCE) +set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + ${CMAKE_CONFIGURATION_TYPES}) +list(GET CMAKE_CONFIGURATION_TYPES 0 BUILD_TYPE) +if((NOT CMAKE_BUILD_TYPE) OR (NOT ("${CMAKE_BUILD_TYPE}" IN_LIST + CMAKE_CONFIGURATION_TYPES))) + set(CMAKE_BUILD_TYPE + "${BUILD_TYPE}" + CACHE STRING "Build Type of the project" FORCE) +endif() + +message(STATUS "Build type: ${CMAKE_BUILD_TYPE}") +message(STATUS "Using toolchain file: ${CMAKE_TOOLCHAIN_FILE}.") + +# Built 32 bit, as the ThreadX and SMP suites are. This is not incidental for +# this suite: the Linux port defines ULONG as unsigned int on x86_64, while the +# compatibility layer passes pointers through ULONG arguments, for instance the +# task argument and the timer identifier. A 64 bit build therefore truncates +# those pointers, which the compiler reports as -Wpointer-to-int-cast and which +# would crash the timer callback wrapper. +add_compile_options(-m32) +add_link_options(-m32) + +# Applied to everything, including the ThreadX build pulled in below. The +# strict warning set is applied to the test code alone, in the regression +# CMakeLists, since neither ThreadX nor the layer under test builds clean +# under -Wextra today and that is not this suite's to fix. +add_compile_options(-ggdb -g3 -fdiagnostics-color) + +enable_testing() + +# The compatibility layer stores a back pointer in each thread control block, +# so ThreadX has to be built with the matching user extension. +set(TX_USER_FILE + ${CMAKE_CURRENT_LIST_DIR}/../fixtures/tx_user.h + CACHE FILEPATH "tx_user.h used for the FreeRTOS layer tests" FORCE) + +add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/../../.. threadx) + +add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/regression) diff --git a/test/freertos/cmake/regression/CMakeLists.txt b/test/freertos/cmake/regression/CMakeLists.txt new file mode 100644 index 000000000..783e95406 --- /dev/null +++ b/test/freertos/cmake/regression/CMakeLists.txt @@ -0,0 +1,83 @@ +############################################################################## +# 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. +# +# AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +# The AI-generated portions may be considered public domain (CC0-1.0) +# and not subject to the project's licence. The human contributor has +# reviewed and verified that the code is correct. +# +# SPDX-License-Identifier: MIT and CC0-1.0 +############################################################################## + +cmake_minimum_required(VERSION 3.13 FATAL_ERROR) +cmake_policy(SET CMP0057 NEW) + +project(freertos_regression_test LANGUAGES C) + +set(SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/../../regression) +set(FIXTURE_DIR ${CMAKE_CURRENT_LIST_DIR}/../../fixtures) +set(REPO_ROOT ${CMAKE_CURRENT_LIST_DIR}/../../../..) +set(LAYER_SOURCE ${REPO_ROOT}/utility/rtos_compatibility_layers/FreeRTOS/tx_freertos.c) +set(LAYER_INCLUDE_DIR ${REPO_ROOT}/utility/rtos_compatibility_layers/FreeRTOS) + +set(freertos_test_cases + ${SOURCE_DIR}/txfr_queue_create_test.c + ${SOURCE_DIR}/txfr_task_create_test.c + ${SOURCE_DIR}/txfr_sync_create_test.c) + +# tx_api.h maps the public API onto the error checking entry points, so those +# are the symbols that exist at link time and the ones the harness wraps. A +# name that does not resolve is silently ignored by the linker, so this list +# must be kept in step with the __wrap_ functions in txfr_test_harness.c. +set(wrapped_symbols + _txe_byte_allocate + _txe_byte_release + _txe_semaphore_create + _txe_semaphore_delete + _txe_mutex_create + _txe_mutex_delete + _txe_event_flags_create + _txe_event_flags_delete + _txe_timer_create + _txe_timer_delete + _txe_thread_create + _txe_thread_delete) + +set(wrap_link_options "") +foreach(symbol ${wrapped_symbols}) + list(APPEND wrap_link_options "-Wl,--wrap=${symbol}") +endforeach() + +# The layer is compiled from source into each test rather than linked from the +# freertos-threadx target, so that the test's FreeRTOSConfig.h applies. +add_library(freertos_layer_under_test OBJECT ${LAYER_SOURCE}) +target_include_directories(freertos_layer_under_test + PUBLIC ${LAYER_INCLUDE_DIR} ${FIXTURE_DIR}) +target_link_libraries(freertos_layer_under_test PUBLIC azrtos::threadx) + +set(test_warning_options -Wall -Wextra -Werror) + +add_library(freertos_test_harness OBJECT ${SOURCE_DIR}/txfr_test_harness.c) +target_include_directories(freertos_test_harness + PUBLIC ${SOURCE_DIR} ${LAYER_INCLUDE_DIR} ${FIXTURE_DIR}) +target_link_libraries(freertos_test_harness PUBLIC azrtos::threadx) +target_compile_options(freertos_test_harness PRIVATE ${test_warning_options}) + +foreach(test_case ${freertos_test_cases}) + get_filename_component(test_name ${test_case} NAME_WE) + + add_executable(${test_name} ${test_case} + $ + $) + target_include_directories(${test_name} + PRIVATE ${SOURCE_DIR} ${LAYER_INCLUDE_DIR} ${FIXTURE_DIR}) + target_link_libraries(${test_name} PRIVATE azrtos::threadx) + target_link_options(${test_name} PRIVATE ${wrap_link_options}) + target_compile_options(${test_name} PRIVATE ${test_warning_options}) + + add_test(${CMAKE_BUILD_TYPE}::${test_name} ${test_name}) +endforeach() diff --git a/test/freertos/cmake/run.sh b/test/freertos/cmake/run.sh new file mode 100755 index 000000000..bb1c70f88 --- /dev/null +++ b/test/freertos/cmake/run.sh @@ -0,0 +1,112 @@ +#!/bin/bash +############################################################################## +# 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. +# +# AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +# The AI-generated portions may be considered public domain (CC0-1.0) +# and not subject to the project's licence. The human contributor has +# reviewed and verified that the code is correct. +# +# SPDX-License-Identifier: MIT and CC0-1.0 +############################################################################## + +# Builds and runs the FreeRTOS compatibility layer regression suite. The +# interface matches test/tx/cmake/run.sh so that the shared CI template can +# drive it: "run.sh build all" then "run.sh test all". + +set -e + +function help() { + echo "Usage: $0 [build|test] [all| ...]" + echo "Available build_configuration:" + for build in ${build_configurations[*]}; do + echo " $build" + done + exit 1 +} + +function validate() { + for build in ${build_configurations[*]}; do + if [ "$1" == "$build" ]; then + return + fi + done + help +} + +function generate() { + build=$1 + cmake -Bbuild/$build -GNinja -DCMAKE_TOOLCHAIN_FILE=$(dirname $(realpath $0))/../../../cmake/linux.cmake -DCMAKE_BUILD_TYPE=$build . +} + +function build() { + cmake --build build/$1 +} + +function test() { + pushd build/$1 + [ -z "${CTEST_PARALLEL_LEVEL}" ] && parallel="-j$2" + if [ -z "${CTEST_REPEAT_FAIL}" ]; + then + repeat_fail=2 + else + repeat_fail=${CTEST_REPEAT_FAIL} + fi + ctest $parallel --timeout 300 -O $1.txt -T test --no-compress-output --test-output-size-passed 4194304 --test-output-size-failed 4194304 --output-on-failure --repeat until-pass:${repeat_fail} --output-junit $1.xml + popd + grep -E "^(\s*[0-9]+|Total)" build/$1/$1.txt >build/$1.txt + sed -i "s/\x1B\[[0-9;]*[JKmsu]//g" build/$1.txt +} + +cd $(dirname $0) + +result=$(sed -n "/(BUILD_CONFIGURATIONS/,/)/p" CMakeLists.txt|sed ':label;N;s/\n/ /;b label'|grep -Pzo "[a-zA-Z0-9_]*build[a-zA-Z0-9_]*\s*"| tr -d '\0') +IFS=' ' +read -ra build_configurations <<< "$result" + +if [ $# -lt 1 ]; then + help +fi + +command=$1 +shift + +if [ "$#" == "0" ]; then + builds=${build_configurations[0]} +elif [ "$*" == "all" ]; then + builds=${build_configurations[@]} +else + for item in $*; do + validate $item + done + builds=$* +fi + +if [ "$command" == "build" ]; then + for item in $builds; do + generate $item + echo "" + done + + for item in $builds; do + echo "Building $item" + build $item + echo "" + done +elif [ "$command" == "test" ]; then + cores=$(nproc) + if [ -z "${CTEST_PARALLEL_LEVEL}" ]; + then + parallel_jobs=$(($cores + 2)) + fi + for item in $builds; do + echo "Testing $item" + test $item $parallel_jobs + done +else + help +fi diff --git a/test/freertos/fixtures/FreeRTOSConfig.h b/test/freertos/fixtures/FreeRTOSConfig.h new file mode 100644 index 000000000..017b7171f --- /dev/null +++ b/test/freertos/fixtures/FreeRTOSConfig.h @@ -0,0 +1,66 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** FreeRTOS compatibility layer regression test configuration */ +/** */ +/**************************************************************************/ + +/* Configuration used to build the compatibility layer under test. It follows + the shipped template in utility/rtos_compatibility_layers/FreeRTOS/ + config_template, with the choices a test build needs called out below. */ + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +#define configTICK_RATE_HZ (1000u) +#define configMAX_PRIORITIES (32u) +#define configMINIMAL_STACK_SIZE (512u) + +/* Large enough that a handful of leaked descriptors cannot exhaust it. The + tests therefore never infer a leak from an allocation failure; they count + the byte pool operations directly. */ +#define configTOTAL_HEAP_SIZE (1024u * 128u) + +#define configUSE_16_BIT_TICKS 0 +#define configSTACK_DEPTH_TYPE uint32_t + +/* Task deletion is included so that the idle task, and with it the teardown + path the tests exercise, is built. */ +#define INCLUDE_vTaskDelete 1 + +/* The tests drive the error paths deliberately, so neither assertion may halt + the run. A failed expectation is reported by the harness instead. */ +#define configASSERT(x) +#define TX_FREERTOS_ASSERT_FAIL() + +/* The harness calls tx_freertos_init() from tx_application_define(), so the + automatic initialization path is not wanted here. */ +#define TX_FREERTOS_AUTO_INIT 0 + +/* FreeRTOS.h selects portDISABLE_INTERRUPTS() by compiler rather than by + target, so a GNU build resolves it to the bare metal __disable_interrupts() + intrinsic, which does not exist when the layer is hosted on Linux. Both + macros are guarded with #ifndef, so the definitions below pre-empt that + choice with the ThreadX primitives the header's own fallback branch uses. */ +UINT _tx_thread_interrupt_disable(VOID); +VOID _tx_thread_interrupt_restore(UINT previous_posture); +#define portDISABLE_INTERRUPTS() _tx_thread_interrupt_disable() +#define portENABLE_INTERRUPTS() _tx_thread_interrupt_restore(TX_INT_ENABLE) + +#endif /* #ifndef FREERTOS_CONFIG_H */ diff --git a/test/freertos/fixtures/tx_user.h b/test/freertos/fixtures/tx_user.h new file mode 100644 index 000000000..834e711e0 --- /dev/null +++ b/test/freertos/fixtures/tx_user.h @@ -0,0 +1,35 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** FreeRTOS compatibility layer regression test ThreadX settings */ +/** */ +/**************************************************************************/ + +/* Every other ThreadX setting is left at its default; only the extension the + compatibility layer requires is defined here. */ + +#ifndef TX_USER_H +#define TX_USER_H + +/* The layer stores a back pointer to its own task structure in each thread + control block, as documented in the layer's readme.md. Without this the + layer does not compile. */ +#define TX_THREAD_USER_EXTENSION VOID *txfr_thread_ptr; + +#endif /* #ifndef TX_USER_H */ diff --git a/test/freertos/readme.md b/test/freertos/readme.md new file mode 100644 index 000000000..0bb1b650c --- /dev/null +++ b/test/freertos/readme.md @@ -0,0 +1,86 @@ +# FreeRTOS compatibility layer regression tests + +Regression tests for `utility/rtos_compatibility_layers/FreeRTOS/tx_freertos.c`, +built against the real ThreadX Linux port. + +## Running them + +```bash +./scripts/build_freertos.sh +./scripts/test_freertos.sh +``` + +Or directly, which is the same thing: + +```bash +test/freertos/cmake/run.sh build all +test/freertos/cmake/run.sh test all +``` + +CI runs both scripts through `.github/workflows/regression_test.yml`. + +## What they cover + +Every function in the layer that creates an object takes one or two byte pool +allocations for its bookkeeping and then creates one or more ThreadX kernel +objects. When one of those kernel objects cannot be created, the function +returns `NULL`, or `pdFAIL` for `xTaskCreate()`, and the caller is left with no +handle and therefore no way to call the matching delete function. Anything the +layer fails to release on the way out is lost until the system restarts. + +That makes these error paths invisible from the outside: a leaking version and +a correct version return exactly the same thing to the caller. The suite +therefore counts the ThreadX primitives the layer reaches for, and checks that +each error path gives back precisely what it took. + +| Test | Covers | +| --- | --- | +| `txfr_queue_create_test` | `xQueueCreate`, `xQueueCreateStatic`, `vQueueDelete` | +| `txfr_task_create_test` | `xTaskCreate`, `xTaskCreateStatic` | +| `txfr_sync_create_test` | semaphores, mutexes, event groups and timers | + +## How the fault injection works + +A test asks the harness to fail a chosen kernel creation call, then reads back +how many allocations, releases, object creations and object deletions the layer +performed. The interception is done with the linker's `--wrap` option, so +`tx_freertos.c` is compiled exactly as it ships, with no test hooks in it. + +Two things are worth knowing before adding tests: + +- `tx_api.h` maps the public API onto the error checking entry points, so the + symbols that exist at link time are the `_txe_` variants, and those are what + the wrap list in `cmake/regression/CMakeLists.txt` names. A `--wrap` for a + name that does not resolve is silently ignored, so a typo there produces a + test that quietly never injects anything. +- `txfr_malloc()` and `txfr_free()` cannot be wrapped, because they are defined + in `tx_freertos.c` and called from within it, so the compiler resolves those + calls internally. The byte pool counts stand in for them. + +Because `--wrap` is a GNU ld and lld feature with no MSVC equivalent, this +suite is Linux only. The CMake configuration stops with a clear message rather +than failing later with confusing link errors. + +## Fixtures + +`fixtures/FreeRTOSConfig.h` configures the layer for the tests. Two of its +settings are not arbitrary: + +- `configASSERT()` and `TX_FREERTOS_ASSERT_FAIL()` are empty, since the tests + drive error paths deliberately and neither may halt the run. +- `portDISABLE_INTERRUPTS()` and `portENABLE_INTERRUPTS()` are defined up front. + `FreeRTOS.h` picks those by compiler rather than by target, so a GNU build + otherwise resolves them to the bare metal `__disable_interrupts()` intrinsic, + which does not exist when the layer is hosted on Linux. + +`fixtures/tx_user.h` supplies `TX_THREAD_USER_EXTENSION`, which the layer +requires, as documented in the layer's own `readme.md`. + +## Why the build is 32 bit + +The Linux port defines `ULONG` as `unsigned int` on x86_64, while the layer +passes pointers through `ULONG` arguments, such as the task argument and the +timer identifier. A 64 bit build truncates those pointers, which the compiler +reports as `-Wpointer-to-int-cast` and which crashes the timer callback +wrapper. The ThreadX and SMP suites build 32 bit for their own reasons; this +suite has to. diff --git a/test/freertos/regression/txfr_queue_create_test.c b/test/freertos/regression/txfr_queue_create_test.c new file mode 100644 index 000000000..36eb10170 --- /dev/null +++ b/test/freertos/regression/txfr_queue_create_test.c @@ -0,0 +1,116 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** FreeRTOS compatibility layer, queue creation resource accounting */ +/** */ +/**************************************************************************/ + +/* xQueueCreate() takes two byte pool allocations, the descriptor and the + backing storage, and then creates two semaphores. Since a failure returns + NULL, the caller has no handle and cannot call vQueueDelete(), so anything + the layer fails to undo on the way out is lost for good. These checks pin + down the accounting on each of those paths. + + The failure paths here are the ones reported in issue 570. */ + +#include "txfr_test_harness.h" + +#include "queue.h" + +#define QUEUE_LENGTH 8u +#define QUEUE_ITEM_SIZE 32u + +/* Storage for the static variant. */ +static StaticQueue_t queue_control_block; +static uint8_t queue_storage[QUEUE_LENGTH * QUEUE_ITEM_SIZE]; + + +void txfr_test_body(void) +{ + QueueHandle_t queue; + TXFR_COUNTERS counters; + int i; + int cycles; + + /* A successful creation takes both allocations and creates both + semaphores, and releases nothing. */ + txfr_test_account_start(TXFR_INJECT_NONE, 0); + queue = xQueueCreate(QUEUE_LENGTH, QUEUE_ITEM_SIZE); + txfr_test_account_stop(&counters); + txfr_test_check("xQueueCreate returns a handle", queue != NULL); + txfr_test_check_counts("xQueueCreate accounting", &counters, 2, 0, 2, 0); + + /* Deleting it gives both allocations back and deletes both semaphores. */ + if(queue != NULL) + { + txfr_test_account_start(TXFR_INJECT_NONE, 0); + vQueueDelete(queue); + txfr_test_account_stop(&counters); + txfr_test_check_counts("vQueueDelete accounting", &counters, 0, 2, 0, 2); + } + + /* The read semaphore fails. Nothing was created that needs deleting, but + both allocations must be released. */ + txfr_test_account_start(TXFR_INJECT_SEMAPHORE_CREATE, 1); + queue = xQueueCreate(QUEUE_LENGTH, QUEUE_ITEM_SIZE); + txfr_test_account_stop(&counters); + txfr_test_check("xQueueCreate returns NULL on read_sem failure", queue == NULL); + txfr_test_check_counts("read_sem failure releases both allocations", &counters, 2, 2, 1, 0); + + /* The write semaphore fails. The read semaphore already exists by then, so + it must be deleted as well as both allocations released. */ + txfr_test_account_start(TXFR_INJECT_SEMAPHORE_CREATE, 2); + queue = xQueueCreate(QUEUE_LENGTH, QUEUE_ITEM_SIZE); + txfr_test_account_stop(&counters); + txfr_test_check("xQueueCreate returns NULL on write_sem failure", queue == NULL); + txfr_test_check_counts("write_sem failure unwinds read_sem and memory", &counters, 2, 2, 2, 1); + + /* The static variant takes no allocations and creates both semaphores. */ + txfr_test_account_start(TXFR_INJECT_NONE, 0); + queue = xQueueCreateStatic(QUEUE_LENGTH, QUEUE_ITEM_SIZE, queue_storage, &queue_control_block); + txfr_test_account_stop(&counters); + txfr_test_check("xQueueCreateStatic returns a handle", queue != NULL); + txfr_test_check_counts("xQueueCreateStatic accounting", &counters, 0, 0, 2, 0); + + if(queue != NULL) + { + txfr_test_account_start(TXFR_INJECT_NONE, 0); + vQueueDelete(queue); + txfr_test_account_stop(&counters); + txfr_test_check_counts("vQueueDelete on static queue", &counters, 0, 0, 0, 2); + } + + /* Repeated create and delete cycles must leave the pool able to serve the + same request. This would not catch a small leak on its own, which is why + the counts above are checked directly, but it does catch a descriptor + that is released to the wrong pool or released twice. */ + cycles = 0; + for(i = 0; i < 64; i++) + { + queue = xQueueCreate(QUEUE_LENGTH, QUEUE_ITEM_SIZE); + if(queue == NULL) + { + break; + } + + cycles++; + vQueueDelete(queue); + } + txfr_test_check("64 create and delete cycles succeed", cycles == 64); +} diff --git a/test/freertos/regression/txfr_sync_create_test.c b/test/freertos/regression/txfr_sync_create_test.c new file mode 100644 index 000000000..14bd53d88 --- /dev/null +++ b/test/freertos/regression/txfr_sync_create_test.c @@ -0,0 +1,129 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** FreeRTOS compatibility layer, synchronisation object accounting */ +/** */ +/**************************************************************************/ + +/* Semaphores, mutexes, event groups and timers each take a single descriptor + allocation and then create one kernel object. Every one of them must give + the descriptor back when that kernel object cannot be created. */ + +#include "txfr_test_harness.h" + +#include "semphr.h" +#include "event_groups.h" +#include "timers.h" + + +static void test_timer_callback(TimerHandle_t timer) +{ + (void)timer; +} + + +void txfr_test_body(void) +{ + SemaphoreHandle_t semaphore; + EventGroupHandle_t event_group; + TimerHandle_t timer; + TXFR_COUNTERS counters; + + /* Counting semaphore. */ + txfr_test_account_start(TXFR_INJECT_NONE, 0); + semaphore = xSemaphoreCreateCounting(4u, 0u); + txfr_test_account_stop(&counters); + txfr_test_check("xSemaphoreCreateCounting returns a handle", semaphore != NULL); + txfr_test_check_counts("xSemaphoreCreateCounting accounting", &counters, 1, 0, 1, 0); + if(semaphore != NULL) + { + vSemaphoreDelete(semaphore); + } + + txfr_test_account_start(TXFR_INJECT_SEMAPHORE_CREATE, 1); + semaphore = xSemaphoreCreateCounting(4u, 0u); + txfr_test_account_stop(&counters); + txfr_test_check("xSemaphoreCreateCounting returns NULL on failure", semaphore == NULL); + txfr_test_check_counts("counting semaphore failure releases descriptor", &counters, 1, 1, 1, 0); + + /* Binary semaphore, which shares the same descriptor path. */ + txfr_test_account_start(TXFR_INJECT_SEMAPHORE_CREATE, 1); + semaphore = xSemaphoreCreateBinary(); + txfr_test_account_stop(&counters); + txfr_test_check("xSemaphoreCreateBinary returns NULL on failure", semaphore == NULL); + txfr_test_check_counts("binary semaphore failure releases descriptor", &counters, 1, 1, 1, 0); + + /* Mutex. */ + txfr_test_account_start(TXFR_INJECT_NONE, 0); + semaphore = xSemaphoreCreateMutex(); + txfr_test_account_stop(&counters); + txfr_test_check("xSemaphoreCreateMutex returns a handle", semaphore != NULL); + txfr_test_check_counts("xSemaphoreCreateMutex accounting", &counters, 1, 0, 1, 0); + if(semaphore != NULL) + { + vSemaphoreDelete(semaphore); + } + + txfr_test_account_start(TXFR_INJECT_MUTEX_CREATE, 1); + semaphore = xSemaphoreCreateMutex(); + txfr_test_account_stop(&counters); + txfr_test_check("xSemaphoreCreateMutex returns NULL on failure", semaphore == NULL); + txfr_test_check_counts("mutex failure releases descriptor", &counters, 1, 1, 1, 0); + + /* Recursive mutex, which differs only in the inheritance argument. */ + txfr_test_account_start(TXFR_INJECT_MUTEX_CREATE, 1); + semaphore = xSemaphoreCreateRecursiveMutex(); + txfr_test_account_stop(&counters); + txfr_test_check("xSemaphoreCreateRecursiveMutex returns NULL on failure", semaphore == NULL); + txfr_test_check_counts("recursive mutex failure releases descriptor", &counters, 1, 1, 1, 0); + + /* Event group. */ + txfr_test_account_start(TXFR_INJECT_NONE, 0); + event_group = xEventGroupCreate(); + txfr_test_account_stop(&counters); + txfr_test_check("xEventGroupCreate returns a handle", event_group != NULL); + txfr_test_check_counts("xEventGroupCreate accounting", &counters, 1, 0, 1, 0); + if(event_group != NULL) + { + vEventGroupDelete(event_group); + } + + txfr_test_account_start(TXFR_INJECT_EVENT_FLAGS_CREATE, 1); + event_group = xEventGroupCreate(); + txfr_test_account_stop(&counters); + txfr_test_check("xEventGroupCreate returns NULL on failure", event_group == NULL); + txfr_test_check_counts("event group failure releases descriptor", &counters, 1, 1, 1, 0); + + /* Timer. */ + txfr_test_account_start(TXFR_INJECT_NONE, 0); + timer = xTimerCreate("t", 10u, pdFALSE, NULL, test_timer_callback); + txfr_test_account_stop(&counters); + txfr_test_check("xTimerCreate returns a handle", timer != NULL); + txfr_test_check_counts("xTimerCreate accounting", &counters, 1, 0, 1, 0); + if(timer != NULL) + { + (void)xTimerDelete(timer, 0u); + } + + txfr_test_account_start(TXFR_INJECT_TIMER_CREATE, 1); + timer = xTimerCreate("t", 10u, pdFALSE, NULL, test_timer_callback); + txfr_test_account_stop(&counters); + txfr_test_check("xTimerCreate returns NULL on failure", timer == NULL); + txfr_test_check_counts("timer failure releases descriptor", &counters, 1, 1, 1, 0); +} diff --git a/test/freertos/regression/txfr_task_create_test.c b/test/freertos/regression/txfr_task_create_test.c new file mode 100644 index 000000000..288d34907 --- /dev/null +++ b/test/freertos/regression/txfr_task_create_test.c @@ -0,0 +1,105 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** FreeRTOS compatibility layer, task creation resource accounting */ +/** */ +/**************************************************************************/ + +/* xTaskCreate() takes two byte pool allocations, the stack and the task + structure, then creates a notification semaphore and a thread. It is the + function the rest of the layer's error handling is modelled on, so these + checks also serve as the reference for what correct unwinding looks like. */ + +#include "txfr_test_harness.h" + +#include "task.h" + +#define TASK_STACK_DEPTH (configMINIMAL_STACK_SIZE) +#define TASK_PRIORITY (3u) + +static StaticTask_t task_control_block; +static StackType_t task_stack[TASK_STACK_DEPTH]; + + +static void test_task_entry(void *p_arg) +{ + (void)p_arg; + + /* Never scheduled at this priority while the test thread runs, but a task + entry point must not return. */ + for(;;) + { + vTaskDelay(portMAX_DELAY); + } +} + + +void txfr_test_body(void) +{ + BaseType_t result; + TaskHandle_t task; + TXFR_COUNTERS counters; + + /* A successful creation takes both allocations, creates the notification + semaphore and the thread, and releases nothing. */ + task = NULL; + txfr_test_account_start(TXFR_INJECT_NONE, 0); + result = xTaskCreate(test_task_entry, "ok", TASK_STACK_DEPTH, NULL, TASK_PRIORITY, &task); + txfr_test_account_stop(&counters); + txfr_test_check("xTaskCreate reports success", result == pdPASS); + txfr_test_check("xTaskCreate returns a handle", task != NULL); + txfr_test_check_counts("xTaskCreate accounting", &counters, 2, 0, 2, 0); + + if(task != NULL) + { + vTaskDelete(task); + } + + /* The notification semaphore fails before anything else is created, so + both allocations must come back and nothing needs deleting. */ + task = NULL; + txfr_test_account_start(TXFR_INJECT_SEMAPHORE_CREATE, 1); + result = xTaskCreate(test_task_entry, "sem", TASK_STACK_DEPTH, NULL, TASK_PRIORITY, &task); + txfr_test_account_stop(&counters); + txfr_test_check("xTaskCreate fails when the semaphore fails", result != pdPASS); + txfr_test_check_counts("semaphore failure releases stack and task", &counters, 2, 2, 1, 0); + + /* The thread creation fails with the semaphore already in place, so that + semaphore must be deleted and both allocations released. */ + task = NULL; + txfr_test_account_start(TXFR_INJECT_THREAD_CREATE, 1); + result = xTaskCreate(test_task_entry, "thread", TASK_STACK_DEPTH, NULL, TASK_PRIORITY, &task); + txfr_test_account_stop(&counters); + txfr_test_check("xTaskCreate fails when the thread fails", result != pdPASS); + txfr_test_check_counts("thread failure unwinds the semaphore too", &counters, 2, 2, 2, 1); + + /* The static variant takes no allocations, and creates the semaphore and + the thread from the caller's buffers. */ + txfr_test_account_start(TXFR_INJECT_NONE, 0); + task = xTaskCreateStatic(test_task_entry, "static", TASK_STACK_DEPTH, NULL, TASK_PRIORITY, + task_stack, &task_control_block); + txfr_test_account_stop(&counters); + txfr_test_check("xTaskCreateStatic returns a handle", task != NULL); + txfr_test_check_counts("xTaskCreateStatic accounting", &counters, 0, 0, 2, 0); + + if(task != NULL) + { + vTaskDelete(task); + } +} diff --git a/test/freertos/regression/txfr_test_harness.c b/test/freertos/regression/txfr_test_harness.c new file mode 100644 index 000000000..ead2bfb0f --- /dev/null +++ b/test/freertos/regression/txfr_test_harness.c @@ -0,0 +1,366 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** FreeRTOS compatibility layer test harness */ +/** */ +/**************************************************************************/ + +#include "txfr_test_harness.h" + +#include +#include + +/* Accounting state. Only the single test thread touches these. */ +static int txfr_accounting; +static TXFR_INJECT_TARGET txfr_inject_target; +static int txfr_inject_fail_on; +static int txfr_inject_call_index; +static TXFR_COUNTERS txfr_counters; +static int txfr_failures; + +/* The real entry points, supplied by the linker in response to --wrap. */ +UINT __real__txe_byte_allocate(TX_BYTE_POOL *pool_ptr, VOID **memory_ptr, ULONG memory_size, ULONG wait_option); +UINT __real__txe_byte_release(VOID *memory_ptr); +UINT __real__txe_semaphore_create(TX_SEMAPHORE *semaphore_ptr, CHAR *name_ptr, ULONG initial_count, UINT semaphore_control_block_size); +UINT __real__txe_semaphore_delete(TX_SEMAPHORE *semaphore_ptr); +UINT __real__txe_mutex_create(TX_MUTEX *mutex_ptr, CHAR *name_ptr, UINT inherit, UINT mutex_control_block_size); +UINT __real__txe_mutex_delete(TX_MUTEX *mutex_ptr); +UINT __real__txe_event_flags_create(TX_EVENT_FLAGS_GROUP *group_ptr, CHAR *name_ptr, UINT event_control_block_size); +UINT __real__txe_event_flags_delete(TX_EVENT_FLAGS_GROUP *group_ptr); +UINT __real__txe_timer_create(TX_TIMER *timer_ptr, CHAR *name_ptr, VOID (*expiration_function)(ULONG input), + ULONG expiration_input, ULONG initial_ticks, ULONG reschedule_ticks, + UINT auto_activate, UINT timer_control_block_size); +UINT __real__txe_timer_delete(TX_TIMER *timer_ptr); +UINT __real__txe_thread_create(TX_THREAD *thread_ptr, CHAR *name_ptr, VOID (*entry_function)(ULONG entry_input), + ULONG entry_input, VOID *stack_start, ULONG stack_size, UINT priority, + UINT preempt_threshold, ULONG time_slice, UINT auto_start, + UINT thread_control_block_size); +UINT __real__txe_thread_delete(TX_THREAD *thread_ptr); + + +/* Determine whether the call now being made is the one the test asked to fail. + Only calls made while accounting is active are considered, which keeps the + objects created by tx_freertos_init() and by the harness out of the count. */ +static int txfr_should_fail(TXFR_INJECT_TARGET target) +{ + if((txfr_accounting == 0) || (txfr_inject_target != target)) + { + return 0; + } + + txfr_inject_call_index++; + + return (txfr_inject_call_index == txfr_inject_fail_on) ? 1 : 0; +} + + +UINT __wrap__txe_byte_allocate(TX_BYTE_POOL *pool_ptr, VOID **memory_ptr, ULONG memory_size, ULONG wait_option) +{ + if(txfr_accounting != 0) + { + txfr_counters.byte_allocate++; + } + + return __real__txe_byte_allocate(pool_ptr, memory_ptr, memory_size, wait_option); +} + + +UINT __wrap__txe_byte_release(VOID *memory_ptr) +{ + if(txfr_accounting != 0) + { + txfr_counters.byte_release++; + } + + return __real__txe_byte_release(memory_ptr); +} + + +UINT __wrap__txe_semaphore_create(TX_SEMAPHORE *semaphore_ptr, CHAR *name_ptr, ULONG initial_count, UINT semaphore_control_block_size) +{ + if(txfr_should_fail(TXFR_INJECT_SEMAPHORE_CREATE) != 0) + { + txfr_counters.semaphore_create++; + return TX_SEMAPHORE_ERROR; + } + + if(txfr_accounting != 0) + { + txfr_counters.semaphore_create++; + } + + return __real__txe_semaphore_create(semaphore_ptr, name_ptr, initial_count, semaphore_control_block_size); +} + + +UINT __wrap__txe_semaphore_delete(TX_SEMAPHORE *semaphore_ptr) +{ + if(txfr_accounting != 0) + { + txfr_counters.semaphore_delete++; + } + + return __real__txe_semaphore_delete(semaphore_ptr); +} + + +UINT __wrap__txe_mutex_create(TX_MUTEX *mutex_ptr, CHAR *name_ptr, UINT inherit, UINT mutex_control_block_size) +{ + if(txfr_should_fail(TXFR_INJECT_MUTEX_CREATE) != 0) + { + txfr_counters.mutex_create++; + return TX_MUTEX_ERROR; + } + + if(txfr_accounting != 0) + { + txfr_counters.mutex_create++; + } + + return __real__txe_mutex_create(mutex_ptr, name_ptr, inherit, mutex_control_block_size); +} + + +UINT __wrap__txe_mutex_delete(TX_MUTEX *mutex_ptr) +{ + if(txfr_accounting != 0) + { + txfr_counters.mutex_delete++; + } + + return __real__txe_mutex_delete(mutex_ptr); +} + + +UINT __wrap__txe_event_flags_create(TX_EVENT_FLAGS_GROUP *group_ptr, CHAR *name_ptr, UINT event_control_block_size) +{ + if(txfr_should_fail(TXFR_INJECT_EVENT_FLAGS_CREATE) != 0) + { + txfr_counters.event_flags_create++; + return TX_GROUP_ERROR; + } + + if(txfr_accounting != 0) + { + txfr_counters.event_flags_create++; + } + + return __real__txe_event_flags_create(group_ptr, name_ptr, event_control_block_size); +} + + +UINT __wrap__txe_event_flags_delete(TX_EVENT_FLAGS_GROUP *group_ptr) +{ + if(txfr_accounting != 0) + { + txfr_counters.event_flags_delete++; + } + + return __real__txe_event_flags_delete(group_ptr); +} + + +UINT __wrap__txe_timer_create(TX_TIMER *timer_ptr, CHAR *name_ptr, VOID (*expiration_function)(ULONG input), + ULONG expiration_input, ULONG initial_ticks, ULONG reschedule_ticks, + UINT auto_activate, UINT timer_control_block_size) +{ + if(txfr_should_fail(TXFR_INJECT_TIMER_CREATE) != 0) + { + txfr_counters.timer_create++; + return TX_TIMER_ERROR; + } + + if(txfr_accounting != 0) + { + txfr_counters.timer_create++; + } + + return __real__txe_timer_create(timer_ptr, name_ptr, expiration_function, expiration_input, + initial_ticks, reschedule_ticks, auto_activate, timer_control_block_size); +} + + +UINT __wrap__txe_timer_delete(TX_TIMER *timer_ptr) +{ + if(txfr_accounting != 0) + { + txfr_counters.timer_delete++; + } + + return __real__txe_timer_delete(timer_ptr); +} + + +UINT __wrap__txe_thread_create(TX_THREAD *thread_ptr, CHAR *name_ptr, VOID (*entry_function)(ULONG entry_input), + ULONG entry_input, VOID *stack_start, ULONG stack_size, UINT priority, + UINT preempt_threshold, ULONG time_slice, UINT auto_start, + UINT thread_control_block_size) +{ + if(txfr_should_fail(TXFR_INJECT_THREAD_CREATE) != 0) + { + txfr_counters.thread_create++; + return TX_THREAD_ERROR; + } + + if(txfr_accounting != 0) + { + txfr_counters.thread_create++; + } + + return __real__txe_thread_create(thread_ptr, name_ptr, entry_function, entry_input, stack_start, + stack_size, priority, preempt_threshold, time_slice, auto_start, + thread_control_block_size); +} + + +UINT __wrap__txe_thread_delete(TX_THREAD *thread_ptr) +{ + if(txfr_accounting != 0) + { + txfr_counters.thread_delete++; + } + + return __real__txe_thread_delete(thread_ptr); +} + + +void txfr_test_account_start(TXFR_INJECT_TARGET target, int fail_on_call) +{ + TX_MEMSET(&txfr_counters, 0, sizeof(txfr_counters)); + txfr_inject_target = target; + txfr_inject_fail_on = fail_on_call; + txfr_inject_call_index = 0; + txfr_accounting = 1; +} + + +void txfr_test_account_stop(TXFR_COUNTERS *p_counters) +{ + txfr_accounting = 0; + txfr_inject_target = TXFR_INJECT_NONE; + + if(p_counters != NULL) + { + *p_counters = txfr_counters; + } +} + + +void txfr_test_check(const char *label, int condition) +{ + printf("%-52s %s\n", label, (condition != 0) ? "PASS" : "FAIL"); + + if(condition == 0) + { + txfr_failures++; + } +} + + +void txfr_test_check_counts(const char *label, const TXFR_COUNTERS *p_counters, + int expect_allocate, int expect_release, + int expect_object_create, int expect_object_delete) +{ + int object_create; + int object_delete; + int ok; + + /* Only one kind of kernel object is exercised per check, so the totals + identify it unambiguously. */ + object_create = p_counters->semaphore_create + p_counters->mutex_create + + p_counters->event_flags_create + p_counters->timer_create + + p_counters->thread_create; + object_delete = p_counters->semaphore_delete + p_counters->mutex_delete + + p_counters->event_flags_delete + p_counters->timer_delete + + p_counters->thread_delete; + + ok = ((p_counters->byte_allocate == expect_allocate) && + (p_counters->byte_release == expect_release) && + (object_create == expect_object_create) && + (object_delete == expect_object_delete)) ? 1 : 0; + + printf("%-52s %s\n", label, (ok != 0) ? "PASS" : "FAIL"); + + if(ok == 0) + { + printf("%-52s got alloc=%d release=%d create=%d delete=%d\n", "", + p_counters->byte_allocate, p_counters->byte_release, object_create, object_delete); + printf("%-52s expected alloc=%d release=%d create=%d delete=%d\n", "", + expect_allocate, expect_release, expect_object_create, expect_object_delete); + txfr_failures++; + } +} + + +int txfr_test_failures(void) +{ + return txfr_failures; +} + + +/* Test thread. The byte pool operations under test require thread context. */ + +static TX_THREAD txfr_test_thread; +static ULONG txfr_test_stack[4096]; + + +static void txfr_test_thread_entry(ULONG id) +{ + (void)id; + + txfr_test_body(); + + printf("\n%s\n", (txfr_failures == 0) ? "ALL CHECKS PASSED" : "THERE WERE FAILED CHECKS"); + fflush(stdout); + + /* The kernel owns the calling thread, so returning here would simply idle. + Leave the process with a status ctest can read. */ + exit((txfr_failures == 0) ? 0 : 1); +} + + +void tx_application_define(void *first_unused_memory) +{ + UINT ret; + + (void)first_unused_memory; + + ret = tx_freertos_init(); + if(ret != TX_SUCCESS) + { + printf("tx_freertos_init() failed with %u\n", ret); + exit(2); + } + + ret = tx_thread_create(&txfr_test_thread, "txfr_test", txfr_test_thread_entry, 0u, + txfr_test_stack, sizeof(txfr_test_stack), 16u, 16u, 0u, TX_AUTO_START); + if(ret != TX_SUCCESS) + { + printf("tx_thread_create() failed with %u\n", ret); + exit(2); + } +} + + +int main(void) +{ + tx_kernel_enter(); + + return 0; +} diff --git a/test/freertos/regression/txfr_test_harness.h b/test/freertos/regression/txfr_test_harness.h new file mode 100644 index 000000000..a0db51623 --- /dev/null +++ b/test/freertos/regression/txfr_test_harness.h @@ -0,0 +1,98 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** FreeRTOS compatibility layer test harness */ +/** */ +/**************************************************************************/ + +/* This harness lets a test force a ThreadX object creation call to fail and + then account for what the compatibility layer did with the resources it had + already taken. The creation entry points of the layer take a byte pool + allocation for the descriptor, sometimes a second one for backing storage, + and then create one or more kernel objects; an error path that forgets to + undo any of that is invisible to the caller, which only ever sees NULL. + + Interception is done with the linker's --wrap option rather than with hooks + in the layer itself, so tx_freertos.c is compiled exactly as it ships. Note + that tx_api.h maps the public API onto the error checking entry points, so + the symbols that exist at link time, and therefore the ones wrapped, are the + _txe_ variants. The wrap options live in the test CMakeLists. + + This mechanism is specific to GNU ld and lld, so the suite is Linux only. */ + +#ifndef TXFR_TEST_HARNESS_H +#define TXFR_TEST_HARNESS_H + +#include "FreeRTOS.h" + +/* Identifies the kernel creation call a test wants to fail. */ +typedef enum TXFR_INJECT_TARGET_ENUM +{ + TXFR_INJECT_NONE = 0, + TXFR_INJECT_SEMAPHORE_CREATE, + TXFR_INJECT_MUTEX_CREATE, + TXFR_INJECT_EVENT_FLAGS_CREATE, + TXFR_INJECT_TIMER_CREATE, + TXFR_INJECT_THREAD_CREATE +} TXFR_INJECT_TARGET; + +/* Counts of the ThreadX primitives the layer reached for while accounting was + active. The byte pool counts stand in for txfr_malloc() and txfr_free(), + which cannot be wrapped: they are defined in tx_freertos.c and called from + within it, so the compiler resolves those calls internally. */ +typedef struct TXFR_COUNTERS_STRUCT +{ + int byte_allocate; + int byte_release; + int semaphore_create; + int semaphore_delete; + int mutex_create; + int mutex_delete; + int event_flags_create; + int event_flags_delete; + int timer_create; + int timer_delete; + int thread_create; + int thread_delete; +} TXFR_COUNTERS; + +/* Start accounting. Pass TXFR_INJECT_NONE to only count, or a target together + with the 1 based index of the call to fail, counted from this call onward. */ +void txfr_test_account_start(TXFR_INJECT_TARGET target, int fail_on_call); + +/* Stop accounting and copy out what was counted. */ +void txfr_test_account_stop(TXFR_COUNTERS *p_counters); + +/* Record the outcome of one expectation. Prints a line per check and remembers + whether anything failed. */ +void txfr_test_check(const char *label, int condition); + +/* As above, with the observed and expected counts printed on a failure. */ +void txfr_test_check_counts(const char *label, const TXFR_COUNTERS *p_counters, + int expect_allocate, int expect_release, + int expect_object_create, int expect_object_delete); + +/* Number of failed checks so far. */ +int txfr_test_failures(void); + +/* Each test file defines this. It runs in thread context, since the byte pool + operations under test are not callable from initialization. */ +void txfr_test_body(void); + +#endif /* TXFR_TEST_HARNESS_H */ From cfed1d8095f7f0c32f74570c5df7a47655241bb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Sun, 9 Aug 2026 08:44:30 -0400 Subject: [PATCH 016/181] Fixed the kernel object leaks on the static creation error paths (#584) xQueueCreateStatic() and xTaskCreateStatic() take their storage from the caller, so neither leaks memory, but both create ThreadX objects and both return NULL when a later step fails. The caller is left without a handle and cannot call the matching delete function, so any object already created stays registered in the kernel, pointing into a caller buffer that the application is now free to reuse or discard. Three paths were affected. xQueueCreateStatic() abandoned the read semaphore when the write semaphore could not be created. xTaskCreateStatic() abandoned the notification semaphore when the thread could not be created, and abandoned both the semaphore and the thread when the thread could not be resumed. Delete what was already created before returning on each of them. The resume path terminates the thread before deleting it, since a thread created with TX_DONT_START is suspended rather than terminated, which is the same order the idle task uses when it reaps a deleted task. Extend the regression suite to cover all three paths, and add thread resume to the set of entry points the harness can force to fail. Each static failure case now uses its own control block, so a future regression on one path cannot carry damage into the next case and report misleading counts there. Verified against the layer as it stands on dev, where the three new checks fail with the objects left behind, and against the fixed layer, where the suite passes. Assisted-by: Claude Code (Opus 5) --- test/freertos/cmake/regression/CMakeLists.txt | 3 +- .../regression/txfr_queue_create_test.c | 16 ++++++++ .../regression/txfr_task_create_test.c | 40 +++++++++++++++++++ test/freertos/regression/txfr_test_harness.c | 18 +++++++++ test/freertos/regression/txfr_test_harness.h | 7 +++- .../FreeRTOS/tx_freertos.c | 8 ++++ 6 files changed, 90 insertions(+), 2 deletions(-) diff --git a/test/freertos/cmake/regression/CMakeLists.txt b/test/freertos/cmake/regression/CMakeLists.txt index 783e95406..21da2a6dc 100644 --- a/test/freertos/cmake/regression/CMakeLists.txt +++ b/test/freertos/cmake/regression/CMakeLists.txt @@ -45,7 +45,8 @@ set(wrapped_symbols _txe_timer_create _txe_timer_delete _txe_thread_create - _txe_thread_delete) + _txe_thread_delete + _txe_thread_resume) set(wrap_link_options "") foreach(symbol ${wrapped_symbols}) diff --git a/test/freertos/regression/txfr_queue_create_test.c b/test/freertos/regression/txfr_queue_create_test.c index 36eb10170..aa9960704 100644 --- a/test/freertos/regression/txfr_queue_create_test.c +++ b/test/freertos/regression/txfr_queue_create_test.c @@ -96,6 +96,22 @@ void txfr_test_body(void) txfr_test_check_counts("vQueueDelete on static queue", &counters, 0, 0, 0, 2); } + /* The static variant owns no memory, but it still creates two semaphores + and still hands back nothing on failure, so the caller cannot call + vQueueDelete(). A read semaphore left behind here would stay registered + in the kernel, pointing into the caller's StaticQueue_t. */ + txfr_test_account_start(TXFR_INJECT_SEMAPHORE_CREATE, 1); + queue = xQueueCreateStatic(QUEUE_LENGTH, QUEUE_ITEM_SIZE, queue_storage, &queue_control_block); + txfr_test_account_stop(&counters); + txfr_test_check("xQueueCreateStatic returns NULL on read_sem failure", queue == NULL); + txfr_test_check_counts("static read_sem failure leaves nothing behind", &counters, 0, 0, 1, 0); + + txfr_test_account_start(TXFR_INJECT_SEMAPHORE_CREATE, 2); + queue = xQueueCreateStatic(QUEUE_LENGTH, QUEUE_ITEM_SIZE, queue_storage, &queue_control_block); + txfr_test_account_stop(&counters); + txfr_test_check("xQueueCreateStatic returns NULL on write_sem failure", queue == NULL); + txfr_test_check_counts("static write_sem failure unwinds read_sem", &counters, 0, 0, 2, 1); + /* Repeated create and delete cycles must leave the pool able to serve the same request. This would not catch a small leak on its own, which is why the counts above are checked directly, but it does catch a descriptor diff --git a/test/freertos/regression/txfr_task_create_test.c b/test/freertos/regression/txfr_task_create_test.c index 288d34907..2371bcc05 100644 --- a/test/freertos/regression/txfr_task_create_test.c +++ b/test/freertos/regression/txfr_task_create_test.c @@ -36,6 +36,18 @@ static StaticTask_t task_control_block; static StackType_t task_stack[TASK_STACK_DEPTH]; +/* Each failure case gets its own buffers, for two reasons. vTaskDelete() only + queues a task for the idle task to reap, so the control block of a task + deleted above is still live while this test thread runs. And if one of these + paths ever regresses and leaves an object behind, a shared buffer would + carry that damage into the next case and report misleading counts there. */ +static StaticTask_t semaphore_failure_control_block; +static StackType_t semaphore_failure_stack[TASK_STACK_DEPTH]; +static StaticTask_t thread_failure_control_block; +static StackType_t thread_failure_stack[TASK_STACK_DEPTH]; +static StaticTask_t resume_failure_control_block; +static StackType_t resume_failure_stack[TASK_STACK_DEPTH]; + static void test_task_entry(void *p_arg) { @@ -102,4 +114,32 @@ void txfr_test_body(void) { vTaskDelete(task); } + + /* As with the queues, the static variant owns no memory but still creates + kernel objects and still returns nothing on failure. A semaphore or a + thread left behind here stays registered in the kernel, pointing into + the caller's StaticTask_t. */ + txfr_test_account_start(TXFR_INJECT_SEMAPHORE_CREATE, 1); + task = xTaskCreateStatic(test_task_entry, "s_sem", TASK_STACK_DEPTH, NULL, TASK_PRIORITY, + semaphore_failure_stack, &semaphore_failure_control_block); + txfr_test_account_stop(&counters); + txfr_test_check("xTaskCreateStatic returns NULL on semaphore failure", task == NULL); + txfr_test_check_counts("static semaphore failure leaves nothing behind", &counters, 0, 0, 1, 0); + + txfr_test_account_start(TXFR_INJECT_THREAD_CREATE, 1); + task = xTaskCreateStatic(test_task_entry, "s_thr", TASK_STACK_DEPTH, NULL, TASK_PRIORITY, + thread_failure_stack, &thread_failure_control_block); + txfr_test_account_stop(&counters); + txfr_test_check("xTaskCreateStatic returns NULL on thread failure", task == NULL); + txfr_test_check_counts("static thread failure unwinds the semaphore", &counters, 0, 0, 2, 1); + + /* The resume is the last step, so by then both kernel objects exist. The + thread has to be terminated before it can be deleted, which is the order + the idle task uses when it reaps a deleted task. */ + txfr_test_account_start(TXFR_INJECT_THREAD_RESUME, 1); + task = xTaskCreateStatic(test_task_entry, "s_res", TASK_STACK_DEPTH, NULL, TASK_PRIORITY, + resume_failure_stack, &resume_failure_control_block); + txfr_test_account_stop(&counters); + txfr_test_check("xTaskCreateStatic returns NULL on resume failure", task == NULL); + txfr_test_check_counts("static resume failure unwinds thread and semaphore", &counters, 0, 0, 2, 2); } diff --git a/test/freertos/regression/txfr_test_harness.c b/test/freertos/regression/txfr_test_harness.c index ead2bfb0f..9f9ec887e 100644 --- a/test/freertos/regression/txfr_test_harness.c +++ b/test/freertos/regression/txfr_test_harness.c @@ -52,6 +52,7 @@ UINT __real__txe_thread_create(TX_THREAD *thread_ptr, CHAR *name_ptr, VOID (*ent UINT preempt_threshold, ULONG time_slice, UINT auto_start, UINT thread_control_block_size); UINT __real__txe_thread_delete(TX_THREAD *thread_ptr); +UINT __real__txe_thread_resume(TX_THREAD *thread_ptr); /* Determine whether the call now being made is the one the test asked to fail. @@ -240,6 +241,23 @@ UINT __wrap__txe_thread_delete(TX_THREAD *thread_ptr) } +UINT __wrap__txe_thread_resume(TX_THREAD *thread_ptr) +{ + if(txfr_should_fail(TXFR_INJECT_THREAD_RESUME) != 0) + { + txfr_counters.thread_resume++; + return TX_RESUME_ERROR; + } + + if(txfr_accounting != 0) + { + txfr_counters.thread_resume++; + } + + return __real__txe_thread_resume(thread_ptr); +} + + void txfr_test_account_start(TXFR_INJECT_TARGET target, int fail_on_call) { TX_MEMSET(&txfr_counters, 0, sizeof(txfr_counters)); diff --git a/test/freertos/regression/txfr_test_harness.h b/test/freertos/regression/txfr_test_harness.h index a0db51623..ffb6db0e3 100644 --- a/test/freertos/regression/txfr_test_harness.h +++ b/test/freertos/regression/txfr_test_harness.h @@ -49,7 +49,8 @@ typedef enum TXFR_INJECT_TARGET_ENUM TXFR_INJECT_MUTEX_CREATE, TXFR_INJECT_EVENT_FLAGS_CREATE, TXFR_INJECT_TIMER_CREATE, - TXFR_INJECT_THREAD_CREATE + TXFR_INJECT_THREAD_CREATE, + TXFR_INJECT_THREAD_RESUME } TXFR_INJECT_TARGET; /* Counts of the ThreadX primitives the layer reached for while accounting was @@ -70,6 +71,10 @@ typedef struct TXFR_COUNTERS_STRUCT int timer_delete; int thread_create; int thread_delete; + + /* Counted, but not part of the object totals checked below, since a + resume creates nothing. */ + int thread_resume; } TXFR_COUNTERS; /* Start accounting. Pass TXFR_INJECT_NONE to only count, or a target together diff --git a/utility/rtos_compatibility_layers/FreeRTOS/tx_freertos.c b/utility/rtos_compatibility_layers/FreeRTOS/tx_freertos.c index 8d55586dd..f3a19a01d 100644 --- a/utility/rtos_compatibility_layers/FreeRTOS/tx_freertos.c +++ b/utility/rtos_compatibility_layers/FreeRTOS/tx_freertos.c @@ -350,6 +350,7 @@ TaskHandle_t xTaskCreateStatic(TaskFunction_t pxTaskCode, ret = tx_thread_create(&pxTaskBuffer->thread, (CHAR *)pcName, txfr_thread_wrapper, (ULONG)pvParameters, puxStackBuffer, stack_depth_bytes, prio, prio, 0u, TX_DONT_START); if(ret != TX_SUCCESS) { + (void)tx_semaphore_delete(&pxTaskBuffer->notification_sem); TX_FREERTOS_ASSERT_FAIL(); return NULL; } @@ -358,6 +359,12 @@ TaskHandle_t xTaskCreateStatic(TaskFunction_t pxTaskCode, ret = tx_thread_resume(&pxTaskBuffer->thread); if(ret != TX_SUCCESS) { + /* The thread exists but was never started. It has to be terminated + before it can be deleted, which is the order the idle task uses when + it reaps a deleted task. */ + (void)tx_thread_terminate(&pxTaskBuffer->thread); + (void)tx_thread_delete(&pxTaskBuffer->thread); + (void)tx_semaphore_delete(&pxTaskBuffer->notification_sem); TX_FREERTOS_ASSERT_FAIL(); return NULL; } @@ -1489,6 +1496,7 @@ QueueHandle_t xQueueCreateStatic(UBaseType_t uxQueueLength, ret = tx_semaphore_create(&pxQueueBuffer->write_sem, "", uxQueueLength); if(ret != TX_SUCCESS) { + (void)tx_semaphore_delete(&pxQueueBuffer->read_sem); return NULL; } From cbdf924d6bca6463ee78ba0f6ebfc47697ea018a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Sun, 9 Aug 2026 10:12:09 -0400 Subject: [PATCH 017/181] Removed the duplicated function body in the Cortex-M4 AC6 port (#589) _tx_thread_system_return_inline() in the Cortex-M4 AC6 tx_port.h was followed by a second, orphaned copy of its own body. The copy had no function header, so it declared interrupt_save at file scope and then placed statements there, which does not compile. It is also the older version of the body, without the dsb and isb barriers, so it was left behind rather than intended: the barriers were added by commit 33efad3f and the previous text was not removed. Delete the orphaned copy. What remains is the same body every sibling port carries: after this change ports/cortex_m4/ac6/inc/tx_port.h differs from ports/cortex_m4/iar/inc/tx_port.h and ports/cortex_m7/ac6/inc/tx_port.h only in the port name in the banner and the version string, as it should. Verified by compiling the function in isolation, which fails on the file scope statements before the change and is clean afterwards, and by a structural scan of all 208 tx_port.h files in the repository confirming this was the only occurrence. Fixes https://github.com/eclipse-threadx/threadx/issues/569 Assisted-by: Claude Code (Opus 5) --- ports/cortex_m4/ac6/inc/tx_port.h | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/ports/cortex_m4/ac6/inc/tx_port.h b/ports/cortex_m4/ac6/inc/tx_port.h index 4b634b64b..e1d21df1a 100644 --- a/ports/cortex_m4/ac6/inc/tx_port.h +++ b/ports/cortex_m4/ac6/inc/tx_port.h @@ -11,6 +11,7 @@ // Some portions generated by Gemini (Gemini 2.0 Flash). // Some portions generated by Copilot (Claude Sonnet 4.6). +// Some portions generated by Claude Code (Opus 5). /**************************************************************************/ @@ -594,21 +595,6 @@ unsigned int interrupt_save; __restore_interrupt(interrupt_save); } } -unsigned int interrupt_save; - - /* Set PendSV to invoke ThreadX scheduler. */ - *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); - if (__get_ipsr_value() == 0) - { - interrupt_save = __get_interrupt_posture(); -#ifdef TX_PORT_USE_BASEPRI - __set_basepri_value(0); -#else - __enable_interrupts(); -#endif - __restore_interrupt(interrupt_save); - } -} #define TX_INTERRUPT_SAVE_AREA UINT interrupt_save; #define TX_DISABLE interrupt_save = __disable_interrupts(); From eb4ec4e3b52c17099ad2b4af35b594c19bbeba55 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Sun, 9 Aug 2026 10:42:54 -0400 Subject: [PATCH 018/181] Restored ports_arch as the source of truth for the Cortex-M ports (#590) The Cortex-M ports under ports/ are generated. scripts/copy_armv7_m.sh copies one tx_port.h and the per tool sources to fifteen M3, M4 and M7 targets, and scripts/copy_armv8_m.sh does the same for nine M33, M55 and M85 targets. The ports_arch_check workflow runs both scripts and fails if the tree is not reproducible, so those copies are meant never to be edited directly. They were. Every Cortex-M fix since #523 was applied to the generated copies and not to the source, so the source fell behind and the check went red: running the three scripts on dev changes 35 files. The check triggers only on pull requests targeting master, which is why nothing caught it while the fixes were merged into dev. Left alone, the next run of these scripts would have reverted three separate pieces of work: the memory barriers and clobbers from #523, the correction of the IAR assembly header to use the assembler's own comment syntax, and the move of tx_initialize_low_level.S into example_build for the M33, M55 and M85 GNU ports from #514. Bring the sources up to what the ports carry today, and regenerate. Two behavioural changes come with that, both deliberate. The barriers from #523 reach the ac5 and keil variants of M3, M4 and M7, which were outside the scope of that fix and never received it. The barrier that follows restoring the interrupt posture, which #523 gave only to the GNU ports because GNU was the only toolchain that could be tested, now applies to every tool; the identical asm statement already shipped in the AC6 and IAR ports, so this adds a pipeline flush rather than any new compiler exposure. Regenerating also drops a stray #endif at the end of the Cortex-M85 IAR tx_port.h, added by #523, which left that header with one more #endif than #if and unable to compile. Every other ARMv8-M port was balanced. Verified that the scripts are idempotent afterwards, that ports_arch_check would pass, that no port loses a barrier or a clobber, that every regenerated header is preprocessor balanced, and that every Cortex-M port covered by the two scripts now carries the entry barrier. Assisted-by: Claude Code (Opus 5) --- ports/cortex_m3/ac5/inc/tx_port.h | 11 +- ports/cortex_m3/ac6/inc/tx_port.h | 5 +- .../ac6/src/tx_thread_system_return.S | 2 + ports/cortex_m3/gnu/inc/tx_port.h | 4 + ports/cortex_m3/iar/inc/tx_port.h | 5 +- .../iar/src/tx_thread_system_return.s | 2 + ports/cortex_m3/keil/inc/tx_port.h | 11 +- ports/cortex_m33/ac6/inc/tx_port.h | 2 + .../ac6/src/tx_thread_system_return.S | 2 + ports/cortex_m33/gnu/inc/tx_port.h | 2 + ports/cortex_m33/iar/inc/tx_port.h | 2 + .../iar/src/tx_thread_system_return.s | 2 + ports/cortex_m4/ac5/inc/tx_port.h | 11 +- ports/cortex_m4/ac6/inc/tx_port.h | 3 +- .../ac6/src/tx_thread_system_return.S | 2 + ports/cortex_m4/gnu/inc/tx_port.h | 3 +- ports/cortex_m4/iar/inc/tx_port.h | 5 +- .../iar/src/tx_thread_system_return.s | 2 + ports/cortex_m4/keil/inc/tx_port.h | 11 +- ports/cortex_m55/ac6/inc/tx_port.h | 8 +- .../ac6/src/tx_thread_system_return.S | 6 + ports/cortex_m55/gnu/inc/tx_port.h | 1 + ports/cortex_m55/iar/inc/tx_port.h | 7 +- .../iar/src/tx_thread_system_return.s | 2 + ports/cortex_m7/ac5/inc/tx_port.h | 11 +- ports/cortex_m7/ac6/inc/tx_port.h | 5 +- .../ac6/src/tx_thread_system_return.S | 2 + ports/cortex_m7/gnu/inc/tx_port.h | 4 +- ports/cortex_m7/iar/inc/tx_port.h | 5 +- .../iar/src/tx_thread_system_return.s | 2 + ports/cortex_m85/ac6/inc/tx_port.h | 8 +- .../ac6/src/tx_thread_system_return.S | 6 + ports/cortex_m85/gnu/inc/tx_port.h | 1 + ports/cortex_m85/iar/inc/tx_port.h | 7 +- .../iar/src/tx_thread_system_return.s | 2 + .../threadx/ac6/src/tx_thread_system_return.S | 6 + .../threadx/gnu/src/tx_thread_system_return.S | 6 + .../threadx/iar/src/tx_thread_system_return.s | 29 +- ports_arch/ARMv7-M/threadx/inc/tx_port.h | 11 +- .../threadx/ac6/src/tx_thread_system_return.S | 6 + ports_arch/ARMv8-M/threadx/gnu/CMakeLists.txt | 11 +- .../threadx/gnu/src/tx_initialize_low_level.S | 276 ------------------ .../threadx/gnu/src/tx_thread_system_return.S | 6 + .../threadx/iar/src/tx_thread_system_return.s | 29 +- ports_arch/ARMv8-M/threadx/inc/tx_port.h | 8 +- .../src/tx_thread_system_return.S | 6 + .../src/tx_thread_system_return.S | 6 + .../src/tx_thread_system_return.s | 29 +- .../src/tx_thread_system_return.S | 6 + .../src/tx_thread_system_return.S | 6 + .../src/tx_thread_system_return.s | 29 +- .../src/tx_thread_system_return.S | 6 + .../src/tx_thread_system_return.S | 6 + .../src/tx_thread_system_return.s | 29 +- 54 files changed, 313 insertions(+), 362 deletions(-) delete mode 100644 ports_arch/ARMv8-M/threadx/gnu/src/tx_initialize_low_level.S diff --git a/ports/cortex_m3/ac5/inc/tx_port.h b/ports/cortex_m3/ac5/inc/tx_port.h index 62783624a..62cae66d0 100644 --- a/ports/cortex_m3/ac5/inc/tx_port.h +++ b/ports/cortex_m3/ac5/inc/tx_port.h @@ -9,6 +9,10 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Gemini (Gemini 2.0 Flash). +// Some portions generated by Copilot (Claude Sonnet 4.6). +// Some portions generated by Claude Code (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -539,8 +543,9 @@ unsigned int posture; #ifdef TX_PORT_USE_BASEPRI __attribute__( ( always_inline ) ) static inline void __set_basepri_value(unsigned int basepri_value) { - __asm__ volatile ("MSR BASEPRI,%0 ": : "r" (basepri_value)); + __asm__ volatile ("MSR BASEPRI,%0 ": : "r" (basepri_value) : "memory"); } + #else __attribute__( ( always_inline ) ) static inline void __enable_interrupts(void) { @@ -552,7 +557,7 @@ __attribute__( ( always_inline ) ) static inline void __restore_interrupt(unsign { #ifdef TX_PORT_USE_BASEPRI __set_basepri_value(int_posture); - //__asm__ volatile ("MSR BASEPRI,%0": : "r" (int_posture): "memory"); + __asm__ volatile ("" : : : "memory"); #else __asm__ volatile ("MSR PRIMASK,%0": : "r" (int_posture): "memory"); #endif @@ -578,6 +583,7 @@ unsigned int interrupt_save; /* Set PendSV to invoke ThreadX scheduler. */ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); + __asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory"); if (__get_ipsr_value() == 0) { interrupt_save = __get_interrupt_posture(); @@ -587,6 +593,7 @@ unsigned int interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); + __asm__ volatile ("isb 0xF " : : : "memory"); } } diff --git a/ports/cortex_m3/ac6/inc/tx_port.h b/ports/cortex_m3/ac6/inc/tx_port.h index df44632b0..7265724ef 100644 --- a/ports/cortex_m3/ac6/inc/tx_port.h +++ b/ports/cortex_m3/ac6/inc/tx_port.h @@ -11,6 +11,7 @@ // Some portions generated by Gemini (Gemini 2.0 Flash). // Some portions generated by Copilot (Claude Sonnet 4.6). +// Some portions generated by Claude Code (Opus 5). /**************************************************************************/ @@ -544,8 +545,8 @@ __attribute__( ( always_inline ) ) static inline void __set_basepri_value(unsign { __asm__ volatile ("MSR BASEPRI,%0 ": : "r" (basepri_value) : "memory"); } -#else +#else __attribute__( ( always_inline ) ) static inline void __enable_interrupts(void) { __asm__ volatile ("CPSIE i": : : "memory"); @@ -592,8 +593,10 @@ unsigned int interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); + __asm__ volatile ("isb 0xF " : : : "memory"); } } + #define TX_INTERRUPT_SAVE_AREA UINT interrupt_save; #define TX_DISABLE interrupt_save = __disable_interrupts(); #define TX_RESTORE __restore_interrupt(interrupt_save); diff --git a/ports/cortex_m3/ac6/src/tx_thread_system_return.S b/ports/cortex_m3/ac6/src/tx_thread_system_return.S index a8654f6ba..6d0e26afa 100644 --- a/ports/cortex_m3/ac6/src/tx_thread_system_return.S +++ b/ports/cortex_m3/ac6/src/tx_thread_system_return.S @@ -85,10 +85,12 @@ _tx_thread_system_return: MOV r0, #0 MSR BASEPRI, r0 // Enable interrupts MSR BASEPRI, r1 // Restore original interrupt posture + ISB #0xF // Flush pipeline #else MRS r1, PRIMASK // Thread context returning, pickup PRIMASK CPSIE i // Enable interrupts MSR PRIMASK, r1 // Restore original interrupt posture + ISB #0xF // Flush pipeline #endif _isr_context: BX lr // Return to caller diff --git a/ports/cortex_m3/gnu/inc/tx_port.h b/ports/cortex_m3/gnu/inc/tx_port.h index d36b9ea38..d5299cb38 100644 --- a/ports/cortex_m3/gnu/inc/tx_port.h +++ b/ports/cortex_m3/gnu/inc/tx_port.h @@ -10,6 +10,8 @@ **************************************************************************/ // Some portions generated by Gemini (Gemini 2.0 Flash). +// Some portions generated by Copilot (Claude Sonnet 4.6). +// Some portions generated by Claude Code (Opus 5). /**************************************************************************/ @@ -543,6 +545,7 @@ __attribute__( ( always_inline ) ) static inline void __set_basepri_value(unsign { __asm__ volatile ("MSR BASEPRI,%0 ": : "r" (basepri_value) : "memory"); } + #else __attribute__( ( always_inline ) ) static inline void __enable_interrupts(void) { @@ -554,6 +557,7 @@ __attribute__( ( always_inline ) ) static inline void __restore_interrupt(unsign { #ifdef TX_PORT_USE_BASEPRI __set_basepri_value(int_posture); + __asm__ volatile ("" : : : "memory"); #else __asm__ volatile ("MSR PRIMASK,%0": : "r" (int_posture): "memory"); #endif diff --git a/ports/cortex_m3/iar/inc/tx_port.h b/ports/cortex_m3/iar/inc/tx_port.h index 18c7e9f2e..5b05c277a 100644 --- a/ports/cortex_m3/iar/inc/tx_port.h +++ b/ports/cortex_m3/iar/inc/tx_port.h @@ -11,6 +11,7 @@ // Some portions generated by Gemini (Gemini 2.0 Flash). // Some portions generated by Copilot (Claude Sonnet 4.6). +// Some portions generated by Claude Code (Opus 5). /**************************************************************************/ @@ -544,8 +545,8 @@ __attribute__( ( always_inline ) ) static inline void __set_basepri_value(unsign { __asm__ volatile ("MSR BASEPRI,%0 ": : "r" (basepri_value) : "memory"); } -#else +#else __attribute__( ( always_inline ) ) static inline void __enable_interrupts(void) { __asm__ volatile ("CPSIE i": : : "memory"); @@ -592,8 +593,10 @@ unsigned int interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); + __asm__ volatile ("isb 0xF " : : : "memory"); } } + #define TX_INTERRUPT_SAVE_AREA UINT interrupt_save; #define TX_DISABLE interrupt_save = __disable_interrupts(); #define TX_RESTORE __restore_interrupt(interrupt_save); diff --git a/ports/cortex_m3/iar/src/tx_thread_system_return.s b/ports/cortex_m3/iar/src/tx_thread_system_return.s index 8bd4ca820..7bc5f2ebc 100644 --- a/ports/cortex_m3/iar/src/tx_thread_system_return.s +++ b/ports/cortex_m3/iar/src/tx_thread_system_return.s @@ -83,10 +83,12 @@ _tx_thread_system_return: MOV r0, #0 MSR BASEPRI, r0 // Enable interrupts MSR BASEPRI, r1 // Restore original interrupt posture + ISB SY // Flush pipeline #else MRS r1, PRIMASK // Thread context returning, pickup PRIMASK CPSIE i // Enable interrupts MSR PRIMASK, r1 // Restore original interrupt posture + ISB SY // Flush pipeline #endif _isr_context: BX lr // Return to caller diff --git a/ports/cortex_m3/keil/inc/tx_port.h b/ports/cortex_m3/keil/inc/tx_port.h index d7a7e9412..0fc2ea65a 100644 --- a/ports/cortex_m3/keil/inc/tx_port.h +++ b/ports/cortex_m3/keil/inc/tx_port.h @@ -9,6 +9,10 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Gemini (Gemini 2.0 Flash). +// Some portions generated by Copilot (Claude Sonnet 4.6). +// Some portions generated by Claude Code (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -539,8 +543,9 @@ unsigned int posture; #ifdef TX_PORT_USE_BASEPRI __attribute__( ( always_inline ) ) static inline void __set_basepri_value(unsigned int basepri_value) { - __asm__ volatile ("MSR BASEPRI,%0 ": : "r" (basepri_value)); + __asm__ volatile ("MSR BASEPRI,%0 ": : "r" (basepri_value) : "memory"); } + #else __attribute__( ( always_inline ) ) static inline void __enable_interrupts(void) { @@ -552,7 +557,7 @@ __attribute__( ( always_inline ) ) static inline void __restore_interrupt(unsign { #ifdef TX_PORT_USE_BASEPRI __set_basepri_value(int_posture); - //__asm__ volatile ("MSR BASEPRI,%0": : "r" (int_posture): "memory"); + __asm__ volatile ("" : : : "memory"); #else __asm__ volatile ("MSR PRIMASK,%0": : "r" (int_posture): "memory"); #endif @@ -578,6 +583,7 @@ unsigned int interrupt_save; /* Set PendSV to invoke ThreadX scheduler. */ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); + __asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory"); if (__get_ipsr_value() == 0) { interrupt_save = __get_interrupt_posture(); @@ -587,6 +593,7 @@ unsigned int interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); + __asm__ volatile ("isb 0xF " : : : "memory"); } } diff --git a/ports/cortex_m33/ac6/inc/tx_port.h b/ports/cortex_m33/ac6/inc/tx_port.h index bfdff366b..86411a859 100644 --- a/ports/cortex_m33/ac6/inc/tx_port.h +++ b/ports/cortex_m33/ac6/inc/tx_port.h @@ -10,6 +10,7 @@ **************************************************************************/ // Some portions generated by Gemini (Gemini 2.0 Flash). +// Some portions generated by Claude Code (Opus 5). /**************************************************************************/ @@ -592,6 +593,7 @@ UINT interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); + __asm__ volatile ("isb 0xF " : : : "memory"); } } diff --git a/ports/cortex_m33/ac6/src/tx_thread_system_return.S b/ports/cortex_m33/ac6/src/tx_thread_system_return.S index e57b28ea2..cd183702f 100644 --- a/ports/cortex_m33/ac6/src/tx_thread_system_return.S +++ b/ports/cortex_m33/ac6/src/tx_thread_system_return.S @@ -86,10 +86,12 @@ _tx_thread_system_return: MOV r0, #0 MSR BASEPRI, r0 // Enable interrupts MSR BASEPRI, r1 // Restore original interrupt posture + ISB #0xF // Flush pipeline #else MRS r1, PRIMASK // Thread context returning, pickup PRIMASK CPSIE i // Enable interrupts MSR PRIMASK, r1 // Restore original interrupt posture + ISB #0xF // Flush pipeline #endif _isr_context: BX lr // Return to caller diff --git a/ports/cortex_m33/gnu/inc/tx_port.h b/ports/cortex_m33/gnu/inc/tx_port.h index bc6321c0b..dc67c0015 100644 --- a/ports/cortex_m33/gnu/inc/tx_port.h +++ b/ports/cortex_m33/gnu/inc/tx_port.h @@ -10,6 +10,7 @@ **************************************************************************/ // Some portions generated by Gemini (Gemini 2.0 Flash). +// Some portions generated by Claude Code (Opus 5). /**************************************************************************/ @@ -556,6 +557,7 @@ __attribute__( ( always_inline ) ) static inline void __restore_interrupt(UINT i { #ifdef TX_PORT_USE_BASEPRI __set_basepri_value(int_posture); + __asm__ volatile ("" : : : "memory"); #else __asm__ volatile ("MSR PRIMASK,%0": : "r" (int_posture): "memory"); #endif diff --git a/ports/cortex_m33/iar/inc/tx_port.h b/ports/cortex_m33/iar/inc/tx_port.h index a5667779c..6527b34a1 100644 --- a/ports/cortex_m33/iar/inc/tx_port.h +++ b/ports/cortex_m33/iar/inc/tx_port.h @@ -10,6 +10,7 @@ **************************************************************************/ // Some portions generated by Gemini (Gemini 2.0 Flash). +// Some portions generated by Claude Code (Opus 5). /**************************************************************************/ @@ -592,6 +593,7 @@ UINT interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); + __asm__ volatile ("isb 0xF " : : : "memory"); } } diff --git a/ports/cortex_m33/iar/src/tx_thread_system_return.s b/ports/cortex_m33/iar/src/tx_thread_system_return.s index 83eb4a66a..89f086fc5 100644 --- a/ports/cortex_m33/iar/src/tx_thread_system_return.s +++ b/ports/cortex_m33/iar/src/tx_thread_system_return.s @@ -82,10 +82,12 @@ _tx_thread_system_return: MOV r0, #0 MSR BASEPRI, r0 // Enable interrupts MSR BASEPRI, r1 // Restore original interrupt posture + ISB SY // Flush pipeline #else MRS r1, PRIMASK // Thread context returning, pickup PRIMASK CPSIE i // Enable interrupts MSR PRIMASK, r1 // Restore original interrupt posture + ISB SY // Flush pipeline #endif _isr_context: BX lr // Return to caller diff --git a/ports/cortex_m4/ac5/inc/tx_port.h b/ports/cortex_m4/ac5/inc/tx_port.h index febc6e8fe..ea89ed1aa 100644 --- a/ports/cortex_m4/ac5/inc/tx_port.h +++ b/ports/cortex_m4/ac5/inc/tx_port.h @@ -9,6 +9,10 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Gemini (Gemini 2.0 Flash). +// Some portions generated by Copilot (Claude Sonnet 4.6). +// Some portions generated by Claude Code (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -539,8 +543,9 @@ unsigned int posture; #ifdef TX_PORT_USE_BASEPRI __attribute__( ( always_inline ) ) static inline void __set_basepri_value(unsigned int basepri_value) { - __asm__ volatile ("MSR BASEPRI,%0 ": : "r" (basepri_value)); + __asm__ volatile ("MSR BASEPRI,%0 ": : "r" (basepri_value) : "memory"); } + #else __attribute__( ( always_inline ) ) static inline void __enable_interrupts(void) { @@ -552,7 +557,7 @@ __attribute__( ( always_inline ) ) static inline void __restore_interrupt(unsign { #ifdef TX_PORT_USE_BASEPRI __set_basepri_value(int_posture); - //__asm__ volatile ("MSR BASEPRI,%0": : "r" (int_posture): "memory"); + __asm__ volatile ("" : : : "memory"); #else __asm__ volatile ("MSR PRIMASK,%0": : "r" (int_posture): "memory"); #endif @@ -578,6 +583,7 @@ unsigned int interrupt_save; /* Set PendSV to invoke ThreadX scheduler. */ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); + __asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory"); if (__get_ipsr_value() == 0) { interrupt_save = __get_interrupt_posture(); @@ -587,6 +593,7 @@ unsigned int interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); + __asm__ volatile ("isb 0xF " : : : "memory"); } } diff --git a/ports/cortex_m4/ac6/inc/tx_port.h b/ports/cortex_m4/ac6/inc/tx_port.h index e1d21df1a..3946fec21 100644 --- a/ports/cortex_m4/ac6/inc/tx_port.h +++ b/ports/cortex_m4/ac6/inc/tx_port.h @@ -545,8 +545,8 @@ __attribute__( ( always_inline ) ) static inline void __set_basepri_value(unsign { __asm__ volatile ("MSR BASEPRI,%0 ": : "r" (basepri_value) : "memory"); } -#else +#else __attribute__( ( always_inline ) ) static inline void __enable_interrupts(void) { __asm__ volatile ("CPSIE i": : : "memory"); @@ -593,6 +593,7 @@ unsigned int interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); + __asm__ volatile ("isb 0xF " : : : "memory"); } } diff --git a/ports/cortex_m4/ac6/src/tx_thread_system_return.S b/ports/cortex_m4/ac6/src/tx_thread_system_return.S index 4c5068ee9..59a7210d5 100644 --- a/ports/cortex_m4/ac6/src/tx_thread_system_return.S +++ b/ports/cortex_m4/ac6/src/tx_thread_system_return.S @@ -85,10 +85,12 @@ _tx_thread_system_return: MOV r0, #0 MSR BASEPRI, r0 // Enable interrupts MSR BASEPRI, r1 // Restore original interrupt posture + ISB #0xF // Flush pipeline #else MRS r1, PRIMASK // Thread context returning, pickup PRIMASK CPSIE i // Enable interrupts MSR PRIMASK, r1 // Restore original interrupt posture + ISB #0xF // Flush pipeline #endif _isr_context: BX lr // Return to caller diff --git a/ports/cortex_m4/gnu/inc/tx_port.h b/ports/cortex_m4/gnu/inc/tx_port.h index d35a6d4ee..98d81669f 100644 --- a/ports/cortex_m4/gnu/inc/tx_port.h +++ b/ports/cortex_m4/gnu/inc/tx_port.h @@ -11,6 +11,7 @@ // Some portions generated by Gemini (Gemini 2.0 Flash). // Some portions generated by Copilot (Claude Sonnet 4.6). +// Some portions generated by Claude Code (Opus 5). /**************************************************************************/ @@ -544,8 +545,8 @@ __attribute__( ( always_inline ) ) static inline void __set_basepri_value(unsign { __asm__ volatile ("MSR BASEPRI,%0 ": : "r" (basepri_value) : "memory"); } -#else +#else __attribute__( ( always_inline ) ) static inline void __enable_interrupts(void) { __asm__ volatile ("CPSIE i": : : "memory"); diff --git a/ports/cortex_m4/iar/inc/tx_port.h b/ports/cortex_m4/iar/inc/tx_port.h index 84711da1e..8acba9076 100644 --- a/ports/cortex_m4/iar/inc/tx_port.h +++ b/ports/cortex_m4/iar/inc/tx_port.h @@ -11,6 +11,7 @@ // Some portions generated by Gemini (Gemini 2.0 Flash). // Some portions generated by Copilot (Claude Sonnet 4.6). +// Some portions generated by Claude Code (Opus 5). /**************************************************************************/ @@ -544,8 +545,8 @@ __attribute__( ( always_inline ) ) static inline void __set_basepri_value(unsign { __asm__ volatile ("MSR BASEPRI,%0 ": : "r" (basepri_value) : "memory"); } -#else +#else __attribute__( ( always_inline ) ) static inline void __enable_interrupts(void) { __asm__ volatile ("CPSIE i": : : "memory"); @@ -592,8 +593,10 @@ unsigned int interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); + __asm__ volatile ("isb 0xF " : : : "memory"); } } + #define TX_INTERRUPT_SAVE_AREA UINT interrupt_save; #define TX_DISABLE interrupt_save = __disable_interrupts(); #define TX_RESTORE __restore_interrupt(interrupt_save); diff --git a/ports/cortex_m4/iar/src/tx_thread_system_return.s b/ports/cortex_m4/iar/src/tx_thread_system_return.s index f9a668d96..b466bacaa 100644 --- a/ports/cortex_m4/iar/src/tx_thread_system_return.s +++ b/ports/cortex_m4/iar/src/tx_thread_system_return.s @@ -83,10 +83,12 @@ _tx_thread_system_return: MOV r0, #0 MSR BASEPRI, r0 // Enable interrupts MSR BASEPRI, r1 // Restore original interrupt posture + ISB SY // Flush pipeline #else MRS r1, PRIMASK // Thread context returning, pickup PRIMASK CPSIE i // Enable interrupts MSR PRIMASK, r1 // Restore original interrupt posture + ISB SY // Flush pipeline #endif _isr_context: BX lr // Return to caller diff --git a/ports/cortex_m4/keil/inc/tx_port.h b/ports/cortex_m4/keil/inc/tx_port.h index c502b37ea..415d5f507 100644 --- a/ports/cortex_m4/keil/inc/tx_port.h +++ b/ports/cortex_m4/keil/inc/tx_port.h @@ -9,6 +9,10 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Gemini (Gemini 2.0 Flash). +// Some portions generated by Copilot (Claude Sonnet 4.6). +// Some portions generated by Claude Code (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -539,8 +543,9 @@ unsigned int posture; #ifdef TX_PORT_USE_BASEPRI __attribute__( ( always_inline ) ) static inline void __set_basepri_value(unsigned int basepri_value) { - __asm__ volatile ("MSR BASEPRI,%0 ": : "r" (basepri_value)); + __asm__ volatile ("MSR BASEPRI,%0 ": : "r" (basepri_value) : "memory"); } + #else __attribute__( ( always_inline ) ) static inline void __enable_interrupts(void) { @@ -552,7 +557,7 @@ __attribute__( ( always_inline ) ) static inline void __restore_interrupt(unsign { #ifdef TX_PORT_USE_BASEPRI __set_basepri_value(int_posture); - //__asm__ volatile ("MSR BASEPRI,%0": : "r" (int_posture): "memory"); + __asm__ volatile ("" : : : "memory"); #else __asm__ volatile ("MSR PRIMASK,%0": : "r" (int_posture): "memory"); #endif @@ -578,6 +583,7 @@ unsigned int interrupt_save; /* Set PendSV to invoke ThreadX scheduler. */ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); + __asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory"); if (__get_ipsr_value() == 0) { interrupt_save = __get_interrupt_posture(); @@ -587,6 +593,7 @@ unsigned int interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); + __asm__ volatile ("isb 0xF " : : : "memory"); } } diff --git a/ports/cortex_m55/ac6/inc/tx_port.h b/ports/cortex_m55/ac6/inc/tx_port.h index 9ee2abfb8..f3cbba3a1 100644 --- a/ports/cortex_m55/ac6/inc/tx_port.h +++ b/ports/cortex_m55/ac6/inc/tx_port.h @@ -9,6 +9,9 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Gemini (Gemini 2.0 Flash). +// Some portions generated by Claude Code (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -541,7 +544,7 @@ UINT posture; #ifdef TX_PORT_USE_BASEPRI __attribute__( ( always_inline ) ) static inline void __set_basepri_value(UINT basepri_value) { - __asm__ volatile ("MSR BASEPRI,%0 ": : "r" (basepri_value)); + __asm__ volatile ("MSR BASEPRI,%0 ": : "r" (basepri_value) : "memory"); } #else __attribute__( ( always_inline ) ) static inline void __enable_interrupts(void) @@ -554,6 +557,7 @@ __attribute__( ( always_inline ) ) static inline void __restore_interrupt(UINT i { #ifdef TX_PORT_USE_BASEPRI __set_basepri_value(int_posture); + __asm__ volatile ("" : : : "memory"); #else __asm__ volatile ("MSR PRIMASK,%0": : "r" (int_posture): "memory"); #endif @@ -579,6 +583,7 @@ UINT interrupt_save; /* Set PendSV to invoke ThreadX scheduler. */ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); + __asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory"); if (_tx_ipsr_get() == 0) { interrupt_save = __get_interrupt_posture(); @@ -588,6 +593,7 @@ UINT interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); + __asm__ volatile ("isb 0xF " : : : "memory"); } } diff --git a/ports/cortex_m55/ac6/src/tx_thread_system_return.S b/ports/cortex_m55/ac6/src/tx_thread_system_return.S index a27c2756e..a72a9a418 100644 --- a/ports/cortex_m55/ac6/src/tx_thread_system_return.S +++ b/ports/cortex_m55/ac6/src/tx_thread_system_return.S @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Gemini (Gemini 2.0 Flash). + /**************************************************************************/ /**************************************************************************/ @@ -74,6 +76,8 @@ _tx_thread_system_return: MOV r0, #0x10000000 // Load PENDSVSET bit MOV r1, #0xE000E000 // Load NVIC base STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR + DSB #0xF // Ensure memory access is complete + ISB #0xF // Flush pipeline MRS r0, IPSR // Pickup IPSR CMP r0, #0 // Is it a thread returning? BNE _isr_context // If ISR, skip interrupt enable @@ -82,10 +86,12 @@ _tx_thread_system_return: MOV r0, #0 MSR BASEPRI, r0 // Enable interrupts MSR BASEPRI, r1 // Restore original interrupt posture + ISB #0xF // Flush pipeline #else MRS r1, PRIMASK // Thread context returning, pickup PRIMASK CPSIE i // Enable interrupts MSR PRIMASK, r1 // Restore original interrupt posture + ISB #0xF // Flush pipeline #endif _isr_context: BX lr // Return to caller diff --git a/ports/cortex_m55/gnu/inc/tx_port.h b/ports/cortex_m55/gnu/inc/tx_port.h index 9ceac0915..3f91c12d4 100644 --- a/ports/cortex_m55/gnu/inc/tx_port.h +++ b/ports/cortex_m55/gnu/inc/tx_port.h @@ -10,6 +10,7 @@ **************************************************************************/ // Some portions generated by Gemini (Gemini 2.0 Flash). +// Some portions generated by Claude Code (Opus 5). /**************************************************************************/ diff --git a/ports/cortex_m55/iar/inc/tx_port.h b/ports/cortex_m55/iar/inc/tx_port.h index 786cef0a7..3ff916b30 100644 --- a/ports/cortex_m55/iar/inc/tx_port.h +++ b/ports/cortex_m55/iar/inc/tx_port.h @@ -9,6 +9,9 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Gemini (Gemini 2.0 Flash). +// Some portions generated by Claude Code (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -541,7 +544,7 @@ UINT posture; #ifdef TX_PORT_USE_BASEPRI __attribute__( ( always_inline ) ) static inline void __set_basepri_value(UINT basepri_value) { - __asm__ volatile ("MSR BASEPRI,%0 ": : "r" (basepri_value)); + __asm__ volatile ("MSR BASEPRI,%0 ": : "r" (basepri_value) : "memory"); } #else __attribute__( ( always_inline ) ) static inline void __enable_interrupts(void) @@ -554,6 +557,7 @@ __attribute__( ( always_inline ) ) static inline void __restore_interrupt(UINT i { #ifdef TX_PORT_USE_BASEPRI __set_basepri_value(int_posture); + __asm__ volatile ("" : : : "memory"); #else __asm__ volatile ("MSR PRIMASK,%0": : "r" (int_posture): "memory"); #endif @@ -589,6 +593,7 @@ UINT interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); + __asm__ volatile ("isb 0xF " : : : "memory"); } } diff --git a/ports/cortex_m55/iar/src/tx_thread_system_return.s b/ports/cortex_m55/iar/src/tx_thread_system_return.s index 20493afcb..cb311a479 100644 --- a/ports/cortex_m55/iar/src/tx_thread_system_return.s +++ b/ports/cortex_m55/iar/src/tx_thread_system_return.s @@ -82,10 +82,12 @@ _tx_thread_system_return: MOV r0, #0 MSR BASEPRI, r0 // Enable interrupts MSR BASEPRI, r1 // Restore original interrupt posture + ISB SY // Flush pipeline #else MRS r1, PRIMASK // Thread context returning, pickup PRIMASK CPSIE i // Enable interrupts MSR PRIMASK, r1 // Restore original interrupt posture + ISB SY // Flush pipeline #endif _isr_context: BX lr // Return to caller diff --git a/ports/cortex_m7/ac5/inc/tx_port.h b/ports/cortex_m7/ac5/inc/tx_port.h index 1a8679569..8f84e7fe7 100644 --- a/ports/cortex_m7/ac5/inc/tx_port.h +++ b/ports/cortex_m7/ac5/inc/tx_port.h @@ -9,6 +9,10 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Gemini (Gemini 2.0 Flash). +// Some portions generated by Copilot (Claude Sonnet 4.6). +// Some portions generated by Claude Code (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -539,8 +543,9 @@ unsigned int posture; #ifdef TX_PORT_USE_BASEPRI __attribute__( ( always_inline ) ) static inline void __set_basepri_value(unsigned int basepri_value) { - __asm__ volatile ("MSR BASEPRI,%0 ": : "r" (basepri_value)); + __asm__ volatile ("MSR BASEPRI,%0 ": : "r" (basepri_value) : "memory"); } + #else __attribute__( ( always_inline ) ) static inline void __enable_interrupts(void) { @@ -552,7 +557,7 @@ __attribute__( ( always_inline ) ) static inline void __restore_interrupt(unsign { #ifdef TX_PORT_USE_BASEPRI __set_basepri_value(int_posture); - //__asm__ volatile ("MSR BASEPRI,%0": : "r" (int_posture): "memory"); + __asm__ volatile ("" : : : "memory"); #else __asm__ volatile ("MSR PRIMASK,%0": : "r" (int_posture): "memory"); #endif @@ -578,6 +583,7 @@ unsigned int interrupt_save; /* Set PendSV to invoke ThreadX scheduler. */ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); + __asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory"); if (__get_ipsr_value() == 0) { interrupt_save = __get_interrupt_posture(); @@ -587,6 +593,7 @@ unsigned int interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); + __asm__ volatile ("isb 0xF " : : : "memory"); } } diff --git a/ports/cortex_m7/ac6/inc/tx_port.h b/ports/cortex_m7/ac6/inc/tx_port.h index f3947f71b..bf2276eb0 100644 --- a/ports/cortex_m7/ac6/inc/tx_port.h +++ b/ports/cortex_m7/ac6/inc/tx_port.h @@ -11,6 +11,7 @@ // Some portions generated by Gemini (Gemini 2.0 Flash). // Some portions generated by Copilot (Claude Sonnet 4.6). +// Some portions generated by Claude Code (Opus 5). /**************************************************************************/ @@ -544,8 +545,8 @@ __attribute__( ( always_inline ) ) static inline void __set_basepri_value(unsign { __asm__ volatile ("MSR BASEPRI,%0 ": : "r" (basepri_value) : "memory"); } -#else +#else __attribute__( ( always_inline ) ) static inline void __enable_interrupts(void) { __asm__ volatile ("CPSIE i": : : "memory"); @@ -592,8 +593,10 @@ unsigned int interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); + __asm__ volatile ("isb 0xF " : : : "memory"); } } + #define TX_INTERRUPT_SAVE_AREA UINT interrupt_save; #define TX_DISABLE interrupt_save = __disable_interrupts(); #define TX_RESTORE __restore_interrupt(interrupt_save); diff --git a/ports/cortex_m7/ac6/src/tx_thread_system_return.S b/ports/cortex_m7/ac6/src/tx_thread_system_return.S index a092e34c8..d0243dea6 100644 --- a/ports/cortex_m7/ac6/src/tx_thread_system_return.S +++ b/ports/cortex_m7/ac6/src/tx_thread_system_return.S @@ -85,10 +85,12 @@ _tx_thread_system_return: MOV r0, #0 MSR BASEPRI, r0 // Enable interrupts MSR BASEPRI, r1 // Restore original interrupt posture + ISB #0xF // Flush pipeline #else MRS r1, PRIMASK // Thread context returning, pickup PRIMASK CPSIE i // Enable interrupts MSR PRIMASK, r1 // Restore original interrupt posture + ISB #0xF // Flush pipeline #endif _isr_context: BX lr // Return to caller diff --git a/ports/cortex_m7/gnu/inc/tx_port.h b/ports/cortex_m7/gnu/inc/tx_port.h index b6fd6e482..b01873cf1 100644 --- a/ports/cortex_m7/gnu/inc/tx_port.h +++ b/ports/cortex_m7/gnu/inc/tx_port.h @@ -11,6 +11,7 @@ // Some portions generated by Gemini (Gemini 2.0 Flash). // Some portions generated by Copilot (Claude Sonnet 4.6). +// Some portions generated by Claude Code (Opus 5). /**************************************************************************/ @@ -544,8 +545,8 @@ __attribute__( ( always_inline ) ) static inline void __set_basepri_value(unsign { __asm__ volatile ("MSR BASEPRI,%0 ": : "r" (basepri_value) : "memory"); } -#else +#else __attribute__( ( always_inline ) ) static inline void __enable_interrupts(void) { __asm__ volatile ("CPSIE i": : : "memory"); @@ -562,7 +563,6 @@ __attribute__( ( always_inline ) ) static inline void __restore_interrupt(unsign #endif } - __attribute__( ( always_inline ) ) static inline unsigned int __disable_interrupts(void) { unsigned int int_posture; diff --git a/ports/cortex_m7/iar/inc/tx_port.h b/ports/cortex_m7/iar/inc/tx_port.h index b6f19933f..a9ebe3c88 100644 --- a/ports/cortex_m7/iar/inc/tx_port.h +++ b/ports/cortex_m7/iar/inc/tx_port.h @@ -11,6 +11,7 @@ // Some portions generated by Gemini (Gemini 2.0 Flash). // Some portions generated by Copilot (Claude Sonnet 4.6). +// Some portions generated by Claude Code (Opus 5). /**************************************************************************/ @@ -544,8 +545,8 @@ __attribute__( ( always_inline ) ) static inline void __set_basepri_value(unsign { __asm__ volatile ("MSR BASEPRI,%0 ": : "r" (basepri_value) : "memory"); } -#else +#else __attribute__( ( always_inline ) ) static inline void __enable_interrupts(void) { __asm__ volatile ("CPSIE i": : : "memory"); @@ -592,8 +593,10 @@ unsigned int interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); + __asm__ volatile ("isb 0xF " : : : "memory"); } } + #define TX_INTERRUPT_SAVE_AREA UINT interrupt_save; #define TX_DISABLE interrupt_save = __disable_interrupts(); #define TX_RESTORE __restore_interrupt(interrupt_save); diff --git a/ports/cortex_m7/iar/src/tx_thread_system_return.s b/ports/cortex_m7/iar/src/tx_thread_system_return.s index 00a07ea87..345fca808 100644 --- a/ports/cortex_m7/iar/src/tx_thread_system_return.s +++ b/ports/cortex_m7/iar/src/tx_thread_system_return.s @@ -83,10 +83,12 @@ _tx_thread_system_return: MOV r0, #0 MSR BASEPRI, r0 // Enable interrupts MSR BASEPRI, r1 // Restore original interrupt posture + ISB SY // Flush pipeline #else MRS r1, PRIMASK // Thread context returning, pickup PRIMASK CPSIE i // Enable interrupts MSR PRIMASK, r1 // Restore original interrupt posture + ISB SY // Flush pipeline #endif _isr_context: BX lr // Return to caller diff --git a/ports/cortex_m85/ac6/inc/tx_port.h b/ports/cortex_m85/ac6/inc/tx_port.h index 90917cbf3..38def972b 100644 --- a/ports/cortex_m85/ac6/inc/tx_port.h +++ b/ports/cortex_m85/ac6/inc/tx_port.h @@ -9,6 +9,9 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Gemini (Gemini 2.0 Flash). +// Some portions generated by Claude Code (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -541,7 +544,7 @@ UINT posture; #ifdef TX_PORT_USE_BASEPRI __attribute__( ( always_inline ) ) static inline void __set_basepri_value(UINT basepri_value) { - __asm__ volatile ("MSR BASEPRI,%0 ": : "r" (basepri_value)); + __asm__ volatile ("MSR BASEPRI,%0 ": : "r" (basepri_value) : "memory"); } #else __attribute__( ( always_inline ) ) static inline void __enable_interrupts(void) @@ -554,6 +557,7 @@ __attribute__( ( always_inline ) ) static inline void __restore_interrupt(UINT i { #ifdef TX_PORT_USE_BASEPRI __set_basepri_value(int_posture); + __asm__ volatile ("" : : : "memory"); #else __asm__ volatile ("MSR PRIMASK,%0": : "r" (int_posture): "memory"); #endif @@ -579,6 +583,7 @@ UINT interrupt_save; /* Set PendSV to invoke ThreadX scheduler. */ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); + __asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory"); if (_tx_ipsr_get() == 0) { interrupt_save = __get_interrupt_posture(); @@ -588,6 +593,7 @@ UINT interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); + __asm__ volatile ("isb 0xF " : : : "memory"); } } diff --git a/ports/cortex_m85/ac6/src/tx_thread_system_return.S b/ports/cortex_m85/ac6/src/tx_thread_system_return.S index 2b335f8d3..639af9fbb 100644 --- a/ports/cortex_m85/ac6/src/tx_thread_system_return.S +++ b/ports/cortex_m85/ac6/src/tx_thread_system_return.S @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Gemini (Gemini 2.0 Flash). + /**************************************************************************/ /**************************************************************************/ @@ -74,6 +76,8 @@ _tx_thread_system_return: MOV r0, #0x10000000 // Load PENDSVSET bit MOV r1, #0xE000E000 // Load NVIC base STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR + DSB #0xF // Ensure memory access is complete + ISB #0xF // Flush pipeline MRS r0, IPSR // Pickup IPSR CMP r0, #0 // Is it a thread returning? BNE _isr_context // If ISR, skip interrupt enable @@ -82,10 +86,12 @@ _tx_thread_system_return: MOV r0, #0 MSR BASEPRI, r0 // Enable interrupts MSR BASEPRI, r1 // Restore original interrupt posture + ISB #0xF // Flush pipeline #else MRS r1, PRIMASK // Thread context returning, pickup PRIMASK CPSIE i // Enable interrupts MSR PRIMASK, r1 // Restore original interrupt posture + ISB #0xF // Flush pipeline #endif _isr_context: BX lr // Return to caller diff --git a/ports/cortex_m85/gnu/inc/tx_port.h b/ports/cortex_m85/gnu/inc/tx_port.h index 0f67673b5..1f1702dfa 100644 --- a/ports/cortex_m85/gnu/inc/tx_port.h +++ b/ports/cortex_m85/gnu/inc/tx_port.h @@ -10,6 +10,7 @@ **************************************************************************/ // Some portions generated by Gemini (Gemini 2.0 Flash). +// Some portions generated by Claude Code (Opus 5). /**************************************************************************/ diff --git a/ports/cortex_m85/iar/inc/tx_port.h b/ports/cortex_m85/iar/inc/tx_port.h index 2d0024ab9..26ab0c756 100644 --- a/ports/cortex_m85/iar/inc/tx_port.h +++ b/ports/cortex_m85/iar/inc/tx_port.h @@ -9,6 +9,9 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Gemini (Gemini 2.0 Flash). +// Some portions generated by Claude Code (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -580,6 +583,7 @@ UINT interrupt_save; /* Set PendSV to invoke ThreadX scheduler. */ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); + __asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory"); if (_tx_ipsr_get() == 0) { interrupt_save = __get_interrupt_posture(); @@ -589,6 +593,7 @@ UINT interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); + __asm__ volatile ("isb 0xF " : : : "memory"); } } @@ -624,5 +629,3 @@ extern CHAR _tx_version_id[]; #endif #endif - -#endif diff --git a/ports/cortex_m85/iar/src/tx_thread_system_return.s b/ports/cortex_m85/iar/src/tx_thread_system_return.s index fcc87228c..8b62acc19 100644 --- a/ports/cortex_m85/iar/src/tx_thread_system_return.s +++ b/ports/cortex_m85/iar/src/tx_thread_system_return.s @@ -82,10 +82,12 @@ _tx_thread_system_return: MOV r0, #0 MSR BASEPRI, r0 // Enable interrupts MSR BASEPRI, r1 // Restore original interrupt posture + ISB SY // Flush pipeline #else MRS r1, PRIMASK // Thread context returning, pickup PRIMASK CPSIE i // Enable interrupts MSR PRIMASK, r1 // Restore original interrupt posture + ISB SY // Flush pipeline #endif _isr_context: BX lr // Return to caller diff --git a/ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_system_return.S b/ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_system_return.S index 75d518133..ad07e2aa9 100644 --- a/ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_system_return.S +++ b/ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_system_return.S @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Gemini (Gemini 2.0 Flash). + /**************************************************************************/ /**************************************************************************/ @@ -73,6 +75,8 @@ _tx_thread_system_return: MOV r0, #0x10000000 // Load PENDSVSET bit MOV r1, #0xE000E000 // Load NVIC base STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR + DSB #0xF // Ensure memory access is complete + ISB #0xF // Flush pipeline MRS r0, IPSR // Pickup IPSR CMP r0, #0 // Is it a thread returning? BNE _isr_context // If ISR, skip interrupt enable @@ -81,10 +85,12 @@ _tx_thread_system_return: MOV r0, #0 MSR BASEPRI, r0 // Enable interrupts MSR BASEPRI, r1 // Restore original interrupt posture + ISB #0xF // Flush pipeline #else MRS r1, PRIMASK // Thread context returning, pickup PRIMASK CPSIE i // Enable interrupts MSR PRIMASK, r1 // Restore original interrupt posture + ISB #0xF // Flush pipeline #endif _isr_context: BX lr // Return to caller diff --git a/ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_system_return.S b/ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_system_return.S index 8b6817478..af17e9a74 100644 --- a/ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_system_return.S +++ b/ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_system_return.S @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Gemini (Gemini 2.0 Flash). + /**************************************************************************/ /**************************************************************************/ @@ -73,6 +75,8 @@ _tx_thread_system_return: MOV r0, #0x10000000 // Load PENDSVSET bit MOV r1, #0xE000E000 // Load NVIC base STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR + DSB #0xF // Ensure memory access is complete + ISB #0xF // Flush pipeline MRS r0, IPSR // Pickup IPSR CMP r0, #0 // Is it a thread returning? BNE _isr_context // If ISR, skip interrupt enable @@ -81,10 +85,12 @@ _tx_thread_system_return: MOV r0, #0 MSR BASEPRI, r0 // Enable interrupts MSR BASEPRI, r1 // Restore original interrupt posture + ISB #0xF // Flush pipeline #else MRS r1, PRIMASK // Thread context returning, pickup PRIMASK CPSIE i // Enable interrupts MSR PRIMASK, r1 // Restore original interrupt posture + ISB #0xF // Flush pipeline #endif _isr_context: BX lr // Return to caller diff --git a/ports_arch/ARMv7-M/threadx/iar/src/tx_thread_system_return.s b/ports_arch/ARMv7-M/threadx/iar/src/tx_thread_system_return.s index 65bec5a57..18a449325 100644 --- a/ports_arch/ARMv7-M/threadx/iar/src/tx_thread_system_return.s +++ b/ports_arch/ARMv7-M/threadx/iar/src/tx_thread_system_return.s @@ -1,16 +1,19 @@ -/*************************************************************************** - * Copyright (c) 2024 Microsoft Corporation - * Copyright (c) 2026-present 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 - **************************************************************************/ +;*************************************************************************** +;* Copyright (c) 2024 Microsoft Corporation +;* Copyright (c) 2026-present 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 +;************************************************************************** +; Some portions generated by Gemini (Gemini 2.0 Flash). + + +;************************************************************************** -/**************************************************************************/ /**************************************************************************/ /** */ /** ThreadX Component */ @@ -70,6 +73,8 @@ _tx_thread_system_return: MOV r0, #0x10000000 // Load PENDSVSET bit MOV r1, #0xE000E000 // Load NVIC base STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR + DSB SY // Ensure memory access is complete + ISB SY // Flush pipeline MRS r0, IPSR // Pickup IPSR CMP r0, #0 // Is it a thread returning? BNE _isr_context // If ISR, skip interrupt enable @@ -78,10 +83,12 @@ _tx_thread_system_return: MOV r0, #0 MSR BASEPRI, r0 // Enable interrupts MSR BASEPRI, r1 // Restore original interrupt posture + ISB SY // Flush pipeline #else MRS r1, PRIMASK // Thread context returning, pickup PRIMASK CPSIE i // Enable interrupts MSR PRIMASK, r1 // Restore original interrupt posture + ISB SY // Flush pipeline #endif _isr_context: BX lr // Return to caller diff --git a/ports_arch/ARMv7-M/threadx/inc/tx_port.h b/ports_arch/ARMv7-M/threadx/inc/tx_port.h index ac21ab556..b988675f1 100644 --- a/ports_arch/ARMv7-M/threadx/inc/tx_port.h +++ b/ports_arch/ARMv7-M/threadx/inc/tx_port.h @@ -9,6 +9,10 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Gemini (Gemini 2.0 Flash). +// Some portions generated by Copilot (Claude Sonnet 4.6). +// Some portions generated by Claude Code (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -539,8 +543,9 @@ unsigned int posture; #ifdef TX_PORT_USE_BASEPRI __attribute__( ( always_inline ) ) static inline void __set_basepri_value(unsigned int basepri_value) { - __asm__ volatile ("MSR BASEPRI,%0 ": : "r" (basepri_value)); + __asm__ volatile ("MSR BASEPRI,%0 ": : "r" (basepri_value) : "memory"); } + #else __attribute__( ( always_inline ) ) static inline void __enable_interrupts(void) { @@ -552,7 +557,7 @@ __attribute__( ( always_inline ) ) static inline void __restore_interrupt(unsign { #ifdef TX_PORT_USE_BASEPRI __set_basepri_value(int_posture); - //__asm__ volatile ("MSR BASEPRI,%0": : "r" (int_posture): "memory"); + __asm__ volatile ("" : : : "memory"); #else __asm__ volatile ("MSR PRIMASK,%0": : "r" (int_posture): "memory"); #endif @@ -578,6 +583,7 @@ unsigned int interrupt_save; /* Set PendSV to invoke ThreadX scheduler. */ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); + __asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory"); if (__get_ipsr_value() == 0) { interrupt_save = __get_interrupt_posture(); @@ -587,6 +593,7 @@ unsigned int interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); + __asm__ volatile ("isb 0xF " : : : "memory"); } } diff --git a/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_system_return.S b/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_system_return.S index e31c4a557..5e2164cb0 100644 --- a/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_system_return.S +++ b/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_system_return.S @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Gemini (Gemini 2.0 Flash). + /**************************************************************************/ /**************************************************************************/ @@ -74,6 +76,8 @@ _tx_thread_system_return: MOV r0, #0x10000000 // Load PENDSVSET bit MOV r1, #0xE000E000 // Load NVIC base STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR + DSB #0xF // Ensure memory access is complete + ISB #0xF // Flush pipeline MRS r0, IPSR // Pickup IPSR CMP r0, #0 // Is it a thread returning? BNE _isr_context // If ISR, skip interrupt enable @@ -82,10 +86,12 @@ _tx_thread_system_return: MOV r0, #0 MSR BASEPRI, r0 // Enable interrupts MSR BASEPRI, r1 // Restore original interrupt posture + ISB #0xF // Flush pipeline #else MRS r1, PRIMASK // Thread context returning, pickup PRIMASK CPSIE i // Enable interrupts MSR PRIMASK, r1 // Restore original interrupt posture + ISB #0xF // Flush pipeline #endif _isr_context: BX lr // Return to caller diff --git a/ports_arch/ARMv8-M/threadx/gnu/CMakeLists.txt b/ports_arch/ARMv8-M/threadx/gnu/CMakeLists.txt index 5ad3b8e75..763a2696c 100644 --- a/ports_arch/ARMv8-M/threadx/gnu/CMakeLists.txt +++ b/ports_arch/ARMv8-M/threadx/gnu/CMakeLists.txt @@ -1,7 +1,8 @@ -target_sources(${PROJECT_NAME} PRIVATE +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} ${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_secure_stack_allocate.c ${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_secure_stack_free.c - ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.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_interrupt_control.S @@ -14,8 +15,10 @@ target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} ) -target_include_directories(${PROJECT_NAME} PUBLIC - inc +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports_arch/ARMv8-M/threadx/gnu/src/tx_initialize_low_level.S b/ports_arch/ARMv8-M/threadx/gnu/src/tx_initialize_low_level.S deleted file mode 100644 index f0b326a17..000000000 --- a/ports_arch/ARMv8-M/threadx/gnu/src/tx_initialize_low_level.S +++ /dev/null @@ -1,276 +0,0 @@ -/*************************************************************************** - * Copyright (c) 2024 Microsoft Corporation - * Copyright (c) 2026-present 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 - **************************************************************************/ - - -/**************************************************************************/ -/**************************************************************************/ -/** */ -/** ThreadX Component */ -/** */ -/** Initialize */ -/** */ -/**************************************************************************/ -/**************************************************************************/ - -#ifdef TX_INCLUDE_USER_DEFINE_FILE -#include "tx_user.h" -#endif - -SYSTEM_CLOCK = 6000000 -SYSTICK_CYCLES = ((SYSTEM_CLOCK / 100) -1) - -/* Setup the stack and heap areas. */ - -STACK_SIZE = 0x00000400 -HEAP_SIZE = 0x00000000 - -/**************************************************************************/ -/* */ -/* FUNCTION RELEASE */ -/* */ -/* _tx_initialize_low_level Cortex-Mxx/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 */ -/* */ -/**************************************************************************/ -// VOID _tx_initialize_low_level(VOID) -// { - .section .text - .balign 4 - .syntax unified - .eabi_attribute Tag_ABI_align_preserved, 1 - .global _tx_initialize_low_level - .thumb_func -.type _tx_initialize_low_level, function -_tx_initialize_low_level: - - /* Disable interrupts during ThreadX initialization. */ - CPSID i - - /* Set base of available memory to end of non-initialised RAM area. */ - LDR r0, =_tx_initialize_unused_memory // Build address of unused memory pointer - LDR r1, =__RAM_segment_used_end__ // Build first free address - ADD r1, r1, #4 // - STR r1, [r0] // Setup first unused memory pointer - - /* Setup Vector Table Offset Register. */ - MOV r0, #0xE000E000 // Build address of NVIC registers - LDR r1, =_vectors // Pickup address of vector table - STR r1, [r0, #0xD08] // Set vector table address - - /* Enable the cycle count register. */ - LDR r0, =0xE0001000 // Build address of DWT register - LDR r1, [r0] // Pickup the current value - ORR r1, r1, #1 // Set the CYCCNTENA bit - STR r1, [r0] // Enable the cycle count register - - /* Set system stack pointer from vector value. */ - LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer - LDR r1, =_vectors // Pickup address of vector table - LDR r1, [r1] // Pickup reset stack pointer - STR r1, [r0] // Save system stack pointer - - /* Configure SysTick. */ - MOV r0, #0xE000E000 // Build address of NVIC registers - MOV r1, #0 // Build value for SysTick reset - STR r1, [r0, #0x10] // Reset SysTick Control - STR r1, [r0, #0x18] // Reset SysTick Counter Value - LDR r1, =SYSTICK_CYCLES - STR r1, [r0, #0x14] // Setup SysTick Reload Value - MOV r1, #0x7 // Build SysTick Control Enable Value - STR r1, [r0, #0x10] // Setup SysTick Control - - /* Configure handler priorities. */ - LDR r1, =0x00000000 // Rsrv, UsgF, BusF, MemM - STR r1, [r0, #0xD18] // Setup System Handlers 4-7 Priority Registers - LDR r1, =0xFF000000 // SVCl, Rsrv, Rsrv, Rsrv - STR r1, [r0, #0xD1C] // Setup System Handlers 8-11 Priority Registers - // Note: SVC must be lowest priority, which is 0xFF - LDR r1, =0x40FF0000 // SysT, PnSV, Rsrv, DbgM - STR r1, [r0, #0xD20] // Setup System Handlers 12-15 Priority Registers - // Note: PnSV must be lowest priority, which is 0xFF - - /* Return to caller. */ - BX lr -// } - - -/* Define shells for each of the unused vectors. */ - .section .text - .balign 4 - .syntax unified - .eabi_attribute Tag_ABI_align_preserved, 1 - .global __tx_BadHandler - .thumb_func -.type __tx_BadHandler, function -__tx_BadHandler: - B __tx_BadHandler - - - .section .text - .balign 4 - .syntax unified - .eabi_attribute Tag_ABI_align_preserved, 1 - .global __tx_IntHandler - .thumb_func -.type __tx_IntHandler, function -__tx_IntHandler: -// VOID InterruptHandler (VOID) -// { - PUSH {r0,lr} // Save LR (and dummy r0 to maintain stack alignment) -#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)) - BL _tx_execution_isr_enter // Call the ISR enter function -#endif - /* Do interrupt handler work here */ - /* .... */ -#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)) - BL _tx_execution_isr_exit // Call the ISR exit function -#endif - POP {r0,lr} - BX lr -// } - - - .section .text - .balign 4 - .syntax unified - .eabi_attribute Tag_ABI_align_preserved, 1 - .global SysTick_Handler - .thumb_func -.type SysTick_Handler, function -SysTick_Handler: -// VOID TimerInterruptHandler (VOID) -// { - PUSH {r0,lr} // Save LR (and dummy r0 to maintain stack alignment) -#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)) - BL _tx_execution_isr_enter // Call the ISR enter function -#endif - BL _tx_timer_interrupt -#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)) - BL _tx_execution_isr_exit // Call the ISR exit function -#endif - POP {r0,lr} - BX lr -// } - - - .section .text - .balign 4 - .syntax unified - .eabi_attribute Tag_ABI_align_preserved, 1 - .global HardFault_Handler - .thumb_func -.type HardFault_Handler, function -HardFault_Handler: - B HardFault_Handler - - - .section .text - .balign 4 - .syntax unified - .eabi_attribute Tag_ABI_align_preserved, 1 - .global UsageFault_Handler - .thumb_func -.type UsageFault_Handler, function -UsageFault_Handler: - CPSID i // Disable interrupts - // Check for stack limit fault - LDR r0, =0xE000ED28 // CFSR address - LDR r1,[r0] // Pick up CFSR - TST r1, #0x00100000 // Check for Stack Overflow -_unhandled_usage_loop: - BEQ _unhandled_usage_loop // If not stack overflow then loop - - // Handle stack overflow - STR r1, [r0] // Clear CFSR flag(s) - -#ifdef __ARM_FP - LDR r0, =0xE000EF34 // Cleanup FPU context: Load FPCCR address - LDR r1, [r0] // Load FPCCR - BIC r1, r1, #1 // Clear the lazy preservation active bit - STR r1, [r0] // Store the value -#endif - - LDR r0, =_tx_thread_current_ptr // Build current thread pointer address - LDR r0,[r0] // Pick up current thread pointer - PUSH {r0,lr} // Save LR (and r0 to maintain stack alignment) - BL _tx_thread_stack_error_handler // Call ThreadX/user handler - POP {r0,lr} // Restore LR and dummy reg - -#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)) - // Call the thread exit function to indicate the thread is no longer executing. - PUSH {r0, lr} // Save LR (and r0 just for alignment) - BL _tx_execution_thread_exit // Call the thread exit function - POP {r0, lr} // Recover LR -#endif - - MOV r1, #0 // Build NULL value - LDR r0, =_tx_thread_current_ptr // Pickup address of current thread pointer - STR r1, [r0] // Clear current thread pointer - - // Return from UsageFault_Handler exception - LDR r0, =0xE000ED04 // Load ICSR - LDR r1, =0x10000000 // Set PENDSVSET bit - STR r1, [r0] // Store ICSR - DSB // Wait for memory access to complete - CPSIE i // Enable interrupts - BX lr // Return from exception - - - - .section .text - .balign 4 - .syntax unified - .eabi_attribute Tag_ABI_align_preserved, 1 - .global __tx_NMIHandler - .thumb_func -.type __tx_NMIHandler, function -__tx_NMIHandler: - B __tx_NMIHandler - - - .section .text - .balign 4 - .syntax unified - .eabi_attribute Tag_ABI_align_preserved, 1 - .global __tx_DBGHandler - .thumb_func -.type __tx_DBGHandler, function -__tx_DBGHandler: - B __tx_DBGHandler - - .end diff --git a/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_system_return.S b/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_system_return.S index 1e84582eb..420a6ef39 100644 --- a/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_system_return.S +++ b/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_system_return.S @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Gemini (Gemini 2.0 Flash). + /**************************************************************************/ /**************************************************************************/ @@ -74,6 +76,8 @@ _tx_thread_system_return: MOV r0, #0x10000000 // Load PENDSVSET bit MOV r1, #0xE000E000 // Load NVIC base STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR + DSB #0xF // Ensure memory access is complete + ISB #0xF // Flush pipeline MRS r0, IPSR // Pickup IPSR CMP r0, #0 // Is it a thread returning? BNE _isr_context // If ISR, skip interrupt enable @@ -82,10 +86,12 @@ _tx_thread_system_return: MOV r0, #0 MSR BASEPRI, r0 // Enable interrupts MSR BASEPRI, r1 // Restore original interrupt posture + ISB #0xF // Flush pipeline #else MRS r1, PRIMASK // Thread context returning, pickup PRIMASK CPSIE i // Enable interrupts MSR PRIMASK, r1 // Restore original interrupt posture + ISB #0xF // Flush pipeline #endif _isr_context: BX lr // Return to caller diff --git a/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_system_return.s b/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_system_return.s index f2a187ea0..4bc165238 100644 --- a/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_system_return.s +++ b/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_system_return.s @@ -1,16 +1,19 @@ -/*************************************************************************** - * Copyright (c) 2024 Microsoft Corporation - * Copyright (c) 2026-present 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 - **************************************************************************/ +;*************************************************************************** +;* Copyright (c) 2024 Microsoft Corporation +;* Copyright (c) 2026-present 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 +;************************************************************************** +; Some portions generated by Gemini (Gemini 2.0 Flash). + + +;************************************************************************** -/**************************************************************************/ /**************************************************************************/ /** */ /** ThreadX Component */ @@ -69,6 +72,8 @@ _tx_thread_system_return: MOV r0, #0x10000000 // Load PENDSVSET bit MOV r1, #0xE000E000 // Load NVIC base STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR + DSB SY // Ensure memory access is complete + ISB SY // Flush pipeline MRS r0, IPSR // Pickup IPSR CMP r0, #0 // Is it a thread returning? BNE _isr_context // If ISR, skip interrupt enable @@ -77,10 +82,12 @@ _tx_thread_system_return: MOV r0, #0 MSR BASEPRI, r0 // Enable interrupts MSR BASEPRI, r1 // Restore original interrupt posture + ISB SY // Flush pipeline #else MRS r1, PRIMASK // Thread context returning, pickup PRIMASK CPSIE i // Enable interrupts MSR PRIMASK, r1 // Restore original interrupt posture + ISB SY // Flush pipeline #endif _isr_context: BX lr // Return to caller diff --git a/ports_arch/ARMv8-M/threadx/inc/tx_port.h b/ports_arch/ARMv8-M/threadx/inc/tx_port.h index 316da65b7..1f088d412 100644 --- a/ports_arch/ARMv8-M/threadx/inc/tx_port.h +++ b/ports_arch/ARMv8-M/threadx/inc/tx_port.h @@ -9,6 +9,9 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Gemini (Gemini 2.0 Flash). +// Some portions generated by Claude Code (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -541,7 +544,7 @@ UINT posture; #ifdef TX_PORT_USE_BASEPRI __attribute__( ( always_inline ) ) static inline void __set_basepri_value(UINT basepri_value) { - __asm__ volatile ("MSR BASEPRI,%0 ": : "r" (basepri_value)); + __asm__ volatile ("MSR BASEPRI,%0 ": : "r" (basepri_value) : "memory"); } #else __attribute__( ( always_inline ) ) static inline void __enable_interrupts(void) @@ -554,6 +557,7 @@ __attribute__( ( always_inline ) ) static inline void __restore_interrupt(UINT i { #ifdef TX_PORT_USE_BASEPRI __set_basepri_value(int_posture); + __asm__ volatile ("" : : : "memory"); #else __asm__ volatile ("MSR PRIMASK,%0": : "r" (int_posture): "memory"); #endif @@ -579,6 +583,7 @@ UINT interrupt_save; /* Set PendSV to invoke ThreadX scheduler. */ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); + __asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory"); if (_tx_ipsr_get() == 0) { interrupt_save = __get_interrupt_posture(); @@ -588,6 +593,7 @@ UINT interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); + __asm__ volatile ("isb 0xF " : : : "memory"); } } diff --git a/ports_module/cortex_m3/ac6/module_manager/src/tx_thread_system_return.S b/ports_module/cortex_m3/ac6/module_manager/src/tx_thread_system_return.S index e1c5c2a2c..6d0e26afa 100644 --- a/ports_module/cortex_m3/ac6/module_manager/src/tx_thread_system_return.S +++ b/ports_module/cortex_m3/ac6/module_manager/src/tx_thread_system_return.S @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Gemini (Gemini 2.0 Flash). + /**************************************************************************/ /**************************************************************************/ @@ -73,6 +75,8 @@ _tx_thread_system_return: MOV r0, #0x10000000 // Load PENDSVSET bit MOV r1, #0xE000E000 // Load NVIC base STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR + DSB #0xF // Ensure memory access is complete + ISB #0xF // Flush pipeline MRS r0, IPSR // Pickup IPSR CMP r0, #0 // Is it a thread returning? BNE _isr_context // If ISR, skip interrupt enable @@ -81,10 +85,12 @@ _tx_thread_system_return: MOV r0, #0 MSR BASEPRI, r0 // Enable interrupts MSR BASEPRI, r1 // Restore original interrupt posture + ISB #0xF // Flush pipeline #else MRS r1, PRIMASK // Thread context returning, pickup PRIMASK CPSIE i // Enable interrupts MSR PRIMASK, r1 // Restore original interrupt posture + ISB #0xF // Flush pipeline #endif _isr_context: BX lr // Return to caller diff --git a/ports_module/cortex_m3/gnu/module_manager/src/tx_thread_system_return.S b/ports_module/cortex_m3/gnu/module_manager/src/tx_thread_system_return.S index 9d9a32fc9..92ad3f628 100644 --- a/ports_module/cortex_m3/gnu/module_manager/src/tx_thread_system_return.S +++ b/ports_module/cortex_m3/gnu/module_manager/src/tx_thread_system_return.S @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Gemini (Gemini 2.0 Flash). + /**************************************************************************/ /**************************************************************************/ @@ -73,6 +75,8 @@ _tx_thread_system_return: MOV r0, #0x10000000 // Load PENDSVSET bit MOV r1, #0xE000E000 // Load NVIC base STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR + DSB #0xF // Ensure memory access is complete + ISB #0xF // Flush pipeline MRS r0, IPSR // Pickup IPSR CMP r0, #0 // Is it a thread returning? BNE _isr_context // If ISR, skip interrupt enable @@ -81,10 +85,12 @@ _tx_thread_system_return: MOV r0, #0 MSR BASEPRI, r0 // Enable interrupts MSR BASEPRI, r1 // Restore original interrupt posture + ISB #0xF // Flush pipeline #else MRS r1, PRIMASK // Thread context returning, pickup PRIMASK CPSIE i // Enable interrupts MSR PRIMASK, r1 // Restore original interrupt posture + ISB #0xF // Flush pipeline #endif _isr_context: BX lr // Return to caller diff --git a/ports_module/cortex_m3/iar/module_manager/src/tx_thread_system_return.s b/ports_module/cortex_m3/iar/module_manager/src/tx_thread_system_return.s index 712a6e5ce..7bc5f2ebc 100644 --- a/ports_module/cortex_m3/iar/module_manager/src/tx_thread_system_return.s +++ b/ports_module/cortex_m3/iar/module_manager/src/tx_thread_system_return.s @@ -1,16 +1,19 @@ -/*************************************************************************** - * Copyright (c) 2024 Microsoft Corporation - * Copyright (c) 2026-present 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 - **************************************************************************/ +;*************************************************************************** +;* Copyright (c) 2024 Microsoft Corporation +;* Copyright (c) 2026-present 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 +;************************************************************************** +; Some portions generated by Gemini (Gemini 2.0 Flash). + + +;************************************************************************** -/**************************************************************************/ /**************************************************************************/ /** */ /** ThreadX Component */ @@ -70,6 +73,8 @@ _tx_thread_system_return: MOV r0, #0x10000000 // Load PENDSVSET bit MOV r1, #0xE000E000 // Load NVIC base STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR + DSB SY // Ensure memory access is complete + ISB SY // Flush pipeline MRS r0, IPSR // Pickup IPSR CMP r0, #0 // Is it a thread returning? BNE _isr_context // If ISR, skip interrupt enable @@ -78,10 +83,12 @@ _tx_thread_system_return: MOV r0, #0 MSR BASEPRI, r0 // Enable interrupts MSR BASEPRI, r1 // Restore original interrupt posture + ISB SY // Flush pipeline #else MRS r1, PRIMASK // Thread context returning, pickup PRIMASK CPSIE i // Enable interrupts MSR PRIMASK, r1 // Restore original interrupt posture + ISB SY // Flush pipeline #endif _isr_context: BX lr // Return to caller diff --git a/ports_module/cortex_m4/ac6/module_manager/src/tx_thread_system_return.S b/ports_module/cortex_m4/ac6/module_manager/src/tx_thread_system_return.S index b4348f9db..59a7210d5 100644 --- a/ports_module/cortex_m4/ac6/module_manager/src/tx_thread_system_return.S +++ b/ports_module/cortex_m4/ac6/module_manager/src/tx_thread_system_return.S @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Gemini (Gemini 2.0 Flash). + /**************************************************************************/ /**************************************************************************/ @@ -73,6 +75,8 @@ _tx_thread_system_return: MOV r0, #0x10000000 // Load PENDSVSET bit MOV r1, #0xE000E000 // Load NVIC base STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR + DSB #0xF // Ensure memory access is complete + ISB #0xF // Flush pipeline MRS r0, IPSR // Pickup IPSR CMP r0, #0 // Is it a thread returning? BNE _isr_context // If ISR, skip interrupt enable @@ -81,10 +85,12 @@ _tx_thread_system_return: MOV r0, #0 MSR BASEPRI, r0 // Enable interrupts MSR BASEPRI, r1 // Restore original interrupt posture + ISB #0xF // Flush pipeline #else MRS r1, PRIMASK // Thread context returning, pickup PRIMASK CPSIE i // Enable interrupts MSR PRIMASK, r1 // Restore original interrupt posture + ISB #0xF // Flush pipeline #endif _isr_context: BX lr // Return to caller diff --git a/ports_module/cortex_m4/gnu/module_manager/src/tx_thread_system_return.S b/ports_module/cortex_m4/gnu/module_manager/src/tx_thread_system_return.S index 8c4a09fd1..4709af37f 100644 --- a/ports_module/cortex_m4/gnu/module_manager/src/tx_thread_system_return.S +++ b/ports_module/cortex_m4/gnu/module_manager/src/tx_thread_system_return.S @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Gemini (Gemini 2.0 Flash). + /**************************************************************************/ /**************************************************************************/ @@ -73,6 +75,8 @@ _tx_thread_system_return: MOV r0, #0x10000000 // Load PENDSVSET bit MOV r1, #0xE000E000 // Load NVIC base STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR + DSB #0xF // Ensure memory access is complete + ISB #0xF // Flush pipeline MRS r0, IPSR // Pickup IPSR CMP r0, #0 // Is it a thread returning? BNE _isr_context // If ISR, skip interrupt enable @@ -81,10 +85,12 @@ _tx_thread_system_return: MOV r0, #0 MSR BASEPRI, r0 // Enable interrupts MSR BASEPRI, r1 // Restore original interrupt posture + ISB #0xF // Flush pipeline #else MRS r1, PRIMASK // Thread context returning, pickup PRIMASK CPSIE i // Enable interrupts MSR PRIMASK, r1 // Restore original interrupt posture + ISB #0xF // Flush pipeline #endif _isr_context: BX lr // Return to caller diff --git a/ports_module/cortex_m4/iar/module_manager/src/tx_thread_system_return.s b/ports_module/cortex_m4/iar/module_manager/src/tx_thread_system_return.s index 4f8b9870f..b466bacaa 100644 --- a/ports_module/cortex_m4/iar/module_manager/src/tx_thread_system_return.s +++ b/ports_module/cortex_m4/iar/module_manager/src/tx_thread_system_return.s @@ -1,16 +1,19 @@ -/*************************************************************************** - * Copyright (c) 2024 Microsoft Corporation - * Copyright (c) 2026-present 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 - **************************************************************************/ +;*************************************************************************** +;* Copyright (c) 2024 Microsoft Corporation +;* Copyright (c) 2026-present 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 +;************************************************************************** +; Some portions generated by Gemini (Gemini 2.0 Flash). + + +;************************************************************************** -/**************************************************************************/ /**************************************************************************/ /** */ /** ThreadX Component */ @@ -70,6 +73,8 @@ _tx_thread_system_return: MOV r0, #0x10000000 // Load PENDSVSET bit MOV r1, #0xE000E000 // Load NVIC base STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR + DSB SY // Ensure memory access is complete + ISB SY // Flush pipeline MRS r0, IPSR // Pickup IPSR CMP r0, #0 // Is it a thread returning? BNE _isr_context // If ISR, skip interrupt enable @@ -78,10 +83,12 @@ _tx_thread_system_return: MOV r0, #0 MSR BASEPRI, r0 // Enable interrupts MSR BASEPRI, r1 // Restore original interrupt posture + ISB SY // Flush pipeline #else MRS r1, PRIMASK // Thread context returning, pickup PRIMASK CPSIE i // Enable interrupts MSR PRIMASK, r1 // Restore original interrupt posture + ISB SY // Flush pipeline #endif _isr_context: BX lr // Return to caller diff --git a/ports_module/cortex_m7/ac6/module_manager/src/tx_thread_system_return.S b/ports_module/cortex_m7/ac6/module_manager/src/tx_thread_system_return.S index 831c00e4c..d0243dea6 100644 --- a/ports_module/cortex_m7/ac6/module_manager/src/tx_thread_system_return.S +++ b/ports_module/cortex_m7/ac6/module_manager/src/tx_thread_system_return.S @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Gemini (Gemini 2.0 Flash). + /**************************************************************************/ /**************************************************************************/ @@ -73,6 +75,8 @@ _tx_thread_system_return: MOV r0, #0x10000000 // Load PENDSVSET bit MOV r1, #0xE000E000 // Load NVIC base STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR + DSB #0xF // Ensure memory access is complete + ISB #0xF // Flush pipeline MRS r0, IPSR // Pickup IPSR CMP r0, #0 // Is it a thread returning? BNE _isr_context // If ISR, skip interrupt enable @@ -81,10 +85,12 @@ _tx_thread_system_return: MOV r0, #0 MSR BASEPRI, r0 // Enable interrupts MSR BASEPRI, r1 // Restore original interrupt posture + ISB #0xF // Flush pipeline #else MRS r1, PRIMASK // Thread context returning, pickup PRIMASK CPSIE i // Enable interrupts MSR PRIMASK, r1 // Restore original interrupt posture + ISB #0xF // Flush pipeline #endif _isr_context: BX lr // Return to caller diff --git a/ports_module/cortex_m7/gnu/module_manager/src/tx_thread_system_return.S b/ports_module/cortex_m7/gnu/module_manager/src/tx_thread_system_return.S index ce5a3f46f..180894b3b 100644 --- a/ports_module/cortex_m7/gnu/module_manager/src/tx_thread_system_return.S +++ b/ports_module/cortex_m7/gnu/module_manager/src/tx_thread_system_return.S @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Gemini (Gemini 2.0 Flash). + /**************************************************************************/ /**************************************************************************/ @@ -73,6 +75,8 @@ _tx_thread_system_return: MOV r0, #0x10000000 // Load PENDSVSET bit MOV r1, #0xE000E000 // Load NVIC base STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR + DSB #0xF // Ensure memory access is complete + ISB #0xF // Flush pipeline MRS r0, IPSR // Pickup IPSR CMP r0, #0 // Is it a thread returning? BNE _isr_context // If ISR, skip interrupt enable @@ -81,10 +85,12 @@ _tx_thread_system_return: MOV r0, #0 MSR BASEPRI, r0 // Enable interrupts MSR BASEPRI, r1 // Restore original interrupt posture + ISB #0xF // Flush pipeline #else MRS r1, PRIMASK // Thread context returning, pickup PRIMASK CPSIE i // Enable interrupts MSR PRIMASK, r1 // Restore original interrupt posture + ISB #0xF // Flush pipeline #endif _isr_context: BX lr // Return to caller diff --git a/ports_module/cortex_m7/iar/module_manager/src/tx_thread_system_return.s b/ports_module/cortex_m7/iar/module_manager/src/tx_thread_system_return.s index 0cef80c6f..345fca808 100644 --- a/ports_module/cortex_m7/iar/module_manager/src/tx_thread_system_return.s +++ b/ports_module/cortex_m7/iar/module_manager/src/tx_thread_system_return.s @@ -1,16 +1,19 @@ -/*************************************************************************** - * Copyright (c) 2024 Microsoft Corporation - * Copyright (c) 2026-present 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 - **************************************************************************/ +;*************************************************************************** +;* Copyright (c) 2024 Microsoft Corporation +;* Copyright (c) 2026-present 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 +;************************************************************************** +; Some portions generated by Gemini (Gemini 2.0 Flash). + + +;************************************************************************** -/**************************************************************************/ /**************************************************************************/ /** */ /** ThreadX Component */ @@ -70,6 +73,8 @@ _tx_thread_system_return: MOV r0, #0x10000000 // Load PENDSVSET bit MOV r1, #0xE000E000 // Load NVIC base STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR + DSB SY // Ensure memory access is complete + ISB SY // Flush pipeline MRS r0, IPSR // Pickup IPSR CMP r0, #0 // Is it a thread returning? BNE _isr_context // If ISR, skip interrupt enable @@ -78,10 +83,12 @@ _tx_thread_system_return: MOV r0, #0 MSR BASEPRI, r0 // Enable interrupts MSR BASEPRI, r1 // Restore original interrupt posture + ISB SY // Flush pipeline #else MRS r1, PRIMASK // Thread context returning, pickup PRIMASK CPSIE i // Enable interrupts MSR PRIMASK, r1 // Restore original interrupt posture + ISB SY // Flush pipeline #endif _isr_context: BX lr // Return to caller From 08b120d2bcf45fa87e6771610e845c08c498f1c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Sun, 9 Aug 2026 10:48:29 -0400 Subject: [PATCH 019/181] Added port consistency checks and wired them into CI and release preparation (#591) Three defects reached the repository through the port trees recently, and each of them is mechanically detectable without a cross compiler. Add scripts/check_ports.sh, which looks for exactly those three, and give CI and the release process the same command a contributor can run locally. The generated Cortex-M ports must be reproducible from ports_arch. Fixes were applied to the generated copies instead of the source for eight months, and the next run of the copy scripts would have reverted them. Preprocessor directives must balance. A fix left the Cortex-M85 IAR tx_port.h with one more #endif than #if, so that header could not compile. No port header may carry a statement outside a function body. A fix left a second, headerless copy of a function body in the Cortex-M4 AC6 tx_port.h, which is issue 569. The check tracks brace depth while skipping preprocessor lines, multi-line macro bodies and comments, and reports assignments, dereferences and control statements that land at file scope. Headers under example_build are excluded, since those trees vendor third party SDK code. A fourth section reports, without failing the run, on port families that have no copy script and so cannot be checked for reproducibility. It currently observes that the Cortex-M0 ac5, ac6 and keil ports lack the barriers their gnu and iar siblings have. ports_arch_check now calls the script rather than inlining a copy and diff, so CI and the command line check the same things by the same definition, and the workflow now triggers on pull requests to dev as well as master. Triggering on master alone is why the drift went unseen. prepare_release.sh runs the checks before it branches or rewrites anything, and stops if they fail, with SKIP_PORT_CHECKS=1 as the escape hatch. Each check was verified by reintroducing the defect it exists to catch and confirming that the script fails, then confirming it passes on a clean tree. Assisted-by: Claude Code (Opus 5) --- .github/workflows/ports_arch_check.yml | 44 ++--- scripts/check_ports.sh | 224 +++++++++++++++++++++++++ scripts/prepare_release.sh | 14 ++ 3 files changed, 262 insertions(+), 20 deletions(-) create mode 100755 scripts/check_ports.sh diff --git a/.github/workflows/ports_arch_check.yml b/.github/workflows/ports_arch_check.yml index 4a99c032d..a2c69aeaf 100644 --- a/.github/workflows/ports_arch_check.yml +++ b/.github/workflows/ports_arch_check.yml @@ -6,7 +6,10 @@ name: ports_arch_check # events but only for the master branch on: pull_request: - branches: [ master ] + # dev is included as well as master. The check only ever ran against master, + # so eight months of port fixes merged into dev without it, and the ports + # drifted from ports_arch unnoticed. + branches: [ master, dev ] paths: - ".github/workflows/ports_arch_check.yml" - 'common/**' @@ -27,21 +30,20 @@ jobs: # Steps represent a sequence of tasks that will be executed as part of the job steps: # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - - name: Checkout sources recursively - uses: actions/checkout@v2 - with: - token: ${{ secrets.REPO_SCOPED_TOKEN }} - submodules: true + # No token input: secrets are not available to pull requests from forks, so + # passing one made this job fail at checkout with "Input required and not + # supplied: token" and the check never evaluated anything. The default + # GITHUB_TOKEN is enough to check out a public repository, and the + # repository has no submodules. + - name: Checkout sources + uses: actions/checkout@v4 - # Copy ports arch - - name: Copy ports arch - run: | - scripts/copy_armv7_m.sh && scripts/copy_armv8_m.sh && scripts/copy_module_armv7_m.sh - if [[ -n $(git status --porcelain -uno) ]]; then - echo "Ports for ARM architecture is not updated" - git status - exit 1 - fi + # Check the port trees: the generated ports must be reproducible from + # ports_arch, and no port header may be left unbalanced or carrying code + # outside a function. The same script runs locally, so a contributor sees + # exactly what CI sees. + - name: Check ports + run: scripts/check_ports.sh cortex-a: # Check ports for cortex-a @@ -50,11 +52,13 @@ jobs: # Steps represent a sequence of tasks that will be executed as part of the job steps: # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - - name: Checkout sources recursively - uses: actions/checkout@v2 - with: - token: ${{ secrets.REPO_SCOPED_TOKEN }} - submodules: true + # No token input: secrets are not available to pull requests from forks, so + # passing one made this job fail at checkout with "Input required and not + # supplied: token" and the check never evaluated anything. The default + # GITHUB_TOKEN is enough to check out a public repository, and the + # repository has no submodules. + - name: Checkout sources + uses: actions/checkout@v4 # Copy ports arch - name: Copy ports arch diff --git a/scripts/check_ports.sh b/scripts/check_ports.sh new file mode 100755 index 000000000..5add21b79 --- /dev/null +++ b/scripts/check_ports.sh @@ -0,0 +1,224 @@ +#!/bin/bash +############################################################################## +# 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. +# +# AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +# The AI-generated portions may be considered public domain (CC0-1.0) +# and not subject to the project's licence. The human contributor has +# reviewed and verified that the code is correct. +# +# SPDX-License-Identifier: MIT and CC0-1.0 +############################################################################## + +# Consistency checks for the port trees. Run it before cutting a release, or +# any time the ports have been touched: +# +# scripts/check_ports.sh +# +# Options: +# --no-regen Skip the reproducibility check, which needs a clean tree. +# --quiet Print only failures and the summary. +# +# Exit status is 0 when every check passes and 1 otherwise, so the same +# command serves CI and the command line. +# +# Each check exists because a real defect reached the repository through it: +# +# 1. Reproducibility. The Cortex-M ports are generated by the copy scripts, +# but fixes were applied to the generated copies instead of the source for +# eight months. The next run of those scripts would have reverted them. +# +# 2. Preprocessor balance. A fix left ports/cortex_m85/iar/inc/tx_port.h with +# one more #endif than #if, so that header could not compile. +# +# 3. Code at file scope. A fix left a second, headerless copy of a function +# body in ports/cortex_m4/ac6/inc/tx_port.h, which placed statements +# outside any function. See issue 569. +# +# The last section reports, without failing, on port families that have no copy +# script and so cannot be checked for reproducibility. +# +# Headers under example_build are skipped: those trees vendor third party SDK +# code, which is not ours to hold to these rules. + +set -u + +cd "$(dirname "$(realpath "$0")")/.." + +regen=1 +quiet=0 +for arg in "$@"; do + case "$arg" in + --no-regen) regen=0 ;; + --quiet) quiet=1 ;; + -h|--help) sed -n '17,30p' "$0"; exit 0 ;; + *) echo "Unknown option: $arg" >&2; exit 2 ;; + esac +done + +failures=0 + +say() { [ "$quiet" -eq 1 ] || echo "$@"; } +fail() { echo " FAIL: $*"; failures=$((failures + 1)); } + +# -------------------------------------------------------------------------- +# 1. The generated ports must be reproducible from ports_arch. +# -------------------------------------------------------------------------- +say "" +say "== Generated ports are reproducible from ports_arch ==" + +if [ "$regen" -eq 0 ]; then + say " skipped (--no-regen)" +elif ! command -v git >/dev/null 2>&1; then + say " skipped (git not available)" +elif [ -n "$(git status --porcelain -uno)" ]; then + fail "the working tree has uncommitted changes; commit or stash them, or pass --no-regen" +else + ./scripts/copy_armv7_m.sh >/dev/null 2>&1 + ./scripts/copy_armv8_m.sh >/dev/null 2>&1 + ./scripts/copy_module_armv7_m.sh >/dev/null 2>&1 + + drift="$(git status --porcelain -uno)" + if [ -n "$drift" ]; then + fail "running the copy scripts changed $(echo "$drift" | wc -l) file(s)." + echo " The ports below were edited directly instead of through ports_arch." + echo " Re-apply the change to ports_arch and re-run the copy scripts." + echo "$drift" | sed 's/^/ /' + git checkout -- . >/dev/null 2>&1 + else + say " ok: the copy scripts change nothing" + fi +fi + +# -------------------------------------------------------------------------- +# 2. Preprocessor directives must balance in every port header. +# -------------------------------------------------------------------------- +say "" +say "== Preprocessor directives balance ==" + +unbalanced=0 +while IFS= read -r f; do + result="$(awk ' + /^[ \t]*#[ \t]*(if|ifdef|ifndef)/ { depth++ } + /^[ \t]*#[ \t]*endif/ { + depth-- + if (depth < 0 && first == 0) { first = NR } + } + END { printf "%d %d", depth, first } + ' "$f")" + depth="${result% *}" + first="${result#* }" + if [ "$depth" -ne 0 ]; then + if [ "$first" -ne 0 ]; then + fail "$f: #endif without a matching #if at line $first (final depth $depth)" + else + fail "$f: $depth unterminated #if (final depth $depth)" + fi + unbalanced=$((unbalanced + 1)) + fi +done < <(find ports ports_arch ports_module ports_smp -name "*.h" -type f \ + ! -path "*/example_build/*" 2>/dev/null | sort) + +[ "$unbalanced" -eq 0 ] && say " ok: every port header balances" + +# -------------------------------------------------------------------------- +# 3. No statements outside a function body in a port header. +# -------------------------------------------------------------------------- +# Tracks brace depth, ignoring preprocessor lines, comments and strings, and +# reports any statement that lands at depth zero. Declarations, typedefs, +# externs and macro definitions are expected there; assignments, calls and +# dereferences are not, and an orphaned function body shows up as exactly that. +say "" +say "== No code at file scope in port headers ==" + +orphans=0 +while IFS= read -r f; do + result="$(awk ' + # Skip preprocessor lines, including multi-line macro bodies, whose + # continuations are statements by design. + /^[ \t]*#/ { if (/\\[ \t]*$/) { in_macro = 1 }; next } + in_macro { if (!/\\[ \t]*$/) { in_macro = 0 }; next } + + # Skip comments, both kinds, including continuation lines. + in_comment { if (/\*\//) { in_comment = 0 }; next } + /^[ \t]*\/\// { next } + /\/\*/ { if (!/\*\//) { in_comment = 1 }; next } + + { + line = $0 + gsub(/"[^"]*"/, "", line) + gsub(/\/\/.*$/, "", line) + stripped = line + gsub(/^[ \t]+|[ \t]+$/, "", stripped) + + # A statement at file scope ends in a semicolon and either assigns, + # dereferences or opens a control structure. Declarations and + # prototypes also end in a semicolon but match none of these. + if (depth == 0 && stripped ~ /;[ \t]*$/ && + (stripped ~ /^\*\(/ || + stripped ~ /^[A-Za-z_][A-Za-z0-9_]*([ \t]*(\[[^]]*\]|->[ \t]*[A-Za-z_][A-Za-z0-9_]*|\.[A-Za-z_][A-Za-z0-9_]*))*[ \t]*=[^=]/ || + stripped ~ /^(return|if|while|for|switch|do)[ \t(]/)) { + print NR ": " stripped + found++ + } + + n = gsub(/{/, "{", line); m = gsub(/}/, "}", line) + depth += n - m + if (depth < 0) { depth = 0 } + } + END { exit (found > 0 ? 1 : 0) } + ' "$f")" + if [ -n "$result" ]; then + fail "$f: statement(s) outside any function body" + echo "$result" | sed 's/^/ /' + orphans=$((orphans + 1)) + fi +done < <(find ports ports_arch ports_module ports_smp -name "*.h" -type f \ + ! -path "*/example_build/*" 2>/dev/null | sort) + +[ "$orphans" -eq 0 ] && say " ok: no port header carries code at file scope" + +# -------------------------------------------------------------------------- +# 4. Report only: families with no copy script. +# -------------------------------------------------------------------------- +# These are maintained by hand, so a fix applied to one toolchain can silently +# miss the others. Nothing here fails the run; it is a prompt to look. +say "" +say "== Families with no copy script (report only) ==" + +if [ "$quiet" -eq 0 ]; then + for family in ports/cortex_m0 ports/cortex_m0+ ports/cortex_m23; do + [ -d "$family" ] || continue + for probe in "dsb 0xF" "isb 0xF"; do + have=""; missing="" + for header in "$family"/*/inc/tx_port.h; do + [ -f "$header" ] || continue + grep -q "0xE000ED04" "$header" || continue + tool="$(basename "$(dirname "$(dirname "$header")")")" + if grep -q "$probe" "$header"; then + have="$have $tool" + else + missing="$missing $tool" + fi + done + if [ -n "$have" ] && [ -n "$missing" ]; then + echo " $family: \"$probe\" present in$have but absent in$missing" + fi + done + done + say " (nothing above means the toolchains within each family agree)" +fi + +# -------------------------------------------------------------------------- +say "" +if [ "$failures" -eq 0 ]; then + say "All port consistency checks passed." + exit 0 +fi + +echo "$failures port consistency check(s) failed." +exit 1 diff --git a/scripts/prepare_release.sh b/scripts/prepare_release.sh index c33fa8f8d..c6b1d93c4 100755 --- a/scripts/prepare_release.sh +++ b/scripts/prepare_release.sh @@ -78,6 +78,20 @@ printf "\nThreadX release preparation\n" printf " Repository : %s\n" "${REPO_ROOT}" printf " Current version : %s\n" "${CURR_VER}" printf " Target version : %s\n\n" "${VERSION}" + +# -------------------------------------------------------------------------- +# Port consistency checks +# -------------------------------------------------------------------------- +# Run before anything is branched or rewritten, so a release is never cut on +# top of ports that have drifted from ports_arch or headers that cannot +# compile. Set SKIP_PORT_CHECKS=1 to proceed anyway. +if [ "${SKIP_PORT_CHECKS:-0}" = "1" ]; then + printf "Skipping the port consistency checks (SKIP_PORT_CHECKS=1).\n\n" +elif ! "${SCRIPT_DIR}/check_ports.sh"; then + printf "\nRelease preparation stopped: the port consistency checks failed.\n" + printf "Fix the problems above, or set SKIP_PORT_CHECKS=1 to proceed anyway.\n" + exit 1 +fi printf "Proceed with update? [y/N] " read -r CONFIRM case "${CONFIRM}" in From f23a1807a2ad10aefbeaa87871b49dc93c5fc39c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Sun, 9 Aug 2026 10:55:29 -0400 Subject: [PATCH 020/181] Added bash A profile update scripts and restored ports_arch as their source (#592) The ARMv7-A and ARMv8-A ports are generated by update.ps1, which needs PowerShell, so the cortex-a job in ports_arch_check ran on a Windows image and nobody could reproduce it locally on Linux. Add update.sh beside each update.ps1, with the same cores, compilers, copy sets and patches, and move the job to the same Linux image as everything else. The bash scripts were checked against the PowerShell ones by comparing what each reports as drifted. They agree exactly on the 63 files the Windows job last reported, and differ on 12 more, which turn out to be a defect in update.ps1 rather than in the port. Its two .cproject patterns are written as 'value=`"cortex-a7`"' with backticks that survive into the pattern, so that replacement has never matched, while the neighbouring Cortex-A7.NoFPU pattern has no backticks and always worked. The result is that the AC6 example builds for the A5, A8, A9, A12, A15 and A17 cores name cortex-a7 as their CPU while their FPU string is correct. The bash scripts do what the PowerShell ones intended, so regenerating corrects those twelve files. Restore ports_arch as the source for the rest. The implementation of _tx_thread_smp_time_get from #555 was applied to the twenty four generated SMP ports and never to ports_arch, which still held MOV x0, #0 with a FIXME comment, so regenerating would have replaced a working generic timer read with a stub. That implementation now lives in the source. The remaining differences are cosmetic and resolve in favour of the source: a trailing blank line in 38 copies of tx_thread_schedule.S and comment spacing in one tx_port.h. Note that the Cortex-A VFP fix is already present in ports_arch and was never at risk, contrary to what the description of the port consistency checks change said before this was measured. Extend scripts/check_ports.sh to run the A profile generators too, and make it fail when a generator fails or is missing rather than reporting a clean tree, which would have been a false pass. Pin every workflow to ubuntu-24.04. ubuntu-latest already resolves to that image, so nothing changes today, but a future migration becomes a deliberate commit rather than something that happens underneath the -m32 builds. Assisted-by: Claude Code (Opus 5) --- .github/workflows/ci_cortex_m.yml | 2 +- .github/workflows/ports_arch_check.yml | 31 ++-- .github/workflows/regression_template.yml | 4 +- .../example_build/sample_threadx/.cproject | 4 +- .../cortex_a12/ac6/example_build/tx/.cproject | 4 +- ports/cortex_a12/ac6/src/tx_thread_schedule.S | 1 - ports/cortex_a12/gnu/src/tx_thread_schedule.S | 1 - .../example_build/sample_threadx/.cproject | 4 +- .../cortex_a15/ac6/example_build/tx/.cproject | 4 +- ports/cortex_a15/ac6/src/tx_thread_schedule.S | 1 - ports/cortex_a15/gnu/src/tx_thread_schedule.S | 1 - .../example_build/sample_threadx/.cproject | 4 +- .../cortex_a17/ac6/example_build/tx/.cproject | 4 +- ports/cortex_a17/ac6/src/tx_thread_schedule.S | 1 - ports/cortex_a17/gnu/src/tx_thread_schedule.S | 1 - ports/cortex_a35/ac6/src/tx_thread_schedule.S | 1 - ports/cortex_a35/gnu/src/tx_thread_schedule.S | 1 - .../example_build/sample_threadx/.cproject | 4 +- .../cortex_a5/ac6/example_build/tx/.cproject | 4 +- ports/cortex_a5/ac6/src/tx_thread_schedule.S | 1 - ports/cortex_a5/gnu/src/tx_thread_schedule.S | 1 - ports/cortex_a53/ac6/src/tx_thread_schedule.S | 1 - ports/cortex_a53/gnu/src/tx_thread_schedule.S | 1 - ports/cortex_a55/ac6/src/tx_thread_schedule.S | 1 - ports/cortex_a55/gnu/src/tx_thread_schedule.S | 1 - ports/cortex_a57/ac6/src/tx_thread_schedule.S | 1 - ports/cortex_a57/gnu/src/tx_thread_schedule.S | 1 - ports/cortex_a65/ac6/src/tx_thread_schedule.S | 1 - ports/cortex_a65/gnu/src/tx_thread_schedule.S | 1 - .../cortex_a65ae/ac6/src/tx_thread_schedule.S | 1 - .../cortex_a65ae/gnu/src/tx_thread_schedule.S | 1 - ports/cortex_a7/ac6/src/tx_thread_schedule.S | 1 - ports/cortex_a7/gnu/src/tx_thread_schedule.S | 1 - ports/cortex_a72/ac6/src/tx_thread_schedule.S | 1 - ports/cortex_a72/gnu/src/tx_thread_schedule.S | 1 - ports/cortex_a73/ac6/src/tx_thread_schedule.S | 1 - ports/cortex_a73/gnu/src/tx_thread_schedule.S | 1 - ports/cortex_a75/ac6/src/tx_thread_schedule.S | 1 - ports/cortex_a75/gnu/src/tx_thread_schedule.S | 1 - ports/cortex_a76/ac6/src/tx_thread_schedule.S | 1 - ports/cortex_a76/gnu/src/tx_thread_schedule.S | 1 - .../cortex_a76ae/ac6/src/tx_thread_schedule.S | 1 - .../cortex_a76ae/gnu/src/tx_thread_schedule.S | 1 - ports/cortex_a77/ac6/src/tx_thread_schedule.S | 1 - ports/cortex_a77/gnu/src/tx_thread_schedule.S | 1 - .../example_build/sample_threadx/.cproject | 4 +- .../cortex_a8/ac6/example_build/tx/.cproject | 4 +- ports/cortex_a8/ac6/src/tx_thread_schedule.S | 1 - ports/cortex_a8/gnu/src/tx_thread_schedule.S | 1 - .../example_build/sample_threadx/.cproject | 4 +- .../cortex_a9/ac6/example_build/tx/.cproject | 4 +- ports/cortex_a9/ac6/src/tx_thread_schedule.S | 1 - ports/cortex_a9/gnu/src/tx_thread_schedule.S | 1 - ports_arch/ARMv7-A/update.sh | 164 +++++++++++++++++ .../common/src/tx_thread_smp_time_get.S | 3 +- ports_arch/ARMv8-A/update.sh | 169 ++++++++++++++++++ ports_smp/cortex_a75_smp/gnu/inc/tx_port.h | 2 +- scripts/check_ports.sh | 20 ++- 58 files changed, 397 insertions(+), 84 deletions(-) create mode 100755 ports_arch/ARMv7-A/update.sh create mode 100755 ports_arch/ARMv8-A/update.sh diff --git a/.github/workflows/ci_cortex_m.yml b/.github/workflows/ci_cortex_m.yml index 149490be5..a207ab1be 100644 --- a/.github/workflows/ci_cortex_m.yml +++ b/.github/workflows/ci_cortex_m.yml @@ -23,7 +23,7 @@ jobs: # This workflow contains a single job called "build" build: # The type of runner that the job will run on - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 strategy: matrix: diff --git a/.github/workflows/ports_arch_check.yml b/.github/workflows/ports_arch_check.yml index a2c69aeaf..589ef372c 100644 --- a/.github/workflows/ports_arch_check.yml +++ b/.github/workflows/ports_arch_check.yml @@ -25,7 +25,7 @@ jobs: # Check ports for cortex-m cortex-m: # The type of runner that the job will run on - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 # Steps represent a sequence of tasks that will be executed as part of the job steps: @@ -46,8 +46,10 @@ jobs: run: scripts/check_ports.sh cortex-a: - # Check ports for cortex-a - runs-on: windows-latest + # Check ports for cortex-a. This ran on Windows because the A profile + # tooling was PowerShell only; update.sh beside each update.ps1 means it + # runs on the same image as every other job now. + runs-on: ubuntu-24.04 # Steps represent a sequence of tasks that will be executed as part of the job steps: @@ -60,18 +62,19 @@ jobs: - name: Checkout sources uses: actions/checkout@v4 - # Copy ports arch - - name: Copy ports arch + # Regenerate the A profile ports and fail if anything changed, which means + # a generated port was edited directly instead of ports_arch. + - name: Check the Cortex-A ports run: | - cd ports_arch/ARMv7-A - pwsh -Command ./update.ps1 -PortSets tx -CopyCommonFiles -CopyPortFiles -CopyExample -PatchFiles - cd ../../ports_arch/ARMv8-A - pwsh -Command ./update.ps1 -PortSets tx,tx_smp -CopyCommonFiles -CopyPortFiles -CopyExample -PatchFiles - if ((git status --porcelain -uno) -ne $null) { - Write-Host "Ports for ARM architecture is not updated" - git status - Exit 1 - } + (cd ports_arch/ARMv7-A && ./update.sh --port-sets tx \ + --copy-common-files --copy-port-files --copy-example --patch-files) + (cd ports_arch/ARMv8-A && ./update.sh --port-sets tx,tx_smp \ + --copy-common-files --copy-port-files --copy-example --patch-files) + if [[ -n $(git status --porcelain -uno) ]]; then + echo "The Cortex-A ports are not reproducible from ports_arch:" + git status --porcelain -uno + exit 1 + fi diff --git a/.github/workflows/regression_template.yml b/.github/workflows/regression_template.yml index 205eb5a8c..fad4d2f15 100644 --- a/.github/workflows/regression_template.yml +++ b/.github/workflows/regression_template.yml @@ -58,7 +58,7 @@ jobs: pull-requests: write # The type of runner that the job will run on - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 # Steps represent a sequence of tasks that will be executed as part of the job steps: @@ -160,7 +160,7 @@ jobs: path: ${{ inputs.cmake_path }}/coverage_report/${{ inputs.coverage_name }} deploy_code_coverage: - runs-on: ubuntu-latest + runs-on: ubuntu-24.04 if: ((github.event_name == 'push') || (github.event_name == 'workflow_dispatch')) && !inputs.skip_coverage && !inputs.skip_deploy && !failure() && !cancelled() needs: run_tests environment: diff --git a/ports/cortex_a12/ac6/example_build/sample_threadx/.cproject b/ports/cortex_a12/ac6/example_build/sample_threadx/.cproject index 7882693e3..603e2d868 100644 --- a/ports/cortex_a12/ac6/example_build/sample_threadx/.cproject +++ b/ports/cortex_a12/ac6/example_build/sample_threadx/.cproject @@ -45,7 +45,7 @@ diff --git a/ports/cortex_m0/iar/example_build/tx.ewp b/ports/cortex_m0/iar/example_build/tx.ewp index 94481d2e5..a3b29c58b 100644 --- a/ports/cortex_m0/iar/example_build/tx.ewp +++ b/ports/cortex_m0/iar/example_build/tx.ewp @@ -1047,7 +1047,7 @@ diff --git a/ports/cortex_m3/iar/example_build/tx.ewp b/ports/cortex_m3/iar/example_build/tx.ewp index b40f63a53..66d8bbad7 100644 --- a/ports/cortex_m3/iar/example_build/tx.ewp +++ b/ports/cortex_m3/iar/example_build/tx.ewp @@ -1048,7 +1048,7 @@ diff --git a/ports/cortex_m4/iar/example_build/tx.ewp b/ports/cortex_m4/iar/example_build/tx.ewp index 1a1ad21d7..f46a7d79c 100644 --- a/ports/cortex_m4/iar/example_build/tx.ewp +++ b/ports/cortex_m4/iar/example_build/tx.ewp @@ -1047,7 +1047,7 @@ diff --git a/ports/cortex_m7/iar/example_build/tx.ewp b/ports/cortex_m7/iar/example_build/tx.ewp index 1bb260e3d..ea6d4e89e 100644 --- a/ports/cortex_m7/iar/example_build/tx.ewp +++ b/ports/cortex_m7/iar/example_build/tx.ewp @@ -1047,7 +1047,7 @@ diff --git a/ports/cortex_r4/ac6/example_build/sample_threadx/cortex-r4_tx.launch b/ports/cortex_r4/ac6/example_build/sample_threadx/cortex-r4_tx.launch index 37577868f..a7a8d7675 100644 --- a/ports/cortex_r4/ac6/example_build/sample_threadx/cortex-r4_tx.launch +++ b/ports/cortex_r4/ac6/example_build/sample_threadx/cortex-r4_tx.launch @@ -155,7 +155,7 @@ - + diff --git a/ports/cortex_r4/iar/example_build/tx.ewp b/ports/cortex_r4/iar/example_build/tx.ewp index 72f432f87..c4a959b4b 100644 --- a/ports/cortex_r4/iar/example_build/tx.ewp +++ b/ports/cortex_r4/iar/example_build/tx.ewp @@ -1047,7 +1047,7 @@ diff --git a/ports/cortex_r5/ac6/example_build/sample_threadx/cortex-r5_tx.launch b/ports/cortex_r5/ac6/example_build/sample_threadx/cortex-r5_tx.launch index eccecf150..19e5a2325 100644 --- a/ports/cortex_r5/ac6/example_build/sample_threadx/cortex-r5_tx.launch +++ b/ports/cortex_r5/ac6/example_build/sample_threadx/cortex-r5_tx.launch @@ -123,7 +123,7 @@ - + diff --git a/ports/cortex_r5/iar/example_build/tx.ewp b/ports/cortex_r5/iar/example_build/tx.ewp index 06b419829..1f864b793 100644 --- a/ports/cortex_r5/iar/example_build/tx.ewp +++ b/ports/cortex_r5/iar/example_build/tx.ewp @@ -1047,7 +1047,7 @@ diff --git a/ports_arch/ARMv7-A/threadx/ports/ac6/example_build/sample_threadx/sample_threadx.launch b/ports_arch/ARMv7-A/threadx/ports/ac6/example_build/sample_threadx/sample_threadx.launch index 0bc5b11b0..df957414b 100644 --- a/ports_arch/ARMv7-A/threadx/ports/ac6/example_build/sample_threadx/sample_threadx.launch +++ b/ports_arch/ARMv7-A/threadx/ports/ac6/example_build/sample_threadx/sample_threadx.launch @@ -124,7 +124,7 @@ - + diff --git a/ports_arch/ARMv7-A/threadx/ports/iar/example_build/tx.ewp b/ports_arch/ARMv7-A/threadx/ports/iar/example_build/tx.ewp index ef9fb4749..72f03a7a5 100644 --- a/ports_arch/ARMv7-A/threadx/ports/iar/example_build/tx.ewp +++ b/ports_arch/ARMv7-A/threadx/ports/iar/example_build/tx.ewp @@ -1047,7 +1047,7 @@ diff --git a/ports_arch/ARMv7-M/threadx/iar/example_build/tx.ewp b/ports_arch/ARMv7-M/threadx/iar/example_build/tx.ewp index cccb9a9ac..15b9ab101 100644 --- a/ports_arch/ARMv7-M/threadx/iar/example_build/tx.ewp +++ b/ports_arch/ARMv7-M/threadx/iar/example_build/tx.ewp @@ -1047,7 +1047,7 @@ diff --git a/ports_arch/ARMv8-A/threadx/ports/ac6/example_build/sample_threadx/sample_threadx.launch b/ports_arch/ARMv8-A/threadx/ports/ac6/example_build/sample_threadx/sample_threadx.launch index 4aff966d3..39d305480 100644 --- a/ports_arch/ARMv8-A/threadx/ports/ac6/example_build/sample_threadx/sample_threadx.launch +++ b/ports_arch/ARMv8-A/threadx/ports/ac6/example_build/sample_threadx/sample_threadx.launch @@ -181,7 +181,7 @@ - + @@ -311,15 +311,10 @@ - - - - - diff --git a/ports_arch/ARMv8-A/threadx/ports/gnu/example_build/sample_threadx/sample_threadx.launch b/ports_arch/ARMv8-A/threadx/ports/gnu/example_build/sample_threadx/sample_threadx.launch index 12938fd13..40477c01a 100644 --- a/ports_arch/ARMv8-A/threadx/ports/gnu/example_build/sample_threadx/sample_threadx.launch +++ b/ports_arch/ARMv8-A/threadx/ports/gnu/example_build/sample_threadx/sample_threadx.launch @@ -184,7 +184,7 @@ - + @@ -314,15 +314,10 @@ - - - - - diff --git a/ports_arch/ARMv8-A/threadx_smp/ports/ac6/example_build/sample_threadx/sample_threadx.launch b/ports_arch/ARMv8-A/threadx_smp/ports/ac6/example_build/sample_threadx/sample_threadx.launch index 5a0bdcf4c..639e2f4e0 100644 --- a/ports_arch/ARMv8-A/threadx_smp/ports/ac6/example_build/sample_threadx/sample_threadx.launch +++ b/ports_arch/ARMv8-A/threadx_smp/ports/ac6/example_build/sample_threadx/sample_threadx.launch @@ -214,17 +214,10 @@ - - - - - - - - + @@ -395,19 +388,10 @@ - - - - - - - - - diff --git a/ports_arch/ARMv8-A/threadx_smp/ports/gnu/example_build/sample_threadx/sample_threadx.launch b/ports_arch/ARMv8-A/threadx_smp/ports/gnu/example_build/sample_threadx/sample_threadx.launch index d583631ef..d06144ebd 100644 --- a/ports_arch/ARMv8-A/threadx_smp/ports/gnu/example_build/sample_threadx/sample_threadx.launch +++ b/ports_arch/ARMv8-A/threadx_smp/ports/gnu/example_build/sample_threadx/sample_threadx.launch @@ -239,13 +239,6 @@ - - - - - - - @@ -424,22 +417,10 @@ - - - - - - - - - - - - diff --git a/ports_module/cortex_a35/ac6/example_build/sample_threadx/sample_threadx.launch b/ports_module/cortex_a35/ac6/example_build/sample_threadx/sample_threadx.launch index b0d80e921..212f7cdb1 100644 --- a/ports_module/cortex_a35/ac6/example_build/sample_threadx/sample_threadx.launch +++ b/ports_module/cortex_a35/ac6/example_build/sample_threadx/sample_threadx.launch @@ -180,7 +180,7 @@ - + @@ -310,14 +310,10 @@ - - - - diff --git a/ports_module/cortex_a35/ac6/example_build/sample_threadx_module_manager/sample_threadx_module_manager.launch b/ports_module/cortex_a35/ac6/example_build/sample_threadx_module_manager/sample_threadx_module_manager.launch index a70c574d0..dbc2bf4e1 100644 --- a/ports_module/cortex_a35/ac6/example_build/sample_threadx_module_manager/sample_threadx_module_manager.launch +++ b/ports_module/cortex_a35/ac6/example_build/sample_threadx_module_manager/sample_threadx_module_manager.launch @@ -288,7 +288,7 @@ - + @@ -394,10 +394,6 @@ - - - - diff --git a/ports_module/cortex_a35/gnu/example_build/sample_threadx/sample_threadx.launch b/ports_module/cortex_a35/gnu/example_build/sample_threadx/sample_threadx.launch index 5f96a35c9..d81914a59 100644 --- a/ports_module/cortex_a35/gnu/example_build/sample_threadx/sample_threadx.launch +++ b/ports_module/cortex_a35/gnu/example_build/sample_threadx/sample_threadx.launch @@ -183,7 +183,7 @@ - + @@ -320,14 +320,10 @@ - - - - diff --git a/ports_module/cortex_a35/gnu/example_build/sample_threadx_module_manager/sample_threadx_module_manager.launch b/ports_module/cortex_a35/gnu/example_build/sample_threadx_module_manager/sample_threadx_module_manager.launch index 530cac1f3..bf6b125ad 100644 --- a/ports_module/cortex_a35/gnu/example_build/sample_threadx_module_manager/sample_threadx_module_manager.launch +++ b/ports_module/cortex_a35/gnu/example_build/sample_threadx_module_manager/sample_threadx_module_manager.launch @@ -306,7 +306,7 @@ - + @@ -349,7 +349,6 @@ - @@ -414,10 +413,6 @@ - - - - diff --git a/ports_module/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.launch b/ports_module/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.launch index 6723ac8a2..484e78035 100644 --- a/ports_module/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.launch +++ b/ports_module/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.launch @@ -232,17 +232,10 @@ - - - - - - - - + @@ -381,18 +374,10 @@ - - - - - - - - diff --git a/ports_module/cortex_a35_smp/ac6/example_build/sample_threadx_module_manager/sample_threadx_module_manager.launch b/ports_module/cortex_a35_smp/ac6/example_build/sample_threadx_module_manager/sample_threadx_module_manager.launch index dba4c8c8e..6c4c7fe65 100644 --- a/ports_module/cortex_a35_smp/ac6/example_build/sample_threadx_module_manager/sample_threadx_module_manager.launch +++ b/ports_module/cortex_a35_smp/ac6/example_build/sample_threadx_module_manager/sample_threadx_module_manager.launch @@ -378,7 +378,7 @@ - + @@ -500,10 +500,6 @@ - - - - diff --git a/ports_module/cortex_a35_smp/gnu/example_build/sample_threadx/sample_threadx.launch b/ports_module/cortex_a35_smp/gnu/example_build/sample_threadx/sample_threadx.launch index dd31854e6..e39067f43 100644 --- a/ports_module/cortex_a35_smp/gnu/example_build/sample_threadx/sample_threadx.launch +++ b/ports_module/cortex_a35_smp/gnu/example_build/sample_threadx/sample_threadx.launch @@ -225,17 +225,10 @@ - - - - - - - - + @@ -407,22 +400,10 @@ - - - - - - - - - - - - diff --git a/ports_module/cortex_a35_smp/gnu/example_build/sample_threadx_module_manager/sample_threadx_module_manager.launch b/ports_module/cortex_a35_smp/gnu/example_build/sample_threadx_module_manager/sample_threadx_module_manager.launch index 6152beabe..9f877d868 100644 --- a/ports_module/cortex_a35_smp/gnu/example_build/sample_threadx_module_manager/sample_threadx_module_manager.launch +++ b/ports_module/cortex_a35_smp/gnu/example_build/sample_threadx_module_manager/sample_threadx_module_manager.launch @@ -300,7 +300,7 @@ - + @@ -373,7 +373,6 @@ - @@ -438,10 +437,6 @@ - - - - diff --git a/ports_module/cortex_a7/iar/example_build/sample_threadx_module_manager.ewp b/ports_module/cortex_a7/iar/example_build/sample_threadx_module_manager.ewp index 524b30f05..e77458be3 100644 --- a/ports_module/cortex_a7/iar/example_build/sample_threadx_module_manager.ewp +++ b/ports_module/cortex_a7/iar/example_build/sample_threadx_module_manager.ewp @@ -1811,7 +1811,7 @@ diff --git a/ports_module/cortex_a7/iar/example_build/txm.ewp b/ports_module/cortex_a7/iar/example_build/txm.ewp index b8b34b1f0..ad9974638 100644 --- a/ports_module/cortex_a7/iar/example_build/txm.ewp +++ b/ports_module/cortex_a7/iar/example_build/txm.ewp @@ -1052,7 +1052,7 @@ diff --git a/ports_module/cortex_m0+/ac6/example_build/sample_threadx_module_manager/sample_threadx_module_manager.launch b/ports_module/cortex_m0+/ac6/example_build/sample_threadx_module_manager/sample_threadx_module_manager.launch index d4fd4e3dc..c622a7293 100644 --- a/ports_module/cortex_m0+/ac6/example_build/sample_threadx_module_manager/sample_threadx_module_manager.launch +++ b/ports_module/cortex_m0+/ac6/example_build/sample_threadx_module_manager/sample_threadx_module_manager.launch @@ -207,25 +207,10 @@ - - - - - - - - - - - - - - - - + diff --git a/ports_module/cortex_m0+/gnu/example_build/sample_threadx/sample_threadx.launch b/ports_module/cortex_m0+/gnu/example_build/sample_threadx/sample_threadx.launch index 1dab0b650..8527f632d 100644 --- a/ports_module/cortex_m0+/gnu/example_build/sample_threadx/sample_threadx.launch +++ b/ports_module/cortex_m0+/gnu/example_build/sample_threadx/sample_threadx.launch @@ -126,7 +126,7 @@ - + diff --git a/ports_module/cortex_m0+/gnu/example_build/sample_threadx_module_manager/sample_threadx_module_manager.launch b/ports_module/cortex_m0+/gnu/example_build/sample_threadx_module_manager/sample_threadx_module_manager.launch index debe6d723..13be6145c 100644 --- a/ports_module/cortex_m0+/gnu/example_build/sample_threadx_module_manager/sample_threadx_module_manager.launch +++ b/ports_module/cortex_m0+/gnu/example_build/sample_threadx_module_manager/sample_threadx_module_manager.launch @@ -209,53 +209,10 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/ports_module/cortex_m0+/iar/example_build/txm.ewp b/ports_module/cortex_m0+/iar/example_build/txm.ewp index e13721eb4..12463c9eb 100644 --- a/ports_module/cortex_m0+/iar/example_build/txm.ewp +++ b/ports_module/cortex_m0+/iar/example_build/txm.ewp @@ -1048,7 +1048,7 @@ diff --git a/ports_module/cortex_m3/ac6/example_build/sample_threadx/sample_threadx.launch b/ports_module/cortex_m3/ac6/example_build/sample_threadx/sample_threadx.launch index 5931ba763..41c40864f 100644 --- a/ports_module/cortex_m3/ac6/example_build/sample_threadx/sample_threadx.launch +++ b/ports_module/cortex_m3/ac6/example_build/sample_threadx/sample_threadx.launch @@ -121,7 +121,7 @@ - + diff --git a/ports_module/cortex_m3/ac6/example_build/sample_threadx_module_manager/sample_threadx_module_manager.launch b/ports_module/cortex_m3/ac6/example_build/sample_threadx_module_manager/sample_threadx_module_manager.launch index 05684daaa..123b13a48 100644 --- a/ports_module/cortex_m3/ac6/example_build/sample_threadx_module_manager/sample_threadx_module_manager.launch +++ b/ports_module/cortex_m3/ac6/example_build/sample_threadx_module_manager/sample_threadx_module_manager.launch @@ -132,7 +132,7 @@ - + diff --git a/ports_module/cortex_m4/ac6/example_build/sample_threadx_module_manager/sample_threadx_module_manager.launch b/ports_module/cortex_m4/ac6/example_build/sample_threadx_module_manager/sample_threadx_module_manager.launch index 7ecea14f8..cc468ec0c 100644 --- a/ports_module/cortex_m4/ac6/example_build/sample_threadx_module_manager/sample_threadx_module_manager.launch +++ b/ports_module/cortex_m4/ac6/example_build/sample_threadx_module_manager/sample_threadx_module_manager.launch @@ -137,7 +137,7 @@ - + @@ -216,10 +216,6 @@ - - - - diff --git a/ports_module/cortex_m4/iar/example_build/tx.ewp b/ports_module/cortex_m4/iar/example_build/tx.ewp index 5d8d8dccb..d8e5b5965 100644 --- a/ports_module/cortex_m4/iar/example_build/tx.ewp +++ b/ports_module/cortex_m4/iar/example_build/tx.ewp @@ -1054,7 +1054,7 @@ diff --git a/ports_module/cortex_m4/iar/example_build/txm.ewp b/ports_module/cortex_m4/iar/example_build/txm.ewp index c20bb048f..fb7e0650d 100644 --- a/ports_module/cortex_m4/iar/example_build/txm.ewp +++ b/ports_module/cortex_m4/iar/example_build/txm.ewp @@ -1052,7 +1052,7 @@ diff --git a/ports_module/cortex_m7/ac6/example_build/sample_threadx_module_manager/sample_threadx_module_manager.launch b/ports_module/cortex_m7/ac6/example_build/sample_threadx_module_manager/sample_threadx_module_manager.launch index 7b783402d..187beb067 100644 --- a/ports_module/cortex_m7/ac6/example_build/sample_threadx_module_manager/sample_threadx_module_manager.launch +++ b/ports_module/cortex_m7/ac6/example_build/sample_threadx_module_manager/sample_threadx_module_manager.launch @@ -155,7 +155,7 @@ - + diff --git a/ports_module/cortex_m7/iar/example_build/tx.ewp b/ports_module/cortex_m7/iar/example_build/tx.ewp index 7ff6209d7..09ad5b2ef 100644 --- a/ports_module/cortex_m7/iar/example_build/tx.ewp +++ b/ports_module/cortex_m7/iar/example_build/tx.ewp @@ -1054,7 +1054,7 @@ diff --git a/ports_module/cortex_r4/ac6/example_build/sample_threadx/tx_cortex_r4.launch b/ports_module/cortex_r4/ac6/example_build/sample_threadx/tx_cortex_r4.launch index 4d4f7ba9c..18ea34a21 100644 --- a/ports_module/cortex_r4/ac6/example_build/sample_threadx/tx_cortex_r4.launch +++ b/ports_module/cortex_r4/ac6/example_build/sample_threadx/tx_cortex_r4.launch @@ -265,43 +265,10 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/ports_module/cortex_r4/ac6/example_build/sample_threadx_module_manager/txm_cortex_r4.launch b/ports_module/cortex_r4/ac6/example_build/sample_threadx_module_manager/txm_cortex_r4.launch index 9a6bfc71c..55c1e26f5 100644 --- a/ports_module/cortex_r4/ac6/example_build/sample_threadx_module_manager/txm_cortex_r4.launch +++ b/ports_module/cortex_r4/ac6/example_build/sample_threadx_module_manager/txm_cortex_r4.launch @@ -262,43 +262,10 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + diff --git a/ports_module/cortex_r4/iar/example_build/tx.ewp b/ports_module/cortex_r4/iar/example_build/tx.ewp index 501e64353..a56a49ca2 100644 --- a/ports_module/cortex_r4/iar/example_build/tx.ewp +++ b/ports_module/cortex_r4/iar/example_build/tx.ewp @@ -1049,7 +1049,7 @@ diff --git a/ports_module/cortex_r4/iar/example_build/txm.ewp b/ports_module/cortex_r4/iar/example_build/txm.ewp index af145c0c5..b7115c5b9 100644 --- a/ports_module/cortex_r4/iar/example_build/txm.ewp +++ b/ports_module/cortex_r4/iar/example_build/txm.ewp @@ -1048,7 +1048,7 @@ diff --git a/ports_smp/cortex_a34_smp/ac6/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a34_smp/ac6/example_build/sample_threadx/sample_threadx.launch index 0504845cb..3cbf2cc12 100644 --- a/ports_smp/cortex_a34_smp/ac6/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a34_smp/ac6/example_build/sample_threadx/sample_threadx.launch @@ -214,17 +214,10 @@ - - - - - - - - + @@ -395,19 +388,10 @@ - - - - - - - - - diff --git a/ports_smp/cortex_a34_smp/gnu/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a34_smp/gnu/example_build/sample_threadx/sample_threadx.launch index c3bb42469..385b43c31 100644 --- a/ports_smp/cortex_a34_smp/gnu/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a34_smp/gnu/example_build/sample_threadx/sample_threadx.launch @@ -239,13 +239,6 @@ - - - - - - - @@ -424,22 +417,10 @@ - - - - - - - - - - - - diff --git a/ports_smp/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.launch index 5a0bdcf4c..639e2f4e0 100644 --- a/ports_smp/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a35_smp/ac6/example_build/sample_threadx/sample_threadx.launch @@ -214,17 +214,10 @@ - - - - - - - - + @@ -395,19 +388,10 @@ - - - - - - - - - diff --git a/ports_smp/cortex_a35_smp/gnu/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a35_smp/gnu/example_build/sample_threadx/sample_threadx.launch index d583631ef..d06144ebd 100644 --- a/ports_smp/cortex_a35_smp/gnu/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a35_smp/gnu/example_build/sample_threadx/sample_threadx.launch @@ -239,13 +239,6 @@ - - - - - - - @@ -424,22 +417,10 @@ - - - - - - - - - - - - diff --git a/ports_smp/cortex_a53_smp/ac6/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a53_smp/ac6/example_build/sample_threadx/sample_threadx.launch index 67c1a9278..dc48da27c 100644 --- a/ports_smp/cortex_a53_smp/ac6/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a53_smp/ac6/example_build/sample_threadx/sample_threadx.launch @@ -214,17 +214,10 @@ - - - - - - - - + @@ -395,19 +388,10 @@ - - - - - - - - - diff --git a/ports_smp/cortex_a53_smp/gnu/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a53_smp/gnu/example_build/sample_threadx/sample_threadx.launch index 045ffa6d8..34ec164be 100644 --- a/ports_smp/cortex_a53_smp/gnu/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a53_smp/gnu/example_build/sample_threadx/sample_threadx.launch @@ -239,13 +239,6 @@ - - - - - - - @@ -424,22 +417,10 @@ - - - - - - - - - - - - diff --git a/ports_smp/cortex_a55_smp/ac6/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a55_smp/ac6/example_build/sample_threadx/sample_threadx.launch index be0cec082..4b3361472 100644 --- a/ports_smp/cortex_a55_smp/ac6/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a55_smp/ac6/example_build/sample_threadx/sample_threadx.launch @@ -214,17 +214,10 @@ - - - - - - - - + @@ -395,19 +388,10 @@ - - - - - - - - - diff --git a/ports_smp/cortex_a55_smp/gnu/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a55_smp/gnu/example_build/sample_threadx/sample_threadx.launch index ff7965556..2ad35b44a 100644 --- a/ports_smp/cortex_a55_smp/gnu/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a55_smp/gnu/example_build/sample_threadx/sample_threadx.launch @@ -239,13 +239,6 @@ - - - - - - - @@ -424,22 +417,10 @@ - - - - - - - - - - - - diff --git a/ports_smp/cortex_a57_smp/ac6/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a57_smp/ac6/example_build/sample_threadx/sample_threadx.launch index e931d1ef7..fb3877c62 100644 --- a/ports_smp/cortex_a57_smp/ac6/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a57_smp/ac6/example_build/sample_threadx/sample_threadx.launch @@ -214,17 +214,10 @@ - - - - - - - - + @@ -395,19 +388,10 @@ - - - - - - - - - diff --git a/ports_smp/cortex_a57_smp/gnu/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a57_smp/gnu/example_build/sample_threadx/sample_threadx.launch index 5c4635d68..40fa00b6a 100644 --- a/ports_smp/cortex_a57_smp/gnu/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a57_smp/gnu/example_build/sample_threadx/sample_threadx.launch @@ -239,13 +239,6 @@ - - - - - - - @@ -424,22 +417,10 @@ - - - - - - - - - - - - diff --git a/ports_smp/cortex_a5x_smp/ac6/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a5x_smp/ac6/example_build/sample_threadx/sample_threadx.launch index 1bb76faba..1324b9bdf 100644 --- a/ports_smp/cortex_a5x_smp/ac6/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a5x_smp/ac6/example_build/sample_threadx/sample_threadx.launch @@ -210,13 +210,6 @@ - - - - - - - @@ -387,17 +380,10 @@ - - - - - - - diff --git a/ports_smp/cortex_a5x_smp/ac6/example_build/sample_threadx/startup_AArch64-FVP_Base_AEMv8A.launch b/ports_smp/cortex_a5x_smp/ac6/example_build/sample_threadx/startup_AArch64-FVP_Base_AEMv8A.launch index fc1a8ba95..e64d68f83 100644 --- a/ports_smp/cortex_a5x_smp/ac6/example_build/sample_threadx/startup_AArch64-FVP_Base_AEMv8A.launch +++ b/ports_smp/cortex_a5x_smp/ac6/example_build/sample_threadx/startup_AArch64-FVP_Base_AEMv8A.launch @@ -207,17 +207,10 @@ - - - - - - - - + @@ -388,14 +381,10 @@ - - - - diff --git a/ports_smp/cortex_a5x_smp/gnu/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a5x_smp/gnu/example_build/sample_threadx/sample_threadx.launch index 2718a398a..d5d362042 100644 --- a/ports_smp/cortex_a5x_smp/gnu/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a5x_smp/gnu/example_build/sample_threadx/sample_threadx.launch @@ -233,13 +233,6 @@ - - - - - - - @@ -414,21 +407,10 @@ - - - - - - - - - - - diff --git a/ports_smp/cortex_a65_smp/ac6/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a65_smp/ac6/example_build/sample_threadx/sample_threadx.launch index b9860a7cf..40148e643 100644 --- a/ports_smp/cortex_a65_smp/ac6/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a65_smp/ac6/example_build/sample_threadx/sample_threadx.launch @@ -214,17 +214,10 @@ - - - - - - - - + @@ -395,19 +388,10 @@ - - - - - - - - - diff --git a/ports_smp/cortex_a65_smp/gnu/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a65_smp/gnu/example_build/sample_threadx/sample_threadx.launch index 2a46fcb7e..936fbc87b 100644 --- a/ports_smp/cortex_a65_smp/gnu/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a65_smp/gnu/example_build/sample_threadx/sample_threadx.launch @@ -239,13 +239,6 @@ - - - - - - - @@ -424,22 +417,10 @@ - - - - - - - - - - - - diff --git a/ports_smp/cortex_a65ae_smp/ac6/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a65ae_smp/ac6/example_build/sample_threadx/sample_threadx.launch index b03142d91..7075858b5 100644 --- a/ports_smp/cortex_a65ae_smp/ac6/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a65ae_smp/ac6/example_build/sample_threadx/sample_threadx.launch @@ -214,17 +214,10 @@ - - - - - - - - + @@ -395,19 +388,10 @@ - - - - - - - - - diff --git a/ports_smp/cortex_a65ae_smp/gnu/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a65ae_smp/gnu/example_build/sample_threadx/sample_threadx.launch index 4fc222e40..6fbaed290 100644 --- a/ports_smp/cortex_a65ae_smp/gnu/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a65ae_smp/gnu/example_build/sample_threadx/sample_threadx.launch @@ -239,13 +239,6 @@ - - - - - - - @@ -424,22 +417,10 @@ - - - - - - - - - - - - diff --git a/ports_smp/cortex_a72_smp/ac6/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a72_smp/ac6/example_build/sample_threadx/sample_threadx.launch index 139b1f06d..6e4000367 100644 --- a/ports_smp/cortex_a72_smp/ac6/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a72_smp/ac6/example_build/sample_threadx/sample_threadx.launch @@ -214,17 +214,10 @@ - - - - - - - - + @@ -395,19 +388,10 @@ - - - - - - - - - diff --git a/ports_smp/cortex_a72_smp/gnu/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a72_smp/gnu/example_build/sample_threadx/sample_threadx.launch index 838e26495..0e0032aeb 100644 --- a/ports_smp/cortex_a72_smp/gnu/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a72_smp/gnu/example_build/sample_threadx/sample_threadx.launch @@ -239,13 +239,6 @@ - - - - - - - @@ -424,22 +417,10 @@ - - - - - - - - - - - - diff --git a/ports_smp/cortex_a73_smp/ac6/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a73_smp/ac6/example_build/sample_threadx/sample_threadx.launch index f13939f40..01e2095c5 100644 --- a/ports_smp/cortex_a73_smp/ac6/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a73_smp/ac6/example_build/sample_threadx/sample_threadx.launch @@ -214,17 +214,10 @@ - - - - - - - - + @@ -395,19 +388,10 @@ - - - - - - - - - diff --git a/ports_smp/cortex_a73_smp/gnu/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a73_smp/gnu/example_build/sample_threadx/sample_threadx.launch index 4154e537c..dbd26b959 100644 --- a/ports_smp/cortex_a73_smp/gnu/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a73_smp/gnu/example_build/sample_threadx/sample_threadx.launch @@ -239,13 +239,6 @@ - - - - - - - @@ -424,22 +417,10 @@ - - - - - - - - - - - - diff --git a/ports_smp/cortex_a75_smp/ac6/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a75_smp/ac6/example_build/sample_threadx/sample_threadx.launch index fe933d060..48c03e626 100644 --- a/ports_smp/cortex_a75_smp/ac6/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a75_smp/ac6/example_build/sample_threadx/sample_threadx.launch @@ -214,17 +214,10 @@ - - - - - - - - + @@ -395,19 +388,10 @@ - - - - - - - - - diff --git a/ports_smp/cortex_a75_smp/gnu/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a75_smp/gnu/example_build/sample_threadx/sample_threadx.launch index 9ee277a93..f2e1d3a7c 100644 --- a/ports_smp/cortex_a75_smp/gnu/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a75_smp/gnu/example_build/sample_threadx/sample_threadx.launch @@ -239,13 +239,6 @@ - - - - - - - @@ -424,22 +417,10 @@ - - - - - - - - - - - - diff --git a/ports_smp/cortex_a76_smp/ac6/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a76_smp/ac6/example_build/sample_threadx/sample_threadx.launch index b95a77e9d..557f8e3eb 100644 --- a/ports_smp/cortex_a76_smp/ac6/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a76_smp/ac6/example_build/sample_threadx/sample_threadx.launch @@ -214,17 +214,10 @@ - - - - - - - - + @@ -395,19 +388,10 @@ - - - - - - - - - diff --git a/ports_smp/cortex_a76_smp/gnu/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a76_smp/gnu/example_build/sample_threadx/sample_threadx.launch index 7120ad673..ef5c7bf78 100644 --- a/ports_smp/cortex_a76_smp/gnu/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a76_smp/gnu/example_build/sample_threadx/sample_threadx.launch @@ -239,13 +239,6 @@ - - - - - - - @@ -424,22 +417,10 @@ - - - - - - - - - - - - diff --git a/ports_smp/cortex_a76ae_smp/ac6/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a76ae_smp/ac6/example_build/sample_threadx/sample_threadx.launch index 97f330867..b140704f0 100644 --- a/ports_smp/cortex_a76ae_smp/ac6/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a76ae_smp/ac6/example_build/sample_threadx/sample_threadx.launch @@ -214,17 +214,10 @@ - - - - - - - - + @@ -395,19 +388,10 @@ - - - - - - - - - diff --git a/ports_smp/cortex_a76ae_smp/gnu/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a76ae_smp/gnu/example_build/sample_threadx/sample_threadx.launch index 6f2e230f6..44fc82c04 100644 --- a/ports_smp/cortex_a76ae_smp/gnu/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a76ae_smp/gnu/example_build/sample_threadx/sample_threadx.launch @@ -239,13 +239,6 @@ - - - - - - - @@ -424,22 +417,10 @@ - - - - - - - - - - - - diff --git a/ports_smp/cortex_a77_smp/ac6/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a77_smp/ac6/example_build/sample_threadx/sample_threadx.launch index 4acbbf6ae..956df9268 100644 --- a/ports_smp/cortex_a77_smp/ac6/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a77_smp/ac6/example_build/sample_threadx/sample_threadx.launch @@ -214,17 +214,10 @@ - - - - - - - - + @@ -395,19 +388,10 @@ - - - - - - - - - diff --git a/ports_smp/cortex_a77_smp/gnu/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a77_smp/gnu/example_build/sample_threadx/sample_threadx.launch index a23df1b07..e33dfa127 100644 --- a/ports_smp/cortex_a77_smp/gnu/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a77_smp/gnu/example_build/sample_threadx/sample_threadx.launch @@ -239,13 +239,6 @@ - - - - - - - @@ -424,22 +417,10 @@ - - - - - - - - - - - - diff --git a/ports_smp/cortex_a78_smp/ac6/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a78_smp/ac6/example_build/sample_threadx/sample_threadx.launch index 88ea5a1e9..aac92dec2 100644 --- a/ports_smp/cortex_a78_smp/ac6/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a78_smp/ac6/example_build/sample_threadx/sample_threadx.launch @@ -214,17 +214,10 @@ - - - - - - - - + @@ -395,19 +388,10 @@ - - - - - - - - - diff --git a/ports_smp/cortex_a78_smp/gnu/example_build/sample_threadx/sample_threadx.launch b/ports_smp/cortex_a78_smp/gnu/example_build/sample_threadx/sample_threadx.launch index 13eca7901..baa98e1cf 100644 --- a/ports_smp/cortex_a78_smp/gnu/example_build/sample_threadx/sample_threadx.launch +++ b/ports_smp/cortex_a78_smp/gnu/example_build/sample_threadx/sample_threadx.launch @@ -239,13 +239,6 @@ - - - - - - - @@ -424,22 +417,10 @@ - - - - - - - - - - - - From b0ad67bae9d99fba90f0d4b8f9c98172f30841e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Tue, 11 Aug 2026 19:53:11 -0400 Subject: [PATCH 032/181] Brought the Cortex-R52 examples under the LLVM check, and fixed two blockers (#604) #600 added a line reporting which example builds the LLVM check passes over, and cortex_r52 was on it: its examples are driven by CMake rather than by a build_threadx.sh pair, so the linking stage never touched them. Covering them turned up two reasons they could not have been built with anything but GNU. .arch armv8-r has no portable spelling. GNU as accepts it, and LLVM's integrated assembler rejects every variant -- armv8-r, armv8r, armv8-r+crc -- with "Unknown Arch: armv8-r". There is nothing to substitute, so the directive is gone from entry.S and tx_initialize_low_level.S; -mcpu=cortex-r52 already selects the architecture, both toolchain files pass it, and the directive only restated it. Worth noting where this hid: the assembly stage walks ports/*/gnu/src, so example assembly had never been assembled by LLVM at all. -Wl,--no-warn-rwx-segments is GNU ld only, added in binutils 2.39. ld.lld does not warn about RWX segments and rejects the flag outright, failing the link with "unknown argument". It is now selected on CMAKE_C_COMPILER_ID rather than spelled into all six targets, and the reason it exists at all -- a bare-metal image has one flat DRAM region and leaves access control to the MPU -- moves to the one place that sets it. cmake/cortex_r52_clang.cmake is the toolchain file. It names the tools as found on PATH, which is what CI uses, then pins $HOME/toolchains if that directory exists, mirroring how cortex_r52.cmake pins the GNU toolchain and for the same reason. Falling back rather than requiring the pinned path keeps the file usable on a machine that keeps clang elsewhere. THREADX_TOOLCHAIN stays "gnu": there is no clang port directory, this builds the gnu sources with a different compiler, which is what the whole check does for every other Arm port. check_clang.sh gains a fourth stage for CMake-driven examples, and no longer reports cortex_r52 as a gap. It reads the image list out of the generated ninja graph rather than repeating it, so adding a target cannot escape the check, and filters out the cmake_object_order_depends_target_* phonies -- counting those reported ten images where there are five. Verified with Arm Toolchain for Embedded 22.1.0, the version the workflow pins. All five images link, and all five then run and pass on FVP_BaseR_AEMv8R: boot_check, demo_m2, demo_m3, demo_threadx and demo_mpu. That is a step beyond the AArch64 examples, which are link-verified only. The full check reports 711 of 711 assembly sources, 185 of 185 common C sources for each of nine cores, 42 of 42 script-driven examples and 5 of 5 CMake images, leaving only cortex_a5_smp, cortex_a7_smp and cortex_a9_smp listed as having no driver. GNU is unaffected: the same five images build with no warnings and the FVP test suite passes 5 of 5. Assisted-by: Claude Code (Opus 5) --- cmake/cortex_r52_clang.cmake | 84 +++++++++++++++++++ .../fvp_baser_aemv8r/CMakeLists.txt | 26 ++++-- .../example_build/fvp_baser_aemv8r/entry.S | 7 +- .../tx_initialize_low_level.S | 7 +- scripts/check_clang.sh | 80 ++++++++++++++++-- 5 files changed, 189 insertions(+), 15 deletions(-) create mode 100644 cmake/cortex_r52_clang.cmake diff --git a/cmake/cortex_r52_clang.cmake b/cmake/cortex_r52_clang.cmake new file mode 100644 index 000000000..2105ecbe2 --- /dev/null +++ b/cmake/cortex_r52_clang.cmake @@ -0,0 +1,84 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# Toolchain file for Arm Cortex-R52 (Armv8-R, AArch32) using Arm Toolchain for +# Embedded, which is LLVM based and is the successor to Arm Compiler 6. +# +# There is no separate clang port directory: this builds the gnu port sources +# with a different compiler, which is the same thing scripts/check_clang.sh does +# for every other Arm port. THREADX_TOOLCHAIN stays "gnu" for that reason. +# +# cmake -S . -B build -G Ninja \ +# -DCMAKE_TOOLCHAIN_FILE=cmake/cortex_r52_clang.cmake \ +# -DTX_R52_BUILD_FVP_EXAMPLE=ON + +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR cortex-r52) + +set(THREADX_ARCH "cortex_r52") +set(THREADX_TOOLCHAIN "gnu") + +# Tool names as found on PATH, which is what CI uses: the workflow unpacks the +# toolchain into the workspace and scripts/check_clang.sh passes its location +# through as ATFE_TOOLCHAIN_PATH. +set(CMAKE_C_COMPILER clang) +set(CMAKE_CXX_COMPILER clang++) +set(CMAKE_ASM_COMPILER clang) +set(CMAKE_AR llvm-ar) +set(CMAKE_RANLIB llvm-ranlib) +set(OBJCOPY llvm-objcopy) +set(OBJDUMP llvm-objdump) +set(SIZE llvm-size) + +# Then pin a specific install if one is present, the way cortex_r52.cmake pins +# the GNU toolchain and for the same reason: a local build should not depend on +# PATH ordering. Absent that directory this falls back to the names above rather +# than failing, so the file works on a machine that keeps clang elsewhere. +# Override with -DATFE_TOOLCHAIN_PATH=. +if(NOT DEFINED ATFE_TOOLCHAIN_PATH) + set(ATFE_TOOLCHAIN_PATH "$ENV{HOME}/toolchains/ATfE-22.1.0-Linux-x86_64/bin") +endif() +if(EXISTS "${ATFE_TOOLCHAIN_PATH}/clang") + set(CMAKE_C_COMPILER "${ATFE_TOOLCHAIN_PATH}/clang") + set(CMAKE_CXX_COMPILER "${ATFE_TOOLCHAIN_PATH}/clang++") + set(CMAKE_ASM_COMPILER "${ATFE_TOOLCHAIN_PATH}/clang") + set(CMAKE_AR "${ATFE_TOOLCHAIN_PATH}/llvm-ar") + set(CMAKE_RANLIB "${ATFE_TOOLCHAIN_PATH}/llvm-ranlib") + set(OBJCOPY "${ATFE_TOOLCHAIN_PATH}/llvm-objcopy") + set(OBJDUMP "${ATFE_TOOLCHAIN_PATH}/llvm-objdump") + set(SIZE "${ATFE_TOOLCHAIN_PATH}/llvm-size") +endif() + +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + +# Link the try-compile as a static library, so probing the compiler does not +# need a linker script or a target C library. +set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) + +if(NOT DEFINED TX_R52_FLOAT_ABI) + set(TX_R52_FLOAT_ABI "soft" CACHE STRING "R52 float ABI: soft | hard") +endif() + +set(MCPU_FLAGS "--target=arm-none-eabi -marm -mcpu=cortex-r52") +if(TX_R52_FLOAT_ABI STREQUAL "hard") + set(VFP_FLAGS "-mfpu=fpv5-d16 -mfloat-abi=hard") +else() + set(VFP_FLAGS "-mfloat-abi=soft") +endif() + +set(CMAKE_C_FLAGS "${MCPU_FLAGS} ${VFP_FLAGS} -fdata-sections -ffunction-sections -mlong-calls" CACHE INTERNAL "c compiler flags") +set(CMAKE_CXX_FLAGS "${MCPU_FLAGS} ${VFP_FLAGS} -fdata-sections -ffunction-sections -fno-rtti -fno-exceptions -mlong-calls" CACHE INTERNAL "cxx compiler flags") +set(CMAKE_ASM_FLAGS "${MCPU_FLAGS} ${VFP_FLAGS} -x assembler-with-cpp" CACHE INTERNAL "asm compiler flags") +set(CMAKE_EXE_LINKER_FLAGS "${MCPU_FLAGS} ${VFP_FLAGS} -fuse-ld=lld -Wl,--gc-sections" CACHE INTERNAL "exe link flags") + +set(CMAKE_C_FLAGS_DEBUG "-Og -g" CACHE INTERNAL "c debug compiler flags") +set(CMAKE_CXX_FLAGS_DEBUG "-Og -g" CACHE INTERNAL "cxx debug compiler flags") +set(CMAKE_ASM_FLAGS_DEBUG "-g" CACHE INTERNAL "asm debug compiler flags") + +set(CMAKE_C_FLAGS_RELEASE "-O3" CACHE INTERNAL "c release compiler flags") +set(CMAKE_CXX_FLAGS_RELEASE "-O3" CACHE INTERNAL "cxx release compiler flags") +set(CMAKE_ASM_FLAGS_RELEASE "" CACHE INTERNAL "asm release compiler flags") diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/CMakeLists.txt b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/CMakeLists.txt index dc451bd39..c0824b264 100644 --- a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/CMakeLists.txt +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/CMakeLists.txt @@ -6,6 +6,18 @@ set(FVP_DIR ${CMAKE_CURRENT_LIST_DIR}) +# A bare-metal image has one flat DRAM region and no OS page permissions; access +# control belongs to the MPU, so an RWX segment is expected here rather than a +# mistake. GNU ld has warned about them since binutils 2.39 and takes this flag +# to stay quiet. ld.lld does not warn and rejects the flag outright, failing the +# link with "unknown argument", so the suppression is chosen by toolchain +# instead of being spelled into every target. +if(CMAKE_C_COMPILER_ID STREQUAL "GNU") + set(R52_LINK_QUIET_RWX -Wl,--no-warn-rwx-segments) +else() + set(R52_LINK_QUIET_RWX) +endif() + # Console sources. Both backends are always compiled; console.c selects one at # compile time and --gc-sections drops the unused one, which keeps every image # building in either configuration without per-target source juggling. @@ -30,9 +42,7 @@ target_link_options(boot_check.elf PRIVATE -T${FVP_DIR}/link.lds -nostartfiles -Wl,-Map=boot_check.map - # A bare-metal image has one flat DRAM region and no OS page permissions; - # access control belongs to the MPU, so the RWX-segment note is expected. - -Wl,--no-warn-rwx-segments + ${R52_LINK_QUIET_RWX} ) # AR1/M2 -- cooperative two-thread demo. Links ThreadX and exercises the @@ -56,7 +66,7 @@ target_link_options(demo_m2.elf PRIVATE -T${FVP_DIR}/link.lds -nostartfiles -Wl,-Map=demo_m2.map - -Wl,--no-warn-rwx-segments + ${R52_LINK_QUIET_RWX} ) # AR1/M3 -- periodic tick and preemptive scheduling. Adds GICv3, the generic @@ -87,7 +97,7 @@ target_link_options(demo_m3.elf PRIVATE -T${FVP_DIR}/link.lds -nostartfiles -Wl,-Map=demo_m3.map - -Wl,--no-warn-rwx-segments + ${R52_LINK_QUIET_RWX} ) # AR1/M4 -- the standard eight-thread ThreadX demo. demo_threadx.c is the @@ -118,7 +128,7 @@ target_link_options(demo_threadx.elf PRIVATE -T${FVP_DIR}/link.lds -nostartfiles -Wl,-Map=demo_threadx.map - -Wl,--no-warn-rwx-segments + ${R52_LINK_QUIET_RWX} ) # AR1/M5 -- lazy VFP context save and restore. Only meaningful when the @@ -149,7 +159,7 @@ if(TX_R52_ENABLE_VFP) -T${FVP_DIR}/link.lds -nostartfiles -Wl,-Map=demo_m5.map - -Wl,--no-warn-rwx-segments + ${R52_LINK_QUIET_RWX} ) endif() @@ -184,7 +194,7 @@ target_link_options(demo_mpu.elf PRIVATE -T${FVP_DIR}/link.lds -nostartfiles -Wl,-Map=demo_mpu.map - -Wl,--no-warn-rwx-segments + ${R52_LINK_QUIET_RWX} ) # Every image built here, in the order they should be exercised. diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/entry.S b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/entry.S index 0b89ee82c..01f171dcc 100644 --- a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/entry.S +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/entry.S @@ -41,7 +41,12 @@ #include "platform.h" - .arch armv8-r + /* No .arch directive here. GNU as accepts "armv8-r", LLVM's integrated + assembler accepts no spelling of it at all -- not armv8-r, not armv8r -- + and fails with "Unknown Arch". The architecture is already selected by + -mcpu=cortex-r52 on the command line, which both toolchains require and + both toolchain files pass, so the directive only restated it. */ + .syntax unified .arm diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/tx_initialize_low_level.S b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/tx_initialize_low_level.S index cb473a43e..c8d3f1883 100644 --- a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/tx_initialize_low_level.S +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/tx_initialize_low_level.S @@ -23,7 +23,12 @@ /**************************************************************************/ /**************************************************************************/ - .arch armv8-r + /* No .arch directive here. GNU as accepts "armv8-r", LLVM's integrated + assembler accepts no spelling of it at all -- not armv8-r, not armv8r -- + and fails with "Unknown Arch". The architecture is already selected by + -mcpu=cortex-r52 on the command line, which both toolchains require and + both toolchain files pass, so the directive only restated it. */ + .syntax unified .arm diff --git a/scripts/check_clang.sh b/scripts/check_clang.sh index c32d15892..c0cae4014 100755 --- a/scripts/check_clang.sh +++ b/scripts/check_clang.sh @@ -14,10 +14,11 @@ # SPDX-License-Identifier: MIT and CC0-1.0 ############################################################################## -# Builds the Arm ports with an LLVM based toolchain, in three stages: assemble +# Builds the Arm ports with an LLVM based toolchain, in four stages: assemble # every assembly source of every Arm gnu port, compile the common C sources for -# one core per architecture profile, then link the example builds that have a -# script driver. Only that last stage needs a target C library. +# one core per architecture profile, link the example builds that have a script +# driver, then link those driven by CMake. Only the two linking stages need a +# target C library. # # scripts/check_clang.sh # clang from PATH # scripts/check_clang.sh --clang /path/to/clang @@ -149,6 +150,11 @@ declare -A PORT_TARGET=( # accordingly, so cortex_r5 does not stand in for it. C_CORES="cortex_m0 cortex_m4 cortex_m23 cortex_m33 cortex_m55 cortex_a7 cortex_a53 cortex_r5 cortex_r52" +# Example builds driven by CMake rather than by a build_threadx.sh pair. These +# are covered by their own stage below, so the script-driven loop passes over +# them without reporting them as a gap. +CMAKE_EXAMPLE_CORES="cortex_r52" + # Example builds that are not expected to link, with the reason. Named by # their port directory, which covers both ports/ and ports_smp/. Listed # explicitly rather than silently skipped, so the gaps stay visible. @@ -249,10 +255,14 @@ if [ "$no_examples" -eq 0 ]; then # linux or mips32 as a gap here would be noise, not information. [ -n "${PORT_TARGET[$core]:-}" ] || continue + # Covered by the CMake stage below rather than here. + case " $CMAKE_EXAMPLE_CORES " in + *" $core "*) continue ;; + esac + # A driverless example is not covered by this stage, so say so rather # than dropping out in silence. A port that is simply absent from the - # count reads as covered: the CMake based example builds under - # ports/cortex_r52 looked like part of the 35 while never being built. + # count reads as covered. if [ ! -f "$dir/build_threadx.sh" ]; then example_nodriver="$example_nodriver $core" continue @@ -289,6 +299,66 @@ if [ "$no_examples" -eq 0 ]; then say " no script driver, so outside this stage:$example_nodriver" fi fi +# -------------------------------------------------------------------------- +# The Cortex-R52 examples are built by CMake, so they need a toolchain file +# rather than TOOLCHAIN=atfe. Same compiler, same linker, same purpose as the +# stage above: confirm the images still link when the toolchain is not GNU. +if [ "$no_examples" -eq 0 ]; then + say "" + say "== CMake example builds, linked with lld ==" + + if ! command -v cmake >/dev/null 2>&1 || ! command -v ninja >/dev/null 2>&1; then + say " skipped: cmake and ninja are both required" + else + for core in $CMAKE_EXAMPLE_CORES; do + build_dir="$(mktemp -d)" + # ATFE_TOOLCHAIN_PATH follows --clang, so the stage uses the same + # compiler as every other stage rather than whatever is on PATH. + if cmake -S . -B "$build_dir" -G Ninja \ + -DCMAKE_TOOLCHAIN_FILE="cmake/${core}_clang.cmake" \ + -DATFE_TOOLCHAIN_PATH="$(cd "$(dirname "$CC")" && pwd)" \ + -DTX_R52_BUILD_FVP_EXAMPLE=ON \ + -DTX_R52_ENABLE_MPU=ON >"$build_dir/configure.log" 2>&1; then + # Read the image list from the generated graph instead of + # repeating it here, so adding a target cannot silently escape + # this check. The images are EXCLUDE_FROM_ALL, so "ninja" alone + # would build none of them. + # + # The cmake_object_order_depends_target_* entries are CMake's + # own ordering phonies, one per real image and named after it. + # Counting those doubled the total and reported ten images built + # where there are five. + images="$(ninja -C "$build_dir" -t targets all 2>/dev/null \ + | grep -oE '^[A-Za-z0-9_]+\.elf' \ + | grep -v '^cmake_' | sort -u)" + if [ -z "$images" ]; then + fail "$core: no .elf targets found in the CMake graph" + failures=$((failures + 1)) + else + built=0; total=0 + for image in $images; do + total=$((total + 1)) + if ninja -C "$build_dir" "$image" \ + >"$build_dir/$image.log" 2>&1; then + built=$((built + 1)) + else + fail "$core: $image did not build" + tail -6 "$build_dir/$image.log" | sed 's/^/ /' + failures=$((failures + 1)) + fi + done + say " $core: $built of $total images linked" + fi + else + fail "$core: CMake configure failed" + tail -6 "$build_dir/configure.log" | sed 's/^/ /' + failures=$((failures + 1)) + fi + rm -rf "$build_dir" + done + fi +fi + # -------------------------------------------------------------------------- say "" if [ "$failures" -eq 0 ]; then From 990d51b65d7559e6d82329b0479a5219a8c4f091 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Wed, 12 Aug 2026 10:25:35 -0400 Subject: [PATCH 033/181] Brought up ThreadX on S32Z280 silicon and fixed the MPU encoding it exposed (#606) * Added an S32Z280-594EVB example build for the Cortex-R52 port First silicon bring-up for the Cortex-R52 port: an image that boots RTU0 core 0 on the NXP S32Z280-594EVB, drops from EL2 to EL1 and reports what the core says about itself. Gated behind TX_R52_BUILD_S32Z280_EXAMPLE, separate from the FVP example option so that FVP regression is unaffected by bring-up work and the two boards' differing reset states cannot interact. Verified on the board. The image runs from reset and reaches its completion breakpoint, and the two CPSR values are the point of the exercise: mode 0x1A (Hyp) at EL2 then 0x13 (Supervisor) at EL1, i.e. the EL2 to EL1 drop performed by this code on silicon rather than on a model. MIDR 0x411FD133 Cortex-R52 r1p3, part 0xD13 MPUIR 0x00001400 20 MPU regions at EL1 HMPUIR 0x00000014 EL2 CTR 0x8144C004 MPIDR 0x80000000 ID_PFR0 0x00000131 ID_PFR1 0x10111001 virtualisation field 1: EL2 implemented SCTLR 0x70C50838 MPU, D-cache and I-cache all off at reset CNTFRQ 0x00000000 The FVP reports MIDR 0x410FD0F0, part 0xD0F, which is an architecture envelope model and not a Cortex-R52 -- so these are the first implementation-specific numbers the port has had. Three silicon facts the code exists to encode, each of which presents as working hardware that quietly does the wrong thing: - The core resets in THUMB state. CPSR reads 0x1FA out of reset because the boot instruction NXP plants at the boot address is a T32 branch, so _start is T32 and switches to A32 itself. An A32 entry would execute the first halfword of its own instruction as Thumb. - The debugger holds every core in debug state. NXP's _reset_to_first_instruction() asserts MDM_AP CONTROL2[19:16] = CR52_RTU0_{3,2,1,0}_EDBGREQ and never clears them, though its own comment says start_debug_by_core_name() does. While asserted the core executes nothing, yet registers and memory still respond and MC_ME/RGM report the core released and clocked. tools/read_identity.gdb clears core 0's bit and verifies the clear took. - CNTFRQ reads zero, exactly as on the FVP, and is writable only at the highest implemented exception level. entry.S records it rather than writing a value, because the correct frequency for this board is not yet established and a wrong one would silently mis-scale every derived interval. Timer work must program it first. Memory map: .text is linked and loaded at 0x79900000, the instruction-fetch window and the reset address (MC_ME_PRTN0_CORE0_ADDR reads exactly that). It is writable over the debug AXI port despite NXP's map declaring it read-only, so no load-address alias is needed for a debugger-loaded image; a flash-booted one would use the data alias at 0x32100000, which is the same physical SRAM as confirmed by a sentinel write. Data, bss and the per-mode stacks go to RTU-local data SRAM at 0x31780000. The TCMs are absent on purpose: they are inaccessible at reset until their region registers are programmed, so nothing needed for early boot can live there. Reporting is built so that a failure cannot read as a success: boot_stage distinguishes a fault from a hang and fault handlers record vector, syndrome and address before parking; r52_identity.magic is written last so a half-filled structure is detectable; and bsp_done() is a deliberate breakpoint target so completion is observed rather than inferred from a timeout. The image does not link ThreadX, so a failure here is unambiguously a boot or board problem rather than a kernel one -- the same reasoning as the FVP's boot_check.elf. Not included: console, timer, GIC, MPU programming. LIN9 reaches the host through the daughtercard USB-UART, which is LINFlex_9 at 0x42980000 and not LINFlex_0; what is missing is the clock configuration needed to compute a baud rate, and a console at the wrong rate produces garbage indistinguishable from a crash. Hence reporting through memory for now. FVP example builds and passes 6/6 unchanged. Assisted-by: Claude Code (Opus 5) * Added a LINFlexD console to the S32Z280-594EVB example Polled transmit console on LINFlex_9, which is the instance wired to the daughtercard USB-UART through jumper J248. Not LINFlex_0: that is merely the first instance in the Reference Manual's list and reaches no connector on this board. bsp_boot.c now prints the identity registers as well as recording them in memory; the memory copy stays, because it is what proved the boot path before a console existed and it still works if the console is misconfigured. The baud rate was derived rather than assumed, which mattered because a console at the wrong rate produces garbage indistinguishable from a crash: - LINFlex_9 is clocked by P5_LIN_BAUD_CLK, driven by MC_CGM_5 MUX 2. - Read from the board: MUX_2_CSS selects source 2, MUX_2_DC_0 divides by 1. - The EVB carries a 40 MHz crystal (UG10268 section 3.3.1.1), so 40 MHz. - LFDIV = 40000000 / (16 * 115200) = 21.7014, giving LINIBRR 21 and LINFBRR 11, for an actual 115274 baud -- 0.06% error. Those are exactly the values the BootROM had already left in the registers, which is the corroboration for the 40 MHz figure rather than merely a plausible-looking calculation. They are programmed here anyway instead of inherited, for two reasons. Inheriting register state makes this image's behaviour depend on how the board was last booted. And the BootROM's own configuration is wrong for a console: it leaves PCE set and TxEn clear, because it is listening for a serial-boot download rather than printing, so a host terminal on 8N1 would see framing errors. Verified on the board: the image reaches its completion breakpoint with the console calls in the path, so every byte was accepted and UARTSR.DTF was set for each -- the transmitter is configured, enabled and clocked. That does not by itself prove the rate, since DTF sets at any baud; the rate rests on the arithmetic above and the BootROM's independently matching divisors. Observing the text needs the daughtercard USB-UART connected to a host terminal at 115200 8N1. Register offsets and bit positions are from Reference Manual section 75.5.1 and the UARTCR/UARTSR diagrams. PCE at bit 2 and TxEn at bit 4 are called out in the source because they are easy to transpose and the failure is silent. Assisted-by: Claude Code (Opus 5) * Fixed two silent failures in the S32Z280 LINFlexD console The console transmitted from the first attempt, but what arrived on the wire was wrong in two independent ways, neither of which the target could detect. Both are now fixed and the output is byte-for-byte correct, captured from the USB-UART rather than read off a terminal. 1. UARTCR was written outside initialisation mode. Setting LINCR1.INIT does not put the module in initialisation mode in the same cycle, and most of UARTCR is writable only there. Configuring immediately after the LINCR1 write half-worked: bits being *set* took effect while bits being *cleared* did not. TxEn came on, but PCE stayed on, so the line ran 8E1 against a host expecting 8N1. That corrupts only those characters whose parity bit happens to be 0 and leaves the rest readable, which looks like a marginal baud rate rather than a framing error -- and would have sent the next hour into the clock tree. linflexd_init() now polls LINSR[LINS] until the module reports initialisation mode, reads UARTCR back afterwards, and returns a status mask. bsp_boot.c records it and prints it as CONSOLE; 0 means both the mode entry and every field write were confirmed rather than assumed. 2. DTF was cleared after the byte rather than waited on. DTF is write-one-to-clear and does not de-assert in the same cycle as the clearing write, so the next byte's poll could observe the previous byte's flag, conclude the line was free while it was still busy, and have its own write silently discarded. That cost exactly one character after every "\r\n" pair -- the only place two bytes go out back to back -- so the first letter of every line went missing: MIDR read as IDR, SCTLR as CTLR. The transmit sequence is now write, wait for DTF, clear DTF, then wait for the clear to take effect, with the same bounded guard as the init loop so a stuck flag degrades to slow output rather than a hung boot. Clearing before the write was tried and is worse, not better: the write then lands while the previous byte is still shifting and is dropped, and the poll afterwards sees the previous byte's completion, so most of the output disappears. That failure is what established that the transmitter discards writes while busy, which is the fact both bugs turn on. The source says so, because the ordering looks arbitrary otherwise. Verified end to end on the board, with the USB-UART passed through to WSL2 so the received bytes could be compared against what the code intended to send: === ThreadX Cortex-R52 :: NXP S32Z280-594EVB === MIDR = 0x411FD133 MPUIR = 0x00001400 HMPUIR = 0x00000014 CTR = 0x8144C004 MPIDR = 0x80000000 ID_PFR0 = 0x00000131 ID_PFR1 = 0x10111001 SCTLR = 0x70C50838 CNTFRQ = 0x00000000 CPSR@EL2 = 0x000001DA CPSR@EL1 = 0x600001D3 EL1 MPU regions: 00000014 CONSOLE = 0x00000000 === boot complete === Reaching the completion breakpoint proved only that the transmitter ran; it could not have caught either fault. Comparing bytes is what did. Assisted-by: Claude Code (Opus 5) * Added generic timer support to the S32Z280-594EVB example The Arm generic timer now runs on silicon: CNTFRQ is programmed at EL2 and a one-shot compare fires when it should. CNTFRQ programmed = 0x007A1200 (8000000) elapsed counts = 8000043 (requested 8000000, +0.001%) host interval = 1.0033 s Both halves matter. The elapsed count shows the counter and the compare agree with each other; the host interval shows the rate is actually 8 MHz rather than merely self-consistent, which a wrong CNTFRQ would also produce. The residual 43 counts is about 5 us of polling overhead. CNTFRQ reads zero out of reset here, exactly as on the Armv8-R AEM FVP -- so that FVP behaviour is real silicon behaviour, not a model artefact, and the port readme's warning to re-verify it was well placed. The parallel stops there: the FVP also leaves the system counter itself stopped and its BSP must start it, whereas on this board the BootROM has the counter running and only the software-declared constant was missing. CNTFRQ is writable only at the highest implemented exception level, so entry.S programs it before the drop to EL1. 8 MHz was established three independent ways rather than assumed: - Measured: CNTPCT sampled against host wall-clock time over a 32-second interval gave 8.0227 MHz. - Derived: RTU.GPR CFG_CNTDV reads 4, so the divider is (4+1) = 5, and the board's FXOSC is 40 MHz -- itself already corroborated by the LINFlexD baud divisors the BootROM left behind. 40 / 5 = 8. - Confirmed: the one-shot compare above. The compare is polled with the interrupt masked, deliberately. There is no GIC configured yet, and proving the timer counts and fires first means a later interrupt failure cannot be confused with the timer itself being wrong -- the same staging that made the console tractable. Also recorded, from a detour that cost a run: RTU0.GPR CFG_CNTDV at 0x76120010 is readable by the debugger, which returns 4, but a load from the core at EL1 kills the image. No fault handler runs, boot_stage stays at 4, and the debug connection drops -- the signature of a stalled bus access rather than an abort, and a failure mode that leaves nothing on-target to inspect. The debugger reaches that window over the AXI-AP, which does not go through whatever gates the core's own access to RTU peripheral space. The image no longer touches it; the value lives in platform.h instead. This is the second address on this part that is debugger-visible but not core-reachable, so peripheral windows are now worth probing from the core before relying on them. Assisted-by: Claude Code (Opus 5) * Enabled the R52 peripheral port and located the GIC on S32Z280 Two peripheral windows on this part stalled the core outright when read: no abort, no fault handler, boot_stage frozen at its last value, and the debug connection dropping with it. A stall gives you nothing on-target to inspect, so both were found by printing a marker before each access and seeing which marker came last. The Cortex-R52 TRM r1p3 (100026_0103_00_en) explains both; NXP's reference manual mentions neither. 1. The low-latency peripheral port is disabled at reset. IMP_PERIPHPREGIONR (TRM 3.3.80) describes a region at 0x76000000 of 4 MB on this part -- the RTU peripheral space -- with separate enables for EL2 and EL1/0. Read from the board it was 0x76000034: base 0x76000000, size 0b01101 = 4 MB, and both enable bits clear. The TRM is explicit that each "resets to 0". Until they are set, every access in that window stalls. entry.S now sets both at EL2, which is also where it has to happen: EL1 writes to this register trap to EL2 when HACTLR.PERIPHPREGIONR is clear. PERIPHPRG now reads 0x76000037 and the core reads RTU0.GPR CFG_CNTDV = 4 for itself -- the same value the debugger saw, which independently confirms the divider behind the 8 MHz counter rate from the core's own view rather than the debug path's. 2. The GIC is where NXP says, and needs an MPU mapping to reach. IMP_CBAR (TRM 3.3.17) holds the physical base of the memory-mapped GIC distributor in bits [31:21], its reset value wired from CFGPERIPHBASE. Read from the board it is 0x47800000, confirming NXP's memory map from the hardware rather than from a vendor debugger script -- the reference manual contains no GIC base address anywhere. NXP's cryptic note that the "R52 Cluster set addr [31:21]" is just CFGPERIPHBASE[31:21] restated. TRM Table 9-1 gives the frame layout relative to that base: distributor at +0x000000, redistributor control at +0x100000, redistributor SGI/PPI at +0x110000, then +0x20000 per further core. That matches what the FVP example's driver already assumes, so it should port with address changes. The distributor still stalls, and the TRM says why: "Ensure that the memory region used for the GIC Distributor is configured as Device nGnRnE." The MPU is disabled here -- SCTLR.M reads 0 -- so nothing maps that region. Enabling the peripheral port does not help, the GIC being outside that window and reached over AXIM. Reading it waits on MPU programming, which is the next piece of work; the probe is removed rather than left in, since while present it stalled every run and cost the console and timer results that precede it. gic_probe.c holds the two system-register reads. They cannot hang the bus, unlike the memory accesses they diagnose, which is the point of them. Assisted-by: Claude Code (Opus 5) * Reached the GIC on S32Z280 by mapping it Device nGnRnE The GIC distributor and redistributor now respond on silicon: MPU rgns = 0x00000003 SCTLR = 0x70C50839 (M set; caches still off) GICD_PIDR2 = 0x0000003B architecture revision 3 = GICv3 GICD_TYPER = 0x0248001E GICR_PIDR2 = 0x0000003B redistributor at base + 0x100000 Three independent sources had to agree to get here, and NXP's reference manual supplied none of them. IMP_CBAR reports the distributor base from the hardware (0x47800000). Cortex-R52 TRM Table 9-1 gives the frame layout: distributor at +0x000000, redistributor control at +0x100000, SGI/PPI at +0x110000, then +0x20000 per further core -- the layout the FVP example's gicv3.c already assumes. And the TRM requires the region be Device nGnRnE, which was confirmed rather than taken on faith: mapped Normal write-back the distributor stalls the core outright, mapped Device it reads 0x3B. mpu.c is ported from the FVP example, keeping its PRBAR/PRLAR encoding and the reversed-AP-bit-order finding, with an S32Z280 region table. Caches are left off: the point of this pass was reaching the GIC, and the debugger writes this image straight into SRAM behind the caches, so enabling C and I deserves its own step and its own check. Diagnosis needed two new pieces of machinery, both kept: - Memory-resident progress markers (probe_stage), mirroring the console markers. Enabling the MPU can take the core down in a way that records no fault AND takes the console with it, so boot_stage alone could not say how far a risky sequence got. With markers inside mpu_init the failure went from "somewhere in the MPU code" to "the SCTLR.M write itself" in one run. - Resolving symbol addresses from the current ELF with nm on every post-mortem. Adding probe_stage to the .data block shifted fault_vector, so reusing addresses across builds reads the wrong words -- which nearly produced a conclusion from a stale read. OPEN QUESTION, recorded in mpu.c rather than papered over. A five-region map that adds a second Device window for the RTU peripheral space (0x76000000, 4 MB) makes the SCTLR.M write kill the core: all regions program without error, probe_stage reaches 0x42, and the marker one instruction later never lands. No exception is taken, so it stalls rather than aborts. Coverage is not the explanation -- that map spanned the whole address space, and an earlier comment of mine claiming otherwise was wrong and has been corrected. The cause is not known. Consequence: RTU peripheral access after the MPU is enabled is untested; the CFG_CNTDV read this image does happens before the enable. Also not tightened yet: code is writable and data executable in this map. Wrong for a protection demo, right for bring-up where an unmapped address costs a silent stall rather than a fault. Narrowing it belongs with the ThreadX integration, which can verify it. Assisted-by: Claude Code (Opus 5) * Fixed an out-of-bounds MPU table write that made enabling the MPU stall the core The five-region map now programs correctly and the MPU enables with the GIC reachable: R idx PRBAR PRLAR R 0 00000000 477FFFC1 R 1 47800002 479FFFC3 GIC, XN, Device nGnRnE R 2 47A00000 75FFFFC1 R 3 76000002 763FFFC3 RTU peripherals, XN, Device nGnRnE R 4 76400000 FFFFFFC1 MPU rgns = 5, SCTLR = 0x70C50839 (M set) GICD_PIDR2 = 0x3B, GICD_TYPER = 0x0248001E, GICR_PIDR2 = 0x3B The bug was mine and it was simple: mpu_regions[] is declared with a fixed size, and the FVP example this file came from sized it [3] to match the three regions it programs. A five-region table wrote mpu_regions[3] and [4] past the end of the array. What made it hard to see is what the corruption produced. Every region appeared to program without error, and the failure was a stall on the SCTLR.M write -- no abort, no fault handler, no exception, and the debug connection dropping. Reading the regions back out of the hardware, with the MPU deliberately left disabled so the readback could not itself stall, showed region 3 with base 0x00000000 instead of 0x76000000. With its correct limit that region spanned 0x00000000-0x763FFFFF and overlapped regions 0 to 2, and PMSAv8-R leaves overlapping regions UNPREDICTABLE -- so stalling was permitted behaviour rather than a hardware fault. One bug accounts for every observation: three regions worked, five failed, and it failed identically whether the extra window was Device or Normal, because the memory type was never involved. Fixes: the table capacity is now named (MPU_TABLE_REGIONS) and sized 16, and mpu_init checks mpu_regions_used against it as well as against MPUIR. The existing check only compared against the hardware's region count, which said 20 and told us nothing about the array. Two earlier claims of mine, corrected here rather than left standing. A comment asserting "narrow coverage was the problem" was wrong: the failing map covered the whole address space. And this is NOT a defect inherited from the FVP example -- that code declares [3] and uses three regions, entirely self-consistent. Worth offering upstream only as hardening: the bare [3] with no bound check is what let a growing map overrun it silently. The region readback is kept in the image. It costs eight lines a boot and verifies the map against the hardware every time, which is precisely what turned an unexplained stall into a one-line diagnosis. Assisted-by: Claude Code (Opus 5) * Enabled interrupt-driven ticks by clearing SCTLR.TE Timer interrupts are delivered, acknowledged and re-armed on silicon: SCTLR = 0x30C50838 -> 0x30C50839 (TE cleared, M set) IRQ count = 7 timer INTID = 30 measured, not assumed spurious = 0 unexpected = 0 SCTLR.TE -- Thumb Exception enable -- RESETS SET on this part. Every vector table in entry.S is A32, so the core entered each exception in T32 state, decoded an A32 branch as Thumb, landed mid-instruction at a misaligned address and took an undefined-instruction exception, which repeated the same way. No handler ever ran. entry.S now clears it at EL1 and clears HSCTLR.TE at EL2. The consequence was worse than a crash: it made every fault invisible. boot_stage stayed at its last value, fault_vector stayed zero, and the core sat at el1_vectors+4. A data abort from an unmapped peripheral, an abort from an overlapping MPU region, and a correctly delivered timer interrupt all presented identically -- an unexplained hang with nothing recorded. What gave it away was reading the banked registers: LR_irq and SPSR_irq showed an IRQ had been taken from SVC with interrupts enabled, CPSR showed UND mode with T set, and LR_und pointed at a misaligned address inside the A32 vector table. The Armv8-R AEM FVP resets with TE clear, which is why the same vector tables work there and why nothing in the FVP work anticipated this. This commit also corrects earlier comments of mine. Several places described these failures as "a stalled bus access rather than an abort", with the absence of a recorded fault as the evidence. That was wrong: they were ordinary exceptions whose handlers were unreachable. The two underlying bugs -- the peripheral port disabled at reset, and the out-of-bounds MPU table write -- were real and are correctly fixed, but the explanation for why they presented so mutely was not. Fixed in platform.h, mpu.c and bsp_boot.c. Interrupt plumbing: gicv3.c is ported from the FVP example with the frame bases in platform.h, derived from IMP_CBAR and TRM Table 9-1. el1_irq_entry in entry.S uses the classic A32 form rather than ThreadX's context save/restore, since this image does not link the kernel. irq_dispatch.c counts ticks instead of calling _tx_timer_interrupt, and keeps separate spurious and unexpected-INTID counters so that "no interrupt arrived" and "an interrupt arrived and was mishandled" cannot be confused. timer_start_oneshot_irq arms with IMASK clear; the polled timer_start_oneshot keeps IMASK set, and the two are separate functions because either mistake is silent. Assisted-by: Claude Code (Opus 5) * Ran ThreadX on S32Z280 silicon with threads, tick and preemption The kernel runs on the board: === ThreadX Cortex-R52 :: S32Z280-594EVB === console = 0x00000000 entering kernel === ThreadX on S32Z280: results === ticks = 0x00000064 100 ticks sleeper = 0x00000014 20 wakeups spinner = 0x00159B48 1415496 iterations preempt = 0x00000014 20 preemptions PASS threads, tick and preemption all verified The figures are internally consistent, which is what makes them evidence rather than encouragement: 100 ticks elapsed for a 100-tick sleep, so the tick rate is exactly as configured; 20 sleeper wakeups is precisely 100/5 for a 5-tick sleep; and 20 preemptions means every wakeup took the core from a runnable lower-priority thread rather than receiving it by cooperative handoff. This validates the context-switch assembly merged in #579 on real Cortex-R52 silicon. Until now it had only run against the Armv8-R AEM FVP, which reports MIDR part 0xD0F -- an architecture envelope model, not an R52 implementation. The demo judges four things separately because on first silicon they fail independently: that time advanced (the GIC delivers the timer PPI and _tx_timer_interrupt is reached), that tx_thread_sleep returned (tick-driven scheduling, not merely the interrupt), that the lowest-priority thread ran (the sleeper actually yielded), and that the sleeper resumed while the spinner was runnable (preemption). A demo that only counted whether both threads ran would pass with a broken tick if they happened to yield to each other. Integration pieces, all from the FVP example with the board's differences: - tx_initialize_low_level.S publishes the system stack and the first free address, then calls board_init(). Shorter than the A-profile reference ports because entry.S has already given every mode its own stack from dedicated linker regions. - entry.S routes the IRQ vector through _tx_thread_context_save and _tx_thread_context_restore under TX_R52_USE_THREADX_IRQ, keeping the standalone A32 handler for s32z280_boot.elf, which does not link the kernel so that a boot failure there stays unambiguous. - board_init() runs mpu_init() FIRST. The GIC distributor is unreachable until its region is mapped Device nGnRnE, so any GIC access before the MPU is enabled aborts. - link.lds provides _end as well as end; _tx_initialize_low_level publishes unused memory from _end. - bsp_done() is defined in the demo rather than shared from bsp_boot.c, whose bsp_main would collide with the demo's. s32z280_boot.elf still builds and the FVP example still passes 6/6. Assisted-by: Claude Code (Opus 5) * Tightened the S32Z280 MPU map and verified protection is enforced The map now carries real permissions -- code read-only and executable, data writable and never executable, peripherals Device nGnRnE and never executable, everything else unmapped -- and the enforcement is demonstrated rather than asserted: X1 write to read-only code region faults = 0x00000001 fault DFSR = 0x00000A0C bit 11 (WnR) set: a write fault fault addr = 0x79900000 the address written X2 PASS write to code faulted and was recovered Exactly one fault, identified as a write, at the precise address, followed by successful resumption. ThreadX still passes on the same map: ticks 100, sleeper 20, spinner ~1e6, preempt 20, and IRQ count keeps advancing during the protection test. Reading SCTLR back or listing the programmed regions would only show what was configured. Provoking the violation shows it is enforced, which is the claim that matters for a protection story. entry.S gains a recoverable data-abort path, gated on a fault_expected flag the test arms. It records DFSR and DFAR, counts the fault, and resumes at the instruction after the faulting access -- lr on data-abort entry is the faulting address plus 8, so subs pc, lr, #4 skips the access instead of retrying it forever. Unarmed, a data abort stays fatal and reported, which is what a real bug should get. This supersedes the permissive bring-up map, and the reason that map existed is worth recording: a narrow map had failed earlier and the cause was unknown, so coverage was blamed. Coverage was never the problem. An out-of-bounds write to a [3]-sized region table put a region at base 0 overlapping everything, and SCTLR.TE being set meant the resulting abort could not reach a handler. With both fixed a narrow map works first time, and -- more usefully -- a mistake in it now reports vector, syndrome and faulting address instead of hanging mutely. Until TE was cleared no fault handler on this board could run, so no protection claim about it could be tested at all. This is the first one that could. Assisted-by: Claude Code (Opus 5) * Enabled the S32Z280 caches, with an honest effectiveness result Both caches are on and verified from SCTLR: CLIDR = 0x09200003 SCTLR = 0x30C50839 -> 0x30C5183D (C and I set) cachesOn = 1 counts off = 0x00094DF4 counts on = 0x00094CC8 gain/1000 = 0 C3 PASS caches enabled (SCTLR.C and SCTLR.I set) C4 no significant speedup -- expected here, the workload is already in fast local SRAM cache.c supplies what the FVP example explicitly deferred to silicon: a data-cache set/way sweep that reads CLIDR and CCSIDR and walks every set and way the hardware reports, rather than assuming a geometry. The FVP file notes that this "belongs with the silicon bring-up where it can be verified against the real cache geometry"; this is that. The sweep matters because caches are not architecturally guaranteed invalid out of reset, and enabling a write-back data cache holding stale valid lines would evict them over live memory. The effectiveness result is reported separately from the enable, and that separation was earned. The first version of this test passed on warm < cold and printed "caches on and the workload got faster" for 609904 counts against 609686 -- a 0.036% difference that is measurement noise. That criterion was worthless and the PASS was misleading. It now reports the gain as a fraction and only claims a speedup above 10%. No speedup here is a plausible result rather than a defect: both the code and the data this workload touches live in RTU-local low-latency SRAM, close to core speed already. There is no slow memory on this board to demonstrate a cache against -- DDR would be the place, and DDR is not initialised. So the honest claim is "enabled and harmless", not "enabled and beneficial". cache_clean_all() is called before parking, and this is not optional. With a write-back data cache, values this image writes can sit dirty in cache where a debugger reading SRAM cannot see them -- and the memory-resident progress markers and fault records this bring-up depends on are read exactly that way. Without the clean, a post-mortem read could report stale values and look like a fault that never happened. ThreadX still passes on the same configuration and the protection test still faults correctly: write to the read-only code region takes exactly one write fault at the written address and recovers. Assisted-by: Claude Code (Opus 5) * Made the cache benchmark actually measure the cache The caches now show a real effect instead of noise: D line = 64 bytes D ways = 4 D sets = 64 D bytes = 0x4000 16 KB L1 data cache, read from CCSIDR bench wds = 0x800 8 KB working set, half the cache counts off = 0x000D1B87 858503 counts on = 0x0009F515 652053 gain/1000 = 0xF0 24% faster C4 PASS caches measurably faster (>=10%) The previous benchmark could not have measured anything, and its 0.036% "speedup" was noise. Two things were wrong with it. It used a static buffer in the RTU-local fast-data bank. That memory is close to core speed already, so caching it saves almost nothing -- there is no latency to hide. The benchmark now runs over the extended SRAM at S32Z_EXT_SRAM_BASE, which the Reference Manual describes as NOT RTU-local, and mpu.c gains a sixth region to map it Normal write-back and never executable. And its working set was a guessed 4 KB constant. It is now sized at run time from CCSIDR to half the reported data cache, so it fits and is revisited every pass. A set larger than the cache would stream through and evict, showing little benefit even over slow memory -- a guess could have produced a null result for a reason that has nothing to do with whether the cache works. 24% on this loop is a believable figure rather than a suspiciously large one: the workload is a store-heavy read-modify-write over a write-back cache, so part of the cost is write traffic that still has to reach SRAM. Useful by-product: the L1 data cache geometry is now read and printed rather than assumed. Nothing in the SoC reference manual gives it, and the set/way invalidate sweep in cache.c depends on it being right. ThreadX still passes and the protection test still faults correctly. Assisted-by: Claude Code (Opus 5) * Fixed the PRBAR field encoding and proved execute-never enforcement program_region() shifted every PRBAR field one bit too far left: SH<<4, AP<<2 and XN<<1, where the Cortex-R52 TRM (r1p3 figure 3-39, table 3-80) places BASE[31:6], RES0[5], SH[4:3], AP[2:1] and XN[0]. The intended XN therefore landed in AP[1] -- the EL0-access bit -- and no region was ever execute-never. On this board the core ran instructions straight out of .data with LR_abt at 0x3178000c to prove it. The write-to-read-only test passed throughout, which is why this survived: under the old shift the AP value's low bit happened to land in the real AP[2], the read-only bit, so permissions came out right by accident while XN was silently discarded. Only an instruction fetch from a region marked non-executable could distinguish the two. The AP macros in mpu.h go back to the architectural encoding, AP[2] for read-only and AP[1] for EL0 access. No calibration is needed; the values were correct as published all along. Verified on S32Z280 silicon: the data region now reads back PRBAR 0x31780001 with XN set, a write to the read-only code region faults with DFSR 0xA0C, execution from the data region takes a prefetch abort with IFSR 0x20C at 0x31780000, both faults recover, and the ThreadX demo still reports 100 ticks with 20 preemptions. Assisted-by: Claude Code (Opus 5) * Corrected the same PRBAR encoding bug in the FVP MPU example The FVP example carries the identical off-by-one shift that the S32Z280 bring-up exposed, so no region there was execute-never either: the data region and the whole peripheral region were both freely executable, and each also gained unintended EL0 access from the misplaced XN bit. This also retires the "PRBAR.AP bit order is reversed" claim in mpu.h. That note rested on a real measurement -- four regions, one per AP encoding, privileged write attempted on each, writes faulting for 0b01 and 0b11 -- but the cause was the shift, not the bit order. With AP written into bits[3:2], its low bit lands in the real AP[2], the read-only bit, so writes fault exactly when that bit is set. The "high bit grants EL0 access" half of the conclusion was never tested; under the old shift that bit landed in SH[0], programming a shareability the TRM calls UNPREDICTABLE. The architectural encoding needs no calibration. demo_mpu.c gains the check that would have caught this: an instruction fetch from the execute-never data region must take a prefetch abort. Recovering from one cannot work the way the data-abort path does, since skipping the faulting instruction is impossible when the instruction is what could not be fetched, so entry.S gains a recoverable prefetch-abort path that returns to a landing point recorded by mpu_try_execute. Verified both ways. All five FVP images pass, and the new check reports prefetch aborts 0 -> 1. Restoring the old shift for one run makes it fail with 0 -> 0, so the check is not vacuous. Assisted-by: Claude Code (Opus 5) * Removed the unassemblable .arch directive from the S32Z280 example GNU as accepts ".arch armv8-r"; LLVM's integrated assembler accepts no spelling of it -- not armv8-r, not armv8r, not armv8-r+crc -- and stops with "Unknown Arch: armv8-r". There is nothing to substitute, so the directive goes. The architecture comes from -mcpu=cortex-r52 on the command line, which every toolchain file passes, so it only restated it. entry.S in this example never had one. The two equivalents in the FVP example are handled separately, in the change that brings those images under the LLVM check. Verified: both S32Z280 assembly sources now assemble with Arm Toolchain for Embedded 22.1.0, and the GNU build of s32z280_boot.elf and s32z280_demo.elf is unchanged with no warnings. Assisted-by: Claude Code (Opus 5) * Stopped read_identity.gdb reporting failure after a successful demo run The script reads r52_identity, which only the boot image defines. The kernel demo shares the same bsp_done breakpoint and the same boot_stage marker, so it is convenient to point the same script at either image -- but against the demo the lookup raised and gdb exited 1, after the demo had already printed "PASS threads, tick and preemption all verified" over the console. A tool that reports failure on success is worse than one that prints nothing. The lookup is now guarded, and says which image it is looking at rather than falling over. Everything after it is skipped when the structure is absent. Verified against both images on S32Z280 silicon: the demo exits 0 and reports its own PASS, and the boot image still prints the full identity report with MIDR 0x411FD133 and C3, C4, X2 and X4 all passing. Assisted-by: Claude Code (Opus 5) --- ports/cortex_r52/gnu/CMakeLists.txt | 9 + .../example_build/fvp_baser_aemv8r/demo_mpu.c | 39 + .../example_build/fvp_baser_aemv8r/entry.S | 68 +- .../gnu/example_build/fvp_baser_aemv8r/mpu.c | 9 +- .../gnu/example_build/fvp_baser_aemv8r/mpu.h | 36 +- .../example_build/s32z280_evb/CMakeLists.txt | 81 +++ .../gnu/example_build/s32z280_evb/board.h | 105 +++ .../gnu/example_build/s32z280_evb/bsp_boot.c | 651 +++++++++++++++++ .../gnu/example_build/s32z280_evb/cache.c | 320 +++++++++ .../gnu/example_build/s32z280_evb/cache.h | 64 ++ .../example_build/s32z280_evb/demo_s32z280.c | 230 ++++++ .../gnu/example_build/s32z280_evb/entry.S | 664 ++++++++++++++++++ .../gnu/example_build/s32z280_evb/gic_probe.c | 72 ++ .../gnu/example_build/s32z280_evb/gic_probe.h | 44 ++ .../gnu/example_build/s32z280_evb/gicv3.c | 215 ++++++ .../gnu/example_build/s32z280_evb/gicv3.h | 61 ++ .../example_build/s32z280_evb/irq_dispatch.c | 145 ++++ .../gnu/example_build/s32z280_evb/linflexd.c | 242 +++++++ .../gnu/example_build/s32z280_evb/linflexd.h | 61 ++ .../gnu/example_build/s32z280_evb/link.lds | 153 ++++ .../gnu/example_build/s32z280_evb/mpu.c | 486 +++++++++++++ .../gnu/example_build/s32z280_evb/mpu.h | 118 ++++ .../gnu/example_build/s32z280_evb/platform.h | 158 +++++ .../s32z280_evb/readme_s32z280.txt | 125 ++++ .../gnu/example_build/s32z280_evb/timer.c | 148 ++++ .../gnu/example_build/s32z280_evb/timer.h | 64 ++ .../s32z280_evb/tools/read_identity.gdb | 160 +++++ .../s32z280_evb/tx_initialize_low_level.S | 110 +++ 28 files changed, 4618 insertions(+), 20 deletions(-) create mode 100644 ports/cortex_r52/gnu/example_build/s32z280_evb/CMakeLists.txt create mode 100644 ports/cortex_r52/gnu/example_build/s32z280_evb/board.h create mode 100644 ports/cortex_r52/gnu/example_build/s32z280_evb/bsp_boot.c create mode 100644 ports/cortex_r52/gnu/example_build/s32z280_evb/cache.c create mode 100644 ports/cortex_r52/gnu/example_build/s32z280_evb/cache.h create mode 100644 ports/cortex_r52/gnu/example_build/s32z280_evb/demo_s32z280.c create mode 100644 ports/cortex_r52/gnu/example_build/s32z280_evb/entry.S create mode 100644 ports/cortex_r52/gnu/example_build/s32z280_evb/gic_probe.c create mode 100644 ports/cortex_r52/gnu/example_build/s32z280_evb/gic_probe.h create mode 100644 ports/cortex_r52/gnu/example_build/s32z280_evb/gicv3.c create mode 100644 ports/cortex_r52/gnu/example_build/s32z280_evb/gicv3.h create mode 100644 ports/cortex_r52/gnu/example_build/s32z280_evb/irq_dispatch.c create mode 100644 ports/cortex_r52/gnu/example_build/s32z280_evb/linflexd.c create mode 100644 ports/cortex_r52/gnu/example_build/s32z280_evb/linflexd.h create mode 100644 ports/cortex_r52/gnu/example_build/s32z280_evb/link.lds create mode 100644 ports/cortex_r52/gnu/example_build/s32z280_evb/mpu.c create mode 100644 ports/cortex_r52/gnu/example_build/s32z280_evb/mpu.h create mode 100644 ports/cortex_r52/gnu/example_build/s32z280_evb/platform.h create mode 100644 ports/cortex_r52/gnu/example_build/s32z280_evb/readme_s32z280.txt create mode 100644 ports/cortex_r52/gnu/example_build/s32z280_evb/timer.c create mode 100644 ports/cortex_r52/gnu/example_build/s32z280_evb/timer.h create mode 100644 ports/cortex_r52/gnu/example_build/s32z280_evb/tools/read_identity.gdb create mode 100644 ports/cortex_r52/gnu/example_build/s32z280_evb/tx_initialize_low_level.S diff --git a/ports/cortex_r52/gnu/CMakeLists.txt b/ports/cortex_r52/gnu/CMakeLists.txt index b821ceb43..af4642f82 100644 --- a/ports/cortex_r52/gnu/CMakeLists.txt +++ b/ports/cortex_r52/gnu/CMakeLists.txt @@ -75,3 +75,12 @@ option(TX_R52_BUILD_FVP_EXAMPLE "Build the Armv8-R AEM FVP example targets" OFF) if(TX_R52_BUILD_FVP_EXAMPLE) add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/example_build/fvp_baser_aemv8r) endif() + +# NXP S32Z280-594EVB example build. Separate option from the FVP example so +# that FVP regression stays green while silicon bring-up is in progress, and so +# neither build can perturb the other: the two boards differ in reset state, +# memory map and instruction set at reset. +option(TX_R52_BUILD_S32Z280_EXAMPLE "Build the NXP S32Z280-594EVB example targets" OFF) +if(TX_R52_BUILD_S32Z280_EXAMPLE) + add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/example_build/s32z280_evb) +endif() diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/demo_mpu.c b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/demo_mpu.c index 6d754d5ea..c96afc087 100644 --- a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/demo_mpu.c +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/demo_mpu.c @@ -54,6 +54,18 @@ static ULONG thread_check_stack[DEMO_STACK_SIZE / sizeof(ULONG)]; static volatile unsigned long writable_probe; +/* Execute-never probe. Lives in the data region, holds one A32 "bx lr", and + is only ever reached if XN is NOT enforced -- in which case this check has + already failed and the encoded instruction is simply the most harmless + thing to land on. Not static: nothing in this file reads it, and an + optimising build would otherwise discard it. */ + +volatile unsigned long executable_probe = 0xE12FFF1EUL; + +extern void mpu_try_execute(void (*target)(void)); +extern volatile unsigned long mpu_expect_pabt; +extern volatile unsigned long mpu_pabt_count; + /**************************************************************************/ /* report */ @@ -200,6 +212,33 @@ static void thread_check_entry(ULONG thread_input) (*code_ptr != 0xDEADBEEFUL) ? 1U : 0U); } + /* Enforcement, part 4: the execute-never data region must reject an + instruction fetch. This is the counterpart to part 3 and the check that + pins down PRBAR.XN specifically. It is worth stating why it exists: an + earlier version of program_region() shifted every PRBAR field one bit + too far left, which left XN in the real AP[1] and every "non-executable" + region freely executable. Every check above still passed, because the + accidental AP bits happened to land correctly. Only fetching from a + supposedly non-executable region exposed it -- on S32Z280 silicon, + where the core cheerfully ran instructions out of .data. */ + + { + unsigned long pabts_before = mpu_pabt_count; + + mpu_expect_pabt = 1UL; + mpu_try_execute((void (*)(void)) (void *) &executable_probe); + mpu_expect_pabt = 0UL; + + console_puts("[check] prefetch aborts before/after exec from data = "); + console_puthex(pabts_before); + console_puts(" / "); + console_puthex(mpu_pabt_count); + console_puts("\n"); + + failures += report("[check] execute from non-executable data faulted ", + (mpu_pabt_count == (pabts_before + 1UL)) ? 1U : 0U); + } + /* And the kernel is still healthy afterwards. */ failures += report("[check] kernel still running after the fault ", diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/entry.S b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/entry.S index 01f171dcc..ec25ac252 100644 --- a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/entry.S +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/entry.S @@ -416,7 +416,59 @@ el2_trap_fiq: FAULT_REPORT msg_el2_fiq el1_trap_reset: FAULT_REPORT msg_el1_reset el1_trap_undef: FAULT_REPORT msg_el1_undef el1_trap_svc: FAULT_REPORT msg_el1_svc -el1_trap_pabt: FAULT_REPORT msg_el1_pabt +/* Prefetch abort. Fatal, except during the MPU self-test's execute-never + check. This one cannot recover the way the data-abort path does: skipping + "the faulting instruction" is impossible when the instruction is precisely + what could not be fetched. So mpu_try_execute below records where to land + and this handler returns there, restoring the pre-fault mode from SPSR. */ + +el1_trap_pabt: +#ifdef TX_R52_MPU_FAULT_TEST + push {r0, r1} + ldr r0, =mpu_expect_pabt + ldr r1, [r0] + cmp r1, #0 + beq el1_pabt_fatal + mov r1, #0 + str r1, [r0] /* consume the expectation */ + ldr r0, =mpu_pabt_count + ldr r1, [r0] + add r1, r1, #1 + str r1, [r0] + dsb + ldr r0, =mpu_abort_return + ldr r1, [r0] + mov lr, r1 /* land point, set before pop */ + pop {r0, r1} + subs pc, lr, #0 /* return, restoring CPSR */ +el1_pabt_fatal: + pop {r0, r1} +#endif + FAULT_REPORT msg_el1_pabt + + +#ifdef TX_R52_MPU_FAULT_TEST +/* mpu_try_execute(void (*target)(void)) + Call target and return normally if the fetch is permitted. If it is not, + el1_trap_pabt returns to the same place, so the caller continues either way + and can tell the two apart by mpu_pabt_count. SP is untouched by the + faulting branch, so the saved LR is still on the stack when we land. */ + + .global mpu_try_execute + .type mpu_try_execute, %function +mpu_try_execute: + push {r4, lr} + ldr r1, =mpu_abort_return + adr r2, mpu_try_execute_land + str r2, [r1] + dsb + isb + blx r0 +mpu_try_execute_land: + pop {r4, lr} + bx lr + .size mpu_try_execute, . - mpu_try_execute +#endif /* Data abort. Normally fatal and self-reporting, but the MPU self-test needs to provoke a permission fault and carry on: without that, "the MPU @@ -489,3 +541,17 @@ mpu_expect_abort: .global mpu_abort_count mpu_abort_count: .word 0 + +/* Used by the execute-never self-test (see el1_trap_pabt). */ + + .global mpu_expect_pabt +mpu_expect_pabt: + .word 0 + + .global mpu_pabt_count +mpu_pabt_count: + .word 0 + + .global mpu_abort_return +mpu_abort_return: + .word 0 diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/mpu.c b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/mpu.c index 21e1cf126..29f9fe25f 100644 --- a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/mpu.c +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/mpu.c @@ -275,12 +275,13 @@ static void program_region(unsigned int index, const MPU_REGION *region_ptr) unsigned long prbar; unsigned long prlar; - /* PRBAR: BASE[31:6], SH[5:4], AP[3:2], XN[1]. */ + /* PRBAR: BASE[31:6], RES0[5], SH[4:3], AP[2:1], XN[0]. + Cortex-R52 TRM r1p3 figure 3-39 / table 3-80. */ prbar = (region_ptr->mpu_region_base & 0xFFFFFFC0UL) - | (((unsigned long) region_ptr->mpu_region_shareability & 0x3UL) << 4) - | (((unsigned long) region_ptr->mpu_region_ap & 0x3UL) << 2) - | (((unsigned long) region_ptr->mpu_region_execute_never & 0x1UL) << 1); + | (((unsigned long) region_ptr->mpu_region_shareability & 0x3UL) << 3) + | (((unsigned long) region_ptr->mpu_region_ap & 0x3UL) << 1) + | ((unsigned long) region_ptr->mpu_region_execute_never & 0x1UL); prlar = (region_ptr->mpu_region_limit & 0xFFFFFFC0UL) | (((unsigned long) region_ptr->mpu_region_attr_index & 0x7UL) << 1) diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/mpu.h b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/mpu.h index e90690e9c..aaca31761 100644 --- a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/mpu.h +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/mpu.h @@ -39,28 +39,34 @@ #ifndef MPU_H #define MPU_H -/* Access permissions, PRBAR.AP (bits [3:2]). +/* Access permissions, PRBAR.AP (bits [2:1]). * - * These values were CALIBRATED AGAINST THE HARDWARE, not copied from a - * reference, because the widely-published Armv8-R AArch64 macro set has the - * two bits the other way round (its "read-only, no EL0 access" is 0x2). - * Programming four disjoint regions, one per encoding, and attempting a - * privileged write to each gave: + * AP[2] selects read-only, AP[1] grants EL0 access -- the standard Armv8-R + * encoding, as published. An earlier version of this file claimed the two + * bits were reversed, on the strength of a calibration that programmed four + * regions and attempted a privileged write to each: * * AP=0b00 write allowed AP=0b01 write faulted * AP=0b10 write allowed AP=0b11 write faulted * - * so the low bit is read-only and the high bit grants EL0 access. Using the - * AArch64 ordering here silently produces writable "read-only" regions: the - * MPU still enforces region coverage, so everything appears to work and only - * an explicit write-permission test exposes it. Re-calibrate on S32Z280 - * silicon before trusting these values there. + * That table is real, but the cause was not the AP ordering. program_region() + * shifted every PRBAR field one bit too far left, so the AP value's low bit + * landed in the real AP[2] -- the read-only bit -- making writes fault exactly + * when that bit was set. The "high bit grants EL0 access" half was never + * tested; under the old shift that bit landed in SH[0], programming a + * shareability the TRM defines as UNPREDICTABLE. + * + * The shift is fixed in program_region(). These values are now the + * architectural ones and need no calibration. Verified on S32Z280 silicon: + * a write to an RO region faults, and execution from an XN region takes a + * prefetch abort -- the latter never worked under the old shift, because the + * intended XN bit landed in AP[1] instead. */ -#define MPU_AP_RW_EL1 0U /* EL1 read/write, EL0 no access */ -#define MPU_AP_RO_EL1 1U /* EL1 read-only, EL0 no access */ -#define MPU_AP_RW_EL1_EL0 2U /* EL1 read/write, EL0 read/write */ -#define MPU_AP_RO_EL1_EL0 3U /* EL1 read-only, EL0 read-only */ +#define MPU_AP_RW_EL1 0U /* 0b00 EL1 read/write, no EL0 */ +#define MPU_AP_RW_EL1_EL0 1U /* 0b01 EL1 read/write, EL0 read/write */ +#define MPU_AP_RO_EL1 2U /* 0b10 EL1 read-only, no EL0 */ +#define MPU_AP_RO_EL1_EL0 3U /* 0b11 EL1 read-only, EL0 read-only */ /* Shareability, PRBAR.SH. */ diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/CMakeLists.txt b/ports/cortex_r52/gnu/example_build/s32z280_evb/CMakeLists.txt new file mode 100644 index 000000000..3319d77f1 --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/CMakeLists.txt @@ -0,0 +1,81 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# Example build for Cortex-R52 on the NXP S32Z280-594EVB, RTU0 core 0. +# +# Unlike the FVP example there is no automated test target here: the board is +# reached through a debug probe and a vendor GDB server, not by launching a +# model, so running an image is a manual step. tools/read_identity.gdb loads +# an image, runs it and reports what it found. + +set(EVB_DIR ${CMAKE_CURRENT_LIST_DIR}) + +# Silicon M0 -- boot verification. Deliberately does not link ThreadX: a +# failure here is then unambiguously a boot or board problem rather than a +# kernel one, which is the same reasoning as the FVP's boot_check.elf. +add_executable(s32z280_boot.elf EXCLUDE_FROM_ALL + ${EVB_DIR}/entry.S + ${EVB_DIR}/bsp_boot.c + ${EVB_DIR}/linflexd.c + ${EVB_DIR}/timer.c + ${EVB_DIR}/gic_probe.c + ${EVB_DIR}/mpu.c + ${EVB_DIR}/gicv3.c + ${EVB_DIR}/irq_dispatch.c + ${EVB_DIR}/cache.c +) + +target_include_directories(s32z280_boot.elf PRIVATE ${EVB_DIR}) + +# -g only: this image exists to be inspected through a debugger, and without +# DWARF the identity structure has no type for GDB to walk. No effect on the +# generated code. +target_compile_options(s32z280_boot.elf PRIVATE -g) + +target_link_options(s32z280_boot.elf PRIVATE + -T${EVB_DIR}/link.lds + -nostartfiles + -Wl,-Map=s32z280_boot.map + # Bare metal: one code region and one data region, with access control + # belonging to the MPU rather than to segment permissions. + -Wl,--no-warn-rwx-segments +) + + +# ThreadX demo on silicon: threads, preemption and the timer tick. Separate +# target from s32z280_boot.elf, which deliberately does not link the kernel so +# that a boot failure there is unambiguously a board problem. +add_executable(s32z280_demo.elf EXCLUDE_FROM_ALL + ${EVB_DIR}/entry.S + ${EVB_DIR}/tx_initialize_low_level.S + ${EVB_DIR}/linflexd.c + ${EVB_DIR}/timer.c + ${EVB_DIR}/mpu.c + ${EVB_DIR}/gicv3.c + ${EVB_DIR}/irq_dispatch.c + ${EVB_DIR}/gic_probe.c + ${EVB_DIR}/cache.c + ${EVB_DIR}/demo_s32z280.c +) + +# TX_R52_USE_THREADX_IRQ routes the IRQ vector through _tx_thread_context_save +# instead of the standalone handler, and makes _tx_initialize_low_level call +# board_init(). +target_compile_definitions(s32z280_demo.elf PRIVATE TX_R52_USE_THREADX_IRQ=1) +target_compile_options(s32z280_demo.elf PRIVATE -g) + +target_link_libraries(s32z280_demo.elf PRIVATE threadx) + +target_include_directories(s32z280_demo.elf PRIVATE + ${EVB_DIR} + ${CMAKE_SOURCE_DIR}/common/inc + ${CMAKE_SOURCE_DIR}/ports/${THREADX_ARCH}/${THREADX_TOOLCHAIN}/inc +) + +target_link_options(s32z280_demo.elf PRIVATE + -T${EVB_DIR}/link.lds + -nostartfiles + -Wl,-Map=s32z280_demo.map + -Wl,--no-warn-rwx-segments +) diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/board.h b/ports/cortex_r52/gnu/example_build/s32z280_evb/board.h new file mode 100644 index 000000000..81478488c --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/board.h @@ -0,0 +1,105 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* BOARD SUPPORT RELEASE */ +/* */ +/* board.h Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frédéric Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Interface between the S32Z280 reset path and the C code it enters, */ +/* plus the layout of the structure a debugger reads to confirm what */ +/* the core reported about itself. */ +/* */ +/* Field order here is load-bearing: the debug script reads the */ +/* structure by offset, so members must not be reordered without */ +/* updating tools/read_identity.gdb alongside. */ +/* */ +/**************************************************************************/ + +#ifndef BOARD_H +#define BOARD_H + +/* Written to r52_identity.magic only after every other field is set, so a + reader can tell a complete structure from a half-filled one. */ + +#define R52_IDENTITY_MAGIC 0x52520001UL + +/* What the core reports about itself. EL2-only registers are captured by + entry.S before the drop to EL1; the rest are read in bsp_main. */ + +typedef struct r52_identity_struct +{ + unsigned int magic; + unsigned int midr; /* expect part 0xD13 = Cortex-R52 */ + unsigned int mpuir; /* EL1 MPU, DREGION in bits [15:8] */ + unsigned int ctr; + unsigned int mpidr; + unsigned int id_pfr0; + unsigned int id_pfr1; /* virtualisation field => EL2 */ + unsigned int sctlr_el1; /* MPU and cache enables as found */ + unsigned int hmpuir_el2; /* EL2 MPU, captured at EL2 */ + unsigned int cntfrq_el2; /* recorded, not programmed */ + unsigned int cpsr_el2; /* mode bits should read 0x1A, Hyp */ + unsigned int cpsr_el1; /* mode bits should read 0x13, SVC */ + unsigned int mpu_regions_el1; /* decoded from mpuir */ + unsigned int console_status; /* linflexd_init() result, 0 = OK */ +} r52_identity_t; + +extern r52_identity_t r52_identity; + +/* Entered from entry.S once EL1 is set up; never returns. Declared here to + satisfy MISRA Rule 8.4, which entry.S cannot do for itself. */ + +void bsp_main(void); + +/* Breakpoint target for the debug script; reached once r52_identity is + complete. Declared here so it has a prototype (MISRA Rule 8.4). */ + +void bsp_done(void); + +/* SCTLR as it reads after mpu_init(); M should be set. */ + +unsigned int read_sctlr_after_mpu(void); + +/* Called from el1_irq_entry in entry.S; declared here to satisfy MISRA + Rule 8.4, which assembly cannot do for itself. */ + +void board_irq_handler(void); + +/* Called from _tx_initialize_low_level when the kernel is linked. */ + +void board_init(void); + +/* Branches to a non-executable address to provoke a prefetch abort. Returns + via the abort handler, not normally. */ + +void try_execute_data(unsigned long address); + +/* Interrupt observations, written by the handler. */ + +extern volatile unsigned long board_irq_count; +extern volatile unsigned long board_timer_intid; +extern volatile unsigned long board_spurious_count; +extern volatile unsigned long board_unexpected_intid; +extern volatile unsigned long board_first_intid; + +#endif /* BOARD_H */ diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/bsp_boot.c b/ports/cortex_r52/gnu/example_build/s32z280_evb/bsp_boot.c new file mode 100644 index 000000000..d97ec37a4 --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/bsp_boot.c @@ -0,0 +1,651 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* BOARD SUPPORT RELEASE */ +/* */ +/* bsp_boot.c Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frédéric Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* First-boot verification for the NXP S32Z280-594EVB. Records what */ +/* the core reports about itself into a structure a debugger reads. */ +/* */ +/* There is no console on this board yet: LIN9 reaches the host through*/ +/* the daughtercard USB-UART, but its baud rate depends on clock */ +/* configuration that is not yet established, and a console that prints*/ +/* at the wrong rate produces garbage indistinguishable from a crash. */ +/* So this milestone reports through memory instead, which cannot be */ +/* mis-configured. The console arrives in the next step. */ +/* */ +/* Only EL1-accessible registers are read here. EL2-only ones */ +/* (HMPUIR, CNTFRQ) are captured by entry.S before the drop to EL1, */ +/* because reading them at EL1 would trap rather than return a value. */ +/* */ +/* MISRA C:2012 deviations (justified) */ +/* */ +/* Dir 4.3 -- assembly language shall be encapsulated and isolated. */ +/* Each MRC is wrapped in its own single-statement static function */ +/* below, which is the encapsulation the directive asks for. There */ +/* is no other way to read a coprocessor register from C. */ +/* */ +/* Rule 8.4 -- bsp_main is called from assembly and so has no C caller */ +/* to provide a prototype; it is declared in board.h, which entry.S */ +/* cannot include. */ +/* */ +/**************************************************************************/ + +#include "board.h" +#include "platform.h" +#include "linflexd.h" +#include "timer.h" +#include "gic_probe.h" +#include "mpu.h" +#include "gicv3.h" +#include "cache.h" + +/* Captured at EL2 by entry.S, before the drop to EL1. */ + +extern unsigned int boot_stage; +extern unsigned int cpsr_at_el2; +extern unsigned int cpsr_at_el1; +extern unsigned int cntfrq_at_el2; +extern unsigned int hmpuir_at_el2; +extern unsigned int probe_stage; +extern unsigned int fault_expected; +extern unsigned int fault_taken; + +/* Mirror of the console markers into memory. The UART has twice gone away at + the moment a marker mattered -- once when a stalled access took the debug + connection down with it, once when the USB passthrough detached -- and a + stalled access records no fault, so boot_stage alone cannot say how far the + risky sequence got. This can be read post-mortem without a console. */ + +#define MARK(n) do { probe_stage = (unsigned int)(n); } while (0) + +/* Filled in below and read by the debugger. Not static: the whole point is + for something outside this translation unit to find it. */ + +r52_identity_t r52_identity; + + +/* One MRC per function, each isolated, per MISRA Dir 4.3. */ + +static unsigned int read_midr(void) +{ + unsigned int value; + __asm volatile ("mrc p15, 0, %0, c0, c0, 0" : "=r" (value)); + return value; +} + +static unsigned int read_mpuir(void) +{ + unsigned int value; + __asm volatile ("mrc p15, 0, %0, c0, c0, 4" : "=r" (value)); + return value; +} + +static unsigned int read_ctr(void) +{ + unsigned int value; + __asm volatile ("mrc p15, 0, %0, c0, c0, 1" : "=r" (value)); + return value; +} + +static unsigned int read_mpidr(void) +{ + unsigned int value; + __asm volatile ("mrc p15, 0, %0, c0, c0, 5" : "=r" (value)); + return value; +} + +static unsigned int read_id_pfr0(void) +{ + unsigned int value; + __asm volatile ("mrc p15, 0, %0, c0, c1, 0" : "=r" (value)); + return value; +} + +static unsigned int read_id_pfr1(void) +{ + unsigned int value; + __asm volatile ("mrc p15, 0, %0, c0, c1, 1" : "=r" (value)); + return value; +} + +static unsigned int read_sctlr(void) +{ + unsigned int value; + __asm volatile ("mrc p15, 0, %0, c1, c0, 0" : "=r" (value)); + return value; +} + + +/**************************************************************************/ +/* report -- one "NAME = VALUE" line on the console. */ +/**************************************************************************/ + +static void report(const char *name, unsigned int value) +{ + linflexd_puts(name); + linflexd_puts(" = 0x"); + linflexd_put_hex32(value); + linflexd_putc('\n'); +} + + +/**************************************************************************/ +/* bsp_done -- breakpoint target, reached once the structure is complete.*/ +/* */ +/* Deliberately not static and deliberately not inlined: it exists purely*/ +/* so a debugger can break on a symbol. An optimising build would remove*/ +/* an empty static function, and then the script would have nothing to */ +/* attach to. */ +/**************************************************************************/ + +/* Clear CPSR.I so the GIC can deliver to this core. Interrupts stay masked + from reset all the way to here on purpose: nothing before this point is + prepared to service one. */ + +static void enable_irq_at_el1(void) +{ + __asm volatile ("cpsie i" ::: "memory"); + __asm volatile ("isb"); +} + + +/* Cache benchmark. + * + * Two things have to be right for a cache to show a measurable effect, and the + * first version of this test got both wrong. It used a 4 KB static buffer in + * the RTU-local fast-data bank and reported a 0.036% difference -- noise -- as a + * pass. Fast local SRAM is already close to core speed, so caching it can save + * almost nothing. + * + * 1. The memory must be slower than the core. This uses the extended SRAM at + * S32Z_EXT_SRAM_BASE, which the Reference Manual describes as NOT + * RTU-local, unlike the fast-data bank. + * + * 2. The working set must fit in the cache and be revisited. It is sized + * from CCSIDR at run time -- half the reported L1 data cache -- rather + * than from a guessed constant. A set larger than the cache would stream + * and evict, and would show little benefit even over slow memory. + * + * Reported alongside the timings so the numbers can be judged, not just + * believed. + */ + +static unsigned long cache_bench_words; + +static void cache_workload(void) +{ + volatile unsigned int *buffer = (volatile unsigned int *) S32Z_EXT_SRAM_BASE; + unsigned long pass; + unsigned long i; + + for (pass = 0UL; pass < 32UL; pass++) + { + for (i = 0UL; i < cache_bench_words; i++) + { + buffer[i] = buffer[i] + i + pass; + } + } +} + + +unsigned int fault_syndrome_value(void) +{ + extern unsigned int fault_syndrome; + return fault_syndrome; +} + + +unsigned int fault_address_value(void) +{ + extern unsigned int fault_address; + return fault_address; +} + + +unsigned int read_sctlr_after_mpu(void) +{ + return read_sctlr(); +} + + +void bsp_done(void) +{ + __asm volatile ("nop"); +} + + +/**************************************************************************/ +/* bsp_main -- entered at EL1 (Supervisor) from entry.S. Never returns. */ +/**************************************************************************/ + +void bsp_main(void) +{ + /* Written last, so a debugger that finds the magic knows every other + field is already valid. A partially filled structure would otherwise + be indistinguishable from a complete one. */ + + r52_identity.magic = 0U; + + r52_identity.midr = read_midr(); + r52_identity.mpuir = read_mpuir(); + r52_identity.ctr = read_ctr(); + r52_identity.mpidr = read_mpidr(); + r52_identity.id_pfr0 = read_id_pfr0(); + r52_identity.id_pfr1 = read_id_pfr1(); + r52_identity.sctlr_el1 = read_sctlr(); + + r52_identity.hmpuir_el2 = hmpuir_at_el2; + r52_identity.cntfrq_el2 = cntfrq_at_el2; + r52_identity.cpsr_el2 = cpsr_at_el2; + r52_identity.cpsr_el1 = cpsr_at_el1; + + /* Derived counts, so the debugger script does not have to know where the + field sits in each register. MPUIR reports DREGION in bits [15:8]. + HMPUIR is recorded raw as well, because on this part the count appears + in bits [7:0] instead and that layout still needs confirming against + the Armv8-R specification. */ + + r52_identity.mpu_regions_el1 = (r52_identity.mpuir >> 8) & 0xFFU; + + r52_identity.magic = R52_IDENTITY_MAGIC; + + /* Report over the console as well as through memory. The memory copy + stays: it is what proved the boot path before a console existed, and it + still works if the console itself is misconfigured. */ + + r52_identity.console_status = linflexd_init(); + linflexd_puts("\n=== ThreadX Cortex-R52 :: NXP S32Z280-594EVB ===\n"); + report("MIDR ", r52_identity.midr); + report("MPUIR ", r52_identity.mpuir); + report("HMPUIR ", r52_identity.hmpuir_el2); + report("CTR ", r52_identity.ctr); + report("MPIDR ", r52_identity.mpidr); + report("ID_PFR0 ", r52_identity.id_pfr0); + report("ID_PFR1 ", r52_identity.id_pfr1); + report("SCTLR ", r52_identity.sctlr_el1); + report("CNTFRQ ", r52_identity.cntfrq_el2); + report("CPSR@EL2 ", r52_identity.cpsr_el2); + report("CPSR@EL1 ", r52_identity.cpsr_el1); + linflexd_puts("EL1 MPU regions: "); + linflexd_put_hex32(r52_identity.mpu_regions_el1); + linflexd_putc('\n'); + report("CONSOLE ", r52_identity.console_status); + + /* --- generic timer ---------------------------------------------------- + CNTFRQ is now programmed at EL2 (8 MHz, measured and cross-checked + against CFG_CNTDV and FXOSC). Prove the timer end to end: read it back, + then arm a one-second one-shot and poll for it, bracketed by CNTPCT + samples. If the counter and the compare agree, the elapsed count is + CNTFRQ; if the host also sees one second pass, the rate itself is right + rather than merely self-consistent. + + Interrupt stays masked -- no GIC yet. Polling first means a later + interrupt problem cannot be confused with the timer being wrong. */ + + report("CNTFRQ ", timer_read_cntfrq()); + + { + unsigned long long before; + unsigned long long after; + unsigned int hz = timer_read_cntfrq(); + + /* Sample AFTER the message, not before: at 115200 the line itself is + about 2 ms, and sampling first puts that inside the measurement. */ + + linflexd_puts("TIMER arming 1s one-shot\n"); + before = timer_read_cntpct(); + timer_start_oneshot(hz); + + while (timer_fired() == 0U) + { + /* poll */ + } + + after = timer_read_cntpct(); + timer_stop(); + + linflexd_puts("TIMER fired, elapsed counts = 0x"); + linflexd_put_hex32((unsigned int)((after - before) >> 32)); + linflexd_put_hex32((unsigned int)(after - before)); + linflexd_puts("\n"); + } + + /* --- where is the GIC, and is the port to it open? --------------------- + System-register reads only: a load from the GIC window stalls the core, + so nothing here touches memory. */ + + report("IMP_CBAR ", gic_read_cbar()); + report("PERIPHPRG", gic_read_periphpregionr()); + + /* The peripheral port is now enabled at EL2, so RTU peripheral space + should be reachable. Marker first: if this still stalls, the run dies + here and says so. */ + + linflexd_puts("P1 RTU0.GPR CFG_CNTDV via LLPP\n"); + report("CFG_CNTDV", *(volatile unsigned int *)S32Z_RTU0_GPR_CFG_CNTDV); + + /* --- MPU, then the GIC ------------------------------------------------ + The GIC needs its region mapped Device nGnRnE (Cortex-R52 TRM), which + needs the MPU on. Markers around the enable: if the console survives it, + the UART region is right; if it does not, that is the answer. */ + + MARK(0x10); + linflexd_puts("M1 enabling MPU\n"); + { + unsigned int regions = mpu_init(); + + MARK(0x11); + + /* Read back what the region programming actually did. Five regions die on + the SCTLR.M write while three survive, and the difference is the region + COUNT rather than the Device attribute -- so the question is whether + PRSELR/PRBAR/PRLAR programming takes effect at all for indices 3 and 4, + which nothing has ever exercised: the FVP example this code came from + only ever programs three regions. The MPU is not enabled in this build, + so this cannot stall. */ + + linflexd_puts("R idx PRBAR PRLAR\n"); + { + unsigned int i; + for (i = 0U; i < 8U; i++) + { + unsigned long prbar = 0UL; + unsigned long prlar = 0UL; + + mpu_read_region(i, &prbar, &prlar); + linflexd_puts("R "); + linflexd_put_hex32(i); + linflexd_puts(" "); + linflexd_put_hex32((unsigned int) prbar); + linflexd_puts(" "); + linflexd_put_hex32((unsigned int) prlar); + linflexd_putc('\n'); + } + } + + + report("MPU rgns ", regions); + report("SCTLR ", read_sctlr_after_mpu()); + MARK(0x12); + linflexd_puts("M2 MPU enabled, console alive\n"); + + linflexd_puts("M3 GICD_PIDR2 (was stalling before the MPU)\n"); + MARK(0x13); + report("GICD_PIDR2", *(volatile unsigned int *)(S32Z_GIC_BASE + 0xFFE8UL)); + MARK(0x14); + report("GICD_TYPER", *(volatile unsigned int *)(S32Z_GIC_BASE + 0x0004UL)); + MARK(0x15); + report("GICR_PIDR2", *(volatile unsigned int *)(S32Z_GIC_BASE + 0x10FFE8UL)); + MARK(0x16); + linflexd_puts("M4 GIC reachable\n"); + + /* --- interrupts ------------------------------------------------- + Bring up the GIC properly, enable the timer PPI, arm a 10 ms + one-shot and unmask IRQ at EL1. Then wait and see whether the + handler runs. Polling proved the timer counts and fires; this + proves the interrupt is delivered, which is a different claim. */ + + MARK(0x50); + linflexd_puts("I1 gicv3_init\n"); + gicv3_init(); + + MARK(0x51); + /* Enable the WHOLE PPI range rather than just 30. All three counters + reading zero means nothing reached the CPU interface, and an enabled + but wrong INTID produces exactly that silence -- so let the hardware + say which PPI the timer actually drives. This is how INTID 30 was + established on the FVP too: assume nothing, record what arrives. */ + + linflexd_puts("I2 enable PPIs 16..31\n"); + { + unsigned int ppi; + for (ppi = 16U; ppi <= 31U; ppi++) + { + gicv3_enable_ppi(ppi, 0xA0U); + } + } + + MARK(0x52); + linflexd_puts("I3 arm timer, unmask IRQ\n"); + timer_start_oneshot_irq(timer_read_cntfrq() / 100U); /* 10 ms */ + enable_irq_at_el1(); + + MARK(0x53); + { + unsigned int spins = 0U; + + /* Wait for ticks. Bounded: a missing interrupt must report + itself rather than hang the boot. */ + + while ((board_irq_count < 5UL) && (spins < 30U)) + { + timer_spin(200000U); + spins++; + } + } + + MARK(0x54); + report("IRQ count", (unsigned int) board_irq_count); + report("timer INTID", (unsigned int) board_timer_intid); + report("spurious ", (unsigned int) board_spurious_count); + report("unexpected", (unsigned int) board_unexpected_intid); + report("first INTID", (unsigned int) board_first_intid); + linflexd_puts("I4 interrupt test done\n"); + } + + /* --- GIC: not reachable yet, probe deliberately removed ---------------- + The GIC window NXP's memory map gives for this cluster, 0x47800000, is + unreachable from BOTH paths in the current state. The debugger cannot + read any of it, and a load from the core stalls the core outright: the + run dies at the marker before the access, with no fault recorded and the + debug connection dropped -- the same signature as RTU0.GPR. + + The Reference Manual contains no GIC base address anywhere, so that + address rests entirely on NXP's debugger script. What the manual does + mention is the R52's "Arm low-latency peripheral port". On Cortex-R52 + the LLPP is an implementation-defined region that software programs and + enables; if it is disabled out of reset, or covers a different base, + accesses to a peripheral in that window stall exactly like this. + Settling it needs the Cortex-R52 TRM, which documents the region + registers -- NXP's manual does not. + + The probe is removed rather than left disabled: while it was present the + image stalled here every run, which costs the timer and console results + that come before it. */ + + /* --- caches ------------------------------------------------------------ + Enabled last, and measured rather than merely switched on. Reading + SCTLR back proves a bit was set; timing the same workload before and + after proves the caches are actually doing something. The generic timer + supplies the clock -- 8 MHz, established earlier -- so the comparison is + in real units rather than loop counts. */ + + MARK(0x70); + report("CLIDR ", (unsigned int) cache_read_clidr()); + report("D line ", (unsigned int) cache_dcache_line_bytes()); + report("D ways ", (unsigned int) cache_dcache_ways()); + report("D sets ", (unsigned int) cache_dcache_sets()); + report("D bytes ", (unsigned int) cache_dcache_bytes()); + + /* Half the data cache, in words: fits comfortably and is revisited every + pass, which is the case a cache is meant to win. */ + + cache_bench_words = cache_dcache_bytes() / (2UL * sizeof(unsigned int)); + report("bench wds", (unsigned int) cache_bench_words); + + linflexd_puts("C1 timing over non-RTU-local SRAM, caches OFF\n"); + { + unsigned long long before; + unsigned long long after; + unsigned long cold; + unsigned long warm; + + before = timer_read_cntpct(); + cache_workload(); + after = timer_read_cntpct(); + cold = (unsigned long) (after - before); + + MARK(0x71); + linflexd_puts("C2 enabling caches\n"); + cache_enable(); + MARK(0x72); + report("SCTLR ", read_sctlr_after_mpu()); + report("cachesOn ", cache_enabled()); + + before = timer_read_cntpct(); + cache_workload(); + after = timer_read_cntpct(); + warm = (unsigned long) (after - before); + + MARK(0x73); + report("counts off", cold); + report("counts on ", warm); + + /* Report the two claims separately, because they are separate. + "Enabled" is what SCTLR says and is checkable. "Effective" needs a + measurable speedup, and a criterion of merely warm < cold is + worthless: the first run of this test showed 609904 against 609686, + a 0.036% difference that is noise, and printed PASS on it. + + A cache having little to offer here is plausible rather than + broken. Both the code and the data this workload touches live in + RTU-local low-latency SRAM, which is close to core speed already; + there is no slow memory on this board to demonstrate against. DDR + would be the place to measure a real cache effect, and DDR is not + initialised. */ + + if (cache_enabled() == 1U) + { + linflexd_puts("C3 PASS caches enabled (SCTLR.C and SCTLR.I set)\n"); + } + else + { + linflexd_puts("C3 FAIL caches did not enable\n"); + } + + if (cold > warm) + { + unsigned long gain = ((cold - warm) * 1000UL) / cold; + + report("gain/1000", gain); + + if (gain >= 100UL) + { + linflexd_puts("C4 PASS caches measurably faster (>=10%)\n"); + } + else + { + linflexd_puts("C4 speedup below 10% -- see gain/1000 above\n"); + } + } + else + { + linflexd_puts("C4 no speedup measured\n"); + } + + /* Push the markers and counters out of the write-back cache so a + debugger reading SRAM sees them. Without this a post-mortem read + could report stale values from before the cache was enabled. */ + + cache_clean_all(); + MARK(0x74); + cache_clean_all(); + } + + /* --- protection test --------------------------------------------------- + The map claims code is read-only. Prove it: arm the recoverable abort + path, write to the code region, and check that a fault was actually + taken. Reading SCTLR back or listing the regions would only show what + was programmed; provoking the violation shows it is enforced. + + This is worth doing now for a second reason: until SCTLR.TE was cleared + no fault handler could run at all, so no protection claim about this + board could be checked. */ + + MARK(0x60); + linflexd_puts("X1 write to read-only code region\n"); + fault_taken = 0U; + fault_expected = 1U; + + *(volatile unsigned int *)S32Z_CODE_SRAM_BASE = 0xDEADBEEFUL; + + MARK(0x61); + report("faults ", fault_taken); + report("fault DFSR", fault_syndrome_value()); + report("fault addr", fault_address_value()); + + if (fault_taken == 1U) + { + linflexd_puts("X2 PASS write to code faulted and was recovered\n"); + } + else + { + linflexd_puts("X2 FAIL write to code did NOT fault -- code is writable\n"); + } + + /* --- second protection case: execute from data ------------------------- + The map marks the data region execute-never. Prove that too: branch + into it and check a prefetch abort was taken. Separate from the + write-to-code case because they exercise different permissions and + different fault paths -- a map could plausibly enforce one and not the + other, and DFSR/IFSR come from different registers. */ + + MARK(0x62); + linflexd_puts("X3 execute from non-executable data region\n"); + fault_taken = 0U; + + try_execute_data(S32Z_DATA_SRAM_BASE); + + MARK(0x63); + report("faults ", fault_taken); + report("fault IFSR", fault_syndrome_value()); + report("fault addr", fault_address_value()); + + if (fault_taken == 1U) + { + linflexd_puts("X4 PASS execute from data faulted and was recovered\n"); + } + else + { + linflexd_puts("X4 FAIL data region is executable\n"); + } + + /* Deliberate breakpoint target. The debug script sets a hardware + breakpoint here, so "the image ran to completion" is something the script + observes rather than infers from a timeout. */ + + bsp_done(); + + /* Park. The debugger halts the core and reads r52_identity. + A busy loop rather than WFI: this core's debug behaviour is still being + characterised, and a core sitting in a low-power state is one more + variable between "the code ran" and "the debugger sees it". The nop + also stops the compiler discarding a side-effect-free infinite loop. */ + + for (;;) + { + __asm volatile ("nop"); + } +} diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/cache.c b/ports/cortex_r52/gnu/example_build/s32z280_evb/cache.c new file mode 100644 index 000000000..29b7cc396 --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/cache.c @@ -0,0 +1,320 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* BOARD SUPPORT RELEASE */ +/* */ +/* cache.c Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frederic Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Cache maintenance and enable for the S32Z280-594EVB. */ +/* */ +/* The FVP example enables SCTLR.C and SCTLR.I but only invalidates the*/ +/* instruction cache, with a note that a data-cache set/way sweep */ +/* belongs with silicon bring-up "where it can be verified against the */ +/* real cache geometry". This is that: the sweep here reads CLIDR and */ +/* CCSIDR and walks every set and way the hardware reports, rather than*/ +/* assuming a size. */ +/* */ +/* The sweep matters more here than on a model. This image is written */ +/* into SRAM by a debugger with the caches off, so nothing has been */ +/* allocated yet -- but the caches are not architecturally guaranteed */ +/* to be invalid out of reset, and enabling a write-back data cache */ +/* holding stale valid lines would evict them over live memory. */ +/* */ +/* A CONSEQUENCE WORTH KNOWING */ +/* */ +/* With the write-back data cache on, values this image writes may sit */ +/* dirty in cache where a DEBUGGER READING SRAM CANNOT SEE THEM. The */ +/* memory-resident progress markers and fault records used throughout */ +/* this bring-up are read exactly that way. They stay reliable only */ +/* because cache_clean_all() is called before parking; without that a */ +/* post-mortem read could report stale values and look like a fault */ +/* that never happened. */ +/* */ +/* MISRA C:2012 deviations (justified) */ +/* */ +/* Dir 4.3 -- assembly encapsulated one operation per function. */ +/* */ +/**************************************************************************/ + +#include "cache.h" + +#define SCTLR_C (1UL << 2) +#define SCTLR_I (1UL << 12) + + +static unsigned long read_sctlr(void) +{ + unsigned long value; + __asm volatile ("mrc p15, 0, %0, c1, c0, 0" : "=r" (value)); + return value; +} + +static void write_sctlr(unsigned long value) +{ + __asm volatile ("mcr p15, 0, %0, c1, c0, 0" :: "r" (value)); +} + +static void data_sync_barrier(void) +{ + __asm volatile ("dsb sy" ::: "memory"); +} + +static void instruction_barrier(void) +{ + __asm volatile ("isb sy" ::: "memory"); +} + + +unsigned long cache_read_clidr(void) +{ + unsigned long value; + __asm volatile ("mrc p15, 1, %0, c0, c0, 1" : "=r" (value)); + return value; +} + + +unsigned long cache_read_ccsidr(void) +{ + unsigned long value; + __asm volatile ("mrc p15, 1, %0, c0, c0, 0" : "=r" (value)); + return value; +} + + +/* Select a cache level and type for CCSIDR to describe. Level is zero-based; + type 0 is data/unified, 1 is instruction. */ + +static void select_cache(unsigned long level, unsigned long instruction) +{ + unsigned long csselr = (level << 1) | (instruction & 1UL); + + __asm volatile ("mcr p15, 2, %0, c0, c0, 0" :: "r" (csselr)); + instruction_barrier(); +} + + +void cache_invalidate_icache_all(void) +{ + unsigned long zero = 0UL; + + __asm volatile ("mcr p15, 0, %0, c7, c5, 0" :: "r" (zero)); + data_sync_barrier(); + instruction_barrier(); +} + + +/**************************************************************************/ +/* cache_invalidate_dcache_all -- set/way sweep over real geometry */ +/**************************************************************************/ + +void cache_invalidate_dcache_all(void) +{ + unsigned long clidr = cache_read_clidr(); + unsigned long level; + + for (level = 0UL; level < 7UL; level++) + { + unsigned long ctype = (clidr >> (level * 3UL)) & 7UL; + unsigned long ccsidr; + unsigned long line_shift; + unsigned long ways; + unsigned long sets; + unsigned long way_shift; + unsigned long way; + + /* 0 = none, 1 = instruction only: neither needs a data sweep. */ + + if ((ctype == 0UL) || (ctype == 1UL)) + { + continue; + } + + select_cache(level, 0UL); + ccsidr = cache_read_ccsidr(); + + line_shift = (ccsidr & 7UL) + 4UL; /* log2 line bytes */ + ways = ((ccsidr >> 3) & 0x3FFUL) + 1UL; + sets = ((ccsidr >> 13) & 0x7FFFUL) + 1UL; + + /* Way number sits in the top bits of the DCISW operand, positioned by + the associativity: log2(ways) rounded up. */ + + way_shift = 32UL; + { + unsigned long probe = ways - 1UL; + way_shift = 0UL; + while (probe != 0UL) + { + probe >>= 1; + way_shift++; + } + way_shift = 32UL - way_shift; + } + + for (way = 0UL; way < ways; way++) + { + unsigned long set; + + for (set = 0UL; set < sets; set++) + { + unsigned long operand = (way << way_shift) + | (set << line_shift) + | (level << 1); + + /* DCISW: invalidate data cache line by set/way. */ + + __asm volatile ("mcr p15, 0, %0, c7, c6, 2" :: "r" (operand)); + } + } + } + + data_sync_barrier(); + instruction_barrier(); +} + + +/**************************************************************************/ +/* cache_clean_all -- write dirty lines back to memory */ +/* */ +/* Needed before a debugger reads anything this image wrote: with a */ +/* write-back cache the value may exist only in cache. */ +/**************************************************************************/ + +void cache_clean_all(void) +{ + unsigned long clidr = cache_read_clidr(); + unsigned long level; + + for (level = 0UL; level < 7UL; level++) + { + unsigned long ctype = (clidr >> (level * 3UL)) & 7UL; + unsigned long ccsidr; + unsigned long line_shift; + unsigned long ways; + unsigned long sets; + unsigned long way_shift; + unsigned long way; + + if ((ctype == 0UL) || (ctype == 1UL)) + { + continue; + } + + select_cache(level, 0UL); + ccsidr = cache_read_ccsidr(); + + line_shift = (ccsidr & 7UL) + 4UL; + ways = ((ccsidr >> 3) & 0x3FFUL) + 1UL; + sets = ((ccsidr >> 13) & 0x7FFFUL) + 1UL; + + { + unsigned long probe = ways - 1UL; + way_shift = 0UL; + while (probe != 0UL) + { + probe >>= 1; + way_shift++; + } + way_shift = 32UL - way_shift; + } + + for (way = 0UL; way < ways; way++) + { + unsigned long set; + + for (set = 0UL; set < sets; set++) + { + unsigned long operand = (way << way_shift) + | (set << line_shift) + | (level << 1); + + /* DCCSW: clean data cache line by set/way. */ + + __asm volatile ("mcr p15, 0, %0, c7, c10, 2" :: "r" (operand)); + } + } + } + + data_sync_barrier(); +} + + +/**************************************************************************/ +/* cache_enable -- invalidate both caches, then turn them on */ +/**************************************************************************/ + +void cache_enable(void) +{ + unsigned long sctlr; + + cache_invalidate_dcache_all(); + cache_invalidate_icache_all(); + + sctlr = read_sctlr(); + sctlr |= SCTLR_C | SCTLR_I; + write_sctlr(sctlr); + + data_sync_barrier(); + instruction_barrier(); +} + + +/* L1 data cache geometry, decoded from CCSIDR with level 0 selected. */ + +static unsigned long dcache_ccsidr(void) +{ + select_cache(0UL, 0UL); + return cache_read_ccsidr(); +} + + +unsigned long cache_dcache_line_bytes(void) +{ + return 1UL << ((dcache_ccsidr() & 7UL) + 4UL); +} + + +unsigned long cache_dcache_ways(void) +{ + return ((dcache_ccsidr() >> 3) & 0x3FFUL) + 1UL; +} + + +unsigned long cache_dcache_sets(void) +{ + return ((dcache_ccsidr() >> 13) & 0x7FFFUL) + 1UL; +} + + +unsigned long cache_dcache_bytes(void) +{ + return cache_dcache_line_bytes() * cache_dcache_ways() * cache_dcache_sets(); +} + + +unsigned int cache_enabled(void) +{ + unsigned long sctlr = read_sctlr(); + + return (((sctlr & SCTLR_C) != 0UL) && ((sctlr & SCTLR_I) != 0UL)) ? 1U : 0U; +} diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/cache.h b/ports/cortex_r52/gnu/example_build/s32z280_evb/cache.h new file mode 100644 index 000000000..0ded69370 --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/cache.h @@ -0,0 +1,64 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* BOARD SUPPORT RELEASE */ +/* */ +/* cache.h Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frederic Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Cache maintenance and enable for the S32Z280-594EVB. */ +/* */ +/**************************************************************************/ + +#ifndef CACHE_H +#define CACHE_H + +/* Geometry as the hardware reports it; printed during bring-up so the sweep + below can be checked against real numbers rather than assumed ones. */ + +unsigned long cache_read_clidr(void); +unsigned long cache_read_ccsidr(void); + +void cache_invalidate_icache_all(void); +void cache_invalidate_dcache_all(void); + +/* Write dirty lines back. Call before a debugger reads memory this image + wrote: with a write-back cache the value may exist only in cache. */ + +void cache_clean_all(void); + +/* Invalidate both caches, then set SCTLR.C and SCTLR.I. */ + +void cache_enable(void); + +unsigned int cache_enabled(void); + +/* Decoded L1 data-cache geometry, from CCSIDR. Sizing a cache benchmark + against real numbers rather than a guess is the difference between measuring + the cache and measuring nothing. */ + +unsigned long cache_dcache_line_bytes(void); +unsigned long cache_dcache_ways(void); +unsigned long cache_dcache_sets(void); +unsigned long cache_dcache_bytes(void); + +#endif /* CACHE_H */ diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/demo_s32z280.c b/ports/cortex_r52/gnu/example_build/s32z280_evb/demo_s32z280.c new file mode 100644 index 000000000..9a3d3e389 --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/demo_s32z280.c @@ -0,0 +1,230 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* BOARD SUPPORT RELEASE */ +/* */ +/* demo_s32z280.c Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frederic Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* ThreadX running on S32Z280 silicon: threads, preemption and the */ +/* timer tick. */ +/* */ +/* The demo judges itself and says why it failed, because a hang and a */ +/* wrong answer are equally likely on first silicon and look the same */ +/* from a console. Each check is separate: */ +/* */ +/* ticks -- the tick advanced, so the GIC delivers the timer PPI */ +/* and _tx_timer_interrupt is reached */ +/* sleeper -- tx_thread_sleep returned, so tick-driven scheduling */ +/* works, not merely the interrupt */ +/* spinner -- the low-priority thread ran, so the sleeper actually */ +/* yielded the core rather than blocking it */ +/* preempt -- the sleeper resumed while the spinner was runnable, */ +/* which is preemption rather than cooperative handoff */ +/* */ +/* Counting alone would not distinguish these: a demo that only checked*/ +/* that both threads ran would pass with a broken tick if the threads */ +/* happened to yield to each other. */ +/* */ +/**************************************************************************/ + +#include "tx_api.h" +#include "linflexd.h" +#include "board.h" + +#define DEMO_STACK_SIZE 2048 + +static TX_THREAD sleeper_thread; +static TX_THREAD spinner_thread; +static TX_THREAD judge_thread; + +static unsigned char sleeper_stack[DEMO_STACK_SIZE]; +static unsigned char spinner_stack[DEMO_STACK_SIZE]; +static unsigned char judge_stack[DEMO_STACK_SIZE]; + +static volatile unsigned long sleeper_runs; +static volatile unsigned long spinner_runs; +static volatile unsigned long preempt_observed; + + +/* Breakpoint target for tools/read_identity.gdb. Defined here rather than + pulled from bsp_boot.c, whose bsp_main would collide with this file's. + Not static and not empty, so an optimising build cannot discard it. */ + +void bsp_done(void) +{ + __asm volatile ("nop"); +} + + +static void report(const char *name, unsigned long value) +{ + linflexd_puts(name); + linflexd_puts(" = 0x"); + linflexd_put_hex32((unsigned int) value); + linflexd_putc('\n'); +} + + +/* Highest priority. Sleeps, so it can only run again if the tick advances + and the scheduler resumes it. */ + +static void sleeper_entry(ULONG input) +{ + unsigned long spinner_before; + + (void) input; + + for (;;) + { + spinner_before = spinner_runs; + + tx_thread_sleep(5UL); /* 50 ms at a 10 ms tick */ + + sleeper_runs++; + + /* If the spinner advanced while this thread slept, and this thread is + the higher priority of the two, then resuming it took the core away + from a runnable lower-priority thread. That is preemption. */ + + if (spinner_runs != spinner_before) + { + preempt_observed++; + } + } +} + + +/* Lowest priority. Never blocks, so it only runs when nothing else can. */ + +static void spinner_entry(ULONG input) +{ + (void) input; + + for (;;) + { + spinner_runs++; + } +} + + +/* Middle priority. Waits, then judges and reports. */ + +static void judge_entry(ULONG input) +{ + ULONG ticks_start; + ULONG ticks_end; + UINT failures = 0U; + + (void) input; + + ticks_start = tx_time_get(); + tx_thread_sleep(100UL); /* about one second */ + ticks_end = tx_time_get(); + + linflexd_puts("\n=== ThreadX on S32Z280: results ===\n"); + report("ticks ", (unsigned long) (ticks_end - ticks_start)); + report("sleeper ", sleeper_runs); + report("spinner ", spinner_runs); + report("preempt ", preempt_observed); + + if ((ticks_end - ticks_start) < 50UL) + { + linflexd_puts("FAIL tick did not advance as expected\n"); + failures++; + } + + if (sleeper_runs == 0UL) + { + linflexd_puts("FAIL sleeper never resumed\n"); + failures++; + } + + if (spinner_runs == 0UL) + { + linflexd_puts("FAIL spinner never ran\n"); + failures++; + } + + if (preempt_observed == 0UL) + { + linflexd_puts("FAIL no preemption observed\n"); + failures++; + } + + if (failures == 0U) + { + linflexd_puts("PASS threads, tick and preemption all verified\n"); + } + + linflexd_puts("=== demo complete ===\n"); + + bsp_done(); + + for (;;) + { + tx_thread_sleep(100UL); + } +} + + +void tx_application_define(void *first_unused_memory) +{ + (void) first_unused_memory; + + (void) tx_thread_create(&sleeper_thread, "sleeper", sleeper_entry, 0UL, + sleeper_stack, DEMO_STACK_SIZE, + 1U, 1U, TX_NO_TIME_SLICE, TX_AUTO_START); + + (void) tx_thread_create(&judge_thread, "judge", judge_entry, 0UL, + judge_stack, DEMO_STACK_SIZE, + 10U, 10U, TX_NO_TIME_SLICE, TX_AUTO_START); + + (void) tx_thread_create(&spinner_thread, "spinner", spinner_entry, 0UL, + spinner_stack, DEMO_STACK_SIZE, + 20U, 20U, TX_NO_TIME_SLICE, TX_AUTO_START); +} + + +/**************************************************************************/ +/* bsp_main -- entered at EL1 from entry.S; hands over to the kernel. */ +/**************************************************************************/ + +void bsp_main(void) +{ + unsigned int console_status = linflexd_init(); + + linflexd_puts("\n=== ThreadX Cortex-R52 :: S32Z280-594EVB ===\n"); + report("console ", (unsigned long) console_status); + linflexd_puts("entering kernel\n"); + + tx_kernel_enter(); + + /* Not reached. */ + + linflexd_puts("FAIL tx_kernel_enter returned\n"); + + for (;;) + { + __asm volatile ("nop"); + } +} diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/entry.S b/ports/cortex_r52/gnu/example_build/s32z280_evb/entry.S new file mode 100644 index 000000000..a5b34be7c --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/entry.S @@ -0,0 +1,664 @@ +@/*************************************************************************** +@ * 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. +@ * +@ * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +@ * The AI-generated portions may be considered public domain (CC0-1.0) +@ * and not subject to the project's licence. The human contributor has +@ * reviewed and verified that the code is correct. +@ * +@ * SPDX-License-Identifier: MIT and CC0-1.0 +@ **************************************************************************/ +@ Some portions generated by Claude Code (Opus 5). +@ +@/**************************************************************************/ +@/* */ +@/* BOARD SUPPORT RELEASE */ +@/* */ +@/* entry.S Cortex-R52/GNU */ +@/* 6.5.2 */ +@/* AUTHOR */ +@/* */ +@/* Frédéric Desbiens, Eclipse Foundation */ +@/* */ +@/* DESCRIPTION */ +@/* */ +@/* Reset path for the NXP S32Z280-594EVB, RTU0 core 0: EL2 setup, the */ +@/* drop to EL1, stacks, .bss and the call into bsp_main. */ +@/* */ +@/* Two things differ from the Armv8-R AEM FVP entry path and both are */ +@/* silicon facts rather than choices: */ +@/* */ +@/* 1. The core resets in THUMB state. CPSR reads 0x1FA on this board */ +@/* -- Hyp mode with T set -- because the RTU boot instruction is a */ +@/* T32 branch (NXP writes R52_B0_INSTR_T32 to the boot address). */ +@/* So _start must be T32 and switch to A32 itself. An A32 entry */ +@/* executes the first halfword of its own instruction as Thumb and */ +@/* goes anywhere. */ +@/* */ +@/* 2. There is no semihosting here, so progress cannot be printed. */ +@/* Instead each stage records a marker and the identity registers */ +@/* into .data, where a debugger reads them. boot_stage says how */ +@/* far the reset path got; if a fault handler runs it records the */ +@/* vector, syndrome and return address before parking. Without */ +@/* this a fault would be indistinguishable from a hang. */ +@/* */ +@/* CNTFRQ is read and recorded rather than written. The FVP leaves it */ +@/* zero and its BSP programs a known value, but the correct frequency */ +@/* for this board is not yet established, and writing a wrong one would*/ +@/* silently mis-scale every tick interval derived from it. */ +@/* */ +@/**************************************************************************/ + + .syntax unified + +/* HCR (Hyp Configuration Register) bits cleared below. */ + + .equ HCR_VM, (1 << 0) /* stage-2 MPU enable */ + .equ HCR_AMO, (1 << 3) /* route aborts to EL2 */ + .equ HCR_IMO, (1 << 4) /* route IRQ to EL2 */ + .equ HCR_FMO, (1 << 5) /* route FIQ to EL2 */ + .equ HCR_TGE, (1 << 27) /* trap general exceptions to EL2 */ + .equ HCR_HCD, (1 << 29) /* HVC disable -- must be clear */ + + .equ HCPTR_TCP, (3 << 10) /* trap EL1 access to CP10/CP11 */ + + .equ CNTHCTL_PL1PCTEN, (1 << 0) + .equ CNTHCTL_PL1PCEN, (1 << 1) + + .equ ICC_HSRE_SRE, (1 << 0) + .equ ICC_HSRE_ENABLE, (1 << 3) + +/* IMP_PERIPHPREGIONR: peripheral port enables. Both reset to 0. */ + + .equ PERIPHP_ENABLE_EL10, (1 << 0) + .equ PERIPHP_ENABLE_EL2, (1 << 1) + +/* SCTLR/HSCTLR.TE -- Thumb Exception enable. Set means exceptions are entered + in T32 state. It RESETS SET on this part, and every vector table here is + A32, so it must be cleared or no handler is reachable. */ + + .equ SCTLR_TE, (1 << 30) + +/* CPSR mode and mask bits. */ + + .equ MODE_USR, 0x10 + .equ MODE_FIQ, 0x11 + .equ MODE_IRQ, 0x12 + .equ MODE_SVC, 0x13 + .equ MODE_ABT, 0x17 + .equ MODE_UND, 0x1B + .equ MODE_SYS, 0x1F + .equ PSR_F, 0x40 + .equ PSR_I, 0x80 + .equ PSR_A, 0x100 + +/* System counter frequency; see where it is programmed below. */ + + .equ SYSTEM_COUNTER_HZ, 8000000 + +/* Stage markers, recorded in boot_stage. */ + + .equ STAGE_A32, 1 /* switched out of Thumb */ + .equ STAGE_EL2_DONE, 2 /* EL2 configured */ + .equ STAGE_EL1, 3 /* running at EL1 */ + .equ STAGE_MAIN, 4 /* about to enter bsp_main */ + .equ STAGE_RETURNED, 5 /* bsp_main returned (unexpected) */ + .equ STAGE_FAULT, 0xFF /* a fault handler ran */ + +@/**************************************************************************/ +@/* Observation area. In .data so the debugger's load initialises it and */ +@/* a store needs no stack. */ +@/**************************************************************************/ + + .section .data + .align 2 + + .global boot_stage +boot_stage: .word 0 + .global cpsr_at_el2 +cpsr_at_el2: .word 0 + .global cpsr_at_el1 +cpsr_at_el1: .word 0 + .global cntfrq_at_el2 +cntfrq_at_el2: .word 0 + .global hmpuir_at_el2 +hmpuir_at_el2: .word 0 + .global probe_stage +probe_stage: .word 0 + .global fault_expected +fault_expected: .word 0 + .global fault_taken +fault_taken: .word 0 + .global fault_expected_pabt +fault_expected_pabt: .word 0 + .global abort_return +abort_return: .word 0 + .global fault_vector +fault_vector: .word 0 + .global fault_syndrome +fault_syndrome: .word 0 + .global fault_address +fault_address: .word 0 + +@/**************************************************************************/ +@/* EL2 (Hyp) vector table. 32-byte aligned for HVBAR. */ +@/* */ +@/* Offsets 0x04-0x10 are exceptions taken FROM Hyp mode. Everything */ +@/* routed to EL2 from EL1 or EL0 arrives at 0x14 instead and is decoded */ +@/* from HSR.EC -- the single funnel that partitioning work will use. */ +@/**************************************************************************/ + + .section .vectors_el2, "ax" + .align 5 + .arm + .global el2_vectors +el2_vectors: + b fault_el2_reset /* 0x00 */ + b fault_el2_undef /* 0x04 */ + b fault_el2_svc /* 0x08 */ + b fault_el2_pabt /* 0x0C */ + b fault_el2_dabt /* 0x10 */ + b fault_el2_hyp /* 0x14 from EL1/EL0 */ + b fault_el2_irq /* 0x18 */ + b fault_el2_fiq /* 0x1C */ + +@/**************************************************************************/ +@/* EL1 vector table. */ +@/**************************************************************************/ + + .section .vectors_el1, "ax" + .align 5 + .arm + .global el1_vectors +el1_vectors: + b fault_el1_reset /* 0x00 */ + b fault_el1_undef /* 0x04 */ + b fault_el1_svc /* 0x08 */ + b fault_el1_pabt /* 0x0C */ + b fault_el1_dabt /* 0x10 */ + b fault_el1_reserved /* 0x14 */ + b el1_irq_entry /* 0x18 IRQ */ + b fault_el1_fiq /* 0x1C */ + +@/**************************************************************************/ +@/* _start -- reset entry. Entered in THUMB state, Hyp mode (EL2). */ +@/**************************************************************************/ + + .section .text.boot, "ax" + .thumb + .align 1 + .global _start + .type _start, %function +_start: + /* Leave Thumb before anything else. start_a32 is an A32 symbol, so the + linker clears bit 0 of its address and BX switches state. */ + + ldr r0, =start_a32 + bx r0 + + .arm + .align 2 + .type start_a32, %function +start_a32: + ldr r0, =boot_stage + mov r1, #STAGE_A32 + str r1, [r0] + + /* Hyp stack, before anything can be pushed at EL2. */ + + ldr sp, =__hyp_stack_top + + /* Install the EL2 vector table. */ + + ldr r0, =el2_vectors + mcr p15, 4, r0, c12, c0, 0 /* HVBAR */ + isb + + /* Keep exceptions and interrupts routed to EL1 and the stage-2 MPU off. + HCR_HCD is cleared explicitly so HVC works from EL1 rather than + depending on its reset value. */ + + mrc p15, 4, r0, c1, c1, 0 /* HCR */ + ldr r1, =(HCR_TGE | HCR_AMO | HCR_IMO | HCR_FMO | HCR_VM | HCR_HCD) + bic r0, r0, r1 + mcr p15, 4, r0, c1, c1, 0 + isb + + /* Let EL1 reach the FPU: clear HCPTR.TCP10/TCP11. The R52 always has at + least a single-precision FPU, so this matters even for a soft-float + kernel if application code uses it. */ + + mrc p15, 4, r0, c1, c1, 2 /* HCPTR */ + ldr r1, =HCPTR_TCP + bic r0, r0, r1 + mcr p15, 4, r0, c1, c1, 2 + isb + + /* Record CNTFRQ as found. Deliberately not written: see the file + header. */ + + mrc p15, 0, r0, c14, c0, 0 /* CNTFRQ as found */ + ldr r1, =cntfrq_at_el2 + str r0, [r1] + + /* Program CNTFRQ. It is writable only at the highest implemented + exception level, so it must happen here rather than in bsp_main. + CNTFRQ is a software-declared constant: nothing derives it from the + hardware, and it reads zero out of reset on this silicon exactly as it + does on the FVP. Any code computing a tick interval from it would + divide by zero. + + 8 MHz is not a guess. The counter was measured against host wall-clock + time at 8.0227 MHz over a 32-second interval, and the clock tree agrees: + RTU.GPR CFG_CNTDV reads 4, so the divider is (4+1) = 5, and the board's + FXOSC is 40 MHz -- itself confirmed independently by the LINFlexD baud + divisors the BootROM left behind. 40 / 5 = 8. */ + + ldr r0, =SYSTEM_COUNTER_HZ + mcr p15, 0, r0, c14, c0, 0 /* CNTFRQ */ + + /* HMPUIR is EL2-only, so it has to be read here rather than in bsp_main. + It gives the EL2 MPU region count, which stage-2 partitioning needs and + which the EL1 MPUIR does not report. */ + + mrc p15, 4, r0, c0, c0, 4 /* HMPUIR */ + ldr r1, =hmpuir_at_el2 + str r0, [r1] + + /* Permit EL1/EL0 use of the physical counter and timer; both reset + disabled, so an EL1 access to CNTPCT or CNTP_* would otherwise trap. */ + + mrc p15, 4, r0, c14, c1, 0 /* CNTHCTL */ + orr r0, r0, #(CNTHCTL_PL1PCTEN | CNTHCTL_PL1PCEN) + mcr p15, 4, r0, c14, c1, 0 + isb + + /* Permit EL1 to reach the GIC CPU interface through ICC_* system + registers. Needs no GIC base address, so it is safe to do here even + though the distributor address for this part is not yet established. */ + + mrc p15, 4, r0, c12, c9, 5 /* ICC_HSRE */ + orr r0, r0, #(ICC_HSRE_SRE | ICC_HSRE_ENABLE) + mcr p15, 4, r0, c12, c9, 5 + isb + + /* Clear HSCTLR.TE so EL2 exceptions are entered in A32, matching the EL2 + vector table. See the EL1 equivalent below for why this matters. */ + + mrc p15, 4, r0, c1, c0, 0 /* HSCTLR */ + bic r0, r0, #SCTLR_TE + mcr p15, 4, r0, c1, c0, 0 + isb + + /* Open the low-latency peripheral port. + IMP_PERIPHPREGIONR (Cortex-R52 TRM r1p3, 3.3.80) describes a region at + 0x76000000 of 4 MB on this part -- the RTU peripheral space -- with + separate enables for EL2 and EL1/0 that BOTH RESET TO ZERO. Until they + are set, any access in that window stalls the core: no abort, no fault + handler, no exception at all, and the debug connection drops with it. + Nothing in the SoC reference manual mentions this; it cost a run before + the TRM identified it. Written here because EL1 writes to this register + trap to EL2 when HACTLR.PERIPHPREGIONR is clear. */ + + mrc p15, 0, r0, c15, c0, 0 /* IMP_PERIPHPREGIONR */ + orr r0, r0, #(PERIPHP_ENABLE_EL2 | PERIPHP_ENABLE_EL10) + mcr p15, 0, r0, c15, c0, 0 + isb + + /* Record CPSR while still at EL2: mode bits should read 0x1A (Hyp). */ + + mrs r0, cpsr + ldr r1, =cpsr_at_el2 + str r0, [r1] + + ldr r0, =boot_stage + mov r1, #STAGE_EL2_DONE + str r1, [r0] + + /* Drop to EL1 (Supervisor), interrupts still masked. */ + + ldr r0, =el1_entry + msr ELR_hyp, r0 + ldr r0, =(PSR_A | PSR_I | PSR_F | MODE_SVC) + msr SPSR_hyp, r0 + isb + eret + +@/**************************************************************************/ +@/* el1_entry -- first instruction at EL1. */ +@/**************************************************************************/ + + .align 2 + .type el1_entry, %function +el1_entry: + ldr r0, =boot_stage + mov r1, #STAGE_EL1 + str r1, [r0] + + /* EL1 vector table. */ + + ldr r0, =el1_vectors + mcr p15, 0, r0, c12, c0, 0 /* VBAR */ + isb + + /* Clear SCTLR.TE. This is not cosmetic and it cost a long detour. + * + * TE resets SET on this silicon -- SCTLR reads 0x70C50838, bit 30 high -- + * which makes the core enter every exception in T32 state. All the vector + * tables here are A32. So an exception would branch into the table, decode + * the A32 branch as Thumb, land mid-instruction at a misaligned address and + * take an undefined-instruction exception, which then did the same thing + * again. No handler ever ran. + * + * The consequence was worse than a crash: every fault became invisible. + * boot_stage stayed at its last value, fault_vector stayed zero, and the + * core sat at el1_vectors+4 -- so a data abort from an unmapped peripheral, + * an abort from a bad MPU map, and a correctly delivered timer interrupt all + * presented identically, as an unexplained hang with nothing recorded. Two + * real bugs were diagnosed through that fog before its cause was found. + * + * The Armv8-R AEM FVP resets with TE clear, which is why the same vector + * tables work there and why this never appeared during the FVP work. */ + + mrc p15, 0, r0, c1, c0, 0 /* SCTLR */ + bic r0, r0, #SCTLR_TE + mcr p15, 0, r0, c1, c0, 0 + isb + + /* One stack per mode: an exception taken inside a handler would + otherwise reuse the interrupted mode's stack pointer. */ + + mrs r0, cpsr + bic r0, r0, #0x1F + + orr r1, r0, #MODE_IRQ + msr cpsr_c, r1 + ldr sp, =__irq_stack_top + + orr r1, r0, #MODE_FIQ + msr cpsr_c, r1 + ldr sp, =__fiq_stack_top + + orr r1, r0, #MODE_ABT + msr cpsr_c, r1 + ldr sp, =__abt_stack_top + + orr r1, r0, #MODE_UND + msr cpsr_c, r1 + ldr sp, =__und_stack_top + + orr r1, r0, #MODE_SYS + msr cpsr_c, r1 + ldr sp, =__sys_stack_top + + orr r1, r0, #MODE_SVC + msr cpsr_c, r1 + ldr sp, =__svc_stack_top + + /* Zero .bss. Nothing above this point may rely on a .bss object. */ + + ldr r0, =__bss_start__ + ldr r1, =__bss_end__ + mov r2, #0 +bss_loop: + cmp r0, r1 + strlo r2, [r0], #4 + blo bss_loop + + /* Record CPSR at EL1: mode bits should read 0x13 (Supervisor), which is + what proves the EL2 to EL1 drop actually happened. */ + + mrs r0, cpsr + ldr r1, =cpsr_at_el1 + str r0, [r1] + + ldr r0, =boot_stage + mov r1, #STAGE_MAIN + str r1, [r0] + + bl bsp_main + + /* bsp_main is not expected to return. */ + + ldr r0, =boot_stage + mov r1, #STAGE_RETURNED + str r1, [r0] +park: + b park + +@/**************************************************************************/ +@/**************************************************************************/ +@/* el1_irq_entry -- IRQ vector, standalone. */ +@/* */ +@/* The FVP example routes IRQ through _tx_thread_context_save and */ +@/* __tx_irq_processing_return, which this image cannot do: it does not */ +@/* link ThreadX, deliberately, so that a failure here is a board problem */ +@/* and not a kernel one. This is the classic A32 form instead. */ +@/* */ +@/* lr is adjusted by 4 because an IRQ is taken with lr pointing one */ +@/* instruction past the one that was interrupted. The caret on the ldm */ +@/* restores CPSR from SPSR_irq as it loads pc, which is what returns to */ +@/* the interrupted mode rather than staying in IRQ mode. */ +@/**************************************************************************/ + + .align 2 + .global el1_irq_entry + .type el1_irq_entry, %function +el1_irq_entry: +#ifdef TX_R52_USE_THREADX_IRQ + + /* With the kernel linked, the vector goes straight into + _tx_thread_context_save, which saves the interrupted context and + branches back to __tx_irq_processing_return. A plain B, not BL: + context save adjusts lr itself to find the point of interrupt. */ + + b _tx_thread_context_save + + .global __tx_irq_processing_return +__tx_irq_processing_return: + bl board_irq_handler + b _tx_thread_context_restore + +#else + + /* Standalone: the classic A32 form. lr is adjusted by 4 because an IRQ + is taken with lr one instruction past the interrupted one, and the + caret on the ldm restores CPSR from SPSR_irq as it loads pc. */ + + sub lr, lr, #4 + stmfd sp!, {r0-r3, r12, lr} + bl board_irq_handler + ldmfd sp!, {r0-r3, r12, pc}^ + +#endif + +@/**************************************************************************/ +@/* try_execute_data -- branch to a non-executable address on purpose. */ +@/* */ +@/* Saves its own return address for the prefetch-abort handler to use, */ +@/* arms that handler, then branches to the address in r0. It never */ +@/* returns by itself: the abort handler returns on its behalf. Written */ +@/* in assembly because the return path is not something C can express. */ +@/**************************************************************************/ + + .align 2 + .global try_execute_data + .type try_execute_data, %function +try_execute_data: + ldr r1, =abort_return + str lr, [r1] + ldr r1, =fault_expected_pabt + mov r2, #1 + str r2, [r1] + dsb + isb + bx r0 /* fetch from XN memory: aborts */ + +@/* Fault reporters. Each records which vector ran, a syndrome and a */ +@/* faulting address, then parks. Recording before parking is what makes */ +@/* a fault distinguishable from a hang when there is no console. */ +@/**************************************************************************/ + +@/* Each handler loads its syndrome into r0 and a faulting or return */ +@/* address into r3, then falls into FAULT_TAIL. The instructions are not*/ +@/* passed as macro arguments: GNU as macro arguments are textual, and */ +@/* an instruction containing a comma cannot be passed without quoting, */ +@/* whose handling differs between assembler versions. */ + + .macro FAULT_TAIL vecid + ldr r1, =fault_vector + mov r2, #\vecid + str r2, [r1] + ldr r1, =fault_syndrome + str r0, [r1] + ldr r1, =fault_address + str r3, [r1] + ldr r1, =boot_stage + mov r2, #STAGE_FAULT + str r2, [r1] +1: b 1b + .endm + + .align 2 + +fault_el2_reset: + mov r0, #0 + mov r3, lr + FAULT_TAIL 0x20 +fault_el2_undef: + mov r0, #0 + mov r3, lr + FAULT_TAIL 0x24 +fault_el2_svc: + mov r0, #0 + mov r3, lr + FAULT_TAIL 0x28 +fault_el2_pabt: + mrc p15, 4, r0, c5, c1, 0 /* HSR */ + mov r3, lr + FAULT_TAIL 0x2C +fault_el2_dabt: + mrc p15, 4, r0, c5, c1, 0 /* HSR */ + mrc p15, 4, r3, c6, c0, 0 /* HDFAR */ + FAULT_TAIL 0x30 +fault_el2_hyp: + mrc p15, 4, r0, c5, c2, 0 /* HSR (EC identifies the trap) */ + mrc p15, 4, r3, c6, c0, 0 /* HDFAR */ + FAULT_TAIL 0x34 +fault_el2_irq: + mov r0, #0 + mov r3, lr + FAULT_TAIL 0x38 +fault_el2_fiq: + mov r0, #0 + mov r3, lr + FAULT_TAIL 0x3C + +fault_el1_reset: + mov r0, #0 + mov r3, lr + FAULT_TAIL 0x40 +fault_el1_undef: + mov r0, #0 + mov r3, lr + FAULT_TAIL 0x44 +fault_el1_svc: + mov r0, #0 + mov r3, lr + FAULT_TAIL 0x48 +fault_el1_pabt: + /* Recoverable when a test has armed fault_expected_pabt. + * + * Recovery differs from the data-abort case in kind, not degree. There, + * the faulting instruction is a load or store and skipping it is enough. + * Here the fault is on the instruction FETCH at the target address, so + * there is no instruction to skip -- resuming anywhere near the fault + * just faults again. So the test saves the address it wants to come back + * to in abort_return, and this handler returns there on its behalf. */ + + ldr r0, =fault_expected_pabt + ldr r1, [r0] + cmp r1, #0 + beq fault_el1_pabt_fatal + + mov r1, #0 + str r1, [r0] /* one-shot: disarm */ + + mrc p15, 0, r2, c5, c0, 1 /* IFSR */ + ldr r0, =fault_syndrome + str r2, [r0] + mrc p15, 0, r2, c6, c0, 2 /* IFAR */ + ldr r0, =fault_address + str r2, [r0] + ldr r0, =fault_vector + mov r1, #0x4C + str r1, [r0] + ldr r0, =fault_taken + ldr r1, [r0] + add r1, r1, #1 + str r1, [r0] + dsb + + ldr lr, =abort_return + ldr lr, [lr] + subs pc, lr, #0 /* return to the test, not here */ + +fault_el1_pabt_fatal: + mrc p15, 0, r0, c5, c0, 1 /* IFSR */ + mrc p15, 0, r3, c6, c0, 2 /* IFAR */ + FAULT_TAIL 0x4C +fault_el1_dabt: + /* Recoverable when a test has armed fault_expected. The protection map is + only meaningful if a violation actually faults, so the test provokes one + deliberately and this path lets it continue: record the syndrome and + address, count it, then resume at the instruction AFTER the faulting one. + lr on data-abort entry is faulting_address + 8, so subs pc, lr, #4 skips + the access rather than retrying it forever. + + Without the flag set, a data abort is still fatal and reported, which is + what any real bug should get. */ + + ldr r0, =fault_expected + ldr r1, [r0] + cmp r1, #0 + beq fault_el1_dabt_fatal + + mov r1, #0 + str r1, [r0] /* one-shot: disarm */ + + mrc p15, 0, r2, c5, c0, 0 /* DFSR */ + ldr r0, =fault_syndrome + str r2, [r0] + mrc p15, 0, r2, c6, c0, 0 /* DFAR */ + ldr r0, =fault_address + str r2, [r0] + ldr r0, =fault_vector + mov r1, #0x50 + str r1, [r0] + ldr r0, =fault_taken + ldr r1, [r0] + add r1, r1, #1 + str r1, [r0] + dsb + subs pc, lr, #4 /* resume after the access */ + +fault_el1_dabt_fatal: + mrc p15, 0, r0, c5, c0, 0 /* DFSR */ + mrc p15, 0, r3, c6, c0, 0 /* DFAR */ + FAULT_TAIL 0x50 +fault_el1_reserved: + mov r0, #0 + mov r3, lr + FAULT_TAIL 0x54 +fault_el1_irq: + mov r0, #0 + mov r3, lr + FAULT_TAIL 0x58 +fault_el1_fiq: + mov r0, #0 + mov r3, lr + FAULT_TAIL 0x5C diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/gic_probe.c b/ports/cortex_r52/gnu/example_build/s32z280_evb/gic_probe.c new file mode 100644 index 000000000..b861ae5bc --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/gic_probe.c @@ -0,0 +1,72 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* BOARD SUPPORT RELEASE */ +/* */ +/* gic_probe.c Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frederic Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Asks the core where its GIC is, and whether it can be reached. */ +/* */ +/* A load from the GIC window NXP documents for this cluster stalls */ +/* the core outright, so nothing here touches memory. Both values */ +/* below are system registers: reading them cannot hang the bus. */ +/* */ +/* IMP_CBAR holds the physical base address of the memory-mapped GIC */ +/* distributor -- bits [31:21], wired by the SoC's CFGPERIPHBASE */ +/* input. That is the authoritative answer, as against an address */ +/* taken from a vendor debugger script. */ +/* */ +/* IMP_PERIPHPREGIONR describes the low-latency peripheral port: base */ +/* address in [31:12], size in [6:2], and separate enables for EL2 */ +/* (bit 1) and EL1/0 (bit 0). If the port is disabled, accesses in */ +/* its window go nowhere, which is what a stalled load looks like. */ +/* */ +/* Both from the Cortex-R52 TRM r1p3 (100026_0103_00_en), sections */ +/* 3.3.17 and 3.3.80 -- the SoC reference manual documents neither. */ +/* */ +/* MISRA C:2012 deviations (justified) */ +/* */ +/* Dir 4.3 -- assembly encapsulated one access per function. */ +/* */ +/**************************************************************************/ + +#include "gic_probe.h" + +unsigned int gic_read_cbar(void) +{ + unsigned int value; + + __asm volatile ("mrc p15, 1, %0, c15, c3, 0" : "=r" (value)); + + return value; +} + + +unsigned int gic_read_periphpregionr(void) +{ + unsigned int value; + + __asm volatile ("mrc p15, 0, %0, c15, c0, 0" : "=r" (value)); + + return value; +} diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/gic_probe.h b/ports/cortex_r52/gnu/example_build/s32z280_evb/gic_probe.h new file mode 100644 index 000000000..eaa992de3 --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/gic_probe.h @@ -0,0 +1,44 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* BOARD SUPPORT RELEASE */ +/* */ +/* gic_probe.h Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frederic Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Where the GIC is, and whether the peripheral port reaches it. */ +/* */ +/**************************************************************************/ + +#ifndef GIC_PROBE_H +#define GIC_PROBE_H + +/* IMP_CBAR[31:21] = PERIPHBASE, the GIC distributor base. */ + +unsigned int gic_read_cbar(void); + +/* IMP_PERIPHPREGIONR: LLPP base [31:12], size [6:2], EL2 enable bit 1, + EL1/0 enable bit 0. */ + +unsigned int gic_read_periphpregionr(void); + +#endif /* GIC_PROBE_H */ diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/gicv3.c b/ports/cortex_r52/gnu/example_build/s32z280_evb/gicv3.c new file mode 100644 index 000000000..4a1925094 --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/gicv3.c @@ -0,0 +1,215 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* BOARD SUPPORT RELEASE */ +/* */ +/* gicv3.c Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frédéric Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* GICv3 bring-up for Cortex-R52 on the Armv8-R AEM FVP. */ +/* */ +/* Model characteristics that shape this code, taken from its own */ +/* parameters rather than assumed: */ +/* */ +/* has-two-security-states=0 single security state, so GICD_CTLR.DS */ +/* reads 1 and the Group 1 enable is bit 1*/ +/* ARE-fixed-to-one=1 affinity routing cannot be turned off */ +/* priority-bits=5 only the top 5 priority bits exist, so */ +/* priorities must be multiples of 8 */ +/* */ +/* MISRA C:2012 deviations (justified) */ +/* */ +/* Directive 4.3 -- the CPU interface is only reachable through CP15 */ +/* system registers, so inline assembly is unavoidable. Every such */ +/* access is encapsulated in a one-line accessor below and appears */ +/* nowhere else. */ +/* Rule 11.4/11.6 -- casting integer addresses to volatile pointers is */ +/* inherent to memory-mapped device access; confined to REG32. */ +/* */ +/**************************************************************************/ + +#include "platform.h" +#include "gicv3.h" + +/* Distributor registers. */ + +#define GICD_CTLR 0x0000U +#define GICD_CTLR_ENABLE_GRP1 (1UL << 1) +#define GICD_CTLR_ARE (1UL << 4) + +/* Redistributor RD frame. */ + +#define GICR_WAKER 0x0014U +#define GICR_WAKER_PROC_SLEEP (1UL << 1) +#define GICR_WAKER_CHILD_ASLEEP (1UL << 2) + +/* Redistributor SGI frame (SGIs and PPIs, INTID 0-31). */ + +#define GICR_IGROUPR0 0x0080U +#define GICR_ISENABLER0 0x0100U +#define GICR_IPRIORITYR 0x0400U +#define GICR_ICFGR1 0x0C04U + +#define ICC_PMR_UNMASK_ALL 0xFFUL +#define ICC_SRE_SRE (1UL << 0) +#define ICC_IGRPEN1_ENABLE (1UL << 0) + +#define PPI_FIRST_INTID 16U + + +/**************************************************************************/ +/* CPU interface accessors (AArch32 ICC_* system registers). */ +/**************************************************************************/ + +static unsigned long read_icc_sre(void) +{ + unsigned long value; + __asm__ volatile("mrc p15, 0, %0, c12, c12, 5" : "=r"(value)); + return value; +} + +static void write_icc_sre(unsigned long value) +{ + __asm__ volatile("mcr p15, 0, %0, c12, c12, 5" : : "r"(value) : "memory"); +} + +static void write_icc_pmr(unsigned long value) +{ + __asm__ volatile("mcr p15, 0, %0, c4, c6, 0" : : "r"(value) : "memory"); +} + +static void write_icc_bpr1(unsigned long value) +{ + __asm__ volatile("mcr p15, 0, %0, c12, c12, 3" : : "r"(value) : "memory"); +} + +static void write_icc_igrpen1(unsigned long value) +{ + __asm__ volatile("mcr p15, 0, %0, c12, c12, 7" : : "r"(value) : "memory"); +} + +static void instruction_barrier(void) +{ + __asm__ volatile("isb" : : : "memory"); +} + + +/**************************************************************************/ +/* gicv3_init */ +/**************************************************************************/ + +void gicv3_init(void) +{ + unsigned long waker; + + /* Distributor: affinity routing first, then the Group 1 enable. With a + single security state Group 1 is bit 1 of GICD_CTLR. */ + + REG32(GICD_BASE + GICD_CTLR) |= GICD_CTLR_ARE; + REG32(GICD_BASE + GICD_CTLR) |= GICD_CTLR_ENABLE_GRP1; + + /* Redistributor: clear ProcessorSleep and wait for the redistributor to + report that its children are awake, otherwise no interrupt can be + delivered to this core. */ + + waker = REG32(GICR_RD_BASE + GICR_WAKER); + waker &= ~GICR_WAKER_PROC_SLEEP; + REG32(GICR_RD_BASE + GICR_WAKER) = waker; + + while ((REG32(GICR_RD_BASE + GICR_WAKER) & GICR_WAKER_CHILD_ASLEEP) != 0UL) + { + /* Wait for the redistributor to wake. */ + } + + /* CPU interface: system-register access, then unmask all priorities and + enable Group 1. EL2 has already permitted EL1 system-register access + via ICC_HSRE in entry.S. */ + + write_icc_sre(read_icc_sre() | ICC_SRE_SRE); + instruction_barrier(); + + write_icc_pmr(ICC_PMR_UNMASK_ALL); + write_icc_bpr1(0UL); + write_icc_igrpen1(ICC_IGRPEN1_ENABLE); + instruction_barrier(); +} + + +/**************************************************************************/ +/* gicv3_enable_ppi */ +/**************************************************************************/ + +void gicv3_enable_ppi(unsigned int intid, unsigned int priority) +{ + unsigned long shift; + + if ((intid < PPI_FIRST_INTID) || (intid > 31U)) + { + return; + } + + /* Group 1. */ + + REG32(GICR_SGI_BASE + GICR_IGROUPR0) |= (1UL << intid); + + /* Priority is a byte per INTID. Only the top 5 bits are implemented on + this model, so callers pass multiples of 8. */ + + REG32(GICR_SGI_BASE + GICR_IPRIORITYR + (intid & ~3U)) &= + ~(0xFFUL << ((intid & 3U) * 8U)); + REG32(GICR_SGI_BASE + GICR_IPRIORITYR + (intid & ~3U)) |= + ((unsigned long) priority & 0xFFUL) << ((intid & 3U) * 8U); + + /* Level-sensitive: two configuration bits per INTID, 00 = level. The + generic timer asserts a level, not an edge. */ + + shift = ((unsigned long) intid - PPI_FIRST_INTID) * 2UL; + REG32(GICR_SGI_BASE + GICR_ICFGR1) &= ~(3UL << shift); + + /* Enable. */ + + REG32(GICR_SGI_BASE + GICR_ISENABLER0) = (1UL << intid); +} + + +/**************************************************************************/ +/* gicv3_acknowledge */ +/**************************************************************************/ + +unsigned long gicv3_acknowledge(void) +{ + unsigned long intid; + + __asm__ volatile("mrc p15, 0, %0, c12, c12, 0" : "=r"(intid)); + + return intid; +} + + +/**************************************************************************/ +/* gicv3_end_of_interrupt */ +/**************************************************************************/ + +void gicv3_end_of_interrupt(unsigned long intid) +{ + __asm__ volatile("mcr p15, 0, %0, c12, c12, 1" : : "r"(intid) : "memory"); +} diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/gicv3.h b/ports/cortex_r52/gnu/example_build/s32z280_evb/gicv3.h new file mode 100644 index 000000000..cc35639c0 --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/gicv3.h @@ -0,0 +1,61 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* BOARD SUPPORT RELEASE */ +/* */ +/* gicv3.h Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frédéric Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* GICv3 interrupt controller for Cortex-R52. The CPU interface is */ +/* reached through AArch32 ICC_* system registers; the Distributor and */ +/* Redistributor are memory mapped. */ +/* */ +/**************************************************************************/ + +#ifndef GICV3_H +#define GICV3_H + +/* Spurious interrupt ID returned by the CPU interface when no interrupt is + pending. It must be neither dispatched nor acknowledged with EOI. */ + +#define GICV3_SPURIOUS_INTID 1023UL + +/* Bring up the Distributor, this core's Redistributor and the CPU + interface. Interrupts remain masked at the PSTATE level. */ + +void gicv3_init(void); + +/* Enable one private peripheral interrupt (PPI, INTID 16-31) as a + level-sensitive Group 1 interrupt at the given priority. */ + +void gicv3_enable_ppi(unsigned int intid, unsigned int priority); + +/* Acknowledge the highest-priority pending Group 1 interrupt, returning its + INTID (possibly GICV3_SPURIOUS_INTID). */ + +unsigned long gicv3_acknowledge(void); + +/* Signal completion of the interrupt previously acknowledged. */ + +void gicv3_end_of_interrupt(unsigned long intid); + +#endif /* GICV3_H */ diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/irq_dispatch.c b/ports/cortex_r52/gnu/example_build/s32z280_evb/irq_dispatch.c new file mode 100644 index 000000000..8c4012e5d --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/irq_dispatch.c @@ -0,0 +1,145 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* BOARD SUPPORT RELEASE */ +/* */ +/* irq_dispatch.c Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frederic Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Interrupt dispatch for the S32Z280-594EVB, standalone. */ +/* */ +/* Called from el1_irq_entry in entry.S. Unlike the FVP example this */ +/* does not call _tx_timer_interrupt: the image does not link ThreadX, */ +/* so a failure here is a board or GIC problem and not a kernel one. */ +/* It counts ticks instead, which is what makes the interrupt visible. */ +/* */ +/* Every count is volatile and read by the debugger as well as printed.*/ +/* An interrupt that never arrives and an interrupt that arrives and is*/ +/* mishandled look identical from the console alone, and the separate */ +/* spurious and unexpected counters distinguish them. */ +/* */ +/**************************************************************************/ + +#include "gicv3.h" +#include "timer.h" +#include "board.h" +#include "mpu.h" +#ifdef TX_R52_USE_THREADX_IRQ +#include "tx_api.h" + +/* ThreadX periodic timer entry point. Assembly, and internal to the kernel, + so it is not declared by tx_api.h. Safe to call from C: it uses only r0-r3 + and returns through lr like an ordinary function. */ + +extern void _tx_timer_interrupt(void); +#endif + +/* Observable from both the console and a debugger. */ + +volatile unsigned long board_irq_count; +volatile unsigned long board_timer_intid; +volatile unsigned long board_spurious_count; +volatile unsigned long board_unexpected_intid; +volatile unsigned long board_first_intid = 0xFFFFFFFFUL; + +/* The EL1 physical timer PPI. 30 is the architectural assignment and is what + the FVP turned out to use, but it was discovered there by enabling the whole + PPI range and recording whichever INTID arrived in ICC_IAR1 rather than by + assuming. board_timer_intid records what actually arrives here, so a wrong + value shows up as an unexpected INTID rather than as silence. */ + +#define TIMER_PPI_INTID 30U + +/* Only the top priority bits are implemented; hence a multiple of 8. */ + +#define TIMER_PPI_PRIORITY 0xA0U + + +#ifdef TX_R52_USE_THREADX_IRQ + +/**************************************************************************/ +/* board_init -- called from _tx_initialize_low_level. */ +/* */ +/* Order matters. mpu_init() must run before anything touches the GIC: */ +/* the distributor is unreachable until its region is mapped Device */ +/* nGnRnE, and an access before that aborts. Arming the timer here is */ +/* safe because interrupts stay masked until _tx_thread_schedule enables */ +/* them, so no tick can arrive before the kernel can service one. */ +/**************************************************************************/ + +void board_init(void) +{ + (void) mpu_init(); + gicv3_init(); + gicv3_enable_ppi(TIMER_PPI_INTID, TIMER_PPI_PRIORITY); + + /* One tick every 10 ms at the measured 8 MHz counter rate. */ + + timer_start_oneshot_irq(timer_read_cntfrq() / 100U); +} + +#endif + + +void board_irq_handler(void) +{ + unsigned long intid = gicv3_acknowledge(); + + if (intid == GICV3_SPURIOUS_INTID) + { + /* Nothing was actually pending. Must not be acknowledged with an + end-of-interrupt write, so return without one. */ + + board_spurious_count++; + return; + } + + if (board_first_intid == 0xFFFFFFFFUL) + { + board_first_intid = intid; /* whatever actually arrived */ + } + + if (intid == (unsigned long) TIMER_PPI_INTID) + { + board_timer_intid = intid; + board_irq_count++; + + /* Re-arm first. The generic timer output is level-sensitive, so until + the compare is moved forward the condition stays asserted and the + interrupt would be taken again immediately on return. */ + + timer_start_oneshot_irq(timer_read_cntfrq() / 100U); + +#ifdef TX_R52_USE_THREADX_IRQ + /* Drive the kernel's time base. Called after the re-arm so the next + interval is already running while the kernel does its bookkeeping. */ + + _tx_timer_interrupt(); +#endif + } + else + { + board_unexpected_intid = intid; + } + + gicv3_end_of_interrupt(intid); +} diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/linflexd.c b/ports/cortex_r52/gnu/example_build/s32z280_evb/linflexd.c new file mode 100644 index 000000000..0bd780697 --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/linflexd.c @@ -0,0 +1,242 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* BOARD SUPPORT RELEASE */ +/* */ +/* linflexd.c Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frédéric Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Polled console on LINFlex_9, which is the instance wired to the */ +/* S32Z280-594EVB daughtercard USB-UART through jumper J248. Not */ +/* LINFlex_0: that is simply the first instance in the Reference */ +/* Manual's list and reaches no connector on this board. */ +/* */ +/* BAUD RATE */ +/* */ +/* LINFlex_9 is clocked by P5_LIN_BAUD_CLK, which MC_CGM_5 MUX 2 */ +/* drives. Read from the board: MUX_2_CSS selects source 2 with the */ +/* divider set to 1, and the EVB carries a 40 MHz crystal (UG10268 */ +/* section 3.3.1.1), so the clock is 40 MHz. */ +/* */ +/* LFDIV = 40000000 / (16 * 115200) = 21.7014 */ +/* LINIBRR = 21 */ +/* LINFBRR = round(0.7014 * 16) = 11 */ +/* actual = 40000000 / (16 * 21.6875) = 115274 baud, 0.06% error */ +/* */ +/* Those are exactly the values the BootROM had already left in the */ +/* registers, which is what confirms the 40 MHz figure rather than */ +/* merely assuming it. They are programmed here anyway: inheriting */ +/* another program's register state makes this image's behaviour */ +/* depend on how the board was last booted. */ +/* */ +/* The BootROM's configuration is NOT reused for a second reason: it */ +/* leaves PCE set (parity enabled) and TxEn clear, because it is */ +/* listening for a serial-boot download rather than printing. A host */ +/* terminal set to 8N1 against that would show framing errors. */ +/* */ +/* MISRA C:2012 deviations (justified) */ +/* */ +/* Rule 11.4/11.6 -- casting integer addresses to volatile pointers is */ +/* inherent to memory-mapped device access; confined to REG32. */ +/* */ +/**************************************************************************/ + +#include "linflexd.h" +#include "platform.h" + +/* Register offsets, from the S32Z2 Reference Manual section 75.5.1. */ + +#define LINFLEXD_LINCR1 0x00U +#define LINFLEXD_LINSR 0x08U +#define LINFLEXD_UARTCR 0x10U +#define LINFLEXD_UARTSR 0x14U +#define LINFLEXD_LINFBRR 0x24U +#define LINFLEXD_LINIBRR 0x28U +#define LINFLEXD_BDRL 0x38U + +/* LINCR1 */ +#define LINCR1_INIT (1U << 0) /* initialisation mode */ +#define LINCR1_SLEEP (1U << 1) + +/* UARTCR. Bit positions verified against the register diagram; PCE at bit 2 + and TxEn at bit 4 are the two that matter here and are easy to transpose. */ +#define UARTCR_UART (1U << 0) /* UART rather than LIN mode */ +#define UARTCR_WL0 (1U << 1) /* with WL1 clear: 8-bit */ +#define UARTCR_PCE (1U << 2) /* parity enable */ +#define UARTCR_TXEN (1U << 4) +#define UARTCR_RXEN (1U << 5) + +/* UARTSR */ +#define UARTSR_DTF (1U << 1) /* transmit complete, w1c */ + +/* LINSR[15:12] is the LIN state; 0x1 is initialisation mode. Confirmed by + reading 0x2000 (idle) from the BootROM-configured module. */ +#define LINSR_LINS_MASK (0xFU << 12) +#define LINSR_LINS_INIT (0x1U << 12) + +/* Bounded rather than infinite: a console that hangs the boot is worse than + one that reports it could not configure itself. */ +#define LINFLEXD_INIT_GUARD 100000U + +/* 115200 from a 40 MHz P5_LIN_BAUD_CLK; see the file header. */ +#define LINFLEXD_IBRR_115200 21U +#define LINFLEXD_FBRR_115200 11U + +#define CONSOLE_BASE S32Z_LINFLEX_9_BASE + + +unsigned int linflexd_init(void) +{ + unsigned int status = LINFLEXD_INIT_OK; + unsigned int guard; + unsigned int wanted; + unsigned int got; + + /* Enter initialisation mode and WAIT until the module reports it. + Most of UARTCR is writable only in initialisation mode, and the module + does not enter it in the same cycle as the LINCR1 write. Configuring + without waiting silently half-works: bits being *set* take effect while + bits being *cleared* do not, so PCE stays enabled and the line runs 8E1 + against a host expecting 8N1 -- which corrupts only those characters + whose parity bit happens to be 0 and leaves the rest readable, looking + for all the world like a marginal baud rate. */ + + REG32(CONSOLE_BASE + LINFLEXD_LINCR1) = LINCR1_INIT; + + guard = LINFLEXD_INIT_GUARD; + while (((REG32(CONSOLE_BASE + LINFLEXD_LINSR) & LINSR_LINS_MASK) + != LINSR_LINS_INIT) && (guard > 0U)) + { + guard--; + } + + if (guard == 0U) + { + status |= LINFLEXD_INIT_NO_INITMODE; + } + + /* The UART bit gates writes to the rest of UARTCR, so it has to be set + before the fields that depend on it, not alongside them. */ + + REG32(CONSOLE_BASE + LINFLEXD_UARTCR) = UARTCR_UART; + + /* 8N1, transmit and receive. PCE deliberately left clear: the BootROM + enables parity for serial boot, and a host on 8N1 would see framing + errors. */ + + wanted = UARTCR_UART | UARTCR_WL0 | UARTCR_TXEN | UARTCR_RXEN; + REG32(CONSOLE_BASE + LINFLEXD_UARTCR) = wanted; + + REG32(CONSOLE_BASE + LINFLEXD_LINFBRR) = LINFLEXD_FBRR_115200; + REG32(CONSOLE_BASE + LINFLEXD_LINIBRR) = LINFLEXD_IBRR_115200; + + /* Read back before leaving initialisation mode. A write that was + silently ignored is the failure this driver already made once, so it is + checked rather than assumed. */ + + got = REG32(CONSOLE_BASE + LINFLEXD_UARTCR) & 0xFFU; + if (got != wanted) + { + status |= LINFLEXD_INIT_UARTCR_MISMATCH; + } + + /* Leave initialisation mode; the module starts operating. */ + + REG32(CONSOLE_BASE + LINFLEXD_LINCR1) = 0U; + + return status; +} + + +void linflexd_putc(char c) +{ + if (c == '\n') + { + linflexd_putc('\r'); + } + + unsigned int guard; + + /* Start the byte, wait for completion, clear the flag, then wait for the + clear to actually take effect. + * + * The last step is the subtle one. DTF is write-one-to-clear and does + * not de-assert in the same cycle as the clearing write, so without it + * the *next* byte's poll can observe this byte's flag, conclude the line + * is free while it is still busy, and have its write silently dropped by + * the transmitter. That cost exactly one character after every "\r\n" + * pair -- the only place two bytes are sent back to back -- and showed + * up as the first letter of every line going missing. + * + * Clearing *before* the write instead does not fix it and is worse: the + * write then lands while the previous byte is still shifting and is + * dropped, and the poll afterwards sees the previous byte's completion, + * so most of the output disappears. Order matters in both directions. + */ + + REG32(CONSOLE_BASE + LINFLEXD_BDRL) = (unsigned int)(unsigned char)c; + + /* Polled on purpose: this console runs before any interrupt controller is + configured, and it must work inside a fault handler. */ + + while ((REG32(CONSOLE_BASE + LINFLEXD_UARTSR) & UARTSR_DTF) == 0U) + { + /* wait for this byte to go out */ + } + + REG32(CONSOLE_BASE + LINFLEXD_UARTSR) = UARTSR_DTF; + + guard = LINFLEXD_INIT_GUARD; + while (((REG32(CONSOLE_BASE + LINFLEXD_UARTSR) & UARTSR_DTF) != 0U) + && (guard > 0U)) + { + guard--; + } +} + + +void linflexd_puts(const char *string) +{ + const char *p = string; + + if (p != (const char *)0) + { + while (*p != '\0') + { + linflexd_putc(*p); + p++; + } + } +} + + +void linflexd_put_hex32(unsigned int value) +{ + static const char digits[] = "0123456789ABCDEF"; + unsigned int shift = 32U; + + while (shift > 0U) + { + shift -= 4U; + linflexd_putc(digits[(value >> shift) & 0xFU]); + } +} diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/linflexd.h b/ports/cortex_r52/gnu/example_build/s32z280_evb/linflexd.h new file mode 100644 index 000000000..e1945733c --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/linflexd.h @@ -0,0 +1,61 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* BOARD SUPPORT RELEASE */ +/* */ +/* linflexd.h Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frédéric Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Polled transmit-only console on LINFlexD, for the S32Z280-594EVB. */ +/* */ +/**************************************************************************/ + +#ifndef LINFLEXD_H +#define LINFLEXD_H + +/* Status bits returned by linflexd_init(). */ + +#define LINFLEXD_INIT_OK 0x00U +#define LINFLEXD_INIT_NO_INITMODE 0x01U /* never entered init mode */ +#define LINFLEXD_INIT_UARTCR_MISMATCH 0x02U /* a write was ignored */ + +/* Configure LINFlex_9 for 115200 8N1 and enable the transmitter. Returns + LINFLEXD_INIT_OK, or a mask of the above. It is worth checking: writes to + UARTCR outside initialisation mode are silently dropped, which produces + output that looks like a baud-rate problem rather than a framing one. */ + +unsigned int linflexd_init(void); + +/* Blocking single character. Translates \n to \r\n so the output is + readable on a terminal that does not add the carriage return itself. */ + +void linflexd_putc(char c); + +void linflexd_puts(const char *string); + +/* Eight hex digits, no 0x prefix. Printing register values is the whole + reason this console exists, and a printf would drag in a C library this + image deliberately does not link. */ + +void linflexd_put_hex32(unsigned int value); + +#endif /* LINFLEXD_H */ diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/link.lds b/ports/cortex_r52/gnu/example_build/s32z280_evb/link.lds new file mode 100644 index 000000000..6200bb316 --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/link.lds @@ -0,0 +1,153 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/* Link map for the NXP S32Z280-594EVB, RTU0 core 0. + * + * Code goes to the RTU code SRAM at its instruction-fetch address, 0x79900000, + * which is also where the core resets: MC_ME_PRTN0_CORE0_ADDR reads 0x79900000 + * on this board, so a debugger-loaded image needs no relocation to be reached + * by the reset vector. That window is writable over the debug AXI port even + * though NXP's debugger memory map declares it read-only, so plain `load` + * works and no LMA alias is required. A flash-booted image is different: it + * would have to be written through the data alias at 0x32100000. + * + * Data, bss and the per-mode stacks go to the RTU-local data SRAM at + * 0x31780000. Keeping them out of the code SRAM avoids the boundary problem + * the FVP build hit, where an aligned .data start straddled the code/data + * split, and RTU-local traffic does not leave the RTU. + * + * The TCMs are deliberately unused: they are not accessible at reset until + * their region registers are programmed, so nothing needed for early boot can + * live there. + */ + +__hyp_stack_size__ = 0x0800; +__svc_stack_size__ = 0x1000; +__irq_stack_size__ = 0x0800; +__fiq_stack_size__ = 0x0400; +__abt_stack_size__ = 0x0400; +__und_stack_size__ = 0x0400; +__sys_stack_size__ = 0x0800; + +MEMORY +{ + CODE (rx) : ORIGIN = 0x79900000, LENGTH = 0x00700000 /* 7 MB */ + DATA (rwx) : ORIGIN = 0x31780000, LENGTH = 0x00040000 /* 256 KB */ +} + +ENTRY(_start) + +SECTIONS +{ + /* .text.boot must come FIRST: MC_ME_PRTN0_CORE0_ADDR is 0x79900000 on + * this board, so whatever lands at the start of CODE is what the core + * executes out of reset, and that has to be _start. It must also be a + * T32 instruction, since the core resets in Thumb state. The vector + * tables need alignment but not a fixed address, because HVBAR and VBAR + * are programmed at run time -- so they follow rather than lead. + */ + /* No ALIGN() address expression on any output section below. Written as + * " ALIGN(n) : { }" the ALIGN is the section's *address*, evaluated + * from a location counter that starts at zero, and it silently overrides + * "> CODE" -- every section then lands near address 0 and the link fails + * with "not within region". The FVP script uses that form harmlessly only + * because its region starts at 0x00000000. Alignment comes from the input + * sections (the vector tables carry .align 5) or from an explicit + * ". = ALIGN(n);" inside the braces. + */ + .boot : + { + KEEP(*(.text.boot)) + } > CODE + + .vectors_el2 : + { + KEEP(*(.vectors_el2)) + } > CODE + + .vectors_el1 : + { + KEEP(*(.vectors_el1)) + } > CODE + + .text : + { + *(.text*) + *(.glue_7) + *(.glue_7t) + } > CODE + + .rodata : + { + *(.rodata*) + . = ALIGN(4); + __code_end__ = .; + } > CODE + + .data : + { + . = ALIGN(8); + __data_start__ = .; + *(.data*) + . = ALIGN(8); + __data_end__ = .; + } > DATA + + .bss (NOLOAD) : + { + . = ALIGN(8); + __bss_start__ = .; + *(.bss*) + *(COMMON) + . = ALIGN(8); + __bss_end__ = .; + } > DATA + + /* Per-mode stacks. Each mode needs its own on an R-profile core: an + * exception taken while a handler is running would otherwise reuse the + * interrupted mode's stack pointer. + */ + .stacks (NOLOAD) : + { + . = ALIGN(8); + . = . + __hyp_stack_size__; + __hyp_stack_top = .; + . = ALIGN(8); + . = . + __svc_stack_size__; + __svc_stack_top = .; + . = ALIGN(8); + . = . + __irq_stack_size__; + __irq_stack_top = .; + . = ALIGN(8); + . = . + __fiq_stack_size__; + __fiq_stack_top = .; + . = ALIGN(8); + . = . + __abt_stack_size__; + __abt_stack_top = .; + . = ALIGN(8); + . = . + __und_stack_size__; + __und_stack_top = .; + . = ALIGN(8); + . = . + __sys_stack_size__; + __sys_stack_top = .; + } > DATA + + /* Both spellings: _tx_initialize_low_level publishes the first free + address to tx_application_define from _end, while C library conventions + use end. */ + + PROVIDE(end = .); + PROVIDE(_end = .); +} diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/mpu.c b/ports/cortex_r52/gnu/example_build/s32z280_evb/mpu.c new file mode 100644 index 000000000..33d909c25 --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/mpu.c @@ -0,0 +1,486 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* BOARD SUPPORT RELEASE */ +/* */ +/* mpu.c Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frédéric Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* PMSAv8-R memory protection for the NXP S32Z280-594EVB. */ +/* */ +/* Register model (AArch32): a region is selected through PRSELR and */ +/* then described by PRBAR (base, shareability, access permission, */ +/* execute-never) and PRLAR (inclusive limit, attribute index, enable).*/ +/* Both addresses have a 64-byte granule, so the low six bits of each */ +/* register hold attributes rather than address. Memory types come */ +/* from MAIR through the attribute index, not from the region itself. */ +/* */ +/* Caches are invalidated before being enabled. On this model they */ +/* come out of reset invalid, but silicon does not guarantee that, and */ +/* this code is meant to be the template the S32Z280 port starts from. */ +/* */ +/* MISRA C:2012 deviations (justified) */ +/* */ +/* Directive 4.3 -- the MPU, MAIR, SCTLR and cache maintenance are only*/ +/* reachable through CP15; every access is encapsulated in a one-line*/ +/* accessor below. */ +/* */ +/**************************************************************************/ + +#include "platform.h" + +/* Progress marker, mirrored into memory. Enabling the MPU can take the core + down in a way that records no fault and takes the console with it, so each + step here is stamped where a debugger can read it afterwards. */ + +extern unsigned int probe_stage; +#define MARK(n) do { probe_stage = (unsigned int)(n); } while (0) +#include "mpu.h" +#include "platform.h" + +/* Progress marker, mirrored into memory. Enabling the MPU can take the core + down in a way that records no fault and takes the console with it, so each + step here is stamped where a debugger can read it afterwards. */ + +extern unsigned int probe_stage; +#define MARK(n) do { probe_stage = (unsigned int)(n); } while (0) + +/* SCTLR bits. */ + +#define SCTLR_M (1UL << 0) /* MPU enable */ +#define SCTLR_C (1UL << 2) /* data cache enable */ +#define SCTLR_I (1UL << 12) /* instruction cache enable */ + +/* MAIR attribute bytes. Index 0 is Normal write-back read/write-allocate, + index 1 is Device-nGnRnE, matching MPU_ATTR_* in the header. */ + +#define MAIR_ATTR_NORMAL_WB 0xFFUL +#define MAIR_ATTR_DEVICE 0x00UL + +/* Boundaries supplied by the linker script, all 64-byte aligned. */ + +extern char __code_end__; +extern char __data_start__; +extern char __data_end__; + + +/**************************************************************************/ +/* The region table. */ +/* */ +/* Deliberately minimal and readable: code is read-only and executable, */ +/* everything writable is non-executable, and the peripheral half of the */ +/* address map is Device. A write-protected code region is the point -- */ +/* it is what makes the MPU do something observable, and AR2 extends the */ +/* same table with per-module regions. */ +/**************************************************************************/ + +/* Table capacity. The FVP example this file came from declared this as [3], + matching the three regions it programs; a five-region table then wrote past + the end of it, and the region-3 base assignment landed outside the array. + The region read back with base 0 and limit 0x763FFFFF, overlapping regions + 0-2, and PMSAv8-R makes overlapping regions UNPREDICTABLE -- which is what + killed the core on the SCTLR.M write. Named and guarded so the next map + cannot repeat it. */ + +#define MPU_TABLE_REGIONS 16U + +static MPU_REGION mpu_regions[MPU_TABLE_REGIONS]; +static unsigned int mpu_regions_used; + + +/**************************************************************************/ +/* CP15 accessors. */ +/**************************************************************************/ + +static unsigned long read_mpuir(void) +{ + unsigned long value; + __asm__ volatile("mrc p15, 0, %0, c0, c0, 4" : "=r"(value)); + return value; +} + +static unsigned long read_sctlr(void) +{ + unsigned long value; + __asm__ volatile("mrc p15, 0, %0, c1, c0, 0" : "=r"(value)); + return value; +} + +static void write_sctlr(unsigned long value) +{ + __asm__ volatile("mcr p15, 0, %0, c1, c0, 0" : : "r"(value) : "memory"); +} + +static void write_prselr(unsigned long value) +{ + __asm__ volatile("mcr p15, 0, %0, c6, c2, 1" : : "r"(value) : "memory"); +} + +static void write_prbar(unsigned long value) +{ + __asm__ volatile("mcr p15, 0, %0, c6, c3, 0" : : "r"(value) : "memory"); +} + +static void write_prlar(unsigned long value) +{ + __asm__ volatile("mcr p15, 0, %0, c6, c3, 1" : : "r"(value) : "memory"); +} + +static unsigned long read_prbar(void) +{ + unsigned long value; + __asm__ volatile("mrc p15, 0, %0, c6, c3, 0" : "=r"(value)); + return value; +} + +static unsigned long read_prlar(void) +{ + unsigned long value; + __asm__ volatile("mrc p15, 0, %0, c6, c3, 1" : "=r"(value)); + return value; +} + +static void write_mair0(unsigned long value) +{ + __asm__ volatile("mcr p15, 0, %0, c10, c2, 0" : : "r"(value) : "memory"); +} + +static void write_mair1(unsigned long value) +{ + __asm__ volatile("mcr p15, 0, %0, c10, c2, 1" : : "r"(value) : "memory"); +} + +static void invalidate_icache_all(void) +{ + __asm__ volatile("mcr p15, 0, r0, c7, c5, 0" : : : "memory"); /* ICIALLU */ +} + +static void data_sync_barrier(void) +{ + __asm__ volatile("dsb" : : : "memory"); +} + +static void instruction_barrier(void) +{ + __asm__ volatile("isb" : : : "memory"); +} + + +/**************************************************************************/ +/* mpu_region_count */ +/**************************************************************************/ + +unsigned int mpu_region_count(void) +{ + /* MPUIR.REGION occupies bits [15:8]. */ + + return (unsigned int) ((read_mpuir() >> 8) & 0xFFUL); +} + + +/**************************************************************************/ +/* mpu_is_enabled / mpu_caches_enabled */ +/**************************************************************************/ + +unsigned int mpu_is_enabled(void) +{ + return ((read_sctlr() & SCTLR_M) != 0UL) ? 1U : 0U; +} + +unsigned int mpu_caches_enabled(void) +{ + unsigned long sctlr = read_sctlr(); + + return (((sctlr & SCTLR_C) != 0UL) && ((sctlr & SCTLR_I) != 0UL)) ? 1U : 0U; +} + + +/**************************************************************************/ +/* mpu_region_table */ +/**************************************************************************/ + +const MPU_REGION *mpu_region_table(unsigned int *count_ptr) +{ + if (count_ptr != 0) + { + *count_ptr = mpu_regions_used; + } + + return mpu_regions; +} + + +/**************************************************************************/ +/* mpu_read_region */ +/**************************************************************************/ + +void mpu_read_region(unsigned int index, unsigned long *prbar_ptr, + unsigned long *prlar_ptr) +{ + write_prselr((unsigned long) index); + instruction_barrier(); + + if (prbar_ptr != 0) + { + *prbar_ptr = read_prbar(); + } + if (prlar_ptr != 0) + { + *prlar_ptr = read_prlar(); + } +} + + +/**************************************************************************/ +/* build_table -- describe this image's memory. */ +/**************************************************************************/ + +/* Bisection switch. probe_stage stops at 0x42 with the real five-region map, + meaning the SCTLR.M write itself kills the core with no exception taken. + That has two very different causes: the map is wrong for the first fetch or + stack access, or enabling the MPU on this part needs something we have not + done at all. A single region spanning the whole address space, permissive + and Normal, distinguishes them: if the core survives with this, the map is + at fault; if it dies anyway, enabling M is. */ + +static void build_table(void) +{ + /* Protection map: narrow regions with real permissions, so that anything + this image should not do actually faults. + * + * This supersedes the permissive bring-up map (everything Normal RW X, + * whole address space covered). That map existed because a narrow one + * had failed and the reason was unknown -- the failure looked like a + * stall with nothing recorded, and coverage was blamed. Coverage was + * never the problem: an out-of-bounds write to a [3]-sized table put a + * region at base 0 overlapping everything, and SCTLR.TE being set meant + * the resulting abort could not run a handler. Both are fixed, so a + * narrow map is now both correct and diagnosable: if something outside + * these regions is touched, the fault handler records vector, syndrome + * and faulting address instead of hanging mutely. + * + * Anything not described below is unmapped and faults on access. That + * is the point. + */ + + /* Code: read-only and executable. A write here must fault. */ + + mpu_regions[0].mpu_region_base = S32Z_CODE_SRAM_BASE; + mpu_regions[0].mpu_region_limit = (unsigned long) &__code_end__ - 1UL; + mpu_regions[0].mpu_region_ap = MPU_AP_RO_EL1; + mpu_regions[0].mpu_region_execute_never = 0U; + mpu_regions[0].mpu_region_shareability = MPU_SH_NON; + mpu_regions[0].mpu_region_attr_index = MPU_ATTR_NORMAL_WB; + mpu_regions[0].mpu_region_name = "code RO X normal-wb"; + + /* Data, bss and every per-mode stack: writable, never executable. Sized + from the SRAM bank, not from __data_end__: the stacks are NOLOAD and sit + above that symbol, so sizing from it would leave them unmapped and the + first push after enabling the MPU would abort. */ + + mpu_regions[1].mpu_region_base = S32Z_DATA_SRAM_BASE; + mpu_regions[1].mpu_region_limit = S32Z_DATA_SRAM_BASE + + S32Z_DATA_SRAM_SIZE - 1UL; + mpu_regions[1].mpu_region_ap = MPU_AP_RW_EL1; + mpu_regions[1].mpu_region_execute_never = 1U; + mpu_regions[1].mpu_region_shareability = MPU_SH_NON; + mpu_regions[1].mpu_region_attr_index = MPU_ATTR_NORMAL_WB; + mpu_regions[1].mpu_region_name = "data RW NX normal-wb"; + + /* Console. Mapped narrowly: one 64 KB LINFlexD instance. */ + + mpu_regions[2].mpu_region_base = S32Z_LINFLEX_9_BASE; + mpu_regions[2].mpu_region_limit = S32Z_LINFLEX_9_BASE + 0xFFFFUL; + mpu_regions[2].mpu_region_ap = MPU_AP_RW_EL1; + mpu_regions[2].mpu_region_execute_never = 1U; + mpu_regions[2].mpu_region_shareability = MPU_SH_NON; + mpu_regions[2].mpu_region_attr_index = MPU_ATTR_DEVICE; + mpu_regions[2].mpu_region_name = "uart RW NX device"; + + /* GIC. Device nGnRnE is required by the Cortex-R52 TRM, and confirmed + here: mapped Normal the distributor stalls the core. */ + + mpu_regions[3].mpu_region_base = S32Z_GIC_BASE; + mpu_regions[3].mpu_region_limit = S32Z_GIC_BASE + S32Z_GIC_SIZE - 1UL; + mpu_regions[3].mpu_region_ap = MPU_AP_RW_EL1; + mpu_regions[3].mpu_region_execute_never = 1U; + mpu_regions[3].mpu_region_shareability = MPU_SH_NON; + mpu_regions[3].mpu_region_attr_index = MPU_ATTR_DEVICE; + mpu_regions[3].mpu_region_name = "gic RW NX device"; + + /* RTU peripheral window behind the low-latency peripheral port. */ + + mpu_regions[4].mpu_region_base = S32Z_RTU_PERIPH_BASE; + mpu_regions[4].mpu_region_limit = S32Z_RTU_PERIPH_BASE + + S32Z_RTU_PERIPH_SIZE - 1UL; + mpu_regions[4].mpu_region_ap = MPU_AP_RW_EL1; + mpu_regions[4].mpu_region_execute_never = 1U; + mpu_regions[4].mpu_region_shareability = MPU_SH_NON; + mpu_regions[4].mpu_region_attr_index = MPU_ATTR_DEVICE; + mpu_regions[4].mpu_region_name = "rtu RW NX device"; + + /* Extended SRAM. Deliberately mapped so the cache benchmark has memory + that is NOT RTU-local to work against: the fast-data bank in region 1 is + close to core speed, so caching it shows nothing. Normal write-back and + never executable. */ + + mpu_regions[5].mpu_region_base = S32Z_EXT_SRAM_BASE; + mpu_regions[5].mpu_region_limit = S32Z_EXT_SRAM_BASE + + S32Z_EXT_SRAM_SIZE - 1UL; + mpu_regions[5].mpu_region_ap = MPU_AP_RW_EL1; + mpu_regions[5].mpu_region_execute_never = 1U; + mpu_regions[5].mpu_region_shareability = MPU_SH_NON; + mpu_regions[5].mpu_region_attr_index = MPU_ATTR_NORMAL_WB; + mpu_regions[5].mpu_region_name = "ext RW NX normal-wb"; + + mpu_regions_used = 6U; +} + + +/**************************************************************************/ +/* program_region */ +/**************************************************************************/ + +static void program_region(unsigned int index, const MPU_REGION *region_ptr) +{ + unsigned long prbar; + unsigned long prlar; + + /* PRBAR: BASE[31:6], RES0[5], SH[4:3], AP[2:1], XN[0]. + * + * Per Cortex-R52 TRM r1p3 figure 3-39. Note the field positions: the + * FVP example this file came from shifts every field one bit too far + * left -- SH<<4, AP<<2, XN<<1 -- which silently produces a different + * region than intended. With XN written to bit 1 it lands in the real + * AP[1] (EL0 access) and the region stays EXECUTABLE, which is how this + * board ended up running instructions out of .data. + * + * That bug is also the origin of the "PRBAR.AP bit order is reversed" + * claim recorded during the FVP work. Calibrating AP empirically under + * the wrong shift puts the intended AP's low bit into the real AP[2] + * (the read-only bit) and the intended XN into the real AP[1], which + * looks exactly like a reversed encoding. The architectural order is + * correct as published; there was no reversal. + */ + + prbar = (region_ptr->mpu_region_base & 0xFFFFFFC0UL) + | (((unsigned long) region_ptr->mpu_region_shareability & 0x3UL) << 3) + | (((unsigned long) region_ptr->mpu_region_ap & 0x3UL) << 1) + | ((unsigned long) region_ptr->mpu_region_execute_never & 0x1UL); + + prlar = (region_ptr->mpu_region_limit & 0xFFFFFFC0UL) + | (((unsigned long) region_ptr->mpu_region_attr_index & 0x7UL) << 1) + | 1UL; /* region enable */ + + write_prselr((unsigned long) index); + instruction_barrier(); + write_prbar(prbar); + write_prlar(prlar); +} + + +/**************************************************************************/ +/* mpu_init */ +/**************************************************************************/ + +unsigned int mpu_init(void) +{ + unsigned long sctlr; + unsigned int index; + unsigned int available = mpu_region_count(); + + build_table(); + + if (mpu_regions_used > MPU_TABLE_REGIONS) + { + return 0U; /* build_table overran the table */ + } + + if (available < mpu_regions_used) + { + return 0U; /* hardware has fewer regions than we need */ + } + + /* Memory types first: a region's attribute index is meaningless until + MAIR is populated. */ + + MARK(0x20); + write_mair0((MAIR_ATTR_DEVICE << 8) | MAIR_ATTR_NORMAL_WB); + write_mair1(0UL); + MARK(0x21); + + for (index = 0U; index < mpu_regions_used; index++) + { + program_region(index, &mpu_regions[index]); + MARK(0x30U + index); + } + + /* Disable any regions this image does not use, so that stale enables + cannot grant access we did not intend. */ + + for (index = mpu_regions_used; index < available; index++) + { + write_prselr((unsigned long) index); + instruction_barrier(); + write_prlar(0UL); + } + + MARK(0x40); + data_sync_barrier(); + + /* Caches are invalidated before enabling. The instruction cache has a + single invalidate-all; the data cache is left to the model's reset + state, which is invalid, because a set/way sweep belongs with the + silicon bring-up where it can be verified against the real cache + geometry. */ + + invalidate_icache_all(); + data_sync_barrier(); + instruction_barrier(); + + /* MPU only. Caches are deliberately left off on this first pass: the + point here is reaching the GIC, and enabling caches at the same time + would add coherency questions -- the debugger writes this image straight + into SRAM behind the caches' back -- to a change whose result is meant to + be unambiguous. C and I are a separate step with their own check. */ + + MARK(0x41); + sctlr = read_sctlr(); + MARK(0x42); +#if !defined(MPU_READBACK_ONLY) + sctlr |= SCTLR_M; + write_sctlr(sctlr); +#else + (void) sctlr; /* readback experiment: MPU deliberately NOT enabled */ +#endif + + /* If the map is wrong, the core dies HERE -- the next instruction fetch or + the next stack access is the first thing the new map has to satisfy. A + marker written after this point therefore proves the map holds. */ + + MARK(0x43); + data_sync_barrier(); + instruction_barrier(); + MARK(0x44); + + return mpu_regions_used; +} diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/mpu.h b/ports/cortex_r52/gnu/example_build/s32z280_evb/mpu.h new file mode 100644 index 000000000..a9911e92e --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/mpu.h @@ -0,0 +1,118 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* BOARD SUPPORT RELEASE */ +/* */ +/* mpu.h Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frédéric Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* PMSAv8-R memory protection and cache enable for Cortex-R52. */ +/* */ +/* The region set is described by a table rather than a sequence of */ +/* register writes. That is deliberate and is a roadmap decision, not */ +/* a style preference: AR2 programs a Stage-1 region set per ThreadX */ +/* module and AR3 programs Stage-2 regions per ZoneX partition, and */ +/* both reuse this shape. A table can be swapped at a partition */ +/* switch; open-coded register writes cannot. */ +/* */ +/**************************************************************************/ + +#ifndef MPU_H +#define MPU_H + +/* Access permissions, PRBAR.AP (bits [3:2]). + * + * These values were CALIBRATED AGAINST THE HARDWARE, not copied from a + * reference, because the widely-published Armv8-R AArch64 macro set has the + * two bits the other way round (its "read-only, no EL0 access" is 0x2). + * Programming four disjoint regions, one per encoding, and attempting a + * privileged write to each gave: + * + * AP=0b00 write allowed AP=0b01 write faulted + * AP=0b10 write allowed AP=0b11 write faulted + * + * so the low bit is read-only and the high bit grants EL0 access. Using the + * AArch64 ordering here silently produces writable "read-only" regions: the + * MPU still enforces region coverage, so everything appears to work and only + * an explicit write-permission test exposes it. Re-calibrate on S32Z280 + * silicon before trusting these values there. + */ + +/* PRBAR.AP[2:1] as the architecture defines it: AP[2] selects read-only, + AP[1] grants EL0 access. These are the published values -- the "reversed + bit order" recorded during the FVP work was an artefact of that code + shifting AP into the wrong bits, not a property of the hardware. */ + +#define MPU_AP_RW_EL1 0U /* 0b00 EL1 read/write, no EL0 */ +#define MPU_AP_RW_EL1_EL0 1U /* 0b01 EL1 read/write, EL0 read/write */ +#define MPU_AP_RO_EL1 2U /* 0b10 EL1 read-only, no EL0 */ +#define MPU_AP_RO_EL1_EL0 3U /* 0b11 EL1 read-only, EL0 read-only */ + +/* Shareability, PRBAR.SH. */ + +#define MPU_SH_NON 0U +#define MPU_SH_OUTER 2U +#define MPU_SH_INNER 3U + +/* Attribute indices into MAIR, PRLAR.AttrIndx. */ + +#define MPU_ATTR_NORMAL_WB 0U /* Normal, inner/outer write-back */ +#define MPU_ATTR_DEVICE 1U /* Device-nGnRnE */ + +/* One protection region. The limit is inclusive, matching the hardware. */ + +typedef struct MPU_REGION_STRUCT +{ + unsigned long mpu_region_base; + unsigned long mpu_region_limit; + unsigned char mpu_region_ap; + unsigned char mpu_region_execute_never; + unsigned char mpu_region_shareability; + unsigned char mpu_region_attr_index; + const char *mpu_region_name; +} MPU_REGION; + +/* Number of regions this implementation provides, from MPUIR. */ + +unsigned int mpu_region_count(void); + +/* Program the region table, then enable the MPU and the caches. Returns + the number of regions programmed, or 0 if the table does not fit. */ + +unsigned int mpu_init(void); + +/* True once SCTLR reports the MPU and both caches enabled. */ + +unsigned int mpu_is_enabled(void); +unsigned int mpu_caches_enabled(void); + +/* The active table, for reporting. */ + +const MPU_REGION *mpu_region_table(unsigned int *count_ptr); + +/* Read back what the hardware holds for one region, so that programming can + be verified rather than assumed. */ + +void mpu_read_region(unsigned int index, unsigned long *prbar_ptr, + unsigned long *prlar_ptr); + +#endif /* MPU_H */ diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/platform.h b/ports/cortex_r52/gnu/example_build/s32z280_evb/platform.h new file mode 100644 index 000000000..b9bca7dfa --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/platform.h @@ -0,0 +1,158 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* BOARD SUPPORT RELEASE */ +/* */ +/* platform.h Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frédéric Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Memory map and peripheral addresses for the NXP S32Z280-594EVB, */ +/* RTU0 core 0 (R52_0_0). */ +/* */ +/* Every address below was either read out of the S32Z2 Reference */ +/* Manual (S32Z27RM Rev. 5.1) or confirmed on the board itself, and */ +/* each is marked accordingly. The distinction matters because this */ +/* part differs from the Armv8-R AEM FVP in ways that are silent */ +/* rather than loud: an address that is merely wrong tends to read */ +/* back zero instead of faulting. */ +/* */ +/* MEMORY */ +/* */ +/* The RTU exposes its code SRAM through two windows onto the same */ +/* physical memory: 0x79900000 for instruction fetch (AXI-F) and */ +/* 0x32100000 as data. Confirmed by writing a sentinel to one and */ +/* reading it back through the other. NXP's debugger memory map */ +/* declares the fetch window read-only, but it is writable over the */ +/* debug AXI port -- verified -- so a debugger-loaded image can be */ +/* placed there directly and no load-address alias is needed. A */ +/* self-booting image loaded from flash would still need the data */ +/* alias, since the core's own data side may not write through AXI-F. */ +/* */ +/* The TCMs (0x30000000, 0x30100000, 0x30200000) are NOT accessible */ +/* at reset -- reads fault -- because nothing has programmed the TCM */ +/* region registers yet. They are therefore unusable for early boot */ +/* and are deliberately absent from this map. The DDR window at */ +/* 0x7A000000 is likewise dark until DDR is initialised. */ +/* */ +/**************************************************************************/ + +#ifndef PLATFORM_H +#define PLATFORM_H + +/* Memory-mapped register access. Kept here rather than per-driver so that + every peripheral in this BSP goes through one definition. + MISRA C:2012 Rule 11.4/11.6 deviation: casting an integer address to a + volatile pointer is inherent to memory-mapped device access. */ + +#define REG32(address) (*(volatile unsigned long *)(unsigned long)(address)) + +/* Code SRAM, instruction-fetch view. 7 MB. This is where the core */ +/* resets to, and where .text is linked and loaded. [verified on board] */ + +#define S32Z_CODE_SRAM_BASE 0x79900000UL +#define S32Z_CODE_SRAM_SIZE 0x00700000UL + +/* The same physical SRAM seen as data. Kept here because the boot-from- */ +/* flash path will need it, and because it is how the core's reset */ +/* instruction is planted by an external debugger. [verified on board] */ + +#define S32Z_CODE_SRAM_DATA_ALIAS 0x32100000UL + +/* RTU-local data SRAM. The Reference Manual notes that when an RTU */ +/* accesses its own blocks the traffic stays inside the RTU, so this is */ +/* the right home for stacks and .data. 256 KB. [verified writable] */ + +#define S32Z_DATA_SRAM_BASE 0x31780000UL +#define S32Z_DATA_SRAM_SIZE 0x00040000UL + +/* Larger but not RTU-local: 2 MB, for images that outgrow the above. */ +/* [verified writable] */ + +#define S32Z_EXT_SRAM_BASE 0x31800000UL +#define S32Z_EXT_SRAM_SIZE 0x00200000UL + +/* Console. The EVB user guide (UG10268) dedicates LIN9 to the */ +/* daughtercard USB-UART, selected by jumper J248, so LINFlex_9 is the */ +/* instance that reaches the host -- not LINFlex_0, which is the first */ +/* one in the Reference Manual's list and the tempting wrong choice. */ +/* Base addresses from the RM; LINFlex_0's LINCR1 reset value 0x00000082 */ +/* was read back from the board, which is what confirms the address space.*/ + +#define S32Z_LINFLEX_9_BASE 0x42980000UL /* USB-UART [RM] */ +#define S32Z_LINFLEX_0_BASE 0x40170000UL /* [RM+board] */ + +/* Mode Entry and Reset Generation, used by the debugger's init sequence */ +/* to release and clock the RTU cores. Recorded because their contents */ +/* were what proved the core was released rather than held in reset. [RM]*/ + +#define S32Z_MC_ME_PRTN0_PCONF 0x41900300UL +#define S32Z_MC_ME_PRTN0_CORE0_ADDR 0x4190034CUL +#define S32Z_RGM_PRST0 0x41850048UL + +/* Debug system as seen from a core: MDM-AP holds the per-core external */ +/* debug request bits that must be clear for the core to execute at all. */ +/* Reachable from the core context only. [RM + verified on board] */ + +/* RTU0 general-purpose registers. CFG_CNTDV holds the divider that makes*/ +/* the Cortex-R52 generic timer clock-enable, CNTCLKEN, from a cluster */ +/* clock. Reset value of the CNTDV field is 4. [RM section 9.2.1.6] */ + +/* RTU peripheral window, as described by IMP_PERIPHPREGIONR: 4 MB at */ +/* 0x76000000, reached through the low-latency peripheral port. */ + +#define S32Z_RTU_PERIPH_BASE 0x76000000UL +#define S32Z_RTU_PERIPH_SIZE 0x00400000UL + +#define S32Z_RTU0_GPR_BASE 0x76120000UL +#define S32Z_RTU0_GPR_CFG_CNTDV (S32Z_RTU0_GPR_BASE + 0x10UL) + +/* GICv3 for this R52 cluster. IMP_CBAR reports the distributor base in */ +/* bits [31:21] and reads 0x47800000 on this board, confirming NXP's map */ +/* from the hardware -- the SoC reference manual gives no GIC address at */ +/* all, and its note that the "R52 Cluster set addr [31:21]" is just */ +/* CFGPERIPHBASE[31:21] restated. Frame layout from Cortex-R52 TRM Table */ +/* 9-1: distributor at +0x000000, redistributor control at +0x100000, */ +/* redistributor SGI/PPI at +0x110000, then +0x20000 per further core. */ +/* The region must be mapped Device nGnRnE before it can be read; with the*/ +/* MPU disabled an access stalls the core. */ + +#define S32Z_GIC_BASE 0x47800000UL +#define S32Z_GIC_SIZE 0x00200000UL + +/* Frames within that window, from Cortex-R52 TRM Table 9-1: distributor at + +0x000000, redistributor control at +0x100000, redistributor SGI/PPI at + +0x110000, then +0x20000 per further core. Both frames verified on the + board -- GICD_PIDR2 and GICR_PIDR2 both read 0x3B. + + These must be mapped Device nGnRnE before use. With the region Normal, or + with the MPU disabled, an access stalls the core outright: no abort, no + fault handler, and the debug connection drops. mpu.c maps them. */ + +#define GICD_BASE (S32Z_GIC_BASE + 0x000000UL) +#define GICR_RD_BASE (S32Z_GIC_BASE + 0x100000UL) +#define GICR_SGI_BASE (S32Z_GIC_BASE + 0x110000UL) + +#define S32Z_MDM_AP_BASE 0x4DC11000UL +#define S32Z_MDM_AP_CONTROL2 (S32Z_MDM_AP_BASE + 0x44UL) +#define S32Z_MDM_AP_RTU0_CORE0_EDBGREQ 0x00010000UL + +#endif /* PLATFORM_H */ diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/readme_s32z280.txt b/ports/cortex_r52/gnu/example_build/s32z280_evb/readme_s32z280.txt new file mode 100644 index 000000000..f2a3d1b05 --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/readme_s32z280.txt @@ -0,0 +1,125 @@ +Cortex-R52 example build for the NXP S32Z280-594EVB +=================================================== + +RTU0 core 0 (R52_0_0) on the S32Z280-594EVB daughtercard, reached through an +S32 Debug Probe. This is silicon bring-up: the FVP example under +example_build/fvp_baser_aemv8r validates the architecture, and this one +validates the implementation. MIDR here is 0x411FD133 (Cortex-R52 r1p3); +the FVP reports 0x410FD0F0, part 0xD0F, which is an architecture envelope +model and not an R52 at all. + + +1. Build + + cmake -B build_s32z -G Ninja \ + -DCMAKE_TOOLCHAIN_FILE=cmake/cortex_r52.cmake \ + -DTX_R52_BUILD_S32Z280_EXAMPLE=ON . + ninja -C build_s32z s32z280_boot.elf + + The option is separate from TX_R52_BUILD_FVP_EXAMPLE so that FVP + regression stays green regardless of what bring-up is doing, and so the + two boards' differing reset state and memory maps cannot interact. + + +2. Run + + S32Z280_ELF=build_s32z/ports/cortex_r52/gnu/example_build/s32z280_evb/s32z280_boot.elf \ + arm-none-eabi-gdb-py -batch -x tools/read_identity.gdb + + The host side is not optional and not obvious; see setup.md section 9. In + short: a CCS must be listening on 41475 and it must be the *Windows* CCS, + because its code pushes to the probe complete while the Linux CCS's stall + after "Sending code ... done". Under WSL2 mirrored networking both share + one port namespace, so a stray Linux CCS silently blocks the Windows one. + GTA runs on 45000, and arm-none-eabi-gdb-py needs a source-built Python + 3.10.11 in PYTHONHOME. + + +3. Three silicon facts this build exists to encode + + a. The core resets in THUMB state. CPSR reads 0x1FA out of reset -- Hyp + mode with T set -- because the RTU boot instruction NXP plants at the + boot address is a T32 branch. _start is therefore T32 and switches to + A32 itself. An A32 entry would execute the first halfword of its own + instruction as Thumb and end up anywhere. + + b. The debugger holds every core in debug state. NXP's + _reset_to_first_instruction() asserts MDM_AP CONTROL2[19:16] = + CR52_RTU0_{3,2,1,0}_EDBGREQ and nothing ever clears them, despite the + comment in NXP's own source claiming start_debug_by_core_name() does. + While EDBGREQ is asserted the core cannot execute at all, yet registers + and memory still respond and MC_ME/RGM report the core released and + clocked -- so it presents as working hardware that ignores every + attempt to run. tools/read_identity.gdb clears core 0's bit and + verifies the clear took. + + c. CNTFRQ reads zero, the same as on the FVP. It is writable only at the + highest implemented exception level, so it must be programmed at EL2. + entry.S deliberately records it rather than writing a value, because + the correct frequency for this board is not yet established and a wrong + one would silently mis-scale every interval derived from it. Any timer + work here must program CNTFRQ first. + + +4. Memory map + + Code SRAM is visible through two windows onto the same physical memory: + 0x79900000 for instruction fetch, 0x32100000 as data. The core resets to + 0x79900000 -- MC_ME_PRTN0_CORE0_ADDR reads exactly that -- so .text is + linked and loaded there. That window is writable over the debug AXI port + even though NXP's debugger memory map declares it read-only, so a + debugger-loaded image needs no alias. A flash-booted image would. + + Data, bss and the per-mode stacks live in RTU-local data SRAM at + 0x31780000 (256 KB); 0x31800000 gives 2 MB if an image outgrows it. + + The TCMs at 0x30000000/0x30100000/0x30200000 are NOT accessible at reset -- + reads fault -- until their region registers are programmed, so nothing + needed for early boot can live there. The DDR window at 0x7A000000 is + likewise dark until DDR is initialised. Both are absent from link.lds on + purpose. + + +5. What this image reports + + boot_stage says how far the reset path got, so a fault is distinguishable + from a hang; if a fault handler ran it records the vector, syndrome and + faulting address before parking. r52_identity.magic is written last, so a + half-filled structure cannot be mistaken for a complete one. bsp_done() is + a deliberate breakpoint target, so "the image finished" is observed rather + than inferred from a timeout. + + Verified on the board: + + MIDR 0x411FD133 Cortex-R52 r1p3 + MPUIR 0x00001400 20 MPU regions at EL1 + HMPUIR 0x00000014 EL2; the count field sits in bits [7:0] here + rather than [15:8] as in MPUIR, which still + needs confirming against the Armv8-R spec + CTR 0x8144C004 + MPIDR 0x80000000 + ID_PFR0 0x00000131 + ID_PFR1 0x10111001 virtualisation field 1: EL2 implemented + SCTLR 0x70C50838 MPU, D-cache and I-cache all off at reset + CNTFRQ 0x00000000 + + CPSR at EL2 0x000001DA mode 0x1A, Hyp + CPSR at EL1 0x600001D3 mode 0x13, Supervisor + + The two CPSR values are the point of the milestone: they are the EL2 to EL1 + drop performed by this code on silicon rather than on a model. + + +6. Not here yet + + No console. LIN9 reaches the host through the daughtercard USB-UART + (jumper J248), which is LINFlex_9 at 0x42980000 -- not LINFlex_0 at + 0x40170000, the tempting wrong choice as the first instance in the + Reference Manual's list. What is missing is the clock configuration needed + to compute a baud rate; a console at the wrong rate produces garbage + indistinguishable from a crash, which is why this milestone reports through + memory instead. + + No timer, no GIC, no MPU programming and no ThreadX: this image does not + link the kernel, so a failure here is unambiguously a boot or board problem + rather than a kernel one. diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/timer.c b/ports/cortex_r52/gnu/example_build/s32z280_evb/timer.c new file mode 100644 index 000000000..544102083 --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/timer.c @@ -0,0 +1,148 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* BOARD SUPPORT RELEASE */ +/* */ +/* timer.c Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frédéric Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Arm generic timer access for the S32Z280-594EVB. */ +/* */ +/* CNTFRQ reads zero on this silicon, exactly as it does on the */ +/* Armv8-R AEM FVP. CNTFRQ is only a software-populated constant -- */ +/* nothing derives the counter's real rate from it -- so a zero there */ +/* says nothing about whether the counter is running. The only way to */ +/* find that out is to read CNTPCT twice and see whether it moved, */ +/* which is what this file exists to support. */ +/* */ +/* The rate itself is measured rather than computed. The RTU divides */ +/* a cluster clock by RTU.GPR CFG_CNTDV to generate the timer's */ +/* clock-enable, so deriving it needs the divider AND the cluster clock*/ +/* AND the PLL configuration feeding it -- three places to be wrong. */ +/* Sampling CNTPCT against host wall-clock time needs none of them and */ +/* is checkable against the clock tree afterwards. */ +/* */ +/* MISRA C:2012 deviations (justified) */ +/* */ +/* Dir 4.3 -- assembly language shall be encapsulated and isolated. */ +/* Each coprocessor access is wrapped in its own function below. */ +/* */ +/**************************************************************************/ + +#include "timer.h" + +unsigned long long timer_read_cntpct(void) +{ + unsigned int low; + unsigned int high; + + /* CNTPCT is 64-bit and read as a pair through MRRC. The read is + atomic in the architecture, so no high/low re-read dance is needed. */ + + __asm volatile ("mrrc p15, 0, %0, %1, c14" : "=r" (low), "=r" (high)); + + return ((unsigned long long)high << 32) | (unsigned long long)low; +} + + +unsigned int timer_read_cntfrq(void) +{ + unsigned int value; + + __asm volatile ("mrc p15, 0, %0, c14, c0, 0" : "=r" (value)); + + return value; +} + + +void timer_spin(unsigned int iterations) +{ + unsigned int i; + + for (i = 0U; i < iterations; i++) + { + /* Kept from being optimised away, and kept from being turned into + something clever: the loop's only job is to burn a repeatable + amount of time between two counter samples. */ + + __asm volatile ("nop" ::: "memory"); + } +} + + +/* CNTP_CTL bits. IMASK is set so the compare raises no interrupt: there is + no GIC configured yet, and an unhandled PPI would be taken as an exception + rather than politely ignored. */ + +#define CNTP_CTL_ENABLE (1U << 0) +#define CNTP_CTL_IMASK (1U << 1) +#define CNTP_CTL_ISTATUS (1U << 2) + + +void timer_start_oneshot_irq(unsigned int ticks) +{ + /* Same as timer_start_oneshot but with IMASK CLEAR, so the compare raises + an interrupt instead of only setting ISTATUS. Keeping the two arming + functions separate rather than adding a flag: the polled path must never + accidentally unmask before the GIC is up, and an interrupt-driven path + that silently leaves IMASK set produces a timer that fires internally + while no interrupt is ever delivered -- IRQ count 0 with no spurious and + no unexpected INTID, which is exactly how that mistake presents. */ + + unsigned int control = CNTP_CTL_ENABLE; + + __asm volatile ("mcr p15, 0, %0, c14, c2, 0" :: "r" (ticks)); + __asm volatile ("mcr p15, 0, %0, c14, c2, 1" :: "r" (control)); + __asm volatile ("isb"); +} + + +void timer_start_oneshot(unsigned int ticks) +{ + unsigned int control = CNTP_CTL_ENABLE | CNTP_CTL_IMASK; + + /* TVAL is a down-counter loaded relative to now, which avoids the 64-bit + read-modify-write that setting CVAL absolutely would need. */ + + __asm volatile ("mcr p15, 0, %0, c14, c2, 0" :: "r" (ticks)); + __asm volatile ("mcr p15, 0, %0, c14, c2, 1" :: "r" (control)); + __asm volatile ("isb"); +} + + +unsigned int timer_fired(void) +{ + unsigned int control; + + __asm volatile ("mrc p15, 0, %0, c14, c2, 1" : "=r" (control)); + + return ((control & CNTP_CTL_ISTATUS) != 0U) ? 1U : 0U; +} + + +void timer_stop(void) +{ + unsigned int control = 0U; + + __asm volatile ("mcr p15, 0, %0, c14, c2, 1" :: "r" (control)); + __asm volatile ("isb"); +} diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/timer.h b/ports/cortex_r52/gnu/example_build/s32z280_evb/timer.h new file mode 100644 index 000000000..7cd411efc --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/timer.h @@ -0,0 +1,64 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* BOARD SUPPORT RELEASE */ +/* */ +/* timer.h Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frédéric Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Arm generic timer access for the S32Z280-594EVB. */ +/* */ +/**************************************************************************/ + +#ifndef TIMER_H +#define TIMER_H + +/* The physical count, CNTPCT. 64-bit, read as a pair. Reading it is the + only way to find out whether the system counter is running at all: CNTFRQ + reads zero on this part and so says nothing about the counter itself. */ + +unsigned long long timer_read_cntpct(void); + +/* CNTFRQ as currently programmed. Zero out of reset on this silicon. */ + +unsigned int timer_read_cntfrq(void); + +/* Crude calibrated-by-nothing delay, used only to separate counter samples + far enough apart to measure a rate. Not a time delay: the core clock is + not yet established, which is precisely what the measurement is for. */ + +void timer_spin(unsigned int iterations); + +/* One-shot compare on the EL1 physical timer, interrupt masked. Polled + deliberately: this proves the timer counts and fires before the GIC is + configured, so a later interrupt failure cannot be confused with the timer + itself being wrong. */ + +void timer_start_oneshot(unsigned int ticks); + +/* Arms with the interrupt UNMASKED, for the interrupt-driven path. */ + +void timer_start_oneshot_irq(unsigned int ticks); +unsigned int timer_fired(void); +void timer_stop(void); + +#endif /* TIMER_H */ diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/tools/read_identity.gdb b/ports/cortex_r52/gnu/example_build/s32z280_evb/tools/read_identity.gdb new file mode 100644 index 000000000..e409f8f3f --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/tools/read_identity.gdb @@ -0,0 +1,160 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# Load s32z280_boot.elf onto the S32Z280-594EVB, run it, and report what the +# core said about itself. +# +# Usage: +# S32Z280_ELF= \ +# arm-none-eabi-gdb-py -batch -x tools/read_identity.gdb +# +# Requires, and does not do for you: +# * a CCS listening on 41475 -- use the *Windows* CCS ("ccs.exe -noportquit"), +# whose code pushes to the probe complete; the Linux CCS's push stalls. +# Under WSL2 mirrored networking both share one port namespace, so kill any +# Linux CCS first ("pkill -x ccs", not -f: it runs as ./ccs). +# * GTA on 45000: Server/gta/gta -p 45000 -k +# * PYTHONHOME pointing at a source-built Python 3.10.11, which is what +# arm-none-eabi-gdb-py's embedded interpreter needs. +# +# Two silicon quirks are handled below rather than assumed away: the debugger +# holds every RTU core in debug state through MDM_AP CONTROL2, and the core +# resets in Thumb state. + +py _PROBE_IP = "s32dbg:192.168.50.238" +py _SOC_NAME = "S32Z280" +py _CORE_NAME = "R52_0_0" +py _GDB_SERVER_PORT = 45000 + +source /home/fdesbiens/NXP/S32DS.3.6.10/S32DS/tools/S32Debugger/Debugger/scripts/s32z2e2/s32z2e2_generic_bareboard_all_cores.py + +py board_init() +py s32z2e2_cores.init(_CORE_NAME) +py s32z2e2_cores.start_debug_by_core_name(_CORE_NAME) + +# Select the core context before asking about core state. NXP's core_init() +# omits this and then stop_core() reads the mode of the SoC context, which has +# none, and reports "Core can't be stopped. State is undefined/unknown". +py gta_lib.set_context(context.CORE_CTX[_SOC_NAME + "_" + _CORE_NAME]).unwrap() +py gta_lib.stop_core().unwrap() +py gta_lib.attach().unwrap() + +python +import gdb, os + +# --------------------------------------------------------------------------- +# Release the core from the debugger's external debug request. +# +# _reset_to_first_instruction() asserts MDM_AP CONTROL2[19:16] = +# CR52_RTU0_{3,2,1,0}_EDBGREQ (0x000F0000) and nothing clears them, so every +# RTU0 core is pinned in debug state and executes nothing -- registers and +# memory still respond, which is what makes it look like working hardware. +# --------------------------------------------------------------------------- +CONTROL2 = 0x4DC11044 +EDBGREQ_CORE0 = 0x00010000 + +def rd(addr): + return int(gdb.parse_and_eval("*(unsigned int *)0x%x" % addr)) & 0xFFFFFFFF + +c2 = rd(CONTROL2) +gdb.execute("set *(unsigned int *)0x%x = 0x%x" % (CONTROL2, c2 & ~EDBGREQ_CORE0)) +if rd(CONTROL2) & EDBGREQ_CORE0: + raise gdb.GdbError("CR52_RTU0_0_EDBGREQ is still set; the core will not run") +print("EDBGREQ cleared: CONTROL2 0x%08X -> 0x%08X" % (c2, rd(CONTROL2))) + +elf = os.environ.get("S32Z280_ELF", "s32z280_boot.elf") +gdb.execute("file %s" % elf) +gdb.execute("load") + +# The core resets in Thumb state and CPSR cannot be written through this +# connection, so entry must be the T32 _start. Mask bit 0: GDB reports a Thumb +# function's address with it set, but PC itself must be even. +start = int(gdb.parse_and_eval("(unsigned int)&_start")) & ~1 +gdb.execute("set $pc = 0x%x" % start) +print("PC set to 0x%08X" % start) + +gdb.execute("hbreak bsp_done") +gdb.execute("continue") +end + +echo \n===== boot progress =====\n +python +import gdb + +def rd(addr): + return int(gdb.parse_and_eval("*(unsigned int *)0x%x" % addr)) & 0xFFFFFFFF + +STAGES = {1: "switched out of Thumb", 2: "EL2 configured", 3: "running at EL1", + 4: "entered bsp_main", 5: "bsp_main returned (unexpected)", + 0xFF: "A FAULT HANDLER RAN"} + +stage = int(gdb.parse_and_eval("*(unsigned int *)&boot_stage")) & 0xFFFFFFFF +print(" boot_stage = %d (%s)" % (stage, STAGES.get(stage, "unknown"))) + +ident = None + +if stage == 0xFF: + print(" fault_vector = 0x%02X" % (int(gdb.parse_and_eval("*(unsigned int *)&fault_vector")) & 0xFFFFFFFF)) + print(" fault_syndrome = 0x%08X" % (int(gdb.parse_and_eval("*(unsigned int *)&fault_syndrome")) & 0xFFFFFFFF)) + print(" fault_address = 0x%08X" % (int(gdb.parse_and_eval("*(unsigned int *)&fault_address")) & 0xFFFFFFFF)) +else: + # r52_identity belongs to the boot image, which is what this script is for. + # The kernel demo shares the same breakpoint and progress marker but carries + # no identity structure, so against that image the lookup raised and gdb + # exited 1 -- a failure report for a run that had already passed, which is + # worse than printing nothing. + try: + ident = gdb.parse_and_eval("r52_identity") + except gdb.error: + print("\n This image has no r52_identity structure, so there is no " + "identity report to print.") + print(" Expected for the kernel demo, which reports its own result " + "over the console.") + +if ident is not None: + def f(name): + return int(ident[name]) & 0xFFFFFFFF + + magic = f("magic") + if magic != 0x52520001: + print(" magic = 0x%08X -- structure INCOMPLETE, values below are not " + "trustworthy" % magic) + else: + print(" magic = 0x%08X (complete)" % magic) + + print("\n===== S32Z280 R52_0_0, reported by the core itself =====") + midr = f("midr") + part = (midr >> 4) & 0xFFF + print(" MIDR = 0x%08X implementer 0x%02X variant 0x%X part 0x%03X rev 0x%X" + % (midr, (midr >> 24) & 0xFF, (midr >> 20) & 0xF, part, midr & 0xF)) + print(" part 0x%03X -> %s" % (part, + {0xD13: "Cortex-R52", 0xD16: "Cortex-R52+"}.get(part, "UNRECOGNISED"))) + print(" MPUIR = 0x%08X EL1 MPU regions = %d" + % (f("mpuir"), f("mpu_regions_el1"))) + print(" HMPUIR = 0x%08X (EL2; count field position still to be confirmed)" + % f("hmpuir_el2")) + print(" CTR = 0x%08X" % f("ctr")) + print(" MPIDR = 0x%08X" % f("mpidr")) + print(" ID_PFR0 = 0x%08X" % f("id_pfr0")) + pfr1 = f("id_pfr1") + print(" ID_PFR1 = 0x%08X virtualisation field 0x%X -> EL2 %s" + % (pfr1, (pfr1 >> 12) & 0xF, + "implemented" if ((pfr1 >> 12) & 0xF) != 0 else "ABSENT")) + sctlr = f("sctlr_el1") + print(" SCTLR = 0x%08X M(MPU)=%d C(dcache)=%d I(icache)=%d" + % (sctlr, sctlr & 1, (sctlr >> 2) & 1, (sctlr >> 12) & 1)) + print(" CNTFRQ = 0x%08X (%s)" % (f("cntfrq_el2"), + "zero as on the FVP; a tick interval derived from it would divide by zero" + if f("cntfrq_el2") == 0 else "non-zero, programmed before we got here")) + + print("\n===== exception levels traversed =====") + for label, field, want, wname in (("at EL2 ", "cpsr_el2", 0x1A, "Hyp"), + ("at EL1 ", "cpsr_el1", 0x13, "Supervisor")): + v = f(field) + mode = v & 0x1F + print(" CPSR %s = 0x%08X mode 0x%02X (%s) %s" + % (label, v, mode, + {0x1A: "Hyp", 0x13: "Supervisor", 0x1F: "System"}.get(mode, "?"), + "as expected" if mode == want else "EXPECTED %s (0x%02X)" % (wname, want))) +end diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/tx_initialize_low_level.S b/ports/cortex_r52/gnu/example_build/s32z280_evb/tx_initialize_low_level.S new file mode 100644 index 000000000..097eeafed --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/tx_initialize_low_level.S @@ -0,0 +1,110 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Initialize */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + /* No .arch directive. GNU as accepts "armv8-r"; LLVM's integrated + assembler accepts no spelling of it at all -- not armv8-r, not armv8r -- + and fails with "Unknown Arch". The architecture comes from + -mcpu=cortex-r52 on the command line, which every toolchain file passes, + so the directive only restated it. */ + + .syntax unified + .arm + + .global _tx_thread_system_stack_ptr + .global _tx_initialize_unused_memory + + .text + .balign 4 + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_initialize_low_level Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frédéric Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Low-level initialization for Cortex-R52 on the S32Z280-594EVB. */ +/* Called by _tx_initialize_kernel_enter with the processor already in */ +/* Supervisor mode at EL1. */ +/* */ +/* This is deliberately shorter than the A-profile reference ports: */ +/* entry.S has already given every AArch32 mode its own stack from */ +/* dedicated linker-script regions, so there is no stack carving to do */ +/* here and no run-time stack-overlap check to perform -- the linker */ +/* guarantees the regions do not overlap. */ +/* */ +/* When built with TX_R52_USE_THREADX_IRQ, board_init() brings up the */ +/* MPU, GICv3 and the generic timer tick here. The MPU comes first on */ +/* this board: the GIC region has to be mapped Device nGnRnE before any*/ +/* GIC register can be touched at all. */ +/* and the generic timer tick here. That is safe this early because */ +/* interrupts stay masked until _tx_thread_schedule enables them, so no*/ +/* tick can be delivered before the kernel is ready to take one. */ +/* Without that symbol (the M2 cooperative demo) no tick is created, */ +/* which keeps M2 free of any interrupt dependency. */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_initialize_kernel_enter ThreadX entry function */ +/* */ +/**************************************************************************/ + + .global _tx_initialize_low_level + .type _tx_initialize_low_level, %function +_tx_initialize_low_level: + + /* Record the system stack. The interrupt path uses it when an + exception arrives while no thread is running. */ + + ldr r0, =__sys_stack_top + ldr r1, =_tx_thread_system_stack_ptr + str r0, [r1] + + /* Publish the first free memory address for tx_application_define. + _end sits above the image, .bss and every per-mode stack. Round up + to an 8-byte boundary so pool control blocks are aligned. */ + + ldr r0, =_end + add r0, r0, #7 + bic r0, r0, #7 + ldr r1, =_tx_initialize_unused_memory + str r0, [r1] + +#ifdef TX_R52_USE_THREADX_IRQ + + /* Bring up the interrupt controller and the periodic tick. */ + + push {lr} + bl board_init + pop {lr} + +#endif + + bx lr From 010a6c9fbb4fd037a7efcb8df384cf43bd098b09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Wed, 12 Aug 2026 12:43:57 -0400 Subject: [PATCH 034/181] Gave the gnu ports a CMake build, which most of them lacked (#607) The project guidelines ask for CMake and Ninja, but only 15 of the 59 gnu port directories had a CMakeLists.txt. None of the 27 AArch64 ports had one, so the architecture whose examples were repaired over the last few changes still could not be built the way the project says to build it, and nothing in CI could compile it. Add a CMakeLists.txt to the 44 that lacked one. Three of them are templates in ports_arch, because 34 of the 44 are generated: the ARMv7-A and AArch64 source lists are uniform within each family, so one template per family serves every core in it and update.sh distributes it. The other 10 ports have no generator and get their own file. Add the toolchain files those ports select, following the shape of cmake/cortex_a9.cmake. AArch64 needs a base file of its own rather than a variant of arm-none-eabi.cmake: it has no -marm or -mthumb to choose between and no -mfloat-abi, and aarch64-none-elf-gcc rejects -mlong-calls outright, so that flag cannot be carried across. The tools are named without a path, unlike cmake/cortex_r52.cmake which pins one, because pinning 30 files to a single machine's directory layout is the problem the previous change removed from the launch configurations. Three toolchain files cover ports that already had a CMakeLists.txt but no way to select it: the Armv8-M mainline gnu ports, cortex_m33, cortex_m55 and cortex_m85. Without cmake/.cmake the documented invocation cannot reach them. The top level needed one fix. It derives the SMP port directory as _smp, but ports_smp/linux and ports_smp/win64 predate that convention and carry no suffix, so those two could never be configured. Fall back to the bare name when the suffixed directory is absent. The check only fires when the suffixed directory does not exist, so no port that already resolved changes behaviour, and ports_smp/win64's existing CMakeLists.txt becomes reachable too. Verified by configuring and building every one: 53 of 53 static libraries build with cmake -G Ninja, using Arm GNU Toolchain 14.3.Rel1 for both arm-none-eabi and aarch64-none-elf. That covers the 44 new ports plus the 9 that already worked, and includes ports_smp/linux, which failed before the fallback. scripts/check_ports.sh passes, so the three templates and their 34 generated copies agree. Six gnu ports are still outside the CMake build, all for want of a compiler rather than a CMakeLists.txt: rxv1, rxv2 and rxv3 need the Renesas RX GNU toolchain and mips32_interaptiv_smp needs a MIPS one, neither of which is available here, so writing toolchain files for them would mean shipping untested guesses. risc-v32 and risc-v64 already build through their own differently named toolchain files. Assisted-by: Claude Code (Opus 5) --- CMakeLists.txt | 7 +++ cmake/aarch64-none-elf.cmake | 44 +++++++++++++++++++ cmake/arm11.cmake | 19 ++++++++ cmake/arm9.cmake | 19 ++++++++ cmake/cortex_a12.cmake | 18 ++++++++ cmake/cortex_a15.cmake | 18 ++++++++ cmake/cortex_a17.cmake | 18 ++++++++ cmake/cortex_a34.cmake | 18 ++++++++ cmake/cortex_a35.cmake | 18 ++++++++ cmake/cortex_a5.cmake | 18 ++++++++ cmake/cortex_a53.cmake | 18 ++++++++ cmake/cortex_a55.cmake | 18 ++++++++ cmake/cortex_a57.cmake | 18 ++++++++ cmake/cortex_a5x.cmake | 20 +++++++++ cmake/cortex_a65.cmake | 18 ++++++++ cmake/cortex_a65ae.cmake | 18 ++++++++ cmake/cortex_a7.cmake | 18 ++++++++ cmake/cortex_a72.cmake | 18 ++++++++ cmake/cortex_a73.cmake | 18 ++++++++ cmake/cortex_a75.cmake | 18 ++++++++ cmake/cortex_a76.cmake | 18 ++++++++ cmake/cortex_a76ae.cmake | 18 ++++++++ cmake/cortex_a77.cmake | 18 ++++++++ cmake/cortex_a78.cmake | 18 ++++++++ cmake/cortex_a8.cmake | 18 ++++++++ cmake/cortex_m23.cmake | 19 ++++++++ cmake/cortex_m33.cmake | 18 ++++++++ cmake/cortex_m55.cmake | 22 ++++++++++ cmake/cortex_m85.cmake | 22 ++++++++++ cmake/cortex_r4.cmake | 18 ++++++++ cmake/cortex_r5.cmake | 18 ++++++++ ports/arm11/gnu/CMakeLists.txt | 32 ++++++++++++++ ports/arm9/gnu/CMakeLists.txt | 32 ++++++++++++++ ports/cortex_a12/gnu/CMakeLists.txt | 33 ++++++++++++++ ports/cortex_a15/gnu/CMakeLists.txt | 33 ++++++++++++++ ports/cortex_a17/gnu/CMakeLists.txt | 33 ++++++++++++++ ports/cortex_a34/gnu/CMakeLists.txt | 29 ++++++++++++ ports/cortex_a35/gnu/CMakeLists.txt | 29 ++++++++++++ ports/cortex_a5/gnu/CMakeLists.txt | 33 ++++++++++++++ ports/cortex_a53/gnu/CMakeLists.txt | 29 ++++++++++++ ports/cortex_a55/gnu/CMakeLists.txt | 29 ++++++++++++ ports/cortex_a57/gnu/CMakeLists.txt | 29 ++++++++++++ ports/cortex_a65/gnu/CMakeLists.txt | 29 ++++++++++++ ports/cortex_a65ae/gnu/CMakeLists.txt | 29 ++++++++++++ ports/cortex_a7/gnu/CMakeLists.txt | 33 ++++++++++++++ ports/cortex_a72/gnu/CMakeLists.txt | 29 ++++++++++++ ports/cortex_a73/gnu/CMakeLists.txt | 29 ++++++++++++ ports/cortex_a75/gnu/CMakeLists.txt | 29 ++++++++++++ ports/cortex_a76/gnu/CMakeLists.txt | 29 ++++++++++++ ports/cortex_a76ae/gnu/CMakeLists.txt | 29 ++++++++++++ ports/cortex_a77/gnu/CMakeLists.txt | 29 ++++++++++++ ports/cortex_a8/gnu/CMakeLists.txt | 33 ++++++++++++++ ports/cortex_a9/gnu/CMakeLists.txt | 33 ++++++++++++++ ports/cortex_m23/gnu/CMakeLists.txt | 33 ++++++++++++++ ports/cortex_r4/gnu/CMakeLists.txt | 33 ++++++++++++++ ports/cortex_r5/gnu/CMakeLists.txt | 33 ++++++++++++++ .../ARMv7-A/threadx/ports/gnu/CMakeLists.txt | 33 ++++++++++++++ .../ARMv8-A/threadx/ports/gnu/CMakeLists.txt | 29 ++++++++++++ .../threadx_smp/ports/gnu/CMakeLists.txt | 38 ++++++++++++++++ ports_smp/cortex_a34_smp/gnu/CMakeLists.txt | 38 ++++++++++++++++ ports_smp/cortex_a35_smp/gnu/CMakeLists.txt | 38 ++++++++++++++++ ports_smp/cortex_a53_smp/gnu/CMakeLists.txt | 38 ++++++++++++++++ ports_smp/cortex_a55_smp/gnu/CMakeLists.txt | 38 ++++++++++++++++ ports_smp/cortex_a57_smp/gnu/CMakeLists.txt | 38 ++++++++++++++++ ports_smp/cortex_a5_smp/gnu/CMakeLists.txt | 37 ++++++++++++++++ ports_smp/cortex_a5x_smp/gnu/CMakeLists.txt | 37 ++++++++++++++++ ports_smp/cortex_a65_smp/gnu/CMakeLists.txt | 38 ++++++++++++++++ ports_smp/cortex_a65ae_smp/gnu/CMakeLists.txt | 38 ++++++++++++++++ ports_smp/cortex_a72_smp/gnu/CMakeLists.txt | 38 ++++++++++++++++ ports_smp/cortex_a73_smp/gnu/CMakeLists.txt | 38 ++++++++++++++++ ports_smp/cortex_a75_smp/gnu/CMakeLists.txt | 38 ++++++++++++++++ ports_smp/cortex_a76_smp/gnu/CMakeLists.txt | 38 ++++++++++++++++ ports_smp/cortex_a76ae_smp/gnu/CMakeLists.txt | 38 ++++++++++++++++ ports_smp/cortex_a77_smp/gnu/CMakeLists.txt | 38 ++++++++++++++++ ports_smp/cortex_a78_smp/gnu/CMakeLists.txt | 38 ++++++++++++++++ ports_smp/cortex_a7_smp/gnu/CMakeLists.txt | 36 +++++++++++++++ ports_smp/linux/gnu/CMakeLists.txt | 33 ++++++++++++++ .../mips32_interaptiv_smp/gnu/CMakeLists.txt | 33 ++++++++++++++ 78 files changed, 2165 insertions(+) create mode 100644 cmake/aarch64-none-elf.cmake create mode 100644 cmake/arm11.cmake create mode 100644 cmake/arm9.cmake create mode 100644 cmake/cortex_a12.cmake create mode 100644 cmake/cortex_a15.cmake create mode 100644 cmake/cortex_a17.cmake create mode 100644 cmake/cortex_a34.cmake create mode 100644 cmake/cortex_a35.cmake create mode 100644 cmake/cortex_a5.cmake create mode 100644 cmake/cortex_a53.cmake create mode 100644 cmake/cortex_a55.cmake create mode 100644 cmake/cortex_a57.cmake create mode 100644 cmake/cortex_a5x.cmake create mode 100644 cmake/cortex_a65.cmake create mode 100644 cmake/cortex_a65ae.cmake create mode 100644 cmake/cortex_a7.cmake create mode 100644 cmake/cortex_a72.cmake create mode 100644 cmake/cortex_a73.cmake create mode 100644 cmake/cortex_a75.cmake create mode 100644 cmake/cortex_a76.cmake create mode 100644 cmake/cortex_a76ae.cmake create mode 100644 cmake/cortex_a77.cmake create mode 100644 cmake/cortex_a78.cmake create mode 100644 cmake/cortex_a8.cmake create mode 100644 cmake/cortex_m23.cmake create mode 100644 cmake/cortex_m33.cmake create mode 100644 cmake/cortex_m55.cmake create mode 100644 cmake/cortex_m85.cmake create mode 100644 cmake/cortex_r4.cmake create mode 100644 cmake/cortex_r5.cmake create mode 100644 ports/arm11/gnu/CMakeLists.txt create mode 100644 ports/arm9/gnu/CMakeLists.txt create mode 100644 ports/cortex_a12/gnu/CMakeLists.txt create mode 100644 ports/cortex_a15/gnu/CMakeLists.txt create mode 100644 ports/cortex_a17/gnu/CMakeLists.txt create mode 100644 ports/cortex_a34/gnu/CMakeLists.txt create mode 100644 ports/cortex_a35/gnu/CMakeLists.txt create mode 100644 ports/cortex_a5/gnu/CMakeLists.txt create mode 100644 ports/cortex_a53/gnu/CMakeLists.txt create mode 100644 ports/cortex_a55/gnu/CMakeLists.txt create mode 100644 ports/cortex_a57/gnu/CMakeLists.txt create mode 100644 ports/cortex_a65/gnu/CMakeLists.txt create mode 100644 ports/cortex_a65ae/gnu/CMakeLists.txt create mode 100644 ports/cortex_a7/gnu/CMakeLists.txt create mode 100644 ports/cortex_a72/gnu/CMakeLists.txt create mode 100644 ports/cortex_a73/gnu/CMakeLists.txt create mode 100644 ports/cortex_a75/gnu/CMakeLists.txt create mode 100644 ports/cortex_a76/gnu/CMakeLists.txt create mode 100644 ports/cortex_a76ae/gnu/CMakeLists.txt create mode 100644 ports/cortex_a77/gnu/CMakeLists.txt create mode 100644 ports/cortex_a8/gnu/CMakeLists.txt create mode 100644 ports/cortex_a9/gnu/CMakeLists.txt create mode 100644 ports/cortex_m23/gnu/CMakeLists.txt create mode 100644 ports/cortex_r4/gnu/CMakeLists.txt create mode 100644 ports/cortex_r5/gnu/CMakeLists.txt create mode 100644 ports_arch/ARMv7-A/threadx/ports/gnu/CMakeLists.txt create mode 100644 ports_arch/ARMv8-A/threadx/ports/gnu/CMakeLists.txt create mode 100644 ports_arch/ARMv8-A/threadx_smp/ports/gnu/CMakeLists.txt create mode 100644 ports_smp/cortex_a34_smp/gnu/CMakeLists.txt create mode 100644 ports_smp/cortex_a35_smp/gnu/CMakeLists.txt create mode 100644 ports_smp/cortex_a53_smp/gnu/CMakeLists.txt create mode 100644 ports_smp/cortex_a55_smp/gnu/CMakeLists.txt create mode 100644 ports_smp/cortex_a57_smp/gnu/CMakeLists.txt create mode 100644 ports_smp/cortex_a5_smp/gnu/CMakeLists.txt create mode 100644 ports_smp/cortex_a5x_smp/gnu/CMakeLists.txt create mode 100644 ports_smp/cortex_a65_smp/gnu/CMakeLists.txt create mode 100644 ports_smp/cortex_a65ae_smp/gnu/CMakeLists.txt create mode 100644 ports_smp/cortex_a72_smp/gnu/CMakeLists.txt create mode 100644 ports_smp/cortex_a73_smp/gnu/CMakeLists.txt create mode 100644 ports_smp/cortex_a75_smp/gnu/CMakeLists.txt create mode 100644 ports_smp/cortex_a76_smp/gnu/CMakeLists.txt create mode 100644 ports_smp/cortex_a76ae_smp/gnu/CMakeLists.txt create mode 100644 ports_smp/cortex_a77_smp/gnu/CMakeLists.txt create mode 100644 ports_smp/cortex_a78_smp/gnu/CMakeLists.txt create mode 100644 ports_smp/cortex_a7_smp/gnu/CMakeLists.txt create mode 100644 ports_smp/linux/gnu/CMakeLists.txt create mode 100644 ports_smp/mips32_interaptiv_smp/gnu/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 956f2f101..546606c15 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,6 +35,13 @@ if(THREADX_SMP) set(TX_PORT_DIR "ports_smp") set(TX_COMMON_DIR "common_smp") set(TX_ARCH_DIR "${THREADX_ARCH}_smp") + # Most SMP ports are named _smp, but ports_smp/linux and + # ports_smp/win64 predate that convention and carry no suffix. Fall back to + # the bare name for them. The check only fires when the suffixed directory + # is absent, so no port that already resolves changes. + if(NOT IS_DIRECTORY "${CMAKE_CURRENT_LIST_DIR}/${TX_PORT_DIR}/${TX_ARCH_DIR}") + set(TX_ARCH_DIR "${THREADX_ARCH}") + endif() message(STATUS "Building ThreadX SMP version") else() set(TX_PORT_DIR "ports") diff --git a/cmake/aarch64-none-elf.cmake b/cmake/aarch64-none-elf.cmake new file mode 100644 index 000000000..be2034251 --- /dev/null +++ b/cmake/aarch64-none-elf.cmake @@ -0,0 +1,44 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# Shared settings for the AArch64 bare metal ports, the counterpart of +# arm-none-eabi.cmake beside it. The two differ by more than the tool prefix: +# AArch64 has no -marm or -mthumb to choose between, no -mfloat-abi, and +# aarch64-none-elf-gcc rejects -mlong-calls outright, so that flag cannot simply +# be carried across. +# +# The tools are named without a path, so an aarch64-none-elf toolchain must be +# on PATH. Override CMAKE_C_COMPILER and friends on the command line to use one +# that is not. + +# Toolchain settings +set(CMAKE_C_COMPILER aarch64-none-elf-gcc) +set(CMAKE_CXX_COMPILER aarch64-none-elf-g++) +set(AS aarch64-none-elf-as) +set(AR aarch64-none-elf-ar) +set(OBJCOPY aarch64-none-elf-objcopy) +set(OBJDUMP aarch64-none-elf-objdump) +set(SIZE aarch64-none-elf-size) + +set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set(CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + +# Build the try-compile as a static library so no linker script or startup code +# is needed just to test the compiler. +set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY) + +set(CMAKE_C_FLAGS "${MCPU_FLAGS} ${VFP_FLAGS} ${SPEC_FLAGS} -fdata-sections -ffunction-sections" CACHE INTERNAL "c compiler flags") +set(CMAKE_CXX_FLAGS "${MCPU_FLAGS} ${VFP_FLAGS} -fdata-sections -ffunction-sections -fno-rtti -fno-exceptions" CACHE INTERNAL "cxx compiler flags") +set(CMAKE_ASM_FLAGS "${MCPU_FLAGS} ${VFP_FLAGS} -x assembler-with-cpp" CACHE INTERNAL "asm compiler flags") +set(CMAKE_EXE_LINKER_FLAGS "${MCPU_FLAGS} ${LD_FLAGS} -Wl,--gc-sections" CACHE INTERNAL "exe link flags") + +set(CMAKE_C_FLAGS_DEBUG "-Og -g -ggdb3" CACHE INTERNAL "c debug compiler flags") +set(CMAKE_CXX_FLAGS_DEBUG "-Og -g -ggdb3" CACHE INTERNAL "cxx debug compiler flags") +set(CMAKE_ASM_FLAGS_DEBUG "-g -ggdb3" CACHE INTERNAL "asm debug compiler flags") + +set(CMAKE_C_FLAGS_RELEASE "-O3" CACHE INTERNAL "c release compiler flags") +set(CMAKE_CXX_FLAGS_RELEASE "-O3" CACHE INTERNAL "cxx release compiler flags") +set(CMAKE_ASM_FLAGS_RELEASE "" CACHE INTERNAL "asm release compiler flags") diff --git a/cmake/arm11.cmake b/cmake/arm11.cmake new file mode 100644 index 000000000..cd28e9458 --- /dev/null +++ b/cmake/arm11.cmake @@ -0,0 +1,19 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# Toolchain file for ARM11 using GNU tools. The port readme identifies the +# target as ARM1136J-S, which is what -mcpu selects. + +# Name of the target +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR arm1136j-s) + +set(THREADX_ARCH "arm11") +set(THREADX_TOOLCHAIN "gnu") + +set(MCPU_FLAGS "-marm -mcpu=arm1136j-s") +set(VFP_FLAGS "") +set(SPEC_FLAGS "--specs=nosys.specs") + +include(${CMAKE_CURRENT_LIST_DIR}/arm-none-eabi.cmake) diff --git a/cmake/arm9.cmake b/cmake/arm9.cmake new file mode 100644 index 000000000..5bf113758 --- /dev/null +++ b/cmake/arm9.cmake @@ -0,0 +1,19 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# Toolchain file for ARM9 using GNU tools. This is the oldest core in the +# CMake build; the port readme names ARM9 itself. + +# Name of the target +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR arm9) + +set(THREADX_ARCH "arm9") +set(THREADX_TOOLCHAIN "gnu") + +set(MCPU_FLAGS "-marm -mcpu=arm9") +set(VFP_FLAGS "") +set(SPEC_FLAGS "--specs=nosys.specs") + +include(${CMAKE_CURRENT_LIST_DIR}/arm-none-eabi.cmake) diff --git a/cmake/cortex_a12.cmake b/cmake/cortex_a12.cmake new file mode 100644 index 000000000..54658771c --- /dev/null +++ b/cmake/cortex_a12.cmake @@ -0,0 +1,18 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# Toolchain file for Arm Cortex-A12 using GNU tools. + +# Name of the target +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR cortex-a12) + +set(THREADX_ARCH "cortex_a12") +set(THREADX_TOOLCHAIN "gnu") + +set(MCPU_FLAGS "-marm -mcpu=cortex-a12") +set(VFP_FLAGS "") +set(SPEC_FLAGS "--specs=nosys.specs") + +include(${CMAKE_CURRENT_LIST_DIR}/arm-none-eabi.cmake) diff --git a/cmake/cortex_a15.cmake b/cmake/cortex_a15.cmake new file mode 100644 index 000000000..84f85702f --- /dev/null +++ b/cmake/cortex_a15.cmake @@ -0,0 +1,18 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# Toolchain file for Arm Cortex-A15 using GNU tools. + +# Name of the target +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR cortex-a15) + +set(THREADX_ARCH "cortex_a15") +set(THREADX_TOOLCHAIN "gnu") + +set(MCPU_FLAGS "-marm -mcpu=cortex-a15") +set(VFP_FLAGS "") +set(SPEC_FLAGS "--specs=nosys.specs") + +include(${CMAKE_CURRENT_LIST_DIR}/arm-none-eabi.cmake) diff --git a/cmake/cortex_a17.cmake b/cmake/cortex_a17.cmake new file mode 100644 index 000000000..594ee96f7 --- /dev/null +++ b/cmake/cortex_a17.cmake @@ -0,0 +1,18 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# Toolchain file for Arm Cortex-A17 using GNU tools. + +# Name of the target +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR cortex-a17) + +set(THREADX_ARCH "cortex_a17") +set(THREADX_TOOLCHAIN "gnu") + +set(MCPU_FLAGS "-marm -mcpu=cortex-a17") +set(VFP_FLAGS "") +set(SPEC_FLAGS "--specs=nosys.specs") + +include(${CMAKE_CURRENT_LIST_DIR}/arm-none-eabi.cmake) diff --git a/cmake/cortex_a34.cmake b/cmake/cortex_a34.cmake new file mode 100644 index 000000000..36d855e38 --- /dev/null +++ b/cmake/cortex_a34.cmake @@ -0,0 +1,18 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# Toolchain file for Arm Cortex-A34 using GNU tools. + +# Name of the target +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR cortex-a34) + +set(THREADX_ARCH "cortex_a34") +set(THREADX_TOOLCHAIN "gnu") + +set(MCPU_FLAGS "-mcpu=cortex-a34") +set(VFP_FLAGS "") +set(SPEC_FLAGS "--specs=nosys.specs") + +include(${CMAKE_CURRENT_LIST_DIR}/aarch64-none-elf.cmake) diff --git a/cmake/cortex_a35.cmake b/cmake/cortex_a35.cmake new file mode 100644 index 000000000..ed3d187b5 --- /dev/null +++ b/cmake/cortex_a35.cmake @@ -0,0 +1,18 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# Toolchain file for Arm Cortex-A35 using GNU tools. + +# Name of the target +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR cortex-a35) + +set(THREADX_ARCH "cortex_a35") +set(THREADX_TOOLCHAIN "gnu") + +set(MCPU_FLAGS "-mcpu=cortex-a35") +set(VFP_FLAGS "") +set(SPEC_FLAGS "--specs=nosys.specs") + +include(${CMAKE_CURRENT_LIST_DIR}/aarch64-none-elf.cmake) diff --git a/cmake/cortex_a5.cmake b/cmake/cortex_a5.cmake new file mode 100644 index 000000000..c87577846 --- /dev/null +++ b/cmake/cortex_a5.cmake @@ -0,0 +1,18 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# Toolchain file for Arm Cortex-A5 using GNU tools. + +# Name of the target +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR cortex-a5) + +set(THREADX_ARCH "cortex_a5") +set(THREADX_TOOLCHAIN "gnu") + +set(MCPU_FLAGS "-marm -mcpu=cortex-a5") +set(VFP_FLAGS "") +set(SPEC_FLAGS "--specs=nosys.specs") + +include(${CMAKE_CURRENT_LIST_DIR}/arm-none-eabi.cmake) diff --git a/cmake/cortex_a53.cmake b/cmake/cortex_a53.cmake new file mode 100644 index 000000000..d5011d27b --- /dev/null +++ b/cmake/cortex_a53.cmake @@ -0,0 +1,18 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# Toolchain file for Arm Cortex-A53 using GNU tools. + +# Name of the target +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR cortex-a53) + +set(THREADX_ARCH "cortex_a53") +set(THREADX_TOOLCHAIN "gnu") + +set(MCPU_FLAGS "-mcpu=cortex-a53") +set(VFP_FLAGS "") +set(SPEC_FLAGS "--specs=nosys.specs") + +include(${CMAKE_CURRENT_LIST_DIR}/aarch64-none-elf.cmake) diff --git a/cmake/cortex_a55.cmake b/cmake/cortex_a55.cmake new file mode 100644 index 000000000..8c32ac039 --- /dev/null +++ b/cmake/cortex_a55.cmake @@ -0,0 +1,18 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# Toolchain file for Arm Cortex-A55 using GNU tools. + +# Name of the target +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR cortex-a55) + +set(THREADX_ARCH "cortex_a55") +set(THREADX_TOOLCHAIN "gnu") + +set(MCPU_FLAGS "-mcpu=cortex-a55") +set(VFP_FLAGS "") +set(SPEC_FLAGS "--specs=nosys.specs") + +include(${CMAKE_CURRENT_LIST_DIR}/aarch64-none-elf.cmake) diff --git a/cmake/cortex_a57.cmake b/cmake/cortex_a57.cmake new file mode 100644 index 000000000..9a5b64221 --- /dev/null +++ b/cmake/cortex_a57.cmake @@ -0,0 +1,18 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# Toolchain file for Arm Cortex-A57 using GNU tools. + +# Name of the target +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR cortex-a57) + +set(THREADX_ARCH "cortex_a57") +set(THREADX_TOOLCHAIN "gnu") + +set(MCPU_FLAGS "-mcpu=cortex-a57") +set(VFP_FLAGS "") +set(SPEC_FLAGS "--specs=nosys.specs") + +include(${CMAKE_CURRENT_LIST_DIR}/aarch64-none-elf.cmake) diff --git a/cmake/cortex_a5x.cmake b/cmake/cortex_a5x.cmake new file mode 100644 index 000000000..0fe6730e7 --- /dev/null +++ b/cmake/cortex_a5x.cmake @@ -0,0 +1,20 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# Toolchain file for the Arm Cortex-A5x SMP port using GNU tools. That port +# targets the family rather than one core: its readme and example name A53, +# A55 and A57, so -mcpu selects Cortex-A53, the baseline of the three. + +# Name of the target +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR cortex-a53) + +set(THREADX_ARCH "cortex_a5x") +set(THREADX_TOOLCHAIN "gnu") + +set(MCPU_FLAGS "-mcpu=cortex-a53") +set(VFP_FLAGS "") +set(SPEC_FLAGS "--specs=nosys.specs") + +include(${CMAKE_CURRENT_LIST_DIR}/aarch64-none-elf.cmake) diff --git a/cmake/cortex_a65.cmake b/cmake/cortex_a65.cmake new file mode 100644 index 000000000..389605aa2 --- /dev/null +++ b/cmake/cortex_a65.cmake @@ -0,0 +1,18 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# Toolchain file for Arm Cortex-A65 using GNU tools. + +# Name of the target +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR cortex-a65) + +set(THREADX_ARCH "cortex_a65") +set(THREADX_TOOLCHAIN "gnu") + +set(MCPU_FLAGS "-mcpu=cortex-a65") +set(VFP_FLAGS "") +set(SPEC_FLAGS "--specs=nosys.specs") + +include(${CMAKE_CURRENT_LIST_DIR}/aarch64-none-elf.cmake) diff --git a/cmake/cortex_a65ae.cmake b/cmake/cortex_a65ae.cmake new file mode 100644 index 000000000..717ce0c47 --- /dev/null +++ b/cmake/cortex_a65ae.cmake @@ -0,0 +1,18 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# Toolchain file for Arm Cortex-A65ae using GNU tools. + +# Name of the target +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR cortex-a65ae) + +set(THREADX_ARCH "cortex_a65ae") +set(THREADX_TOOLCHAIN "gnu") + +set(MCPU_FLAGS "-mcpu=cortex-a65ae") +set(VFP_FLAGS "") +set(SPEC_FLAGS "--specs=nosys.specs") + +include(${CMAKE_CURRENT_LIST_DIR}/aarch64-none-elf.cmake) diff --git a/cmake/cortex_a7.cmake b/cmake/cortex_a7.cmake new file mode 100644 index 000000000..5e3f4a9cb --- /dev/null +++ b/cmake/cortex_a7.cmake @@ -0,0 +1,18 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# Toolchain file for Arm Cortex-A7 using GNU tools. + +# Name of the target +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR cortex-a7) + +set(THREADX_ARCH "cortex_a7") +set(THREADX_TOOLCHAIN "gnu") + +set(MCPU_FLAGS "-marm -mcpu=cortex-a7") +set(VFP_FLAGS "") +set(SPEC_FLAGS "--specs=nosys.specs") + +include(${CMAKE_CURRENT_LIST_DIR}/arm-none-eabi.cmake) diff --git a/cmake/cortex_a72.cmake b/cmake/cortex_a72.cmake new file mode 100644 index 000000000..24a65cf98 --- /dev/null +++ b/cmake/cortex_a72.cmake @@ -0,0 +1,18 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# Toolchain file for Arm Cortex-A72 using GNU tools. + +# Name of the target +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR cortex-a72) + +set(THREADX_ARCH "cortex_a72") +set(THREADX_TOOLCHAIN "gnu") + +set(MCPU_FLAGS "-mcpu=cortex-a72") +set(VFP_FLAGS "") +set(SPEC_FLAGS "--specs=nosys.specs") + +include(${CMAKE_CURRENT_LIST_DIR}/aarch64-none-elf.cmake) diff --git a/cmake/cortex_a73.cmake b/cmake/cortex_a73.cmake new file mode 100644 index 000000000..b5bb0c7d7 --- /dev/null +++ b/cmake/cortex_a73.cmake @@ -0,0 +1,18 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# Toolchain file for Arm Cortex-A73 using GNU tools. + +# Name of the target +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR cortex-a73) + +set(THREADX_ARCH "cortex_a73") +set(THREADX_TOOLCHAIN "gnu") + +set(MCPU_FLAGS "-mcpu=cortex-a73") +set(VFP_FLAGS "") +set(SPEC_FLAGS "--specs=nosys.specs") + +include(${CMAKE_CURRENT_LIST_DIR}/aarch64-none-elf.cmake) diff --git a/cmake/cortex_a75.cmake b/cmake/cortex_a75.cmake new file mode 100644 index 000000000..8b4694df2 --- /dev/null +++ b/cmake/cortex_a75.cmake @@ -0,0 +1,18 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# Toolchain file for Arm Cortex-A75 using GNU tools. + +# Name of the target +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR cortex-a75) + +set(THREADX_ARCH "cortex_a75") +set(THREADX_TOOLCHAIN "gnu") + +set(MCPU_FLAGS "-mcpu=cortex-a75") +set(VFP_FLAGS "") +set(SPEC_FLAGS "--specs=nosys.specs") + +include(${CMAKE_CURRENT_LIST_DIR}/aarch64-none-elf.cmake) diff --git a/cmake/cortex_a76.cmake b/cmake/cortex_a76.cmake new file mode 100644 index 000000000..8a4718b6a --- /dev/null +++ b/cmake/cortex_a76.cmake @@ -0,0 +1,18 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# Toolchain file for Arm Cortex-A76 using GNU tools. + +# Name of the target +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR cortex-a76) + +set(THREADX_ARCH "cortex_a76") +set(THREADX_TOOLCHAIN "gnu") + +set(MCPU_FLAGS "-mcpu=cortex-a76") +set(VFP_FLAGS "") +set(SPEC_FLAGS "--specs=nosys.specs") + +include(${CMAKE_CURRENT_LIST_DIR}/aarch64-none-elf.cmake) diff --git a/cmake/cortex_a76ae.cmake b/cmake/cortex_a76ae.cmake new file mode 100644 index 000000000..66c9cd403 --- /dev/null +++ b/cmake/cortex_a76ae.cmake @@ -0,0 +1,18 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# Toolchain file for Arm Cortex-A76ae using GNU tools. + +# Name of the target +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR cortex-a76ae) + +set(THREADX_ARCH "cortex_a76ae") +set(THREADX_TOOLCHAIN "gnu") + +set(MCPU_FLAGS "-mcpu=cortex-a76ae") +set(VFP_FLAGS "") +set(SPEC_FLAGS "--specs=nosys.specs") + +include(${CMAKE_CURRENT_LIST_DIR}/aarch64-none-elf.cmake) diff --git a/cmake/cortex_a77.cmake b/cmake/cortex_a77.cmake new file mode 100644 index 000000000..ba61d0e24 --- /dev/null +++ b/cmake/cortex_a77.cmake @@ -0,0 +1,18 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# Toolchain file for Arm Cortex-A77 using GNU tools. + +# Name of the target +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR cortex-a77) + +set(THREADX_ARCH "cortex_a77") +set(THREADX_TOOLCHAIN "gnu") + +set(MCPU_FLAGS "-mcpu=cortex-a77") +set(VFP_FLAGS "") +set(SPEC_FLAGS "--specs=nosys.specs") + +include(${CMAKE_CURRENT_LIST_DIR}/aarch64-none-elf.cmake) diff --git a/cmake/cortex_a78.cmake b/cmake/cortex_a78.cmake new file mode 100644 index 000000000..b5523913e --- /dev/null +++ b/cmake/cortex_a78.cmake @@ -0,0 +1,18 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# Toolchain file for Arm Cortex-A78 using GNU tools. + +# Name of the target +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR cortex-a78) + +set(THREADX_ARCH "cortex_a78") +set(THREADX_TOOLCHAIN "gnu") + +set(MCPU_FLAGS "-mcpu=cortex-a78") +set(VFP_FLAGS "") +set(SPEC_FLAGS "--specs=nosys.specs") + +include(${CMAKE_CURRENT_LIST_DIR}/aarch64-none-elf.cmake) diff --git a/cmake/cortex_a8.cmake b/cmake/cortex_a8.cmake new file mode 100644 index 000000000..8fd839e94 --- /dev/null +++ b/cmake/cortex_a8.cmake @@ -0,0 +1,18 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# Toolchain file for Arm Cortex-A8 using GNU tools. + +# Name of the target +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR cortex-a8) + +set(THREADX_ARCH "cortex_a8") +set(THREADX_TOOLCHAIN "gnu") + +set(MCPU_FLAGS "-marm -mcpu=cortex-a8") +set(VFP_FLAGS "") +set(SPEC_FLAGS "--specs=nosys.specs") + +include(${CMAKE_CURRENT_LIST_DIR}/arm-none-eabi.cmake) diff --git a/cmake/cortex_m23.cmake b/cmake/cortex_m23.cmake new file mode 100644 index 000000000..22ba78a45 --- /dev/null +++ b/cmake/cortex_m23.cmake @@ -0,0 +1,19 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# Toolchain file for Arm Cortex-M23 using GNU tools. Armv8-M Baseline is +# Thumb only, hence -mthumb with no Arm state alternative. + +# Name of the target +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR cortex-m23) + +set(THREADX_ARCH "cortex_m23") +set(THREADX_TOOLCHAIN "gnu") + +set(MCPU_FLAGS "-mthumb -mcpu=cortex-m23") +set(VFP_FLAGS "") +set(SPEC_FLAGS "--specs=nosys.specs") + +include(${CMAKE_CURRENT_LIST_DIR}/arm-none-eabi.cmake) diff --git a/cmake/cortex_m33.cmake b/cmake/cortex_m33.cmake new file mode 100644 index 000000000..6acab09d7 --- /dev/null +++ b/cmake/cortex_m33.cmake @@ -0,0 +1,18 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# Toolchain file for Arm Cortex-M33 using GNU tools. + +# Name of the target +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR cortex-m33) + +set(THREADX_ARCH "cortex_m33") +set(THREADX_TOOLCHAIN "gnu") + +set(MCPU_FLAGS "-mthumb -mcpu=cortex-m33") +set(VFP_FLAGS "") +set(SPEC_FLAGS "--specs=nosys.specs") + +include(${CMAKE_CURRENT_LIST_DIR}/arm-none-eabi.cmake) diff --git a/cmake/cortex_m55.cmake b/cmake/cortex_m55.cmake new file mode 100644 index 000000000..3a35c8bd1 --- /dev/null +++ b/cmake/cortex_m55.cmake @@ -0,0 +1,22 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# Toolchain file for Arm Cortex-M55 using GNU tools. +# +# The FPU and the MVE unit come with the core, so the hard float ABI +# is selected here rather than left to the caller. scripts/check_clang.sh +# builds this core the same way. + +# Name of the target +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR cortex-m55) + +set(THREADX_ARCH "cortex_m55") +set(THREADX_TOOLCHAIN "gnu") + +set(MCPU_FLAGS "-mthumb -mcpu=cortex-m55") +set(VFP_FLAGS "-mfloat-abi=hard") +set(SPEC_FLAGS "--specs=nosys.specs") + +include(${CMAKE_CURRENT_LIST_DIR}/arm-none-eabi.cmake) diff --git a/cmake/cortex_m85.cmake b/cmake/cortex_m85.cmake new file mode 100644 index 000000000..82b44a736 --- /dev/null +++ b/cmake/cortex_m85.cmake @@ -0,0 +1,22 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# Toolchain file for Arm Cortex-M85 using GNU tools. +# +# The FPU and the MVE unit come with the core, so the hard float ABI +# is selected here rather than left to the caller. scripts/check_clang.sh +# builds this core the same way. + +# Name of the target +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR cortex-m85) + +set(THREADX_ARCH "cortex_m85") +set(THREADX_TOOLCHAIN "gnu") + +set(MCPU_FLAGS "-mthumb -mcpu=cortex-m85") +set(VFP_FLAGS "-mfloat-abi=hard") +set(SPEC_FLAGS "--specs=nosys.specs") + +include(${CMAKE_CURRENT_LIST_DIR}/arm-none-eabi.cmake) diff --git a/cmake/cortex_r4.cmake b/cmake/cortex_r4.cmake new file mode 100644 index 000000000..4b09e076b --- /dev/null +++ b/cmake/cortex_r4.cmake @@ -0,0 +1,18 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# Toolchain file for Arm Cortex-R4 using GNU tools. + +# Name of the target +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR cortex-r4) + +set(THREADX_ARCH "cortex_r4") +set(THREADX_TOOLCHAIN "gnu") + +set(MCPU_FLAGS "-marm -mcpu=cortex-r4") +set(VFP_FLAGS "") +set(SPEC_FLAGS "--specs=nosys.specs") + +include(${CMAKE_CURRENT_LIST_DIR}/arm-none-eabi.cmake) diff --git a/cmake/cortex_r5.cmake b/cmake/cortex_r5.cmake new file mode 100644 index 000000000..8c93a0016 --- /dev/null +++ b/cmake/cortex_r5.cmake @@ -0,0 +1,18 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# Toolchain file for Arm Cortex-R5 using GNU tools. + +# Name of the target +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR cortex-r5) + +set(THREADX_ARCH "cortex_r5") +set(THREADX_TOOLCHAIN "gnu") + +set(MCPU_FLAGS "-marm -mcpu=cortex-r5") +set(VFP_FLAGS "") +set(SPEC_FLAGS "--specs=nosys.specs") + +include(${CMAKE_CURRENT_LIST_DIR}/arm-none-eabi.cmake) diff --git a/ports/arm11/gnu/CMakeLists.txt b/ports/arm11/gnu/CMakeLists.txt new file mode 100644 index 000000000..208d51751 --- /dev/null +++ b/ports/arm11/gnu/CMakeLists.txt @@ -0,0 +1,32 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# ThreadX port sources for arm11, GNU tools. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${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_fiq_context_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fiq_context_save.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fiq_nesting_end.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fiq_nesting_start.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_irq_nesting_end.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_irq_nesting_start.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_vectored_context_save.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports/arm9/gnu/CMakeLists.txt b/ports/arm9/gnu/CMakeLists.txt new file mode 100644 index 000000000..669cedc2c --- /dev/null +++ b/ports/arm9/gnu/CMakeLists.txt @@ -0,0 +1,32 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# ThreadX port sources for arm9, GNU tools. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${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_fiq_context_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fiq_context_save.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fiq_nesting_end.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fiq_nesting_start.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_irq_nesting_end.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_irq_nesting_start.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_vectored_context_save.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports/cortex_a12/gnu/CMakeLists.txt b/ports/cortex_a12/gnu/CMakeLists.txt new file mode 100644 index 000000000..531df96e1 --- /dev/null +++ b/ports/cortex_a12/gnu/CMakeLists.txt @@ -0,0 +1,33 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# ThreadX port sources for the ARMv7-A cores, GNU tools. +# Copied into every ARMv7-A gnu port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${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_fiq_context_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fiq_context_save.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fiq_nesting_end.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fiq_nesting_start.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_irq_nesting_end.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_irq_nesting_start.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_vectored_context_save.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports/cortex_a15/gnu/CMakeLists.txt b/ports/cortex_a15/gnu/CMakeLists.txt new file mode 100644 index 000000000..531df96e1 --- /dev/null +++ b/ports/cortex_a15/gnu/CMakeLists.txt @@ -0,0 +1,33 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# ThreadX port sources for the ARMv7-A cores, GNU tools. +# Copied into every ARMv7-A gnu port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${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_fiq_context_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fiq_context_save.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fiq_nesting_end.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fiq_nesting_start.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_irq_nesting_end.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_irq_nesting_start.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_vectored_context_save.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports/cortex_a17/gnu/CMakeLists.txt b/ports/cortex_a17/gnu/CMakeLists.txt new file mode 100644 index 000000000..531df96e1 --- /dev/null +++ b/ports/cortex_a17/gnu/CMakeLists.txt @@ -0,0 +1,33 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# ThreadX port sources for the ARMv7-A cores, GNU tools. +# Copied into every ARMv7-A gnu port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${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_fiq_context_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fiq_context_save.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fiq_nesting_end.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fiq_nesting_start.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_irq_nesting_end.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_irq_nesting_start.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_vectored_context_save.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports/cortex_a34/gnu/CMakeLists.txt b/ports/cortex_a34/gnu/CMakeLists.txt new file mode 100644 index 000000000..25e5b6b89 --- /dev/null +++ b/ports/cortex_a34/gnu/CMakeLists.txt @@ -0,0 +1,29 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# ThreadX port sources for the AArch64 cores, GNU tools. +# Copied into every AArch64 gnu port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.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_fp_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports/cortex_a35/gnu/CMakeLists.txt b/ports/cortex_a35/gnu/CMakeLists.txt new file mode 100644 index 000000000..25e5b6b89 --- /dev/null +++ b/ports/cortex_a35/gnu/CMakeLists.txt @@ -0,0 +1,29 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# ThreadX port sources for the AArch64 cores, GNU tools. +# Copied into every AArch64 gnu port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.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_fp_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports/cortex_a5/gnu/CMakeLists.txt b/ports/cortex_a5/gnu/CMakeLists.txt new file mode 100644 index 000000000..531df96e1 --- /dev/null +++ b/ports/cortex_a5/gnu/CMakeLists.txt @@ -0,0 +1,33 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# ThreadX port sources for the ARMv7-A cores, GNU tools. +# Copied into every ARMv7-A gnu port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${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_fiq_context_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fiq_context_save.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fiq_nesting_end.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fiq_nesting_start.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_irq_nesting_end.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_irq_nesting_start.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_vectored_context_save.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports/cortex_a53/gnu/CMakeLists.txt b/ports/cortex_a53/gnu/CMakeLists.txt new file mode 100644 index 000000000..25e5b6b89 --- /dev/null +++ b/ports/cortex_a53/gnu/CMakeLists.txt @@ -0,0 +1,29 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# ThreadX port sources for the AArch64 cores, GNU tools. +# Copied into every AArch64 gnu port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.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_fp_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports/cortex_a55/gnu/CMakeLists.txt b/ports/cortex_a55/gnu/CMakeLists.txt new file mode 100644 index 000000000..25e5b6b89 --- /dev/null +++ b/ports/cortex_a55/gnu/CMakeLists.txt @@ -0,0 +1,29 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# ThreadX port sources for the AArch64 cores, GNU tools. +# Copied into every AArch64 gnu port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.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_fp_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports/cortex_a57/gnu/CMakeLists.txt b/ports/cortex_a57/gnu/CMakeLists.txt new file mode 100644 index 000000000..25e5b6b89 --- /dev/null +++ b/ports/cortex_a57/gnu/CMakeLists.txt @@ -0,0 +1,29 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# ThreadX port sources for the AArch64 cores, GNU tools. +# Copied into every AArch64 gnu port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.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_fp_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports/cortex_a65/gnu/CMakeLists.txt b/ports/cortex_a65/gnu/CMakeLists.txt new file mode 100644 index 000000000..25e5b6b89 --- /dev/null +++ b/ports/cortex_a65/gnu/CMakeLists.txt @@ -0,0 +1,29 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# ThreadX port sources for the AArch64 cores, GNU tools. +# Copied into every AArch64 gnu port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.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_fp_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports/cortex_a65ae/gnu/CMakeLists.txt b/ports/cortex_a65ae/gnu/CMakeLists.txt new file mode 100644 index 000000000..25e5b6b89 --- /dev/null +++ b/ports/cortex_a65ae/gnu/CMakeLists.txt @@ -0,0 +1,29 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# ThreadX port sources for the AArch64 cores, GNU tools. +# Copied into every AArch64 gnu port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.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_fp_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports/cortex_a7/gnu/CMakeLists.txt b/ports/cortex_a7/gnu/CMakeLists.txt new file mode 100644 index 000000000..531df96e1 --- /dev/null +++ b/ports/cortex_a7/gnu/CMakeLists.txt @@ -0,0 +1,33 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# ThreadX port sources for the ARMv7-A cores, GNU tools. +# Copied into every ARMv7-A gnu port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${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_fiq_context_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fiq_context_save.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fiq_nesting_end.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fiq_nesting_start.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_irq_nesting_end.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_irq_nesting_start.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_vectored_context_save.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports/cortex_a72/gnu/CMakeLists.txt b/ports/cortex_a72/gnu/CMakeLists.txt new file mode 100644 index 000000000..25e5b6b89 --- /dev/null +++ b/ports/cortex_a72/gnu/CMakeLists.txt @@ -0,0 +1,29 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# ThreadX port sources for the AArch64 cores, GNU tools. +# Copied into every AArch64 gnu port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.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_fp_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports/cortex_a73/gnu/CMakeLists.txt b/ports/cortex_a73/gnu/CMakeLists.txt new file mode 100644 index 000000000..25e5b6b89 --- /dev/null +++ b/ports/cortex_a73/gnu/CMakeLists.txt @@ -0,0 +1,29 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# ThreadX port sources for the AArch64 cores, GNU tools. +# Copied into every AArch64 gnu port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.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_fp_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports/cortex_a75/gnu/CMakeLists.txt b/ports/cortex_a75/gnu/CMakeLists.txt new file mode 100644 index 000000000..25e5b6b89 --- /dev/null +++ b/ports/cortex_a75/gnu/CMakeLists.txt @@ -0,0 +1,29 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# ThreadX port sources for the AArch64 cores, GNU tools. +# Copied into every AArch64 gnu port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.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_fp_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports/cortex_a76/gnu/CMakeLists.txt b/ports/cortex_a76/gnu/CMakeLists.txt new file mode 100644 index 000000000..25e5b6b89 --- /dev/null +++ b/ports/cortex_a76/gnu/CMakeLists.txt @@ -0,0 +1,29 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# ThreadX port sources for the AArch64 cores, GNU tools. +# Copied into every AArch64 gnu port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.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_fp_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports/cortex_a76ae/gnu/CMakeLists.txt b/ports/cortex_a76ae/gnu/CMakeLists.txt new file mode 100644 index 000000000..25e5b6b89 --- /dev/null +++ b/ports/cortex_a76ae/gnu/CMakeLists.txt @@ -0,0 +1,29 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# ThreadX port sources for the AArch64 cores, GNU tools. +# Copied into every AArch64 gnu port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.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_fp_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports/cortex_a77/gnu/CMakeLists.txt b/ports/cortex_a77/gnu/CMakeLists.txt new file mode 100644 index 000000000..25e5b6b89 --- /dev/null +++ b/ports/cortex_a77/gnu/CMakeLists.txt @@ -0,0 +1,29 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# ThreadX port sources for the AArch64 cores, GNU tools. +# Copied into every AArch64 gnu port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.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_fp_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports/cortex_a8/gnu/CMakeLists.txt b/ports/cortex_a8/gnu/CMakeLists.txt new file mode 100644 index 000000000..531df96e1 --- /dev/null +++ b/ports/cortex_a8/gnu/CMakeLists.txt @@ -0,0 +1,33 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# ThreadX port sources for the ARMv7-A cores, GNU tools. +# Copied into every ARMv7-A gnu port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${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_fiq_context_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fiq_context_save.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fiq_nesting_end.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fiq_nesting_start.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_irq_nesting_end.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_irq_nesting_start.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_vectored_context_save.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports/cortex_a9/gnu/CMakeLists.txt b/ports/cortex_a9/gnu/CMakeLists.txt new file mode 100644 index 000000000..531df96e1 --- /dev/null +++ b/ports/cortex_a9/gnu/CMakeLists.txt @@ -0,0 +1,33 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# ThreadX port sources for the ARMv7-A cores, GNU tools. +# Copied into every ARMv7-A gnu port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${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_fiq_context_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fiq_context_save.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fiq_nesting_end.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fiq_nesting_start.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_irq_nesting_end.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_irq_nesting_start.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_vectored_context_save.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports/cortex_m23/gnu/CMakeLists.txt b/ports/cortex_m23/gnu/CMakeLists.txt new file mode 100644 index 000000000..93f52d68f --- /dev/null +++ b/ports/cortex_m23/gnu/CMakeLists.txt @@ -0,0 +1,33 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# ThreadX port sources for cortex_m23, GNU tools. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_misra.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_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_secure_stack.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_secure_stack_allocate.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_secure_stack_free.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_secure_stack_initialize.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + ${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_secure_stack_allocate.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_secure_stack_free.c + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports/cortex_r4/gnu/CMakeLists.txt b/ports/cortex_r4/gnu/CMakeLists.txt new file mode 100644 index 000000000..a5d37879c --- /dev/null +++ b/ports/cortex_r4/gnu/CMakeLists.txt @@ -0,0 +1,33 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# ThreadX port sources for cortex_r4, GNU tools. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_port_offset_check.c + ${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_fiq_context_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fiq_context_save.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fiq_nesting_end.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fiq_nesting_start.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_irq_nesting_end.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_irq_nesting_start.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_vectored_context_save.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports/cortex_r5/gnu/CMakeLists.txt b/ports/cortex_r5/gnu/CMakeLists.txt new file mode 100644 index 000000000..bb1864ef3 --- /dev/null +++ b/ports/cortex_r5/gnu/CMakeLists.txt @@ -0,0 +1,33 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# ThreadX port sources for cortex_r5, GNU tools. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_port_offset_check.c + ${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_fiq_context_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fiq_context_save.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fiq_nesting_end.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fiq_nesting_start.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_irq_nesting_end.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_irq_nesting_start.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_vectored_context_save.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports_arch/ARMv7-A/threadx/ports/gnu/CMakeLists.txt b/ports_arch/ARMv7-A/threadx/ports/gnu/CMakeLists.txt new file mode 100644 index 000000000..531df96e1 --- /dev/null +++ b/ports_arch/ARMv7-A/threadx/ports/gnu/CMakeLists.txt @@ -0,0 +1,33 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# ThreadX port sources for the ARMv7-A cores, GNU tools. +# Copied into every ARMv7-A gnu port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${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_fiq_context_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fiq_context_save.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fiq_nesting_end.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fiq_nesting_start.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_irq_nesting_end.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_irq_nesting_start.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_vectored_context_save.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports_arch/ARMv8-A/threadx/ports/gnu/CMakeLists.txt b/ports_arch/ARMv8-A/threadx/ports/gnu/CMakeLists.txt new file mode 100644 index 000000000..25e5b6b89 --- /dev/null +++ b/ports_arch/ARMv8-A/threadx/ports/gnu/CMakeLists.txt @@ -0,0 +1,29 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# ThreadX port sources for the AArch64 cores, GNU tools. +# Copied into every AArch64 gnu port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.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_fp_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports_arch/ARMv8-A/threadx_smp/ports/gnu/CMakeLists.txt b/ports_arch/ARMv8-A/threadx_smp/ports/gnu/CMakeLists.txt new file mode 100644 index 000000000..a10302809 --- /dev/null +++ b/ports_arch/ARMv8-A/threadx_smp/ports/gnu/CMakeLists.txt @@ -0,0 +1,38 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# ThreadX SMP port sources for the AArch64 cores, GNU tools. +# Copied into every AArch64 gnu SMP port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.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_fp_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_preempt.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_state_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_thread_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_initialize_wait.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_low_level_initialize.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_protect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_time_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_unprotect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports_smp/cortex_a34_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a34_smp/gnu/CMakeLists.txt new file mode 100644 index 000000000..a10302809 --- /dev/null +++ b/ports_smp/cortex_a34_smp/gnu/CMakeLists.txt @@ -0,0 +1,38 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# ThreadX SMP port sources for the AArch64 cores, GNU tools. +# Copied into every AArch64 gnu SMP port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.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_fp_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_preempt.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_state_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_thread_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_initialize_wait.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_low_level_initialize.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_protect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_time_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_unprotect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports_smp/cortex_a35_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a35_smp/gnu/CMakeLists.txt new file mode 100644 index 000000000..a10302809 --- /dev/null +++ b/ports_smp/cortex_a35_smp/gnu/CMakeLists.txt @@ -0,0 +1,38 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# ThreadX SMP port sources for the AArch64 cores, GNU tools. +# Copied into every AArch64 gnu SMP port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.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_fp_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_preempt.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_state_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_thread_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_initialize_wait.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_low_level_initialize.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_protect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_time_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_unprotect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports_smp/cortex_a53_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a53_smp/gnu/CMakeLists.txt new file mode 100644 index 000000000..a10302809 --- /dev/null +++ b/ports_smp/cortex_a53_smp/gnu/CMakeLists.txt @@ -0,0 +1,38 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# ThreadX SMP port sources for the AArch64 cores, GNU tools. +# Copied into every AArch64 gnu SMP port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.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_fp_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_preempt.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_state_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_thread_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_initialize_wait.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_low_level_initialize.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_protect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_time_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_unprotect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports_smp/cortex_a55_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a55_smp/gnu/CMakeLists.txt new file mode 100644 index 000000000..a10302809 --- /dev/null +++ b/ports_smp/cortex_a55_smp/gnu/CMakeLists.txt @@ -0,0 +1,38 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# ThreadX SMP port sources for the AArch64 cores, GNU tools. +# Copied into every AArch64 gnu SMP port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.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_fp_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_preempt.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_state_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_thread_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_initialize_wait.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_low_level_initialize.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_protect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_time_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_unprotect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports_smp/cortex_a57_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a57_smp/gnu/CMakeLists.txt new file mode 100644 index 000000000..a10302809 --- /dev/null +++ b/ports_smp/cortex_a57_smp/gnu/CMakeLists.txt @@ -0,0 +1,38 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# ThreadX SMP port sources for the AArch64 cores, GNU tools. +# Copied into every AArch64 gnu SMP port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.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_fp_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_preempt.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_state_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_thread_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_initialize_wait.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_low_level_initialize.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_protect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_time_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_unprotect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports_smp/cortex_a5_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a5_smp/gnu/CMakeLists.txt new file mode 100644 index 000000000..f08066585 --- /dev/null +++ b/ports_smp/cortex_a5_smp/gnu/CMakeLists.txt @@ -0,0 +1,37 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# ThreadX port sources for cortex_a5_smp, GNU tools. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${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_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_irq_nesting_end.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_irq_nesting_start.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_preempt.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_state_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_thread_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_initialize_wait.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_low_level_initialize.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_protect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_time_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_unprotect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_vectored_context_save.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports_smp/cortex_a5x_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a5x_smp/gnu/CMakeLists.txt new file mode 100644 index 000000000..8e8f8cd0c --- /dev/null +++ b/ports_smp/cortex_a5x_smp/gnu/CMakeLists.txt @@ -0,0 +1,37 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# ThreadX port sources for cortex_a5x_smp, GNU tools. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.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_fp_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_preempt.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_state_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_thread_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_initialize_wait.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_low_level_initialize.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_protect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_time_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_unprotect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports_smp/cortex_a65_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a65_smp/gnu/CMakeLists.txt new file mode 100644 index 000000000..a10302809 --- /dev/null +++ b/ports_smp/cortex_a65_smp/gnu/CMakeLists.txt @@ -0,0 +1,38 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# ThreadX SMP port sources for the AArch64 cores, GNU tools. +# Copied into every AArch64 gnu SMP port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.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_fp_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_preempt.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_state_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_thread_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_initialize_wait.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_low_level_initialize.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_protect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_time_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_unprotect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports_smp/cortex_a65ae_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a65ae_smp/gnu/CMakeLists.txt new file mode 100644 index 000000000..a10302809 --- /dev/null +++ b/ports_smp/cortex_a65ae_smp/gnu/CMakeLists.txt @@ -0,0 +1,38 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# ThreadX SMP port sources for the AArch64 cores, GNU tools. +# Copied into every AArch64 gnu SMP port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.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_fp_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_preempt.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_state_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_thread_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_initialize_wait.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_low_level_initialize.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_protect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_time_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_unprotect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports_smp/cortex_a72_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a72_smp/gnu/CMakeLists.txt new file mode 100644 index 000000000..a10302809 --- /dev/null +++ b/ports_smp/cortex_a72_smp/gnu/CMakeLists.txt @@ -0,0 +1,38 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# ThreadX SMP port sources for the AArch64 cores, GNU tools. +# Copied into every AArch64 gnu SMP port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.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_fp_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_preempt.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_state_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_thread_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_initialize_wait.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_low_level_initialize.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_protect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_time_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_unprotect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports_smp/cortex_a73_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a73_smp/gnu/CMakeLists.txt new file mode 100644 index 000000000..a10302809 --- /dev/null +++ b/ports_smp/cortex_a73_smp/gnu/CMakeLists.txt @@ -0,0 +1,38 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# ThreadX SMP port sources for the AArch64 cores, GNU tools. +# Copied into every AArch64 gnu SMP port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.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_fp_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_preempt.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_state_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_thread_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_initialize_wait.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_low_level_initialize.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_protect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_time_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_unprotect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports_smp/cortex_a75_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a75_smp/gnu/CMakeLists.txt new file mode 100644 index 000000000..a10302809 --- /dev/null +++ b/ports_smp/cortex_a75_smp/gnu/CMakeLists.txt @@ -0,0 +1,38 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# ThreadX SMP port sources for the AArch64 cores, GNU tools. +# Copied into every AArch64 gnu SMP port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.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_fp_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_preempt.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_state_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_thread_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_initialize_wait.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_low_level_initialize.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_protect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_time_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_unprotect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports_smp/cortex_a76_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a76_smp/gnu/CMakeLists.txt new file mode 100644 index 000000000..a10302809 --- /dev/null +++ b/ports_smp/cortex_a76_smp/gnu/CMakeLists.txt @@ -0,0 +1,38 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# ThreadX SMP port sources for the AArch64 cores, GNU tools. +# Copied into every AArch64 gnu SMP port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.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_fp_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_preempt.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_state_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_thread_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_initialize_wait.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_low_level_initialize.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_protect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_time_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_unprotect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports_smp/cortex_a76ae_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a76ae_smp/gnu/CMakeLists.txt new file mode 100644 index 000000000..a10302809 --- /dev/null +++ b/ports_smp/cortex_a76ae_smp/gnu/CMakeLists.txt @@ -0,0 +1,38 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# ThreadX SMP port sources for the AArch64 cores, GNU tools. +# Copied into every AArch64 gnu SMP port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.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_fp_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_preempt.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_state_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_thread_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_initialize_wait.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_low_level_initialize.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_protect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_time_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_unprotect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports_smp/cortex_a77_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a77_smp/gnu/CMakeLists.txt new file mode 100644 index 000000000..a10302809 --- /dev/null +++ b/ports_smp/cortex_a77_smp/gnu/CMakeLists.txt @@ -0,0 +1,38 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# ThreadX SMP port sources for the AArch64 cores, GNU tools. +# Copied into every AArch64 gnu SMP port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.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_fp_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_preempt.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_state_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_thread_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_initialize_wait.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_low_level_initialize.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_protect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_time_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_unprotect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports_smp/cortex_a78_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a78_smp/gnu/CMakeLists.txt new file mode 100644 index 000000000..a10302809 --- /dev/null +++ b/ports_smp/cortex_a78_smp/gnu/CMakeLists.txt @@ -0,0 +1,38 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# ThreadX SMP port sources for the AArch64 cores, GNU tools. +# Copied into every AArch64 gnu SMP port by update.sh, so edit it here. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.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_fp_disable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_fp_enable.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_preempt.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_state_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_thread_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_initialize_wait.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_low_level_initialize.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_protect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_time_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_unprotect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports_smp/cortex_a7_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a7_smp/gnu/CMakeLists.txt new file mode 100644 index 000000000..7e2719460 --- /dev/null +++ b/ports_smp/cortex_a7_smp/gnu/CMakeLists.txt @@ -0,0 +1,36 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# ThreadX port sources for cortex_a7_smp, GNU tools. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${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_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_irq_nesting_end.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_irq_nesting_start.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_preempt.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_state_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_thread_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_initialize_wait.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_low_level_initialize.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_protect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_time_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_vectored_context_save.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports_smp/linux/gnu/CMakeLists.txt b/ports_smp/linux/gnu/CMakeLists.txt new file mode 100644 index 000000000..6ad4d25b1 --- /dev/null +++ b/ports_smp/linux/gnu/CMakeLists.txt @@ -0,0 +1,33 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# ThreadX port sources for linux, GNU tools. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_restore.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_context_save.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_control.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_preempt.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_state_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_thread_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_initialize_wait.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_low_level_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_protect.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_time_get.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_unprotect.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.c + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports_smp/mips32_interaptiv_smp/gnu/CMakeLists.txt b/ports_smp/mips32_interaptiv_smp/gnu/CMakeLists.txt new file mode 100644 index 000000000..1c0ad10df --- /dev/null +++ b/ports_smp/mips32_interaptiv_smp/gnu/CMakeLists.txt @@ -0,0 +1,33 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# ThreadX port sources for mips32_interaptiv_smp, GNU tools. + +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.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_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_core_preempt.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_state_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_current_thread_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_initialize_wait.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_low_level_initialize.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_protect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_time_get.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_smp_unprotect.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) From acdc02b2fcd5883faed61a619d38f8e5f89fc69e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Thu, 13 Aug 2026 10:14:53 -0400 Subject: [PATCH 035/181] Assembled the code behind feature macros, and fixed the POP it found (#608) scripts/check_clang.sh assembled every source with default flags, so the preprocessor discarded each #ifdef block before the assembler saw it. Nothing in the tree had ever assembled a guarded path. That covers the VFP context save and restore in ten ports, and 218 files carrying TX_LOW_POWER or TX_ENABLE_EXECUTION_CHANGE_NOTIFY. Turning those on found a defect. The Cortex-M0 and Cortex-M23 execution-profile paths bracket their call with PUSH {r0, lr} BL _tx_execution_isr_enter POP {r0, lr} and the last of those is invalid on Armv6-M and Armv8-M Baseline, where the 16-bit Thumb POP takes r0-r7 and pc and nothing else. GNU rejects it as well -- "cannot honor width suffix" -- so TX_ENABLE_EXECUTION_CHANGE_NOTIFY and TX_EXECUTION_PROFILE_ENABLE have never been buildable on either port with either toolchain. Four files, all the same shape. The fix pops into a scratch register and moves it, MOV to a high register being permitted where POP is not. r1 is free: the BL may clobber r0-r3, which is the reason r0 is saved in the first place. Disassembling the result gives push {r0, lr} / bl / pop {r0, r1} / mov lr, r1 / bx lr, one 16-bit instruction more than before and otherwise the same. Two findings that were not defects, recorded in the script so they are not rediscovered: Cortex-R4 needs an -mfpu to assemble its VFP path, because its FPU is an option rather than part of the core. GNU fails identically without one, so this is a flags requirement and not a toolchain divergence. The A profile ports must not be given one. Adding -mfpu=vfpv3-d16 uniformly broke 28 files with "register expected", because those ports save D16-D31 and a -d16 FPU does not have those registers. Their defaults were already right. The new stage runs under --asm-only as well, needing no target C library, and reports 37 of 37 VFP files, 8 of 8 TX_LOW_POWER and 218 of 218 TX_ENABLE_EXECUTION_CHANGE_NOTIFY. Restoring the POP for one run makes it fail with 217 of 218 and name the file and the error, so the stage is not vacuous. The other four stages are unchanged: 711 of 711 assembled, 185 of 185 common C sources for each of nine cores, 42 of 42 script-driven examples and 5 of 5 CMake images. The fixed code is verified to assemble with both toolchains and to encode as intended. It is not verified running: there is no Cortex-M0 or Cortex-M23 model here, and these are context save and restore paths, so that gap is worth stating. Assisted-by: Claude Code (Opus 5) --- .../gnu/src/tx_thread_context_restore.S | 9 ++- .../gnu/src/tx_thread_context_save.S | 9 ++- .../gnu/src/tx_thread_context_restore.S | 9 ++- .../gnu/src/tx_thread_context_save.S | 9 ++- scripts/check_clang.sh | 72 +++++++++++++++++-- 5 files changed, 99 insertions(+), 9 deletions(-) diff --git a/ports/cortex_m0/gnu/src/tx_thread_context_restore.S b/ports/cortex_m0/gnu/src/tx_thread_context_restore.S index 968548671..68fd52517 100644 --- a/ports/cortex_m0/gnu/src/tx_thread_context_restore.S +++ b/ports/cortex_m0/gnu/src/tx_thread_context_restore.S @@ -85,7 +85,14 @@ _tx_thread_context_restore: /* Call the ISR exit function to indicate an ISR is complete. */ PUSH {r0, lr} // Save return address BL _tx_execution_isr_exit // Call the ISR exit function - POP {r0, lr} // Recover return address + POP {r0, r1} // Recover r0 and the return address + MOV lr, r1 // This core cannot POP into LR: the + // 16-bit Thumb POP takes r0-r7 and + // pc only. MOV to a high register + // is permitted, so restore LR from + // a scratch register. r1 is free -- + // the BL above may clobber r0-r3, + // which is why r0 is saved at all. #endif BX lr @} diff --git a/ports/cortex_m0/gnu/src/tx_thread_context_save.S b/ports/cortex_m0/gnu/src/tx_thread_context_save.S index 9866da139..e62a28711 100644 --- a/ports/cortex_m0/gnu/src/tx_thread_context_save.S +++ b/ports/cortex_m0/gnu/src/tx_thread_context_save.S @@ -76,7 +76,14 @@ _tx_thread_context_save: /* Call the ISR enter function to indicate an ISR is starting. */ PUSH {r0, lr} // Save return address BL _tx_execution_isr_enter // Call the ISR enter function - POP {r0, lr} // Recover return address + POP {r0, r1} // Recover r0 and the return address + MOV lr, r1 // This core cannot POP into LR: the + // 16-bit Thumb POP takes r0-r7 and + // pc only. MOV to a high register + // is permitted, so restore LR from + // a scratch register. r1 is free -- + // the BL above may clobber r0-r3, + // which is why r0 is saved at all. #endif /* Context is already saved - just return. */ diff --git a/ports/cortex_m23/gnu/src/tx_thread_context_restore.S b/ports/cortex_m23/gnu/src/tx_thread_context_restore.S index 6f2b453cf..e8ddac054 100644 --- a/ports/cortex_m23/gnu/src/tx_thread_context_restore.S +++ b/ports/cortex_m23/gnu/src/tx_thread_context_restore.S @@ -73,7 +73,14 @@ _tx_thread_context_restore: /* Call the ISR exit function to indicate an ISR is complete. */ PUSH {r0, lr} // Save return address BL _tx_execution_isr_exit // Call the ISR exit function - POP {r0, lr} // Recover return address + POP {r0, r1} // Recover r0 and the return address + MOV lr, r1 // This core cannot POP into LR: the + // 16-bit Thumb POP takes r0-r7 and + // pc only. MOV to a high register + // is permitted, so restore LR from + // a scratch register. r1 is free -- + // the BL above may clobber r0-r3, + // which is why r0 is saved at all. #endif BX lr diff --git a/ports/cortex_m23/gnu/src/tx_thread_context_save.S b/ports/cortex_m23/gnu/src/tx_thread_context_save.S index 84bf99083..136c6391f 100644 --- a/ports/cortex_m23/gnu/src/tx_thread_context_save.S +++ b/ports/cortex_m23/gnu/src/tx_thread_context_save.S @@ -73,7 +73,14 @@ _tx_thread_context_save: /* Call the ISR enter function to indicate an ISR is starting. */ PUSH {r0, lr} // Save return address BL _tx_execution_isr_enter // Call the ISR enter function - POP {r0, lr} // Recover return address + POP {r0, r1} // Recover r0 and the return address + MOV lr, r1 // This core cannot POP into LR: the + // 16-bit Thumb POP takes r0-r7 and + // pc only. MOV to a high register + // is permitted, so restore LR from + // a scratch register. r1 is free -- + // the BL above may clobber r0-r3, + // which is why r0 is saved at all. #endif BX lr diff --git a/scripts/check_clang.sh b/scripts/check_clang.sh index c0cae4014..c7ebed79a 100755 --- a/scripts/check_clang.sh +++ b/scripts/check_clang.sh @@ -14,11 +14,11 @@ # SPDX-License-Identifier: MIT and CC0-1.0 ############################################################################## -# Builds the Arm ports with an LLVM based toolchain, in four stages: assemble -# every assembly source of every Arm gnu port, compile the common C sources for -# one core per architecture profile, link the example builds that have a script -# driver, then link those driven by CMake. Only the two linking stages need a -# target C library. +# Builds the Arm ports with an LLVM based toolchain, in five stages: assemble +# every assembly source of every Arm gnu port, assemble again the parts guarded +# by feature macros, compile the common C sources for one core per architecture +# profile, then link the example builds, both the script-driven ones and those +# driven by CMake. Only the linking stages need a target C library. # # scripts/check_clang.sh # clang from PATH # scripts/check_clang.sh --clang /path/to/clang @@ -140,6 +140,28 @@ declare -A PORT_TARGET=( [cortex_a78_smp]="aarch64-none-elf cortex-a78" ) +# Assembly guarded by a feature macro is invisible to the stage above, which +# assembles with default flags and so lets the preprocessor discard every #ifdef +# block before the assembler sees it. These are the macros a user can turn on; +# each file carrying one is assembled again with it defined. +# +# This is not hypothetical. It is where "POP {r0, lr}" was found in the Cortex-M0 +# and Cortex-M23 execution-profile paths: invalid on Armv6-M and Armv8-M +# Baseline, where the 16-bit POP takes r0-r7 and pc only, and rejected by GNU as +# well as by LLVM. Turning the feature on had never once been tried. +FEATURE_MACROS="TX_ENABLE_VFP_SUPPORT TX_LOW_POWER TX_ENABLE_EXECUTION_CHANGE_NOTIFY" + +# Extra flags for the VFP paths, per core, needed only where -mcpu alone cannot +# assemble them. Cortex-R4's FPU is an option rather than part of the core, so +# both toolchains reject its VFP code without an -mfpu. +# +# Do not extend this to the A profile ports. They save D16-D31, which exists only +# on a 32-register FPU, so naming a -d16 FPU takes those registers away and turns +# 28 working files into "register expected". Their defaults are already correct. +declare -A VFP_EXTRA=( + [cortex_r4]="-mfpu=vfpv3-d16 -mfloat-abi=softfp" +) + # One core per architecture profile for the C sources. Compiling all of them # for every core would multiply the run time without adding coverage, since the # port headers differ by profile rather than by core. @@ -200,6 +222,46 @@ if [ -n "$skipped" ]; then say " not Arm, skipped:$(echo $skipped | tr ' ' '\n' | sort -u | tr '\n' ' ')" fi +# -------------------------------------------------------------------------- +say "" +say "== Assembly behind feature macros ==" + +for macro in $FEATURE_MACROS; do + macro_total=0 + macro_bad=0 + for src in $(grep -rl "$macro" ports/*/gnu/src/*.S ports_smp/*/gnu/src/*.S \ + 2>/dev/null | sort); do + core="$(echo "$src" | cut -d/ -f2)" + spec="${PORT_TARGET[$core]:-}" + [ -n "$spec" ] || continue + # shellcheck disable=SC2086 + set -- $spec + target="$1"; cpu="$2"; shift 2; extra="$*" + + # The FPU flags apply to the VFP paths only; the other macros guard no + # floating-point code and do not need them. + fpu="" + if [ "$macro" = "TX_ENABLE_VFP_SUPPORT" ]; then + fpu="${VFP_EXTRA[$core]:-}" + fi + + macro_total=$((macro_total + 1)) + output="$("$CC" --target="$target" -mcpu="$cpu" $extra $fpu \ + -D"$macro" -c "$src" -o /dev/null 2>&1)" + if [ -n "$output" ]; then + fail "$src with -D$macro" + echo "$output" | grep "error:" | head -3 | sed 's/^/ /' + macro_bad=$((macro_bad + 1)) + failures=$((failures + 1)) + fi + done + if [ "$macro_total" -eq 0 ]; then + say " $macro: no assembly is guarded by it" + else + say " $macro: $((macro_total - macro_bad)) of $macro_total assembled" + fi +done + # -------------------------------------------------------------------------- if [ "$asm_only" -eq 0 ]; then say "" From c991c9e6aebc32a99667ca2941d5b839f5b2b1cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Thu, 13 Aug 2026 15:57:18 -0400 Subject: [PATCH 036/181] Added TX_ENABLE_FIQ_SUPPORT to the feature-macro assembly stage (#610) #608 assembled the code behind TX_ENABLE_VFP_SUPPORT, TX_LOW_POWER and TX_ENABLE_EXECUTION_CHANGE_NOTIFY, and missed TX_ENABLE_FIQ_SUPPORT, which guards assembly in 145 files across the A and R profile ports. All 145 assemble today, so this adds no fix, only the regression protection the other three already have. Also recorded why TX_ENABLE_IRQ_NESTING and TX_ENABLE_FIQ_NESTING are not in the list, since their absence otherwise looks like the same oversight. They guard no assembly in the trees this script walks: the nesting start and end routines are separate files compiled unconditionally, and the macros only feed the TX_PORT_SPECIFIC_BUILD_OPTIONS bitfield in tx_port.h. Adding them would assemble nothing new while implying coverage that does not exist. Verified with Arm Toolchain for Embedded 22.1.0: 711 of 711 assembly sources, then 37 of 37 VFP, 145 of 145 FIQ, 8 of 8 TX_LOW_POWER and 218 of 218 TX_ENABLE_EXECUTION_CHANGE_NOTIFY. Assisted-by: Claude Code (Opus 5) --- scripts/check_clang.sh | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/scripts/check_clang.sh b/scripts/check_clang.sh index c7ebed79a..446782df0 100755 --- a/scripts/check_clang.sh +++ b/scripts/check_clang.sh @@ -149,7 +149,14 @@ declare -A PORT_TARGET=( # and Cortex-M23 execution-profile paths: invalid on Armv6-M and Armv8-M # Baseline, where the 16-bit POP takes r0-r7 and pc only, and rejected by GNU as # well as by LLVM. Turning the feature on had never once been tried. -FEATURE_MACROS="TX_ENABLE_VFP_SUPPORT TX_LOW_POWER TX_ENABLE_EXECUTION_CHANGE_NOTIFY" +FEATURE_MACROS="TX_ENABLE_VFP_SUPPORT TX_ENABLE_FIQ_SUPPORT TX_LOW_POWER + TX_ENABLE_EXECUTION_CHANGE_NOTIFY" + +# TX_ENABLE_IRQ_NESTING and TX_ENABLE_FIQ_NESTING are deliberately not here. +# They guard no assembly in the trees this script walks: the nesting start and end +# routines are separate files compiled unconditionally, and the macros only feed +# the TX_PORT_SPECIFIC_BUILD_OPTIONS bitfield in tx_port.h. Adding them would +# assemble nothing new and imply coverage that does not exist. # Extra flags for the VFP paths, per core, needed only where -mcpu alone cannot # assemble them. Cortex-R4's FPU is an option rather than part of the core, so From b877305d13ea2a45d40cb86416adc24938bbe154 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Thu, 13 Aug 2026 17:07:36 -0400 Subject: [PATCH 037/181] Verified lazy VFP context switching on S32Z280 silicon (#609) The FVP proved the lazy save and restore path at AR1/M5, but the board had never run it. Doing so needed one thing the model did not: the FPU has to be turned on. entry.S opens CPACR for CP10/CP11 and sets FPEXC.EN at EL1, guarded by __ARM_FP. EL2 already cleared HCPTR.TCP10/TCP11, but both of the EL1 gates read 0 out of reset, so a floating-point instruction raised an Undefined Instruction exception before this. tx_thread_vfp_enable() does not help: it sets the per-thread software flag that makes the context switch save and restore the registers, and never touches the hardware. Enabling it is the BSP's job. The __ARM_FP guard is what keeps a soft-float build assemblable, since "vmsr fpexc" is not a valid instruction for that target at all. demo_vfp_s32z280.c is the FVP's demo_m5.c test design over the LINFlexD console. The design is kept deliberately, because the two halves of the VFP context path need separate provocation: "fp check" holds eight live doubles across tx_thread_sleep, eight being enough to force the callee-saved D8-D15 bank that a solicited switch must preserve, while "fp busy" sits at the lowest priority and never sleeps, so the tick interrupts it mid-computation and exercises the interrupt half, D0-D15 plus FPSCR. Only these two threads opt in, so the test also shows that opting in is what does the work. s32z280_vfp.elf is gated on TX_R52_ENABLE_VFP, as demo_m5.elf is in the FVP example, since the image is meaningless unless the library was built with a floating-point ABI. Also made this example's -Wl,--no-warn-rwx-segments conditional on the compiler being GNU. #604 did that for the FVP example and this file still carried the literal, so ld.lld failed the link with "unknown argument". With that fixed the S32Z280 images build with Arm Toolchain for Embedded too. Verified on S32Z280 silicon: V2 D8-D15 bank preserved across switches PASS 50 solicited switches iterations = 0x000140A8 82,088 interrupted rounds corruptions = 0x00000000 V3 interrupted FP thread made progress PASS V4 no FP corruption across interrupts PASS filex_ptr = 0xF11EF11E V5 VFP flag did not alias filex_ptr PASS PASS lazy VFP context switch verified on silicon No regression: the soft-float build is warning-free and its image contains no vmsr at all, confirming the guard elides the block, and the existing demo still reports 100 ticks with 20 preemptions on the board. Both S32Z280 images also build with Arm Toolchain for Embedded 22.1.0, the hard-float VFP image included. No FVP file is touched. Assisted-by: Claude Code (Opus 5) --- .../example_build/s32z280_evb/CMakeLists.txt | 52 +++- .../s32z280_evb/demo_vfp_s32z280.c | 283 ++++++++++++++++++ .../gnu/example_build/s32z280_evb/entry.S | 41 +++ 3 files changed, 374 insertions(+), 2 deletions(-) create mode 100644 ports/cortex_r52/gnu/example_build/s32z280_evb/demo_vfp_s32z280.c diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/CMakeLists.txt b/ports/cortex_r52/gnu/example_build/s32z280_evb/CMakeLists.txt index 3319d77f1..017aa7574 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/CMakeLists.txt +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/CMakeLists.txt @@ -11,6 +11,17 @@ set(EVB_DIR ${CMAKE_CURRENT_LIST_DIR}) +# A bare-metal image has one flat SRAM region and no OS page permissions; access +# control belongs to the MPU, so an RWX segment is expected rather than a mistake. +# GNU ld has warned about them since binutils 2.39 and takes this flag to stay +# quiet; ld.lld does not warn and rejects the flag outright, failing the link with +# "unknown argument". Chosen by toolchain, as in the FVP example. +if(CMAKE_C_COMPILER_ID STREQUAL "GNU") + set(EVB_LINK_QUIET_RWX -Wl,--no-warn-rwx-segments) +else() + set(EVB_LINK_QUIET_RWX) +endif() + # Silicon M0 -- boot verification. Deliberately does not link ThreadX: a # failure here is then unambiguously a boot or board problem rather than a # kernel one, which is the same reasoning as the FVP's boot_check.elf. @@ -39,7 +50,7 @@ target_link_options(s32z280_boot.elf PRIVATE -Wl,-Map=s32z280_boot.map # Bare metal: one code region and one data region, with access control # belonging to the MPU rather than to segment permissions. - -Wl,--no-warn-rwx-segments + ${EVB_LINK_QUIET_RWX} ) @@ -77,5 +88,42 @@ target_link_options(s32z280_demo.elf PRIVATE -T${EVB_DIR}/link.lds -nostartfiles -Wl,-Map=s32z280_demo.map - -Wl,--no-warn-rwx-segments + ${EVB_LINK_QUIET_RWX} ) + +# Lazy VFP context save and restore. Only meaningful when the library was built +# with TX_R52_ENABLE_VFP and a floating-point ABI, so like the FVP's demo_m5.elf +# the target exists only in that configuration. The FPU hardware enable lives in +# entry.S under __ARM_FP; tx_thread_vfp_enable() sets only the per-thread flag. +if(TX_R52_ENABLE_VFP) + add_executable(s32z280_vfp.elf EXCLUDE_FROM_ALL + ${EVB_DIR}/entry.S + ${EVB_DIR}/tx_initialize_low_level.S + ${EVB_DIR}/linflexd.c + ${EVB_DIR}/timer.c + ${EVB_DIR}/mpu.c + ${EVB_DIR}/gicv3.c + ${EVB_DIR}/irq_dispatch.c + ${EVB_DIR}/gic_probe.c + ${EVB_DIR}/cache.c + ${EVB_DIR}/demo_vfp_s32z280.c + ) + + target_compile_definitions(s32z280_vfp.elf PRIVATE TX_R52_USE_THREADX_IRQ=1) + target_compile_options(s32z280_vfp.elf PRIVATE -g) + + target_link_libraries(s32z280_vfp.elf PRIVATE threadx) + + target_include_directories(s32z280_vfp.elf PRIVATE + ${EVB_DIR} + ${CMAKE_SOURCE_DIR}/common/inc + ${CMAKE_SOURCE_DIR}/ports/${THREADX_ARCH}/${THREADX_TOOLCHAIN}/inc + ) + + target_link_options(s32z280_vfp.elf PRIVATE + -T${EVB_DIR}/link.lds + -nostartfiles + -Wl,-Map=s32z280_vfp.map + ${EVB_LINK_QUIET_RWX} + ) +endif() diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/demo_vfp_s32z280.c b/ports/cortex_r52/gnu/example_build/s32z280_evb/demo_vfp_s32z280.c new file mode 100644 index 000000000..456ad3190 --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/demo_vfp_s32z280.c @@ -0,0 +1,283 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* BOARD SUPPORT RELEASE */ +/* */ +/* demo_vfp_s32z280.c Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frederic Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Lazy floating-point context save and restore on S32Z280 silicon. */ +/* */ +/* This is the FVP's demo_m5.c test design, reporting over the */ +/* LINFlexD console instead of semihosting. The design is kept */ +/* deliberately: the model established that the two halves of the VFP */ +/* context path need separate provocation, and silicon does not change */ +/* that, it only changes whether the hardware agrees. */ +/* */ +/* fp check holds eight live doubles across tx_thread_sleep. Eight */ +/* forces the compiler onto the callee-saved bank D8-D15, */ +/* which is what a SOLICITED switch must preserve. */ +/* */ +/* fp busy lowest priority and never sleeps, so the periodic tick */ +/* interrupts it mid-computation. That exercises the */ +/* INTERRUPT half, D0-D15 plus FPSCR, and it checks its */ +/* own values every iteration. */ +/* */ +/* Both call tx_thread_vfp_enable(). With lazy save and restore a */ +/* thread that has not asked for floating point does not get its */ +/* registers saved, so a test where every thread opts in would not */ +/* show whether the opt-in is what does the work. */ +/* */ +/* Every constant is an exact binary fraction and the step is 0.5, so */ +/* the comparisons are exact and no epsilon is needed. MISRA C:2012 */ +/* Dir 4.6 and Rule 13.3 would normally object to == on floating */ +/* point; here it is the point, since any inexactness means a register */ +/* was not preserved. */ +/* */ +/* What silicon adds over the model: the FPU must actually be enabled */ +/* by the BSP. entry.S opens CPACR and FPEXC.EN at EL1 under */ +/* __ARM_FP, because tx_thread_vfp_enable() sets only the per-thread */ +/* software flag and never touches the hardware. Without that, the */ +/* first D-register access after a switch takes an Undefined */ +/* Instruction exception -- which on this board was invisible until */ +/* SCTLR.TE was cleared. */ +/* */ +/**************************************************************************/ + +#include "tx_api.h" +#include "linflexd.h" +#include "board.h" + +#define DEMO_STACK_SIZE 2048 +#define FILEX_PTR_SENTINEL ((void *) 0xF11EF11EUL) +#define FP_ITERATIONS 50UL +#define FP_STEP 0.5 /* exactly representable */ + +static TX_THREAD thread_check; +static TX_THREAD thread_fp_busy; + +static ULONG thread_check_stack[DEMO_STACK_SIZE / sizeof(ULONG)]; +static ULONG thread_fp_busy_stack[DEMO_STACK_SIZE / sizeof(ULONG)]; + +static volatile ULONG busy_iterations; +static volatile ULONG busy_corruptions; + + +/* Breakpoint target for tools/read_identity.gdb. Not static and not empty so + an optimising build cannot discard it. */ + +void bsp_done(void) +{ + __asm volatile ("nop"); +} + + +static UINT report(const char *label_ptr, UINT passed) +{ + linflexd_puts(label_ptr); + linflexd_puts((passed != 0U) ? "PASS\n" : "FAIL\n"); + return (passed != 0U) ? 0U : 1U; +} + + +static void report_hex(const char *label_ptr, unsigned long value) +{ + linflexd_puts(label_ptr); + linflexd_puts(" = 0x"); + linflexd_put_hex32((unsigned int) value); + linflexd_putc('\n'); +} + + +/**************************************************************************/ +/* thread_fp_busy_entry -- the interrupt half of the VFP path. */ +/**************************************************************************/ + +static void thread_fp_busy_entry(ULONG thread_input) +{ + (void) thread_input; + + tx_thread_vfp_enable(); + + for (;;) + { + /* Deliberately disjoint from the checking thread's range, so that + state leaking from one context into the other is detectable rather + than coincidentally correct. */ + + double v0 = 1024.5; + double v1 = 2048.25; + double v2 = 4096.125; + double v3 = 8192.0625; + + v0 = (v0 * 2.0) - 1024.5; /* 1024.5 */ + v1 = (v1 * 2.0) - 2048.25; /* 2048.25 */ + v2 = (v2 * 2.0) - 4096.125; /* 4096.125 */ + v3 = (v3 * 2.0) - 8192.0625; /* 8192.0625 */ + + if ((v0 != 1024.5) || (v1 != 2048.25) || + (v2 != 4096.125) || (v3 != 8192.0625)) + { + busy_corruptions++; + } + + busy_iterations++; + } +} + + +/**************************************************************************/ +/* thread_check_entry -- the solicited half, and the judge. */ +/**************************************************************************/ + +static void thread_check_entry(ULONG thread_input) +{ + UINT failures = 0U; + ULONG iteration; + TX_THREAD *self; + + double a = 1.5; + double b = 2.25; + double c = 3.125; + double d = 4.0625; + double e = 5.03125; + double f = 6.015625; + double g = 7.0078125; + double h = 8.00390625; + + (void) thread_input; + + /* The VFP enable flag is reached from assembly by hard-coded offset. On the + Cortex-R4 and R5 ports that offset lands on tx_thread_filex_ptr, because + their TX_THREAD_EXTENSION_2 is empty. A sentinel turns that class of + mistake into a visible failure instead of corruption that only appears + once something actually uses FileX. */ + + self = tx_thread_identify(); + self->tx_thread_filex_ptr = FILEX_PTR_SENTINEL; + + tx_thread_vfp_enable(); + + linflexd_puts("V1 floating-point work across solicited switches\n"); + + for (iteration = 0UL; iteration < FP_ITERATIONS; iteration++) + { + /* Suspending here is the provocation: the switch must preserve all + eight values, and the lower-priority thread runs meanwhile. */ + + tx_thread_sleep(1); + + a += FP_STEP; + b += FP_STEP; + c += FP_STEP; + d += FP_STEP; + e += FP_STEP; + f += FP_STEP; + g += FP_STEP; + h += FP_STEP; + } + + { + const double delta = 0.5 * (double) FP_ITERATIONS; + + failures += report("V2 D8-D15 bank preserved across switches ", + ((a == (1.5 + delta)) && + (b == (2.25 + delta)) && + (c == (3.125 + delta)) && + (d == (4.0625 + delta)) && + (e == (5.03125 + delta)) && + (f == (6.015625 + delta)) && + (g == (7.0078125 + delta)) && + (h == (8.00390625 + delta))) ? 1U : 0U); + } + + report_hex("iterations", busy_iterations); + report_hex("corruptions", busy_corruptions); + + failures += report("V3 interrupted FP thread made progress ", + (busy_iterations > 0UL) ? 1U : 0U); + failures += report("V4 no FP corruption across interrupts ", + (busy_corruptions == 0UL) ? 1U : 0U); + + report_hex("filex_ptr", (unsigned long) self->tx_thread_filex_ptr); + + failures += report("V5 VFP flag did not alias filex_ptr ", + (self->tx_thread_filex_ptr == FILEX_PTR_SENTINEL) ? 1U : 0U); + + if (failures == 0U) + { + linflexd_puts("PASS lazy VFP context switch verified on silicon\n"); + } + else + { + linflexd_puts("FAIL lazy VFP context switch\n"); + } + + linflexd_puts("=== vfp demo complete ===\n"); + + bsp_done(); + + for (;;) + { + tx_thread_sleep(100UL); + } +} + + +void tx_application_define(void *first_unused_memory) +{ + (void) first_unused_memory; + + (void) tx_thread_create(&thread_check, "fp check", thread_check_entry, 0UL, + thread_check_stack, sizeof(thread_check_stack), + 10U, 10U, TX_NO_TIME_SLICE, TX_AUTO_START); + + (void) tx_thread_create(&thread_fp_busy, "fp busy", thread_fp_busy_entry, + 0UL, thread_fp_busy_stack, + sizeof(thread_fp_busy_stack), + 20U, 20U, TX_NO_TIME_SLICE, TX_AUTO_START); +} + + +/**************************************************************************/ +/* bsp_main -- entered at EL1 from entry.S; hands over to the kernel. */ +/**************************************************************************/ + +void bsp_main(void) +{ + unsigned int console_status = linflexd_init(); + + linflexd_puts("\n=== ThreadX Cortex-R52 :: S32Z280-594EVB lazy VFP ===\n"); + report_hex("console", (unsigned long) console_status); + linflexd_puts("entering kernel\n"); + + tx_kernel_enter(); + + /* Not reached. */ + + linflexd_puts("FAIL tx_kernel_enter returned\n"); + + for (;;) + { + __asm volatile ("nop"); + } +} diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/entry.S b/ports/cortex_r52/gnu/example_build/s32z280_evb/entry.S index a5b34be7c..bb90d000a 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/entry.S +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/entry.S @@ -66,6 +66,13 @@ .equ HCPTR_TCP, (3 << 10) /* trap EL1 access to CP10/CP11 */ +/* CPACR grants EL1/EL0 access to CP10 and CP11, the floating-point unit; + FPEXC.EN then enables floating-point execution itself. */ + + .equ CPACR_CP10, (3 << 20) + .equ CPACR_CP11, (3 << 22) + .equ FPEXC_EN, (1 << 30) + .equ CNTHCTL_PL1PCTEN, (1 << 0) .equ CNTHCTL_PL1PCEN, (1 << 1) @@ -345,6 +352,40 @@ el1_entry: mcr p15, 0, r0, c12, c0, 0 /* VBAR */ isb +#ifdef __ARM_FP + + /* Enable the floating-point unit for EL1. + * + * Two gates must be opened and both reset closed: + * CPACR grants EL1/EL0 access to CP10/CP11. It reads 0 out of reset, + * so the first floating-point instruction would otherwise raise + * an Undefined Instruction exception. + * FPEXC .EN enables floating-point execution itself. + * EL2 has already cleared HCPTR.TCP10/TCP11 above, so neither traps to EL2. + * + * This is the BSP's job, not the kernel's. tx_thread_vfp_enable() only sets + * the per-thread flag that makes the context switch save and restore + * floating-point state; it does not turn the hardware on. Without the code + * below, a VFP build faults on the first context switch that touches a + * D-register -- and on this silicon that fault was invisible until + * SCTLR.TE was cleared, which is the trap described further down. + * + * Guarded by __ARM_FP, which the compiler defines exactly when the build can + * emit floating-point instructions. In a soft-float build "vmsr fpexc" is + * not assemblable for this target at all. + */ + + mrc p15, 0, r0, c1, c0, 2 /* CPACR */ + orr r0, r0, #(CPACR_CP10 | CPACR_CP11) + mcr p15, 0, r0, c1, c0, 2 + isb + + mov r0, #FPEXC_EN + vmsr fpexc, r0 + isb + +#endif + /* Clear SCTLR.TE. This is not cosmetic and it cost a long detour. * * TE resets SET on this silicon -- SCTLR reads 0x70C50838, bit 30 high -- From 559460bed92d4d5368cd72cbb53fce18ff59748f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Thu, 13 Aug 2026 17:13:34 -0400 Subject: [PATCH 038/181] Exercised the nested IRQ path, which had never once been entered (#611) _tx_thread_irq_nesting_start and _tx_thread_irq_nesting_end have shipped in this port since it was written, compiled into every build, and nothing had ever called either one. Not on the model, not on silicon, not in any demo. demo_nesting.elf enters them. Provoking nesting needs two sources with different priorities. The generic timer PPI was already there; the second is an SGI, which a core can raise on itself. gicv3.c gains gicv3_enable_sgi and gicv3_send_sgi for that. ICC_SGI1R is 64-bit, so in AArch32 it is an MCRR rather than an MCR, and the AArch64 name the Cortex-A72 example uses, S3_0_C12_C11_5, does not transcribe to the AArch32 CP15 space. The encoding here is confirmed by check N1 in the demo, which raises an SGI from thread context and requires it to be delivered and dispatched. The order of the pairing is the whole difficulty, and getting it wrong does not fail gracefully. The interrupt must be acknowledged BEFORE nesting starts. Reading ICC_IAR1 is what raises the GIC running priority to this interrupt's own, which masks it and everything of equal or lower priority; only then is re-enabling IRQ safe. My first attempt called nesting_start first and acknowledged inside the handler, so the still-pending, still-level-asserted timer was taken again the instant IRQ was enabled, and again, until the IRQ and System stacks were destroyed. It presented as garbage on the console and a hang with no fault to point at, and it broke demo_m3 and demo_threadx while leaving boot_check, demo_m2 and demo_mpu passing, because only the first two depend on the tick advancing. The Cortex-R5 example BSP states the requirement in one line: "ensure all IRQ interrupts are cleared prior to enabling nested IRQ interrupts." So entry.S now acknowledges in IRQ mode, carries the INTID in r4 -- which survives the mode switch, since only SP and LR are banked -- and also pushes it on the IRQ stack so a nested level reusing r4 cannot lose the outer level's value. End-of-interrupt waits until after nesting_end, in IRQ mode with interrupts masked, so dropping the running priority cannot re-admit the same interrupt. board_irq_handler splits in two. board_irq_service does the middle part on an already-acknowledged INTID and neither acknowledges nor EOIs; board_irq_handler keeps its old shape as the non-nesting entry point, so images built without TX_ENABLE_IRQ_NESTING behave exactly as before. The nesting instrumentation in irq_dispatch.c is inert unless an image asks for it. board_nest_provoke gates the SGI that the timer handler raises, so every other image sees the handler it always had. Verified on FVP_BaseR_AEMv8R. The nesting demo reports max depth 2, fifty nested SGIs across fifty ticks, depth unwound to zero, the tick still advancing, the low-priority thread still scheduled, and no spurious or unexpected INTIDs. In the same nesting configuration the five existing images all pass, so the split did not disturb the ordinary path. Both toolchains build it, GNU with no warnings and Arm Toolchain for Embedded 22.1.0 as well. Not done here: the S32Z280 example keeps its own irq_dispatch.c and entry.S and is untouched, so nesting on silicon is a separate change. Assisted-by: Claude Code (Opus 5) --- .../fvp_baser_aemv8r/CMakeLists.txt | 37 +++ .../example_build/fvp_baser_aemv8r/board.h | 23 ++ .../fvp_baser_aemv8r/demo_nesting.c | 216 ++++++++++++++++++ .../example_build/fvp_baser_aemv8r/entry.S | 40 ++++ .../example_build/fvp_baser_aemv8r/gicv3.c | 50 ++++ .../example_build/fvp_baser_aemv8r/gicv3.h | 9 + .../fvp_baser_aemv8r/irq_dispatch.c | 96 +++++++- 7 files changed, 467 insertions(+), 4 deletions(-) create mode 100644 ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/demo_nesting.c diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/CMakeLists.txt b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/CMakeLists.txt index c0824b264..ccb542581 100644 --- a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/CMakeLists.txt +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/CMakeLists.txt @@ -197,6 +197,40 @@ target_link_options(demo_mpu.elf PRIVATE ${R52_LINK_QUIET_RWX} ) +# Nested IRQ handling. Needs the library built with TX_R52_ENABLE_IRQ_NESTING, +# because _tx_thread_irq_nesting_start only re-enables IRQ usefully when +# tx_port.h agrees the configuration supports it, and entry.S only emits the +# start/end pairing under the same macro. The image therefore exists in that +# configuration only, as demo_m5.elf does for VFP. +if(TX_R52_ENABLE_IRQ_NESTING) + add_executable(demo_nesting.elf EXCLUDE_FROM_ALL + ${FVP_DIR}/entry.S + ${R52_CONSOLE_SOURCES} + ${FVP_DIR}/gicv3.c + ${FVP_DIR}/timer.c + ${FVP_DIR}/irq_dispatch.c + ${FVP_DIR}/tx_initialize_low_level.S + ${FVP_DIR}/demo_nesting.c + ) + + target_compile_definitions(demo_nesting.elf PRIVATE TX_R52_USE_THREADX_IRQ) + + target_link_libraries(demo_nesting.elf PRIVATE threadx) + + target_include_directories(demo_nesting.elf PRIVATE + ${FVP_DIR} + ${CMAKE_SOURCE_DIR}/common/inc + ${CMAKE_SOURCE_DIR}/ports/${THREADX_ARCH}/${THREADX_TOOLCHAIN}/inc + ) + + target_link_options(demo_nesting.elf PRIVATE + -T${FVP_DIR}/link.lds + -nostartfiles + -Wl,-Map=demo_nesting.map + ${R52_LINK_QUIET_RWX} + ) +endif() + # Every image built here, in the order they should be exercised. set(R52_IMAGES boot_check.elf demo_m2.elf demo_m3.elf demo_threadx.elf demo_mpu.elf) @@ -209,6 +243,9 @@ endforeach() if(TX_R52_ENABLE_VFP) list(APPEND R52_IMAGES demo_m5.elf) endif() +if(TX_R52_ENABLE_IRQ_NESTING) + list(APPEND R52_IMAGES demo_nesting.elf) +endif() # Console backend. Semihosting is the default because it needs no peripheral # and so cannot be broken by a wrong memory map; the PL011 path is what real diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/board.h b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/board.h index b514d29cf..2e985e500 100644 --- a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/board.h +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/board.h @@ -55,6 +55,13 @@ void board_init(void); void board_irq_handler(void); +/* The nesting path splits the handler in three, because the acknowledge has to + happen in IRQ mode before nesting starts and the end-of-interrupt after it + finishes. board_irq_service does the middle part on an INTID that has + already been acknowledged, and does not acknowledge or EOI itself. */ + +void board_irq_service(unsigned long intid); + /* Interrupt observability, maintained by board_irq_handler. */ extern volatile unsigned long board_irq_count; @@ -62,6 +69,22 @@ extern volatile unsigned long board_timer_intid; extern volatile unsigned long board_spurious_count; extern volatile unsigned long board_unexpected_intid; +/* Nesting observability, maintained by board_irq_handler. All of this is inert + unless the image was built with TX_ENABLE_IRQ_NESTING: without it the handler + runs in IRQ mode with interrupts masked and can never be re-entered. */ + +extern volatile unsigned long board_nest_depth; +extern volatile unsigned long board_nest_max; +extern volatile unsigned long board_sgi_count; +extern volatile unsigned long board_sgi_nested_count; + +/* Set by demo_nesting to make the timer handler provoke a nested SGI. Left at + zero every other image behaves exactly as before. */ + +extern volatile unsigned long board_nest_provoke; + +#define BOARD_NEST_SGI_INTID 8U + /* Counted by the EL2 hyp-trap handler in entry.S; the ZoneX seam. */ extern volatile unsigned long _hvc_call_count; diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/demo_nesting.c b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/demo_nesting.c new file mode 100644 index 000000000..0e204d061 --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/demo_nesting.c @@ -0,0 +1,216 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* BOARD SUPPORT RELEASE */ +/* */ +/* demo_nesting.c Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frederic Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Nested IRQ handling: _tx_thread_irq_nesting_start and */ +/* _tx_thread_irq_nesting_end. */ +/* */ +/* Those two routines have shipped in this port since it was written */ +/* and nothing had ever called them. They were compiled into every */ +/* build, never entered by any image, on the model or on silicon. */ +/* This is the image that enters them. */ +/* */ +/* HOW NESTING IS PROVOKED */ +/* */ +/* Two interrupt sources are needed and one must outrank the other. */ +/* The generic timer PPI is already there; the second is an SGI, which */ +/* a core can raise on itself, given a numerically lower priority so */ +/* the GIC lets it preempt. */ +/* */ +/* Inside the timer handler, after nesting_start has left IRQ mode for */ +/* System mode and re-enabled IRQ, board_irq_handler raises the SGI and */ +/* spins briefly. The SGI outranks the timer, so it is delivered */ +/* immediately and re-enters el1_irq_entry while the timer handler is */ +/* still on the stack. That is nesting, and the depth counter sees 2. */ +/* */ +/* The spin is bounded. Without TX_ENABLE_IRQ_NESTING the SGI can */ +/* never arrive, and a test that hangs in that configuration would be */ +/* worse than one that fails. */ +/* */ +/* WHAT EACH CHECK IS FOR */ +/* */ +/* N1 the SGI arrives at all. This is separate on purpose: it tests */ +/* the ICC_SGI1R encoding, which does not transcribe from the */ +/* AArch64 alias, so if N1 fails the fault is in gicv3_send_sgi and */ +/* not in the nesting routines. */ +/* N2 the SGI arrived while another handler was active, depth 2. */ +/* N3 depth returned to zero, so the pairing unwound. */ +/* N4 the tick still advances afterwards, so nesting did not damage */ +/* the timer path. */ +/* N5 threads still run and preempt, so the context save and restore */ +/* survived being re-entered. */ +/* */ +/**************************************************************************/ + +#include "tx_api.h" +#include "board.h" +#include "console.h" +#include "gicv3.h" + +#define DEMO_STACK_SIZE 2048 + +static TX_THREAD thread_check; +static TX_THREAD thread_spin; + +static ULONG thread_check_stack[DEMO_STACK_SIZE / sizeof(ULONG)]; +static ULONG thread_spin_stack[DEMO_STACK_SIZE / sizeof(ULONG)]; + +static volatile ULONG spin_runs; + + +static UINT report(const char *label_ptr, UINT passed) +{ + console_puts(label_ptr); + console_puts((passed != 0U) ? "PASS\n" : "FAIL\n"); + return (passed != 0U) ? 0U : 1U; +} + + +static void report_hex(const char *label_ptr, unsigned long value) +{ + console_puts(label_ptr); + console_puthex(value); + console_puts("\n"); +} + + +/* Lowest priority, never blocks: gives the tick something to preempt and shows + the scheduler is still alive after handlers have been nested. */ + +static void thread_spin_entry(ULONG thread_input) +{ + (void) thread_input; + + for (;;) + { + spin_runs++; + } +} + + +static void thread_check_entry(ULONG thread_input) +{ + UINT failures = 0U; + ULONG sgi_before; + ULONG ticks_start; + ULONG ticks_end; + ULONG spin_before; + + (void) thread_input; + + /* N1 first, with provocation still off, so this measures only whether an + SGI raised from thread context is delivered and dispatched. */ + + console_puts("[check] raising an SGI from thread context\n"); + + sgi_before = board_sgi_count; + gicv3_send_sgi(BOARD_NEST_SGI_INTID); + tx_thread_sleep(2); + + failures += report("[check] N1 SGI delivered and dispatched ", + (board_sgi_count > sgi_before) ? 1U : 0U); + + if (board_sgi_count == sgi_before) + { + /* Everything below depends on the SGI working, so say so rather than + reporting four more failures that all have the same cause. */ + + console_puts("[check] SGI never arrived; the remaining checks would\n" + " only restate that, so they are skipped.\n"); + console_puts("\nNESTING RESULT: FAILED\n"); + console_exit(1U); + } + + /* Now let the timer handler provoke a nested SGI, and give it time for a + good number of ticks. */ + + console_puts("[check] enabling nested provocation in the timer handler\n"); + + board_nest_provoke = 1UL; + ticks_start = tx_time_get(); + spin_before = spin_runs; + tx_thread_sleep(50); + ticks_end = tx_time_get(); + board_nest_provoke = 0UL; + + report_hex("[check] max nesting depth observed = ", board_nest_max); + report_hex("[check] nested SGI count = ", board_sgi_nested_count); + report_hex("[check] nesting depth now = ", board_nest_depth); + + failures += report("[check] N2 SGI nested inside another handler ", + (board_sgi_nested_count > 0UL) && + (board_nest_max >= 2UL) ? 1U : 0U); + + failures += report("[check] N3 nesting unwound to depth zero ", + (board_nest_depth == 0UL) ? 1U : 0U); + + failures += report("[check] N4 tick still advancing after nesting ", + ((ticks_end - ticks_start) >= 40UL) ? 1U : 0U); + + failures += report("[check] N5 lower-priority thread still scheduled ", + (spin_runs > spin_before) ? 1U : 0U); + + report_hex("[check] spurious interrupts = ", board_spurious_count); + report_hex("[check] unexpected INTID = ", board_unexpected_intid); + + failures += report("[check] no spurious or unexpected interrupts ", + ((board_spurious_count == 0UL) && + (board_unexpected_intid == 0UL)) ? 1U : 0U); + + if (failures == 0U) + { + console_puts("\nNESTING RESULT: ALL CHECKS PASSED\n"); + } + else + { + console_puts("\nNESTING RESULT: FAILED\n"); + } + + console_exit(failures); +} + + +void tx_application_define(void *first_unused_memory) +{ + (void) first_unused_memory; + + (void) tx_thread_create(&thread_check, "nest check", thread_check_entry, + 0UL, thread_check_stack, sizeof(thread_check_stack), + 10U, 10U, TX_NO_TIME_SLICE, TX_AUTO_START); + + (void) tx_thread_create(&thread_spin, "spinner", thread_spin_entry, + 0UL, thread_spin_stack, sizeof(thread_spin_stack), + 20U, 20U, TX_NO_TIME_SLICE, TX_AUTO_START); +} + + +void bsp_main(void) +{ + console_puts("\n=== ThreadX nested IRQ handling " + "(Cortex-R52, Armv8-R AArch32, Armv8-R AEM FVP) ===\n"); + + tx_kernel_enter(); +} diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/entry.S b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/entry.S index ec25ac252..ec783b991 100644 --- a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/entry.S +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/entry.S @@ -356,7 +356,47 @@ el1_irq_entry: .global __tx_irq_processing_return __tx_irq_processing_return: +#ifdef TX_ENABLE_IRQ_NESTING + + /* Nested IRQ handling. _tx_thread_irq_nesting_start leaves IRQ mode for + * System mode and re-enables IRQ, so an interrupt of higher priority can + * preempt this handler and re-enter at el1_irq_entry above. It is paired + * with _tx_thread_irq_nesting_end before _tx_thread_context_restore. + * + * The ORDER here is the whole difficulty, and getting it wrong does not + * fail gracefully. The interrupt must be ACKNOWLEDGED BEFORE nesting is + * started. Reading ICC_IAR1 is what raises the GIC's running priority to + * this interrupt's own, which is what masks it and everything of equal or + * lower priority; only then is re-enabling IRQ safe. Acknowledge after + * nesting_start instead and the still-pending, still-level-asserted timer + * is taken again the instant IRQ is enabled, and again, until the IRQ and + * System stacks are destroyed. That presents as garbage on the console and + * a hang, with no fault to point at it. The Cortex-R5 example BSP says the + * same thing in one line: "ensure all IRQ interrupts are cleared prior to + * enabling nested IRQ interrupts". + * + * The INTID is carried in r4, which survives the mode switch because only + * SP and LR are banked, and is also pushed on the IRQ stack so a nested + * level that reuses r4 cannot lose this level's value. End-of-interrupt is + * left until after nesting_end, in IRQ mode with interrupts masked, so + * dropping the running priority cannot re-admit this same interrupt. + */ + + bl gicv3_acknowledge /* IRQ mode, interrupts masked */ + mov r4, r0 + stmdb sp!, {r4, r5} /* r5 keeps 8-byte alignment */ + + bl _tx_thread_irq_nesting_start + mov r0, r4 + bl board_irq_service + bl _tx_thread_irq_nesting_end + + ldmia sp!, {r4, r5} + mov r0, r4 + bl gicv3_end_of_interrupt +#else bl board_irq_handler +#endif b _tx_thread_context_restore #else FAULT_REPORT msg_el1_irq diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/gicv3.c b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/gicv3.c index 4a1925094..eb5c029c8 100644 --- a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/gicv3.c +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/gicv3.c @@ -195,6 +195,56 @@ void gicv3_enable_ppi(unsigned int intid, unsigned int priority) /* gicv3_acknowledge */ /**************************************************************************/ +/**************************************************************************/ +/* gicv3_enable_sgi */ +/* */ +/* An SGI lives in the same redistributor frame as a PPI, so this is */ +/* gicv3_enable_ppi without the ICFGR step: INTIDs 0-15 have no */ +/* configurable edge/level, they are always edge-triggered. */ +/**************************************************************************/ + +void gicv3_enable_sgi(unsigned int intid, unsigned int priority) +{ + if (intid > 15U) + { + return; + } + + REG32(GICR_SGI_BASE + GICR_IGROUPR0) |= (1UL << intid); + + REG32(GICR_SGI_BASE + GICR_IPRIORITYR + (intid & ~3U)) &= + ~(0xFFUL << ((intid & 3U) * 8U)); + REG32(GICR_SGI_BASE + GICR_IPRIORITYR + (intid & ~3U)) |= + ((unsigned long) priority & 0xFFUL) << ((intid & 3U) * 8U); + + REG32(GICR_SGI_BASE + GICR_ISENABLER0) = (1UL << intid); +} + + +/**************************************************************************/ +/* gicv3_send_sgi */ +/* */ +/* ICC_SGI1R is 64-bit, so in AArch32 it is an MCRR rather than an MCR. */ +/* Fields: INTID in [27:24], TargetList in [15:0], Aff1/2/3 and IRM zero */ +/* for this single-core configuration, so TargetList = 1 selects core 0. */ +/* */ +/* The AArch64 name for this register is S3_0_C12_C11_5, which the */ +/* Cortex-A72 example uses, but that encoding does not transcribe to the */ +/* AArch32 64-bit CP15 space. The CRm here was confirmed by observing */ +/* that the SGI is actually delivered and acknowledged with the expected */ +/* INTID rather than by reading it off the A-profile alias. */ +/**************************************************************************/ + +void gicv3_send_sgi(unsigned int intid) +{ + unsigned long low = (((unsigned long) intid & 0xFUL) << 24) | 1UL; + unsigned long high = 0UL; + + __asm volatile ("mcrr p15, 0, %0, %1, c12" :: "r" (low), "r" (high) : "memory"); + instruction_barrier(); +} + + unsigned long gicv3_acknowledge(void) { unsigned long intid; diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/gicv3.h b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/gicv3.h index cc35639c0..03f1b2c07 100644 --- a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/gicv3.h +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/gicv3.h @@ -49,6 +49,15 @@ void gicv3_init(void); void gicv3_enable_ppi(unsigned int intid, unsigned int priority); +/* Enable a software-generated interrupt, INTID 0-15. Same registers as a PPI: + the redistributor's SGI/PPI frame covers INTIDs 0-31. */ + +void gicv3_enable_sgi(unsigned int intid, unsigned int priority); + +/* Raise an SGI on this core. */ + +void gicv3_send_sgi(unsigned int intid); + /* Acknowledge the highest-priority pending Group 1 interrupt, returning its INTID (possibly GICV3_SPURIOUS_INTID). */ diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/irq_dispatch.c b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/irq_dispatch.c index 0028dddbd..026721083 100644 --- a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/irq_dispatch.c +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/irq_dispatch.c @@ -54,6 +54,12 @@ volatile unsigned long board_timer_intid; volatile unsigned long board_spurious_count; volatile unsigned long board_unexpected_intid; +volatile unsigned long board_nest_depth; +volatile unsigned long board_nest_max; +volatile unsigned long board_sgi_count; +volatile unsigned long board_sgi_nested_count; +volatile unsigned long board_nest_provoke; + /* Timer PPI priority. Only the top 5 priority bits are implemented on this model, so the value is a multiple of 8. */ @@ -73,6 +79,13 @@ void board_init(void) { gicv3_init(); gicv3_enable_ppi(TIMER_PPI_INTID, TIMER_PPI_PRIORITY); + + /* The nesting SGI must outrank the timer or it could never preempt it: + in the GIC a numerically lower priority value wins. Enabling it costs + nothing in images that never raise it. */ + + gicv3_enable_sgi(BOARD_NEST_SGI_INTID, TIMER_PPI_PRIORITY / 2U); + timer_init(); } @@ -81,10 +94,15 @@ void board_init(void) /* board_irq_handler */ /**************************************************************************/ -void board_irq_handler(void) -{ - unsigned long intid = gicv3_acknowledge(); +/**************************************************************************/ +/* board_irq_service -- service an already-acknowledged INTID. */ +/* */ +/* Split out so the nesting path in entry.S can acknowledge in IRQ mode */ +/* before nesting starts. Does not acknowledge and does not EOI. */ +/**************************************************************************/ +void board_irq_service(unsigned long intid) +{ if (intid == GICV3_SPURIOUS_INTID) { /* No interrupt was actually pending; must not be acknowledged. */ @@ -93,6 +111,17 @@ void board_irq_handler(void) return; } + /* Depth is incremented after the spurious check so a spurious entry does + not register as nesting. It reaches 2 only if a second interrupt is + taken while this handler is still on the stack, which cannot happen + without TX_ENABLE_IRQ_NESTING. */ + + board_nest_depth++; + if (board_nest_depth > board_nest_max) + { + board_nest_max = board_nest_depth; + } + if (intid == (unsigned long) TIMER_PPI_INTID) { board_timer_intid = intid; @@ -102,12 +131,71 @@ void board_irq_handler(void) this also deasserts the level-sensitive timer output. */ timer_reload(); + + /* Provoke the nesting, if this image asked for it. Raising the SGI + here is only useful because _tx_thread_irq_nesting_start has already + re-enabled IRQ; the bounded spin gives the GIC the chance to deliver + it before this handler returns, so the nesting is deterministic + rather than a race we hope wins. The bound matters: without + TX_ENABLE_IRQ_NESTING the SGI can never arrive and this must not + become a hang. */ + + if (board_nest_provoke != 0UL) + { + unsigned long seen = board_sgi_count; + unsigned long guard; + + gicv3_send_sgi(BOARD_NEST_SGI_INTID); + + for (guard = 0UL; guard < 100000UL; guard++) + { + if (board_sgi_count != seen) + { + break; + } + } + } + _tx_timer_interrupt(); } + else if (intid == (unsigned long) BOARD_NEST_SGI_INTID) + { + board_sgi_count++; + + /* Depth above 1 means this SGI arrived inside another handler, which + is the whole point of the test. */ + + if (board_nest_depth > 1UL) + { + board_sgi_nested_count++; + } + } else { board_unexpected_intid = intid; } - gicv3_end_of_interrupt(intid); + board_nest_depth--; +} + + +/**************************************************************************/ +/* board_irq_handler -- the non-nesting entry point. */ +/* */ +/* Acknowledges, services and ends the interrupt, all in IRQ mode with */ +/* interrupts masked. entry.S calls this when the image was built without */ +/* TX_ENABLE_IRQ_NESTING, so the behaviour of every existing image is */ +/* exactly what it was. */ +/**************************************************************************/ + +void board_irq_handler(void) +{ + unsigned long intid = gicv3_acknowledge(); + + board_irq_service(intid); + + if (intid != GICV3_SPURIOUS_INTID) + { + gicv3_end_of_interrupt(intid); + } } From 5a7f4f8f7c9a5d8f193bd2c67d883b0b56930957 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Fri, 14 Aug 2026 11:07:06 -0400 Subject: [PATCH 039/181] Verified nested IRQ handling on S32Z280 silicon (#612) #611 exercised the nesting routines on the FVP and established what breaks them: the interrupt must be acknowledged before nesting starts, or the still-pending level-asserted timer is retaken the moment IRQ is enabled and recurses until the stacks are gone. entry.S here carries the same ordering for the same reason, and irq_dispatch.c splits the same way, board_irq_service taking an already-acknowledged INTID while board_irq_handler keeps its old shape as the non-nesting entry point. What the model could not answer is whether a real GIC-600 agrees, and two things could have differed. The first is the number of implemented priority bits. Equal priorities do not preempt and it is the low bits that vanish, so if the timer and the SGI collapse to one value after truncation then nesting cannot happen at all -- and the test would fail without saying why. gicv3_priority_bits discovers the count by writing 0xFF to a priority byte and reading back which bits stick, board_init records the two effective values, and check P1 requires the SGI to still outrank the timer. This silicon keeps five bits, the same as the FVP, so 0xA0 and 0x50 stay distinct; that is now measured and reported rather than assumed. The second is whether an SGI raised on real hardware is delivered at all. ICC_SGI1R is a 64-bit AArch32 CP15 register whose encoding does not transcribe from the AArch64 alias, so check N1 raises one from thread context and requires delivery before nesting is involved. It arrives. Verified on S32Z280 silicon: priority bits = 0x00000005 timer effective = 0x000000A0 sgi effective = 0x00000050 P1 SGI outranks timer after truncation PASS N1 SGI delivered and dispatched PASS max depth = 0x00000002 nested SGIs = 0x00000032 depth now = 0x00000000 N2 SGI nested inside another handler PASS N3 nesting unwound to depth zero PASS N4 tick still advancing after nesting PASS N5 lower-priority thread still scheduled PASS N6 no spurious or unexpected interrupts PASS Fifty nested SGIs across fifty ticks, one per tick, and depth never exceeded two. No regression, checked in both configurations on the board. In the nesting build the ThreadX demo still reports 100 ticks with 20 preemptions and the boot image still passes its cache and protection checks. In the default build the image links no nesting symbols at all and the demo is unchanged. Both toolchains compile every file, GNU with no warnings and Arm Toolchain for Embedded 22.1.0 as well. Assisted-by: Claude Code (Opus 5) --- .../example_build/s32z280_evb/CMakeLists.txt | 37 +++ .../gnu/example_build/s32z280_evb/board.h | 22 ++ .../s32z280_evb/demo_nesting_s32z280.c | 240 ++++++++++++++++++ .../gnu/example_build/s32z280_evb/entry.S | 32 +++ .../gnu/example_build/s32z280_evb/gicv3.c | 99 ++++++++ .../gnu/example_build/s32z280_evb/gicv3.h | 14 + .../example_build/s32z280_evb/irq_dispatch.c | 114 ++++++++- 7 files changed, 554 insertions(+), 4 deletions(-) create mode 100644 ports/cortex_r52/gnu/example_build/s32z280_evb/demo_nesting_s32z280.c diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/CMakeLists.txt b/ports/cortex_r52/gnu/example_build/s32z280_evb/CMakeLists.txt index 017aa7574..00878c296 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/CMakeLists.txt +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/CMakeLists.txt @@ -127,3 +127,40 @@ if(TX_R52_ENABLE_VFP) ${EVB_LINK_QUIET_RWX} ) endif() + +# Nested IRQ handling on silicon. Needs the library built with +# TX_R52_ENABLE_IRQ_NESTING, since entry.S only emits the nesting_start and +# nesting_end pairing under that macro, so the image exists in that +# configuration only -- as s32z280_vfp.elf does for the floating-point ABI. +if(TX_R52_ENABLE_IRQ_NESTING) + add_executable(s32z280_nesting.elf EXCLUDE_FROM_ALL + ${EVB_DIR}/entry.S + ${EVB_DIR}/tx_initialize_low_level.S + ${EVB_DIR}/linflexd.c + ${EVB_DIR}/timer.c + ${EVB_DIR}/mpu.c + ${EVB_DIR}/gicv3.c + ${EVB_DIR}/irq_dispatch.c + ${EVB_DIR}/gic_probe.c + ${EVB_DIR}/cache.c + ${EVB_DIR}/demo_nesting_s32z280.c + ) + + target_compile_definitions(s32z280_nesting.elf PRIVATE TX_R52_USE_THREADX_IRQ=1) + target_compile_options(s32z280_nesting.elf PRIVATE -g) + + target_link_libraries(s32z280_nesting.elf PRIVATE threadx) + + target_include_directories(s32z280_nesting.elf PRIVATE + ${EVB_DIR} + ${CMAKE_SOURCE_DIR}/common/inc + ${CMAKE_SOURCE_DIR}/ports/${THREADX_ARCH}/${THREADX_TOOLCHAIN}/inc + ) + + target_link_options(s32z280_nesting.elf PRIVATE + -T${EVB_DIR}/link.lds + -nostartfiles + -Wl,-Map=s32z280_nesting.map + ${EVB_LINK_QUIET_RWX} + ) +endif() diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/board.h b/ports/cortex_r52/gnu/example_build/s32z280_evb/board.h index 81478488c..3e8b7264c 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/board.h +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/board.h @@ -85,6 +85,13 @@ unsigned int read_sctlr_after_mpu(void); void board_irq_handler(void); +/* The nesting path splits the handler in three: the acknowledge happens in IRQ + mode before nesting starts, and the end-of-interrupt after it finishes. + board_irq_service does the middle part on an already-acknowledged INTID and + neither acknowledges nor EOIs. */ + +void board_irq_service(unsigned long intid); + /* Called from _tx_initialize_low_level when the kernel is linked. */ void board_init(void); @@ -102,4 +109,19 @@ extern volatile unsigned long board_spurious_count; extern volatile unsigned long board_unexpected_intid; extern volatile unsigned long board_first_intid; +/* Nesting observability. Inert unless the image was built with + TX_ENABLE_IRQ_NESTING: without it the handler runs in IRQ mode with + interrupts masked and can never be re-entered. */ + +extern volatile unsigned long board_nest_depth; +extern volatile unsigned long board_nest_max; +extern volatile unsigned long board_sgi_count; +extern volatile unsigned long board_sgi_nested_count; +extern volatile unsigned long board_nest_provoke; +extern volatile unsigned long board_priority_bits; +extern volatile unsigned long board_timer_priority; +extern volatile unsigned long board_sgi_priority; + +#define BOARD_NEST_SGI_INTID 8U + #endif /* BOARD_H */ diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/demo_nesting_s32z280.c b/ports/cortex_r52/gnu/example_build/s32z280_evb/demo_nesting_s32z280.c new file mode 100644 index 000000000..ca2a67754 --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/demo_nesting_s32z280.c @@ -0,0 +1,240 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* BOARD SUPPORT RELEASE */ +/* */ +/* demo_nesting_s32z280.c Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frederic Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Nested IRQ handling on S32Z280 silicon. */ +/* */ +/* The FVP established that the nesting routines work and, more */ +/* usefully, what breaks them: the interrupt has to be acknowledged */ +/* before nesting starts, or the still-pending level-asserted timer is */ +/* retaken the moment IRQ is enabled and recurses until the stacks are */ +/* gone. entry.S here has the same ordering for the same reason. */ +/* */ +/* What the model could not answer is whether a real GIC-600 agrees. */ +/* Two things differ from a model and both are visible here: */ +/* */ +/* P1 how many priority bits the GIC implements. Equal priorities */ +/* do not preempt, and it is the low bits that vanish, so if the */ +/* timer and the SGI collapse to the same value after truncation */ +/* nesting cannot happen at all. board_init discovers the count */ +/* by write and readback rather than assuming the model's five, */ +/* and this demo reports it. */ +/* */ +/* P2 whether an SGI raised on real silicon is delivered at all. */ +/* ICC_SGI1R is a 64-bit AArch32 CP15 register and its encoding */ +/* does not transcribe from the AArch64 alias, so N1 tests SGI */ +/* delivery on its own before nesting is involved. */ +/* */ +/**************************************************************************/ + +#include "tx_api.h" +#include "linflexd.h" +#include "board.h" +#include "gicv3.h" + +#define DEMO_STACK_SIZE 2048 + +static TX_THREAD thread_check; +static TX_THREAD thread_spin; + +static ULONG thread_check_stack[DEMO_STACK_SIZE / sizeof(ULONG)]; +static ULONG thread_spin_stack[DEMO_STACK_SIZE / sizeof(ULONG)]; + +static volatile ULONG spin_runs; + + +/* Breakpoint target for tools/read_identity.gdb. Not static and not empty so + an optimising build cannot discard it. */ + +void bsp_done(void) +{ + __asm volatile ("nop"); +} + + +static UINT report(const char *label_ptr, UINT passed) +{ + linflexd_puts(label_ptr); + linflexd_puts((passed != 0U) ? "PASS\n" : "FAIL\n"); + return (passed != 0U) ? 0U : 1U; +} + + +static void report_hex(const char *label_ptr, unsigned long value) +{ + linflexd_puts(label_ptr); + linflexd_puts(" = 0x"); + linflexd_put_hex32((unsigned int) value); + linflexd_putc('\n'); +} + + +static void thread_spin_entry(ULONG thread_input) +{ + (void) thread_input; + + for (;;) + { + spin_runs++; + } +} + + +static void thread_check_entry(ULONG thread_input) +{ + UINT failures = 0U; + ULONG sgi_before; + ULONG ticks_start; + ULONG ticks_end; + ULONG spin_before; + + (void) thread_input; + + /* P1: what the GIC actually implements, and whether the two priorities this + test depends on survive truncation. */ + + report_hex("priority bits", board_priority_bits); + report_hex("timer effective", board_timer_priority); + report_hex("sgi effective", board_sgi_priority); + + failures += report("P1 SGI outranks timer after truncation ", + (board_sgi_priority < board_timer_priority) ? 1U : 0U); + + /* N1: SGI delivery on its own, before nesting is involved. */ + + linflexd_puts("N1 raising an SGI from thread context\n"); + + sgi_before = board_sgi_count; + gicv3_send_sgi(BOARD_NEST_SGI_INTID); + tx_thread_sleep(2); + + failures += report("N1 SGI delivered and dispatched ", + (board_sgi_count > sgi_before) ? 1U : 0U); + + if (board_sgi_count == sgi_before) + { + /* Everything below needs the SGI, so reporting four more failures with + the same cause would only obscure it. */ + + linflexd_puts("SGI never arrived; the nesting checks would only\n" + "restate that, so they are skipped.\n"); + linflexd_puts("FAIL nested IRQ handling\n"); + linflexd_puts("=== nesting demo complete ===\n"); + bsp_done(); + for (;;) + { + tx_thread_sleep(100UL); + } + } + + /* N2 onwards: let the timer handler provoke a nested SGI. */ + + linflexd_puts("N2 enabling nested provocation in the timer handler\n"); + + board_nest_provoke = 1UL; + ticks_start = tx_time_get(); + spin_before = spin_runs; + tx_thread_sleep(50); + ticks_end = tx_time_get(); + board_nest_provoke = 0UL; + + report_hex("max depth", board_nest_max); + report_hex("nested SGIs", board_sgi_nested_count); + report_hex("depth now", board_nest_depth); + + failures += report("N2 SGI nested inside another handler ", + ((board_sgi_nested_count > 0UL) && + (board_nest_max >= 2UL)) ? 1U : 0U); + + failures += report("N3 nesting unwound to depth zero ", + (board_nest_depth == 0UL) ? 1U : 0U); + + failures += report("N4 tick still advancing after nesting ", + ((ticks_end - ticks_start) >= 40UL) ? 1U : 0U); + + failures += report("N5 lower-priority thread still scheduled ", + (spin_runs > spin_before) ? 1U : 0U); + + report_hex("spurious", board_spurious_count); + report_hex("unexpected", board_unexpected_intid); + + failures += report("N6 no spurious or unexpected interrupts ", + ((board_spurious_count == 0UL) && + (board_unexpected_intid == 0UL)) ? 1U : 0U); + + if (failures == 0U) + { + linflexd_puts("PASS nested IRQ handling verified on silicon\n"); + } + else + { + linflexd_puts("FAIL nested IRQ handling\n"); + } + + linflexd_puts("=== nesting demo complete ===\n"); + + bsp_done(); + + for (;;) + { + tx_thread_sleep(100UL); + } +} + + +void tx_application_define(void *first_unused_memory) +{ + (void) first_unused_memory; + + (void) tx_thread_create(&thread_check, "nest check", thread_check_entry, + 0UL, thread_check_stack, sizeof(thread_check_stack), + 10U, 10U, TX_NO_TIME_SLICE, TX_AUTO_START); + + (void) tx_thread_create(&thread_spin, "spinner", thread_spin_entry, + 0UL, thread_spin_stack, sizeof(thread_spin_stack), + 20U, 20U, TX_NO_TIME_SLICE, TX_AUTO_START); +} + + +void bsp_main(void) +{ + unsigned int console_status = linflexd_init(); + + linflexd_puts("\n=== ThreadX Cortex-R52 :: S32Z280-594EVB nested IRQ ===\n"); + report_hex("console", (unsigned long) console_status); + linflexd_puts("entering kernel\n"); + + tx_kernel_enter(); + + /* Not reached. */ + + linflexd_puts("FAIL tx_kernel_enter returned\n"); + + for (;;) + { + __asm volatile ("nop"); + } +} diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/entry.S b/ports/cortex_r52/gnu/example_build/s32z280_evb/entry.S index bb90d000a..9dc542bac 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/entry.S +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/entry.S @@ -501,7 +501,39 @@ el1_irq_entry: .global __tx_irq_processing_return __tx_irq_processing_return: +#ifdef TX_ENABLE_IRQ_NESTING + + /* Nested IRQ handling, the same shape as the FVP example, and the ordering + * matters as much here. The interrupt is acknowledged in IRQ mode with + * interrupts still masked, BEFORE nesting starts: reading ICC_IAR1 raises + * the GIC running priority to this interrupt's own, which masks it and + * everything of equal or lower priority, and only then is re-enabling IRQ + * safe. Start nesting first and the still-pending, still-level-asserted + * timer is retaken the instant IRQ is enabled, recursing until the IRQ and + * System stacks are gone -- a hang with no fault to point at. + * + * The INTID rides in r4, which survives the mode switch because only SP and + * LR are banked, and is pushed on the IRQ stack as well so a nested level + * reusing r4 cannot lose this level's value. End-of-interrupt waits for + * IRQ mode with interrupts masked again, so dropping the running priority + * cannot re-admit this same interrupt. + */ + + bl gicv3_acknowledge + mov r4, r0 + stmdb sp!, {r4, r5} /* r5 keeps 8-byte alignment */ + + bl _tx_thread_irq_nesting_start + mov r0, r4 + bl board_irq_service + bl _tx_thread_irq_nesting_end + + ldmia sp!, {r4, r5} + mov r0, r4 + bl gicv3_end_of_interrupt +#else bl board_irq_handler +#endif b _tx_thread_context_restore #else diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/gicv3.c b/ports/cortex_r52/gnu/example_build/s32z280_evb/gicv3.c index 4a1925094..6dc3a24f5 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/gicv3.c +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/gicv3.c @@ -195,6 +195,105 @@ void gicv3_enable_ppi(unsigned int intid, unsigned int priority) /* gicv3_acknowledge */ /**************************************************************************/ +/**************************************************************************/ +/* gicv3_enable_sgi */ +/* */ +/* An SGI lives in the same redistributor frame as a PPI, so this is */ +/* gicv3_enable_ppi without the ICFGR step: INTIDs 0-15 have no */ +/* configurable edge/level, they are always edge-triggered. */ +/**************************************************************************/ + +void gicv3_enable_sgi(unsigned int intid, unsigned int priority) +{ + if (intid > 15U) + { + return; + } + + REG32(GICR_SGI_BASE + GICR_IGROUPR0) |= (1UL << intid); + + REG32(GICR_SGI_BASE + GICR_IPRIORITYR + (intid & ~3U)) &= + ~(0xFFUL << ((intid & 3U) * 8U)); + REG32(GICR_SGI_BASE + GICR_IPRIORITYR + (intid & ~3U)) |= + ((unsigned long) priority & 0xFFUL) << ((intid & 3U) * 8U); + + REG32(GICR_SGI_BASE + GICR_ISENABLER0) = (1UL << intid); +} + + +/**************************************************************************/ +/* gicv3_send_sgi */ +/* */ +/* ICC_SGI1R is 64-bit, so in AArch32 it is an MCRR rather than an MCR. */ +/* Fields: INTID in [27:24], TargetList in [15:0], Aff1/2/3 and IRM zero */ +/* for this single-core configuration, so TargetList = 1 selects core 0. */ +/* */ +/* The AArch64 name for this register is S3_0_C12_C11_5, which the */ +/* Cortex-A72 example uses, but that encoding does not transcribe to the */ +/* AArch32 64-bit CP15 space. The CRm here was confirmed by observing */ +/* that the SGI is actually delivered and acknowledged with the expected */ +/* INTID rather than by reading it off the A-profile alias. */ +/**************************************************************************/ + +void gicv3_send_sgi(unsigned int intid) +{ + unsigned long low = (((unsigned long) intid & 0xFUL) << 24) | 1UL; + unsigned long high = 0UL; + + __asm volatile ("mcrr p15, 0, %0, %1, c12" :: "r" (low), "r" (high) : "memory"); + instruction_barrier(); +} + + +/**************************************************************************/ +/* gicv3_priority_bits */ +/* */ +/* How many priority bits this GIC actually implements, discovered rather */ +/* than assumed: write 0xFF to a priority byte and see which bits stick. */ +/* The unimplemented bits are the low ones and they read as zero. */ +/* */ +/* This matters for nesting. Two interrupts only preempt one another if */ +/* their priorities differ AFTER truncation, so a test that picks values */ +/* 0x20 apart on a GIC keeping four bits is testing nothing. The FVP */ +/* keeps five; real silicon need not agree. */ +/* */ +/* Called before the SGI is configured, and it leaves the byte at zero, so */ +/* the caller must set the priority it wants afterwards. */ +/**************************************************************************/ + +unsigned int gicv3_priority_bits(unsigned int scratch_intid) +{ + unsigned long shift; + unsigned long readback; + unsigned int bits = 0U; + + if (scratch_intid > 31U) + { + return 0U; + } + + shift = (unsigned long) (scratch_intid & 3U) * 8UL; + + REG32(GICR_SGI_BASE + GICR_IPRIORITYR + (scratch_intid & ~3U)) |= + (0xFFUL << shift); + readback = (REG32(GICR_SGI_BASE + GICR_IPRIORITYR + (scratch_intid & ~3U)) + >> shift) & 0xFFUL; + REG32(GICR_SGI_BASE + GICR_IPRIORITYR + (scratch_intid & ~3U)) &= + ~(0xFFUL << shift); + + while (readback != 0UL) + { + if ((readback & 1UL) != 0UL) + { + bits++; + } + readback >>= 1; + } + + return bits; +} + + unsigned long gicv3_acknowledge(void) { unsigned long intid; diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/gicv3.h b/ports/cortex_r52/gnu/example_build/s32z280_evb/gicv3.h index cc35639c0..7acd6776b 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/gicv3.h +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/gicv3.h @@ -49,6 +49,20 @@ void gicv3_init(void); void gicv3_enable_ppi(unsigned int intid, unsigned int priority); +/* Enable a software-generated interrupt, INTID 0-15. Same registers as a PPI: + the redistributor's SGI/PPI frame covers INTIDs 0-31. */ + +void gicv3_enable_sgi(unsigned int intid, unsigned int priority); + +/* Raise an SGI on this core. */ + +void gicv3_send_sgi(unsigned int intid); + +/* Implemented priority bits, discovered by write and readback. Leaves the + scratch INTID's priority byte at zero. */ + +unsigned int gicv3_priority_bits(unsigned int scratch_intid); + /* Acknowledge the highest-priority pending Group 1 interrupt, returning its INTID (possibly GICV3_SPURIOUS_INTID). */ diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/irq_dispatch.c b/ports/cortex_r52/gnu/example_build/s32z280_evb/irq_dispatch.c index 8c4012e5d..e7d0f5848 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/irq_dispatch.c +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/irq_dispatch.c @@ -61,6 +61,15 @@ volatile unsigned long board_spurious_count; volatile unsigned long board_unexpected_intid; volatile unsigned long board_first_intid = 0xFFFFFFFFUL; +volatile unsigned long board_nest_depth; +volatile unsigned long board_nest_max; +volatile unsigned long board_sgi_count; +volatile unsigned long board_sgi_nested_count; +volatile unsigned long board_nest_provoke; +volatile unsigned long board_priority_bits; +volatile unsigned long board_timer_priority; +volatile unsigned long board_sgi_priority; + /* The EL1 physical timer PPI. 30 is the architectural assignment and is what the FVP turned out to use, but it was discovered there by enabling the whole PPI range and recording whichever INTID arrived in ICC_IAR1 rather than by @@ -92,6 +101,35 @@ void board_init(void) gicv3_init(); gicv3_enable_ppi(TIMER_PPI_INTID, TIMER_PPI_PRIORITY); + /* How many priority bits this GIC keeps decides whether the SGI can preempt + the timer at all: equal priorities do not preempt, and it is the low bits + that vanish. Discovered rather than assumed, because the FVP keeps five + and real silicon need not agree. Recorded so the demo can report it, and + a nesting failure caused by the two priorities colliding is visible + instead of mysterious. */ + + board_priority_bits = gicv3_priority_bits(BOARD_NEST_SGI_INTID); + + /* Half the timer's value so the SGI outranks it: numerically lower wins. + With TIMER_PPI_PRIORITY at 0xA0 that is 0x50, which stays distinct even + if only three priority bits survive truncation. */ + + gicv3_enable_sgi(BOARD_NEST_SGI_INTID, TIMER_PPI_PRIORITY / 2U); + + /* The priorities as the GIC will actually compare them. Only the top + board_priority_bits survive; the low ones read back as zero, so two values + that differ only there would collapse together and never preempt. Recorded + here because this is where the constants live. */ + + { + unsigned long keep = (board_priority_bits >= 8UL) + ? 0xFFUL + : ((0xFFUL << (8UL - board_priority_bits)) & 0xFFUL); + + board_timer_priority = (unsigned long) TIMER_PPI_PRIORITY & keep; + board_sgi_priority = ((unsigned long) TIMER_PPI_PRIORITY / 2UL) & keep; + } + /* One tick every 10 ms at the measured 8 MHz counter rate. */ timer_start_oneshot_irq(timer_read_cntfrq() / 100U); @@ -100,10 +138,15 @@ void board_init(void) #endif -void board_irq_handler(void) -{ - unsigned long intid = gicv3_acknowledge(); +/**************************************************************************/ +/* board_irq_service -- service an already-acknowledged INTID. */ +/* */ +/* Split out so the nesting path in entry.S can acknowledge in IRQ mode */ +/* before nesting starts. Does not acknowledge and does not EOI. */ +/**************************************************************************/ +void board_irq_service(unsigned long intid) +{ if (intid == GICV3_SPURIOUS_INTID) { /* Nothing was actually pending. Must not be acknowledged with an @@ -113,6 +156,16 @@ void board_irq_handler(void) return; } + /* After the spurious check, so a spurious entry does not read as nesting. + Reaches 2 only if a second interrupt is taken while this one is still on + the stack, which cannot happen without TX_ENABLE_IRQ_NESTING. */ + + board_nest_depth++; + if (board_nest_depth > board_nest_max) + { + board_nest_max = board_nest_depth; + } + if (board_first_intid == 0xFFFFFFFFUL) { board_first_intid = intid; /* whatever actually arrived */ @@ -129,6 +182,29 @@ void board_irq_handler(void) timer_start_oneshot_irq(timer_read_cntfrq() / 100U); + /* Provoke nesting, if this image asked for it. Only useful because + _tx_thread_irq_nesting_start has already re-enabled IRQ; the bounded + spin gives the GIC time to deliver the higher-priority SGI before this + handler returns, so the nesting is deterministic rather than a race we + hope wins. The bound matters: with nesting compiled out the SGI can + never arrive here and this must not become a hang. */ + + if (board_nest_provoke != 0UL) + { + unsigned long seen = board_sgi_count; + unsigned long guard; + + gicv3_send_sgi(BOARD_NEST_SGI_INTID); + + for (guard = 0UL; guard < 100000UL; guard++) + { + if (board_sgi_count != seen) + { + break; + } + } + } + #ifdef TX_R52_USE_THREADX_IRQ /* Drive the kernel's time base. Called after the re-arm so the next interval is already running while the kernel does its bookkeeping. */ @@ -136,10 +212,40 @@ void board_irq_handler(void) _tx_timer_interrupt(); #endif } + else if (intid == (unsigned long) BOARD_NEST_SGI_INTID) + { + board_sgi_count++; + + if (board_nest_depth > 1UL) + { + board_sgi_nested_count++; + } + } else { board_unexpected_intid = intid; } - gicv3_end_of_interrupt(intid); + board_nest_depth--; +} + + +/**************************************************************************/ +/* board_irq_handler -- the non-nesting entry point. */ +/* */ +/* Acknowledges, services and ends the interrupt in IRQ mode with */ +/* interrupts masked, which is what every image built without */ +/* TX_ENABLE_IRQ_NESTING did before this split. */ +/**************************************************************************/ + +void board_irq_handler(void) +{ + unsigned long intid = gicv3_acknowledge(); + + board_irq_service(intid); + + if (intid != GICV3_SPURIOUS_INTID) + { + gicv3_end_of_interrupt(intid); + } } From 19d90a49c495d8d51f058b50e282524cf5ed9f96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Fri, 14 Aug 2026 11:42:59 -0400 Subject: [PATCH 040/181] Exercised the nested FIQ path, the last pair nothing had ever called (#613) _tx_thread_fiq_nesting_start and _tx_thread_fiq_nesting_end complete the set: after #611 and #612 covered IRQ nesting on the model and on silicon, these two were the remaining routines compiled into every build and entered by nothing. demo_fiq.elf enters them. FIQ needs more of the GIC than IRQ does. With a single security state the controller delivers Group 0 as FIQ and Group 1 as IRQ, so an interrupt only arrives as an FIQ if it has been moved into Group 0, the distributor and the CPU interface both have Group 0 enabled, and it is acknowledged through the Group 0 registers. Group 1's acknowledge returns the spurious INTID for a Group 0 interrupt and leaves it pending, which would present as a storm rather than as an error. gicv3.c gains IGRPEN0, BPR0, gicv3_enable_sgi_group0, gicv3_send_sgi_group0 and the Group 0 acknowledge and EOI pair. ICC_SGI0R differs from ICC_SGI1R only in opc1, 2 against 0, and each raises into its own group. entry.S routes the EL1 FIQ vector into _tx_thread_fiq_context_save with the same ordering the IRQ path needed: acknowledge in FIQ mode before nesting starts, then nesting_start, service, nesting_end, and end-of-interrupt last. It also leaves FIQ unmasked on the drop to EL1 when FIQ support is compiled in, because tx_thread_stack_build only clears a thread's F bit in that configuration and nothing else ever clears it, so an FIQ raised before the first thread ran would otherwise be silently ignored. Nesting an FIQ means taking an FIQ while an FIQ handler runs, which one source cannot show, so two Group 0 SGIs are used with the second at a numerically lower priority. The low one's handler raises the high one. One mistake worth recording, because the guard it needed is not obvious. TX_ENABLE_FIQ_SUPPORT is PUBLIC on the threadx target, so it reaches every image as soon as the library is built with FIQ -- including images that link no interrupt controller at all. demo_m2 is one of those: no gicv3.c, no irq_dispatch.c. Referencing gicv3_acknowledge_group0 and board_fiq_service from the FIQ vector broke its link outright. The vector is now gated on TX_R52_USE_THREADX_IRQ as well, which is how the IRQ vector has always been gated, and images without the infrastructure keep the fault reporter. Verified on FVP_BaseR_AEMv8R. F1 covers the whole Group 0 chain on its own -- IGRPEN0, the ICC_SGI0R encoding, IAR0 and EOIR0, the EL1 vector and F being unmasked -- so a failure there points somewhere other than the nesting routines. The demo reports 21 low-priority FIQs, 20 high-priority, 20 of them nested, max depth 2, depth unwound to zero, the IRQ tick undisturbed, threads still scheduled and no unexpected Group 0 INTID. All six images pass in the FIQ configuration, and the default build links no FIQ or Group 0 symbol at all, so the work is absent rather than dormant where it is not wanted. Both toolchains build every file, GNU with no warnings and Arm Toolchain for Embedded 22.1.0 as well. Not done here: the S32Z280 example is untouched, so FIQ on silicon is a separate change, as IRQ nesting was. Assisted-by: Claude Code (Opus 5) --- .../fvp_baser_aemv8r/CMakeLists.txt | 35 +++ .../example_build/fvp_baser_aemv8r/board.h | 18 ++ .../example_build/fvp_baser_aemv8r/demo_fiq.c | 215 ++++++++++++++++++ .../example_build/fvp_baser_aemv8r/entry.S | 64 +++++- .../example_build/fvp_baser_aemv8r/gicv3.c | 95 ++++++++ .../example_build/fvp_baser_aemv8r/gicv3.h | 11 + .../fvp_baser_aemv8r/irq_dispatch.c | 105 +++++++++ 7 files changed, 542 insertions(+), 1 deletion(-) create mode 100644 ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/demo_fiq.c diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/CMakeLists.txt b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/CMakeLists.txt index ccb542581..c8339fa70 100644 --- a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/CMakeLists.txt +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/CMakeLists.txt @@ -231,6 +231,38 @@ if(TX_R52_ENABLE_IRQ_NESTING) ) endif() +# Nested FIQ handling. Needs TX_R52_ENABLE_FIQ_NESTING, which the port-level +# CMakeLists already requires TX_R52_ENABLE_FIQ alongside, so the image exists +# only where both the FIQ vector path and the nesting pairing are compiled in. +if(TX_R52_ENABLE_FIQ_NESTING) + add_executable(demo_fiq.elf EXCLUDE_FROM_ALL + ${FVP_DIR}/entry.S + ${R52_CONSOLE_SOURCES} + ${FVP_DIR}/gicv3.c + ${FVP_DIR}/timer.c + ${FVP_DIR}/irq_dispatch.c + ${FVP_DIR}/tx_initialize_low_level.S + ${FVP_DIR}/demo_fiq.c + ) + + target_compile_definitions(demo_fiq.elf PRIVATE TX_R52_USE_THREADX_IRQ) + + target_link_libraries(demo_fiq.elf PRIVATE threadx) + + target_include_directories(demo_fiq.elf PRIVATE + ${FVP_DIR} + ${CMAKE_SOURCE_DIR}/common/inc + ${CMAKE_SOURCE_DIR}/ports/${THREADX_ARCH}/${THREADX_TOOLCHAIN}/inc + ) + + target_link_options(demo_fiq.elf PRIVATE + -T${FVP_DIR}/link.lds + -nostartfiles + -Wl,-Map=demo_fiq.map + ${R52_LINK_QUIET_RWX} + ) +endif() + # Every image built here, in the order they should be exercised. set(R52_IMAGES boot_check.elf demo_m2.elf demo_m3.elf demo_threadx.elf demo_mpu.elf) @@ -246,6 +278,9 @@ endif() if(TX_R52_ENABLE_IRQ_NESTING) list(APPEND R52_IMAGES demo_nesting.elf) endif() +if(TX_R52_ENABLE_FIQ_NESTING) + list(APPEND R52_IMAGES demo_fiq.elf) +endif() # Console backend. Semihosting is the default because it needs no peripheral # and so cannot be broken by a wrong memory map; the PL011 path is what real diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/board.h b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/board.h index 2e985e500..d5e50b809 100644 --- a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/board.h +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/board.h @@ -85,6 +85,24 @@ extern volatile unsigned long board_nest_provoke; #define BOARD_NEST_SGI_INTID 8U +/* FIQ observability. Two Group 0 SGIs, because FIQ nesting means an FIQ taken + while an FIQ handler is running, so a single source cannot show it. The + higher-priority one is raised from inside the lower one's handler. */ + +void board_fiq_handler(void); +void board_fiq_service(unsigned long intid); + +extern volatile unsigned long board_fiq_count; +extern volatile unsigned long board_fiq_high_count; +extern volatile unsigned long board_fiq_nested_count; +extern volatile unsigned long board_fiq_depth; +extern volatile unsigned long board_fiq_max_depth; +extern volatile unsigned long board_fiq_unexpected; +extern volatile unsigned long board_fiq_provoke; + +#define BOARD_FIQ_LOW_INTID 10U +#define BOARD_FIQ_HIGH_INTID 11U + /* Counted by the EL2 hyp-trap handler in entry.S; the ZoneX seam. */ extern volatile unsigned long _hvc_call_count; diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/demo_fiq.c b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/demo_fiq.c new file mode 100644 index 000000000..b28990359 --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/demo_fiq.c @@ -0,0 +1,215 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* BOARD SUPPORT RELEASE */ +/* */ +/* demo_fiq.c Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frederic Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Nested FIQ handling: _tx_thread_fiq_nesting_start and */ +/* _tx_thread_fiq_nesting_end, the last pair in this port that nothing */ +/* had ever called. */ +/* */ +/* FIQ needs more of the GIC than IRQ does. With a single security */ +/* state the controller delivers Group 0 as FIQ and Group 1 as IRQ, so */ +/* an interrupt only arrives as an FIQ if it has been moved into Group */ +/* 0, the distributor and CPU interface both have Group 0 enabled, and */ +/* it is acknowledged through the Group 0 registers. Group 1's */ +/* acknowledge returns the spurious INTID for a Group 0 interrupt and */ +/* leaves it pending, which presents as a storm rather than an error. */ +/* */ +/* FIQ nesting means an FIQ taken while an FIQ handler is running, so */ +/* one source cannot demonstrate it. Two Group 0 SGIs are used, the */ +/* second at a numerically lower priority so it can preempt the first, */ +/* and the first's handler raises it. */ +/* */ +/* WHAT EACH CHECK IS FOR */ +/* */ +/* F1 an FIQ arrives at all. Separate on purpose: it covers the whole */ +/* Group 0 chain -- IGRPEN0, the ICC_SGI0R encoding, IAR0 and */ +/* EOIR0, the EL1 FIQ vector, and F being unmasked. If F1 fails */ +/* the fault is in one of those and not in the nesting routines. */ +/* F2 an FIQ arrived while another FIQ handler was active, depth 2. */ +/* F3 the depth returned to zero, so the pairing unwound. */ +/* F4 the IRQ path is undisturbed: the tick still advances. */ +/* F5 threads still run, so FIQ context save and restore survived */ +/* being re-entered. */ +/* F6 no unexpected Group 0 INTID arrived. */ +/* */ +/**************************************************************************/ + +#include "tx_api.h" +#include "board.h" +#include "console.h" +#include "gicv3.h" + +#define DEMO_STACK_SIZE 2048 + +static TX_THREAD thread_check; +static TX_THREAD thread_spin; + +static ULONG thread_check_stack[DEMO_STACK_SIZE / sizeof(ULONG)]; +static ULONG thread_spin_stack[DEMO_STACK_SIZE / sizeof(ULONG)]; + +static volatile ULONG spin_runs; + + +static UINT report(const char *label_ptr, UINT passed) +{ + console_puts(label_ptr); + console_puts((passed != 0U) ? "PASS\n" : "FAIL\n"); + return (passed != 0U) ? 0U : 1U; +} + + +static void report_hex(const char *label_ptr, unsigned long value) +{ + console_puts(label_ptr); + console_puthex(value); + console_puts("\n"); +} + + +static void thread_spin_entry(ULONG thread_input) +{ + (void) thread_input; + + for (;;) + { + spin_runs++; + } +} + + +static void thread_check_entry(ULONG thread_input) +{ + UINT failures = 0U; + ULONG fiq_before; + ULONG ticks_start; + ULONG ticks_end; + ULONG spin_before; + + (void) thread_input; + + /* F1: the whole Group 0 chain, before nesting is involved. */ + + console_puts("[check] raising a Group 0 SGI from thread context\n"); + + fiq_before = board_fiq_count; + gicv3_send_sgi_group0(BOARD_FIQ_LOW_INTID); + tx_thread_sleep(2); + + report_hex("[check] FIQ count = ", board_fiq_count); + + failures += report("[check] F1 FIQ delivered and dispatched ", + (board_fiq_count > fiq_before) ? 1U : 0U); + + if (board_fiq_count == fiq_before) + { + /* Everything below needs an FIQ to arrive, so repeating the failure + five more times would only bury the cause. */ + + console_puts("[check] no FIQ arrived; the nesting checks would only\n" + " restate that, so they are skipped.\n"); + console_puts("\nFIQ RESULT: FAILED\n"); + console_exit(1U); + } + + /* F2 onwards: let the low-priority FIQ handler raise the high one. */ + + console_puts("[check] enabling nested provocation in the FIQ handler\n"); + + board_fiq_provoke = 1UL; + ticks_start = tx_time_get(); + spin_before = spin_runs; + + { + ULONG i; + + for (i = 0UL; i < 20UL; i++) + { + gicv3_send_sgi_group0(BOARD_FIQ_LOW_INTID); + tx_thread_sleep(2); + } + } + + ticks_end = tx_time_get(); + board_fiq_provoke = 0UL; + + report_hex("[check] low-priority FIQ count = ", board_fiq_count); + report_hex("[check] high-priority FIQ count = ", board_fiq_high_count); + report_hex("[check] nested FIQ count = ", board_fiq_nested_count); + report_hex("[check] max FIQ depth = ", board_fiq_max_depth); + report_hex("[check] FIQ depth now = ", board_fiq_depth); + + failures += report("[check] F2 FIQ nested inside an FIQ handler ", + ((board_fiq_nested_count > 0UL) && + (board_fiq_max_depth >= 2UL)) ? 1U : 0U); + + failures += report("[check] F3 FIQ nesting unwound to depth zero ", + (board_fiq_depth == 0UL) ? 1U : 0U); + + failures += report("[check] F4 IRQ tick undisturbed by FIQ work ", + ((ticks_end - ticks_start) >= 30UL) ? 1U : 0U); + + failures += report("[check] F5 lower-priority thread still scheduled ", + (spin_runs > spin_before) ? 1U : 0U); + + report_hex("[check] unexpected Group 0 INTID = ", board_fiq_unexpected); + + failures += report("[check] F6 no unexpected Group 0 INTID ", + (board_fiq_unexpected == 0UL) ? 1U : 0U); + + if (failures == 0U) + { + console_puts("\nFIQ RESULT: ALL CHECKS PASSED\n"); + } + else + { + console_puts("\nFIQ RESULT: FAILED\n"); + } + + console_exit(failures); +} + + +void tx_application_define(void *first_unused_memory) +{ + (void) first_unused_memory; + + (void) tx_thread_create(&thread_check, "fiq check", thread_check_entry, + 0UL, thread_check_stack, sizeof(thread_check_stack), + 10U, 10U, TX_NO_TIME_SLICE, TX_AUTO_START); + + (void) tx_thread_create(&thread_spin, "spinner", thread_spin_entry, + 0UL, thread_spin_stack, sizeof(thread_spin_stack), + 20U, 20U, TX_NO_TIME_SLICE, TX_AUTO_START); +} + + +void bsp_main(void) +{ + console_puts("\n=== ThreadX nested FIQ handling " + "(Cortex-R52, Armv8-R AArch32, Armv8-R AEM FVP) ===\n"); + + tx_kernel_enter(); +} diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/entry.S b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/entry.S index ec783b991..d59183f8f 100644 --- a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/entry.S +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/entry.S @@ -235,7 +235,20 @@ _start: ldr r0, =el1_entry msr ELR_hyp, r0 +#ifdef TX_ENABLE_FIQ_SUPPORT + + /* FIQ left unmasked, IRQ still masked. ThreadX unmasks IRQ when it + * schedules the first thread; FIQ is different, because tx_thread_stack_build + * only clears the F bit in a thread's CPSR when the library was built with + * FIQ support, and nothing else ever clears it. Leaving PSR_F set here + * would mask FIQ until the first thread ran, which is survivable but makes + * an FIQ raised from bsp_main silently do nothing. + */ + + ldr r0, =(PSR_A | PSR_I | MODE_SVC) +#else ldr r0, =(PSR_A | PSR_I | PSR_F | MODE_SVC) +#endif msr SPSR_hyp, r0 isb eret @@ -539,7 +552,56 @@ el1_dabt_fatal: #endif FAULT_REPORT msg_el1_dabt el1_trap_reserved: FAULT_REPORT msg_el1_reserved -el1_trap_fiq: FAULT_REPORT msg_el1_fiq +el1_trap_fiq: +#if defined(TX_ENABLE_FIQ_SUPPORT) && defined(TX_R52_USE_THREADX_IRQ) + + /* Both guards are needed, and the second is not obvious. + * TX_ENABLE_FIQ_SUPPORT is PUBLIC on the threadx target, so it reaches every + * image the moment the library is built with FIQ, including images that link + * no interrupt controller at all. demo_m2 is one: it has no gicv3.c and no + * irq_dispatch.c, so referencing gicv3_acknowledge_group0 and + * board_fiq_service from here broke its link outright. Images without the + * interrupt infrastructure keep the fault reporter on this vector, which is + * how the IRQ vector above is gated too. + */ + + /* FIQ has its own context save and restore in the port, and its own nesting + * pair. The shape mirrors the IRQ path, and so does the trap: the interrupt + * must be acknowledged before nesting starts. Group 0 has its own + * acknowledge and end-of-interrupt registers -- using the Group 1 ones here + * returns the spurious INTID and leaves the interrupt pending, which + * presents as an FIQ storm rather than as an error. + * + * FIQ mode banks r8-r12 as well as SP and LR, so the INTID cannot ride in a + * high register across the switch to System mode the way r4 does on the IRQ + * path. r4 is not banked in FIQ mode either, so it still works, and it is + * pushed on the FIQ stack as well so a nested level cannot lose it. + */ + + b _tx_thread_fiq_context_save + + .global __tx_fiq_processing_return +__tx_fiq_processing_return: +#ifdef TX_ENABLE_FIQ_NESTING + bl gicv3_acknowledge_group0 + mov r4, r0 + stmdb sp!, {r4, r5} + + bl _tx_thread_fiq_nesting_start + mov r0, r4 + bl board_fiq_service + bl _tx_thread_fiq_nesting_end + + ldmia sp!, {r4, r5} + mov r0, r4 + bl gicv3_end_of_interrupt_group0 +#else + bl board_fiq_handler +#endif + b _tx_thread_fiq_context_restore +#else + FAULT_REPORT msg_el1_fiq +#endif fault_halt: b fault_halt diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/gicv3.c b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/gicv3.c index eb5c029c8..4771625df 100644 --- a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/gicv3.c +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/gicv3.c @@ -53,6 +53,7 @@ /* Distributor registers. */ #define GICD_CTLR 0x0000U +#define GICD_CTLR_ENABLE_GRP0 (1UL << 0) #define GICD_CTLR_ENABLE_GRP1 (1UL << 1) #define GICD_CTLR_ARE (1UL << 4) @@ -102,6 +103,18 @@ static void write_icc_bpr1(unsigned long value) __asm__ volatile("mcr p15, 0, %0, c12, c12, 3" : : "r"(value) : "memory"); } +static void write_icc_igrpen0(unsigned long value) +{ + /* ICC_IGRPEN0 sits at c12, c12, 6, beside IGRPEN1 at opc2 7. */ + + __asm__ volatile("mcr p15, 0, %0, c12, c12, 6" : : "r"(value) : "memory"); +} + +static void write_icc_bpr0(unsigned long value) +{ + __asm__ volatile("mcr p15, 0, %0, c12, c8, 3" : : "r"(value) : "memory"); +} + static void write_icc_igrpen1(unsigned long value) { __asm__ volatile("mcr p15, 0, %0, c12, c12, 7" : : "r"(value) : "memory"); @@ -127,6 +140,12 @@ void gicv3_init(void) REG32(GICD_BASE + GICD_CTLR) |= GICD_CTLR_ARE; REG32(GICD_BASE + GICD_CTLR) |= GICD_CTLR_ENABLE_GRP1; + /* Group 0 as well, which is what the GIC delivers as FIQ. Enabling it costs + nothing while no interrupt is assigned to that group, and images that never + use FIQ see no change: assignment is per interrupt, in GICR_IGROUPR0. */ + + REG32(GICD_BASE + GICD_CTLR) |= GICD_CTLR_ENABLE_GRP0; + /* Redistributor: clear ProcessorSleep and wait for the redistributor to report that its children are awake, otherwise no interrupt can be delivered to this core. */ @@ -150,6 +169,14 @@ void gicv3_init(void) write_icc_pmr(ICC_PMR_UNMASK_ALL); write_icc_bpr1(0UL); write_icc_igrpen1(ICC_IGRPEN1_ENABLE); + + /* The CPU interface half of Group 0: a Group 0 interrupt reaches the core + only if both the distributor and this are enabled. BPR0 at zero gives no + subpriority grouping, so priority alone decides preemption, which is what + the FIQ nesting test depends on. */ + + write_icc_bpr0(0UL); + write_icc_igrpen0(ICC_IGRPEN1_ENABLE); instruction_barrier(); } @@ -245,6 +272,74 @@ void gicv3_send_sgi(unsigned int intid) } +/**************************************************************************/ +/* gicv3_enable_sgi_group0 */ +/* */ +/* As gicv3_enable_sgi, but leaves the interrupt in Group 0 so it arrives */ +/* as an FIQ. The group is chosen by clearing the GICR_IGROUPR0 bit; the */ +/* Group 1 version sets it. */ +/**************************************************************************/ + +void gicv3_enable_sgi_group0(unsigned int intid, unsigned int priority) +{ + if (intid > 15U) + { + return; + } + + REG32(GICR_SGI_BASE + GICR_IGROUPR0) &= ~(1UL << intid); + + REG32(GICR_SGI_BASE + GICR_IPRIORITYR + (intid & ~3U)) &= + ~(0xFFUL << ((intid & 3U) * 8U)); + REG32(GICR_SGI_BASE + GICR_IPRIORITYR + (intid & ~3U)) |= + ((unsigned long) priority & 0xFFUL) << ((intid & 3U) * 8U); + + REG32(GICR_SGI_BASE + GICR_ISENABLER0) = (1UL << intid); +} + + +/**************************************************************************/ +/* gicv3_send_sgi_group0 */ +/* */ +/* ICC_SGI0R rather than ICC_SGI1R: the two differ only in opc1, 2 against */ +/* 0, and each raises the SGI into its own group. Raising a Group 0 */ +/* interrupt through the Group 1 register does not deliver it as an FIQ. */ +/**************************************************************************/ + +void gicv3_send_sgi_group0(unsigned int intid) +{ + unsigned long low = (((unsigned long) intid & 0xFUL) << 24) | 1UL; + unsigned long high = 0UL; + + __asm volatile ("mcrr p15, 2, %0, %1, c12" :: "r" (low), "r" (high) : "memory"); + instruction_barrier(); +} + + +/**************************************************************************/ +/* gicv3_acknowledge_group0 / gicv3_end_of_interrupt_group0 */ +/* */ +/* Group 0 has its own pair at c12, c8, where Group 1 uses c12, c12. */ +/* Acknowledging a Group 0 interrupt through IAR1 returns the spurious */ +/* INTID and leaves the interrupt pending, which presents as an FIQ storm. */ +/**************************************************************************/ + +unsigned long gicv3_acknowledge_group0(void) +{ + unsigned long intid; + + __asm__ volatile("mrc p15, 0, %0, c12, c8, 0" : "=r"(intid)); + return intid & 0xFFFFFFUL; +} + + +void gicv3_end_of_interrupt_group0(unsigned long intid) +{ + instruction_barrier(); + __asm__ volatile("mcr p15, 0, %0, c12, c8, 1" : : "r"(intid) : "memory"); +} + + unsigned long gicv3_acknowledge(void) { unsigned long intid; diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/gicv3.h b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/gicv3.h index 03f1b2c07..1a9980195 100644 --- a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/gicv3.h +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/gicv3.h @@ -58,6 +58,17 @@ void gicv3_enable_sgi(unsigned int intid, unsigned int priority); void gicv3_send_sgi(unsigned int intid); +/* Group 0 support, which is what produces FIQ rather than IRQ. With a single + security state the GIC routes Group 0 to FIQ and Group 1 to IRQ, so an + interrupt has to be moved into Group 0 to arrive as an FIQ at all. Group 0 + has its own acknowledge and end-of-interrupt registers; using the Group 1 ones + on a Group 0 interrupt does not work. */ + +void gicv3_enable_sgi_group0(unsigned int intid, unsigned int priority); +void gicv3_send_sgi_group0(unsigned int intid); +unsigned long gicv3_acknowledge_group0(void); +void gicv3_end_of_interrupt_group0(unsigned long intid); + /* Acknowledge the highest-priority pending Group 1 interrupt, returning its INTID (possibly GICV3_SPURIOUS_INTID). */ diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/irq_dispatch.c b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/irq_dispatch.c index 026721083..f244c3d7b 100644 --- a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/irq_dispatch.c +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/irq_dispatch.c @@ -60,6 +60,14 @@ volatile unsigned long board_sgi_count; volatile unsigned long board_sgi_nested_count; volatile unsigned long board_nest_provoke; +volatile unsigned long board_fiq_count; +volatile unsigned long board_fiq_high_count; +volatile unsigned long board_fiq_nested_count; +volatile unsigned long board_fiq_depth; +volatile unsigned long board_fiq_max_depth; +volatile unsigned long board_fiq_unexpected; +volatile unsigned long board_fiq_provoke; + /* Timer PPI priority. Only the top 5 priority bits are implemented on this model, so the value is a multiple of 8. */ @@ -86,6 +94,17 @@ void board_init(void) gicv3_enable_sgi(BOARD_NEST_SGI_INTID, TIMER_PPI_PRIORITY / 2U); +#ifdef TX_ENABLE_FIQ_SUPPORT + + /* Two Group 0 SGIs for the FIQ path. Group 0 is what the GIC delivers as + FIQ; the high one is given a numerically lower priority so it can preempt + the low one, which is what FIQ nesting means. Both sit above the timer so + the two paths do not interfere. */ + + gicv3_enable_sgi_group0(BOARD_FIQ_LOW_INTID, 0x40U); + gicv3_enable_sgi_group0(BOARD_FIQ_HIGH_INTID, 0x20U); +#endif + timer_init(); } @@ -199,3 +218,89 @@ void board_irq_handler(void) gicv3_end_of_interrupt(intid); } } + + +#ifdef TX_ENABLE_FIQ_SUPPORT +/**************************************************************************/ +/* board_fiq_service -- service an already-acknowledged Group 0 INTID. */ +/* */ +/* The FIQ counterpart of board_irq_service, and split for the same */ +/* reason: the acknowledge has to happen before nesting starts. Does not */ +/* acknowledge and does not EOI. */ +/**************************************************************************/ + +void board_fiq_service(unsigned long intid) +{ + if (intid == GICV3_SPURIOUS_INTID) + { + return; + } + + board_fiq_depth++; + if (board_fiq_depth > board_fiq_max_depth) + { + board_fiq_max_depth = board_fiq_depth; + } + + if (intid == (unsigned long) BOARD_FIQ_LOW_INTID) + { + board_fiq_count++; + + /* Provoke the nested FIQ from inside this handler. Only reachable + because _tx_thread_fiq_nesting_start has re-enabled FIQ; the bounded + spin lets the GIC deliver the higher-priority Group 0 SGI before this + handler returns. Bounded, because with nesting compiled out the + second FIQ cannot arrive and this must not hang. */ + + if (board_fiq_provoke != 0UL) + { + unsigned long seen = board_fiq_high_count; + unsigned long guard; + + gicv3_send_sgi_group0(BOARD_FIQ_HIGH_INTID); + + for (guard = 0UL; guard < 100000UL; guard++) + { + if (board_fiq_high_count != seen) + { + break; + } + } + } + } + else if (intid == (unsigned long) BOARD_FIQ_HIGH_INTID) + { + board_fiq_high_count++; + + /* Depth above 1 means this FIQ arrived inside another FIQ handler. */ + + if (board_fiq_depth > 1UL) + { + board_fiq_nested_count++; + } + } + else + { + board_fiq_unexpected = intid; + } + + board_fiq_depth--; +} + + +/**************************************************************************/ +/* board_fiq_handler -- the non-nesting FIQ entry point. */ +/**************************************************************************/ + +void board_fiq_handler(void) +{ + unsigned long intid = gicv3_acknowledge_group0(); + + board_fiq_service(intid); + + if (intid != GICV3_SPURIOUS_INTID) + { + gicv3_end_of_interrupt_group0(intid); + } +} +#endif From ea91beae42790d769829df6363736df894bb5467 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Fri, 14 Aug 2026 13:34:34 -0400 Subject: [PATCH 041/181] Verified nested FIQ handling on S32Z280 silicon (#614) #613 exercised the FIQ nesting routines on the FVP. What the model could not show is whether a real GIC-600 routes Group 0 to FIQ the same way, which is the reason to run it here. It does, and the counts match the model exactly. The Group 0 support ports across unchanged: IGRPEN0 and BPR0 on the CPU interface, Group 0 in the distributor, gicv3_enable_sgi_group0, gicv3_send_sgi_group0 through ICC_SGI0R, and the separate Group 0 acknowledge and end-of-interrupt pair. entry.S routes the EL1 FIQ vector into _tx_thread_fiq_context_save with the acknowledge before nesting starts, and leaves FIQ unmasked on the drop to EL1 when FIQ support is compiled in, for the same reason as on the FVP: tx_thread_stack_build only clears a thread's F bit in that configuration. One structural difference from the FVP cost a link. This example reports faults through FAULT_TAIL rather than FAULT_REPORT, so the vector table needed a new el1_fiq_entry label that falls back to fault_el1_fiq. Placing that label inside the TX_R52_USE_THREADX_IRQ guard broke s32z280_boot.elf, which does not define it: the vector reference is unconditional, so the label has to be too. It now sits outside the guard and carries its own, the same shape the demo_m2 link break in #613 forced on the FVP side. Verified on S32Z280 silicon: F1 FIQ delivered and dispatched PASS low-priority FIQ count = 0x00000015 21 high-priority FIQ count = 0x00000014 20 nested FIQ count = 0x00000014 20 of 20 nested max FIQ depth = 0x00000002 FIQ depth now = 0x00000000 F2 FIQ nested inside an FIQ handler PASS F3 FIQ nesting unwound to depth zero PASS F4 IRQ tick undisturbed by FIQ work PASS F5 lower-priority thread still scheduled PASS F6 no unexpected Group 0 INTID PASS No regression, both configurations checked on the board. In the FIQ build the ThreadX demo still reports 100 ticks with 20 preemptions and the boot image still passes its cache and protection checks. In the default build the demo is unchanged and the image links no FIQ or Group 0 symbol at all, so the work is absent rather than dormant where it is not wanted -- worth confirming on hardware rather than reasoning about, because the default build now reaches the FIQ vector through a new label even though that label only branches to the fault reporter. entry.S assembles in all four combinations of TX_R52_USE_THREADX_IRQ and FIQ support, on both toolchains, and every file builds with GNU without warnings and with Arm Toolchain for Embedded 22.1.0. Assisted-by: Claude Code (Opus 5) --- .../example_build/s32z280_evb/CMakeLists.txt | 37 +++ .../gnu/example_build/s32z280_evb/board.h | 18 ++ .../s32z280_evb/demo_fiq_s32z280.c | 253 ++++++++++++++++++ .../gnu/example_build/s32z280_evb/entry.S | 61 ++++- .../gnu/example_build/s32z280_evb/gicv3.c | 95 +++++++ .../gnu/example_build/s32z280_evb/gicv3.h | 11 + .../example_build/s32z280_evb/irq_dispatch.c | 105 ++++++++ 7 files changed, 579 insertions(+), 1 deletion(-) create mode 100644 ports/cortex_r52/gnu/example_build/s32z280_evb/demo_fiq_s32z280.c diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/CMakeLists.txt b/ports/cortex_r52/gnu/example_build/s32z280_evb/CMakeLists.txt index 00878c296..f36ee715e 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/CMakeLists.txt +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/CMakeLists.txt @@ -164,3 +164,40 @@ if(TX_R52_ENABLE_IRQ_NESTING) ${EVB_LINK_QUIET_RWX} ) endif() + +# Nested FIQ handling on silicon. Needs TX_R52_ENABLE_FIQ_NESTING, which the +# port-level CMakeLists already requires TX_R52_ENABLE_FIQ alongside, so the image +# exists only where both the FIQ vector path and the nesting pairing are compiled +# in -- as s32z280_nesting.elf does for the IRQ side. +if(TX_R52_ENABLE_FIQ_NESTING) + add_executable(s32z280_fiq.elf EXCLUDE_FROM_ALL + ${EVB_DIR}/entry.S + ${EVB_DIR}/tx_initialize_low_level.S + ${EVB_DIR}/linflexd.c + ${EVB_DIR}/timer.c + ${EVB_DIR}/mpu.c + ${EVB_DIR}/gicv3.c + ${EVB_DIR}/irq_dispatch.c + ${EVB_DIR}/gic_probe.c + ${EVB_DIR}/cache.c + ${EVB_DIR}/demo_fiq_s32z280.c + ) + + target_compile_definitions(s32z280_fiq.elf PRIVATE TX_R52_USE_THREADX_IRQ=1) + target_compile_options(s32z280_fiq.elf PRIVATE -g) + + target_link_libraries(s32z280_fiq.elf PRIVATE threadx) + + target_include_directories(s32z280_fiq.elf PRIVATE + ${EVB_DIR} + ${CMAKE_SOURCE_DIR}/common/inc + ${CMAKE_SOURCE_DIR}/ports/${THREADX_ARCH}/${THREADX_TOOLCHAIN}/inc + ) + + target_link_options(s32z280_fiq.elf PRIVATE + -T${EVB_DIR}/link.lds + -nostartfiles + -Wl,-Map=s32z280_fiq.map + ${EVB_LINK_QUIET_RWX} + ) +endif() diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/board.h b/ports/cortex_r52/gnu/example_build/s32z280_evb/board.h index 3e8b7264c..8c520d652 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/board.h +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/board.h @@ -124,4 +124,22 @@ extern volatile unsigned long board_sgi_priority; #define BOARD_NEST_SGI_INTID 8U +/* FIQ observability. Two Group 0 SGIs, because FIQ nesting means an FIQ taken + while an FIQ handler is running, so a single source cannot show it. The + higher-priority one is raised from inside the lower one's handler. */ + +void board_fiq_handler(void); +void board_fiq_service(unsigned long intid); + +extern volatile unsigned long board_fiq_count; +extern volatile unsigned long board_fiq_high_count; +extern volatile unsigned long board_fiq_nested_count; +extern volatile unsigned long board_fiq_depth; +extern volatile unsigned long board_fiq_max_depth; +extern volatile unsigned long board_fiq_unexpected; +extern volatile unsigned long board_fiq_provoke; + +#define BOARD_FIQ_LOW_INTID 10U +#define BOARD_FIQ_HIGH_INTID 11U + #endif /* BOARD_H */ diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/demo_fiq_s32z280.c b/ports/cortex_r52/gnu/example_build/s32z280_evb/demo_fiq_s32z280.c new file mode 100644 index 000000000..ad359704b --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/demo_fiq_s32z280.c @@ -0,0 +1,253 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* BOARD SUPPORT RELEASE */ +/* */ +/* demo_fiq_s32z280.c Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frederic Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Nested FIQ handling: _tx_thread_fiq_nesting_start and */ +/* _tx_thread_fiq_nesting_end, the last pair in this port that nothing */ +/* had ever called. */ +/* */ +/* The FVP established that the Group 0 chain works and what breaks it. */ +/* What it cannot show is whether a real GIC-600 routes Group 0 to FIQ */ +/* the same way, which is the point of running this here. */ +/* */ +/* FIQ needs more of the GIC than IRQ does. With a single security */ +/* state the controller delivers Group 0 as FIQ and Group 1 as IRQ, so */ +/* an interrupt only arrives as an FIQ if it has been moved into Group */ +/* 0, the distributor and CPU interface both have Group 0 enabled, and */ +/* it is acknowledged through the Group 0 registers. Group 1's */ +/* acknowledge returns the spurious INTID for a Group 0 interrupt and */ +/* leaves it pending, which presents as a storm rather than an error. */ +/* */ +/* FIQ nesting means an FIQ taken while an FIQ handler is running, so */ +/* one source cannot demonstrate it. Two Group 0 SGIs are used, the */ +/* second at a numerically lower priority so it can preempt the first, */ +/* and the first's handler raises it. */ +/* */ +/* WHAT EACH CHECK IS FOR */ +/* */ +/* F1 an FIQ arrives at all. Separate on purpose: it covers the whole */ +/* Group 0 chain -- IGRPEN0, the ICC_SGI0R encoding, IAR0 and */ +/* EOIR0, the EL1 FIQ vector, and F being unmasked. If F1 fails */ +/* the fault is in one of those and not in the nesting routines. */ +/* F2 an FIQ arrived while another FIQ handler was active, depth 2. */ +/* F3 the depth returned to zero, so the pairing unwound. */ +/* F4 the IRQ path is undisturbed: the tick still advances. */ +/* F5 threads still run, so FIQ context save and restore survived */ +/* being re-entered. */ +/* F6 no unexpected Group 0 INTID arrived. */ +/* */ +/**************************************************************************/ + +#include "tx_api.h" +#include "board.h" +#include "linflexd.h" +#include "gicv3.h" + +#define DEMO_STACK_SIZE 2048 + +static TX_THREAD thread_check; +static TX_THREAD thread_spin; + +static ULONG thread_check_stack[DEMO_STACK_SIZE / sizeof(ULONG)]; +static ULONG thread_spin_stack[DEMO_STACK_SIZE / sizeof(ULONG)]; + +static volatile ULONG spin_runs; + + +/* Breakpoint target for tools/read_identity.gdb. Not static and not empty so an + optimising build cannot discard it. */ + +void bsp_done(void) +{ + __asm volatile ("nop"); +} + + +static UINT report(const char *label_ptr, UINT passed) +{ + linflexd_puts(label_ptr); + linflexd_puts((passed != 0U) ? "PASS\n" : "FAIL\n"); + return (passed != 0U) ? 0U : 1U; +} + + +static void report_hex(const char *label_ptr, unsigned long value) +{ + linflexd_puts(label_ptr); + linflexd_puts("0x"); + linflexd_put_hex32((unsigned int) value); + linflexd_putc('\n'); +} + + +static void thread_spin_entry(ULONG thread_input) +{ + (void) thread_input; + + for (;;) + { + spin_runs++; + } +} + + +static void thread_check_entry(ULONG thread_input) +{ + UINT failures = 0U; + ULONG fiq_before; + ULONG ticks_start; + ULONG ticks_end; + ULONG spin_before; + + (void) thread_input; + + /* F1: the whole Group 0 chain, before nesting is involved. */ + + linflexd_puts("raising a Group 0 SGI from thread context\n"); + + fiq_before = board_fiq_count; + gicv3_send_sgi_group0(BOARD_FIQ_LOW_INTID); + tx_thread_sleep(2); + + report_hex("FIQ count = ", board_fiq_count); + + failures += report("F1 FIQ delivered and dispatched ", + (board_fiq_count > fiq_before) ? 1U : 0U); + + if (board_fiq_count == fiq_before) + { + /* Everything below needs an FIQ to arrive, so repeating the failure + five more times would only bury the cause. */ + + linflexd_puts("no FIQ arrived; the nesting checks would only\n" + " restate that, so they are skipped.\n"); + linflexd_puts("FAIL nested FIQ handling\n"); + linflexd_puts("=== fiq demo complete ===\n"); + bsp_done(); + for (;;) + { + tx_thread_sleep(100UL); + } + } + + /* F2 onwards: let the low-priority FIQ handler raise the high one. */ + + linflexd_puts("enabling nested provocation in the FIQ handler\n"); + + board_fiq_provoke = 1UL; + ticks_start = tx_time_get(); + spin_before = spin_runs; + + { + ULONG i; + + for (i = 0UL; i < 20UL; i++) + { + gicv3_send_sgi_group0(BOARD_FIQ_LOW_INTID); + tx_thread_sleep(2); + } + } + + ticks_end = tx_time_get(); + board_fiq_provoke = 0UL; + + report_hex("low-priority FIQ count = ", board_fiq_count); + report_hex("high-priority FIQ count = ", board_fiq_high_count); + report_hex("nested FIQ count = ", board_fiq_nested_count); + report_hex("max FIQ depth = ", board_fiq_max_depth); + report_hex("FIQ depth now = ", board_fiq_depth); + + failures += report("F2 FIQ nested inside an FIQ handler ", + ((board_fiq_nested_count > 0UL) && + (board_fiq_max_depth >= 2UL)) ? 1U : 0U); + + failures += report("F3 FIQ nesting unwound to depth zero ", + (board_fiq_depth == 0UL) ? 1U : 0U); + + failures += report("F4 IRQ tick undisturbed by FIQ work ", + ((ticks_end - ticks_start) >= 30UL) ? 1U : 0U); + + failures += report("F5 lower-priority thread still scheduled ", + (spin_runs > spin_before) ? 1U : 0U); + + report_hex("unexpected Group 0 INTID = ", board_fiq_unexpected); + + failures += report("F6 no unexpected Group 0 INTID ", + (board_fiq_unexpected == 0UL) ? 1U : 0U); + + if (failures == 0U) + { + linflexd_puts("PASS nested FIQ handling verified on silicon\n"); + } + else + { + linflexd_puts("FAIL nested FIQ handling\n"); + } + + linflexd_puts("=== fiq demo complete ===\n"); + + bsp_done(); + + for (;;) + { + tx_thread_sleep(100UL); + } +} + + +void tx_application_define(void *first_unused_memory) +{ + (void) first_unused_memory; + + (void) tx_thread_create(&thread_check, "fiq check", thread_check_entry, + 0UL, thread_check_stack, sizeof(thread_check_stack), + 10U, 10U, TX_NO_TIME_SLICE, TX_AUTO_START); + + (void) tx_thread_create(&thread_spin, "spinner", thread_spin_entry, + 0UL, thread_spin_stack, sizeof(thread_spin_stack), + 20U, 20U, TX_NO_TIME_SLICE, TX_AUTO_START); +} + + +void bsp_main(void) +{ + unsigned int console_status = linflexd_init(); + + linflexd_puts("\n=== ThreadX Cortex-R52 :: S32Z280-594EVB nested FIQ ===\n"); + report_hex("console = ", (unsigned long) console_status); + linflexd_puts("entering kernel\n"); + + tx_kernel_enter(); + + /* Not reached. */ + + linflexd_puts("FAIL tx_kernel_enter returned\n"); + + for (;;) + { + __asm volatile ("nop"); + } +} diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/entry.S b/ports/cortex_r52/gnu/example_build/s32z280_evb/entry.S index 9dc542bac..bd7bdac10 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/entry.S +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/entry.S @@ -189,7 +189,7 @@ el1_vectors: b fault_el1_dabt /* 0x10 */ b fault_el1_reserved /* 0x14 */ b el1_irq_entry /* 0x18 IRQ */ - b fault_el1_fiq /* 0x1C */ + b el1_fiq_entry /* 0x1C FIQ */ @/**************************************************************************/ @/* _start -- reset entry. Entered in THUMB state, Hyp mode (EL2). */ @@ -330,7 +330,19 @@ start_a32: ldr r0, =el1_entry msr ELR_hyp, r0 +#ifdef TX_ENABLE_FIQ_SUPPORT + + /* FIQ left unmasked, IRQ still masked. tx_thread_stack_build only clears a + * thread's F bit when the library was built with FIQ support and nothing + * else ever clears it, so leaving PSR_F set here would mask FIQ until the + * first thread ran and an FIQ raised from bsp_main would silently do + * nothing. + */ + + ldr r0, =(PSR_A | PSR_I | MODE_SVC) +#else ldr r0, =(PSR_A | PSR_I | PSR_F | MODE_SVC) +#endif msr SPSR_hyp, r0 isb eret @@ -536,6 +548,7 @@ __tx_irq_processing_return: #endif b _tx_thread_context_restore + #else /* Standalone: the classic A32 form. lr is adjusted by 4 because an IRQ @@ -549,6 +562,52 @@ __tx_irq_processing_return: #endif +@/**************************************************************************/ +@/* el1_fiq_entry -- FIQ vector at EL1. */ +@/**************************************************************************/ + +el1_fiq_entry: +#if defined(TX_ENABLE_FIQ_SUPPORT) && defined(TX_R52_USE_THREADX_IRQ) + + /* Both guards are needed. TX_ENABLE_FIQ_SUPPORT is PUBLIC on the threadx + * target, so it reaches every image once the library is built with FIQ, + * including images that link no interrupt controller; referencing the GIC + * and board symbols below from those breaks the link outright. That is why + * the IRQ vector is gated the same way. + * + * Group 0 is what the GIC delivers as FIQ, and it has its own acknowledge + * and end-of-interrupt registers -- the Group 1 pair returns the spurious + * INTID for a Group 0 interrupt and leaves it pending, which looks like a + * storm rather than a mistake. As on the IRQ path, the acknowledge happens + * before nesting starts, so the running priority masks this interrupt before + * FIQ is re-enabled. + */ + + b _tx_thread_fiq_context_save + + .global __tx_fiq_processing_return +__tx_fiq_processing_return: +#ifdef TX_ENABLE_FIQ_NESTING + bl gicv3_acknowledge_group0 + mov r4, r0 + stmdb sp!, {r4, r5} + + bl _tx_thread_fiq_nesting_start + mov r0, r4 + bl board_fiq_service + bl _tx_thread_fiq_nesting_end + + ldmia sp!, {r4, r5} + mov r0, r4 + bl gicv3_end_of_interrupt_group0 +#else + bl board_fiq_handler +#endif + b _tx_thread_fiq_context_restore +#else + b fault_el1_fiq +#endif + @/**************************************************************************/ @/* try_execute_data -- branch to a non-executable address on purpose. */ @/* */ diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/gicv3.c b/ports/cortex_r52/gnu/example_build/s32z280_evb/gicv3.c index 6dc3a24f5..1bca8dded 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/gicv3.c +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/gicv3.c @@ -53,6 +53,7 @@ /* Distributor registers. */ #define GICD_CTLR 0x0000U +#define GICD_CTLR_ENABLE_GRP0 (1UL << 0) #define GICD_CTLR_ENABLE_GRP1 (1UL << 1) #define GICD_CTLR_ARE (1UL << 4) @@ -102,6 +103,18 @@ static void write_icc_bpr1(unsigned long value) __asm__ volatile("mcr p15, 0, %0, c12, c12, 3" : : "r"(value) : "memory"); } +static void write_icc_igrpen0(unsigned long value) +{ + /* ICC_IGRPEN0 sits at c12, c12, 6, beside IGRPEN1 at opc2 7. */ + + __asm__ volatile("mcr p15, 0, %0, c12, c12, 6" : : "r"(value) : "memory"); +} + +static void write_icc_bpr0(unsigned long value) +{ + __asm__ volatile("mcr p15, 0, %0, c12, c8, 3" : : "r"(value) : "memory"); +} + static void write_icc_igrpen1(unsigned long value) { __asm__ volatile("mcr p15, 0, %0, c12, c12, 7" : : "r"(value) : "memory"); @@ -127,6 +140,12 @@ void gicv3_init(void) REG32(GICD_BASE + GICD_CTLR) |= GICD_CTLR_ARE; REG32(GICD_BASE + GICD_CTLR) |= GICD_CTLR_ENABLE_GRP1; + /* Group 0 as well, which is what the GIC delivers as FIQ. Enabling it costs + nothing while no interrupt is assigned to that group, and images that never + use FIQ see no change: assignment is per interrupt, in GICR_IGROUPR0. */ + + REG32(GICD_BASE + GICD_CTLR) |= GICD_CTLR_ENABLE_GRP0; + /* Redistributor: clear ProcessorSleep and wait for the redistributor to report that its children are awake, otherwise no interrupt can be delivered to this core. */ @@ -150,6 +169,14 @@ void gicv3_init(void) write_icc_pmr(ICC_PMR_UNMASK_ALL); write_icc_bpr1(0UL); write_icc_igrpen1(ICC_IGRPEN1_ENABLE); + + /* The CPU interface half of Group 0: a Group 0 interrupt reaches the core + only if both the distributor and this are enabled. BPR0 at zero gives no + subpriority grouping, so priority alone decides preemption, which is what + the FIQ nesting test depends on. */ + + write_icc_bpr0(0UL); + write_icc_igrpen0(ICC_IGRPEN1_ENABLE); instruction_barrier(); } @@ -294,6 +321,74 @@ unsigned int gicv3_priority_bits(unsigned int scratch_intid) } +/**************************************************************************/ +/* gicv3_enable_sgi_group0 */ +/* */ +/* As gicv3_enable_sgi, but leaves the interrupt in Group 0 so it arrives */ +/* as an FIQ. The group is chosen by clearing the GICR_IGROUPR0 bit; the */ +/* Group 1 version sets it. */ +/**************************************************************************/ + +void gicv3_enable_sgi_group0(unsigned int intid, unsigned int priority) +{ + if (intid > 15U) + { + return; + } + + REG32(GICR_SGI_BASE + GICR_IGROUPR0) &= ~(1UL << intid); + + REG32(GICR_SGI_BASE + GICR_IPRIORITYR + (intid & ~3U)) &= + ~(0xFFUL << ((intid & 3U) * 8U)); + REG32(GICR_SGI_BASE + GICR_IPRIORITYR + (intid & ~3U)) |= + ((unsigned long) priority & 0xFFUL) << ((intid & 3U) * 8U); + + REG32(GICR_SGI_BASE + GICR_ISENABLER0) = (1UL << intid); +} + + +/**************************************************************************/ +/* gicv3_send_sgi_group0 */ +/* */ +/* ICC_SGI0R rather than ICC_SGI1R: the two differ only in opc1, 2 against */ +/* 0, and each raises the SGI into its own group. Raising a Group 0 */ +/* interrupt through the Group 1 register does not deliver it as an FIQ. */ +/**************************************************************************/ + +void gicv3_send_sgi_group0(unsigned int intid) +{ + unsigned long low = (((unsigned long) intid & 0xFUL) << 24) | 1UL; + unsigned long high = 0UL; + + __asm volatile ("mcrr p15, 2, %0, %1, c12" :: "r" (low), "r" (high) : "memory"); + instruction_barrier(); +} + + +/**************************************************************************/ +/* gicv3_acknowledge_group0 / gicv3_end_of_interrupt_group0 */ +/* */ +/* Group 0 has its own pair at c12, c8, where Group 1 uses c12, c12. */ +/* Acknowledging a Group 0 interrupt through IAR1 returns the spurious */ +/* INTID and leaves the interrupt pending, which presents as an FIQ storm. */ +/**************************************************************************/ + +unsigned long gicv3_acknowledge_group0(void) +{ + unsigned long intid; + + __asm__ volatile("mrc p15, 0, %0, c12, c8, 0" : "=r"(intid)); + return intid & 0xFFFFFFUL; +} + + +void gicv3_end_of_interrupt_group0(unsigned long intid) +{ + instruction_barrier(); + __asm__ volatile("mcr p15, 0, %0, c12, c8, 1" : : "r"(intid) : "memory"); +} + + unsigned long gicv3_acknowledge(void) { unsigned long intid; diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/gicv3.h b/ports/cortex_r52/gnu/example_build/s32z280_evb/gicv3.h index 7acd6776b..184a5b6d4 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/gicv3.h +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/gicv3.h @@ -58,6 +58,17 @@ void gicv3_enable_sgi(unsigned int intid, unsigned int priority); void gicv3_send_sgi(unsigned int intid); +/* Group 0 support, which is what produces FIQ rather than IRQ. With a single + security state the GIC routes Group 0 to FIQ and Group 1 to IRQ, so an + interrupt has to be moved into Group 0 to arrive as an FIQ at all. Group 0 + has its own acknowledge and end-of-interrupt registers; using the Group 1 ones + on a Group 0 interrupt does not work. */ + +void gicv3_enable_sgi_group0(unsigned int intid, unsigned int priority); +void gicv3_send_sgi_group0(unsigned int intid); +unsigned long gicv3_acknowledge_group0(void); +void gicv3_end_of_interrupt_group0(unsigned long intid); + /* Implemented priority bits, discovered by write and readback. Leaves the scratch INTID's priority byte at zero. */ diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/irq_dispatch.c b/ports/cortex_r52/gnu/example_build/s32z280_evb/irq_dispatch.c index e7d0f5848..193f14dea 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/irq_dispatch.c +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/irq_dispatch.c @@ -66,6 +66,14 @@ volatile unsigned long board_nest_max; volatile unsigned long board_sgi_count; volatile unsigned long board_sgi_nested_count; volatile unsigned long board_nest_provoke; + +volatile unsigned long board_fiq_count; +volatile unsigned long board_fiq_high_count; +volatile unsigned long board_fiq_nested_count; +volatile unsigned long board_fiq_depth; +volatile unsigned long board_fiq_max_depth; +volatile unsigned long board_fiq_unexpected; +volatile unsigned long board_fiq_provoke; volatile unsigned long board_priority_bits; volatile unsigned long board_timer_priority; volatile unsigned long board_sgi_priority; @@ -116,6 +124,17 @@ void board_init(void) gicv3_enable_sgi(BOARD_NEST_SGI_INTID, TIMER_PPI_PRIORITY / 2U); +#ifdef TX_ENABLE_FIQ_SUPPORT + + /* Two Group 0 SGIs for the FIQ path. Group 0 is what the GIC delivers as + FIQ; the high one takes a numerically lower priority so it can preempt the + low one, which is what FIQ nesting means. Both sit above the timer so the + IRQ and FIQ paths do not interfere. */ + + gicv3_enable_sgi_group0(BOARD_FIQ_LOW_INTID, 0x40U); + gicv3_enable_sgi_group0(BOARD_FIQ_HIGH_INTID, 0x20U); +#endif + /* The priorities as the GIC will actually compare them. Only the top board_priority_bits survive; the low ones read back as zero, so two values that differ only there would collapse together and never preempt. Recorded @@ -249,3 +268,89 @@ void board_irq_handler(void) gicv3_end_of_interrupt(intid); } } + + +#ifdef TX_ENABLE_FIQ_SUPPORT +/**************************************************************************/ +/* board_fiq_service -- service an already-acknowledged Group 0 INTID. */ +/* */ +/* The FIQ counterpart of board_irq_service, and split for the same */ +/* reason: the acknowledge has to happen before nesting starts. Does not */ +/* acknowledge and does not EOI. */ +/**************************************************************************/ + +void board_fiq_service(unsigned long intid) +{ + if (intid == GICV3_SPURIOUS_INTID) + { + return; + } + + board_fiq_depth++; + if (board_fiq_depth > board_fiq_max_depth) + { + board_fiq_max_depth = board_fiq_depth; + } + + if (intid == (unsigned long) BOARD_FIQ_LOW_INTID) + { + board_fiq_count++; + + /* Provoke the nested FIQ from inside this handler. Only reachable + because _tx_thread_fiq_nesting_start has re-enabled FIQ; the bounded + spin lets the GIC deliver the higher-priority Group 0 SGI before this + handler returns. Bounded, because with nesting compiled out the + second FIQ cannot arrive and this must not hang. */ + + if (board_fiq_provoke != 0UL) + { + unsigned long seen = board_fiq_high_count; + unsigned long guard; + + gicv3_send_sgi_group0(BOARD_FIQ_HIGH_INTID); + + for (guard = 0UL; guard < 100000UL; guard++) + { + if (board_fiq_high_count != seen) + { + break; + } + } + } + } + else if (intid == (unsigned long) BOARD_FIQ_HIGH_INTID) + { + board_fiq_high_count++; + + /* Depth above 1 means this FIQ arrived inside another FIQ handler. */ + + if (board_fiq_depth > 1UL) + { + board_fiq_nested_count++; + } + } + else + { + board_fiq_unexpected = intid; + } + + board_fiq_depth--; +} + + +/**************************************************************************/ +/* board_fiq_handler -- the non-nesting FIQ entry point. */ +/**************************************************************************/ + +void board_fiq_handler(void) +{ + unsigned long intid = gicv3_acknowledge_group0(); + + board_fiq_service(intid); + + if (intid != GICV3_SPURIOUS_INTID) + { + gicv3_end_of_interrupt_group0(intid); + } +} +#endif From 27891f3b8473282e7f5f36adfe6642f488fbb630 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Fri, 14 Aug 2026 14:18:50 -0400 Subject: [PATCH 042/181] Read the TCM configuration off the part, and corrected what we thought we knew (#615) The BSP has recorded since bring-up that the TCMs are inaccessible at reset "because nothing has programmed the TCM region registers yet". Reading those registers shows the reason was wrong. ATCM 0x0000011F 64KB, 1 wait state, ENABLED at EL2 and EL1/EL0 BTCM 0x00000014 16KB, 0 wait states, disabled CTCM 0x00000114 16KB, 1 wait state, disabled Every BASEADDRESS field is zero, so ATCM is live as 64KB at address 0x00000000, not at the 0x30000000 the reference manual documents. The reads that faulted were of an address the TCM is not at. ATCM's enables reset set because CFGTCMBOOTx is tied high on this part, which the Cortex-R52 TRM gives as the one exception to "at reset all bits are 0 apart from SIZE and WAITSTATES". BTCM and CTCM really are disabled. The sizes and wait states match the S32Z2 reference manual exactly -- TCMA 64KB with one wait state, TCMB 16KB with none, TCMC 16KB with one -- so the TRM's field layout, NXP's documented configuration and the silicon all agree. That agreement is the point of reading before writing. ECC is implemented and enabled: IMP_MEMPROTCTLR reads 0x00000011, both RAMPROTIMP and RAMPROTEN set. TRM 6.2.2 therefore applies rather than being hypothetical: a TCM location must be written before it is read, or the read reports an error -- which looks exactly like "the TCM is not accessible" and sends the reader back to region registers that were already correct. The preload widths differ too, ATCM needing 64-bit aligned STRD or STM where BTCM and CTCM accept 32-bit stores, so a C loop over unsigned int would leave ATCM's check bits invalid. tcm.c reads and decodes only; nothing is programmed here. The layouts in tcm.h are quoted from TRM r1p3 section 3.3.94 table 3-136 and section 3.3.76 table 3-114, not inferred from a neighbouring register: BASEADDRESS is [31:13] where IMP_PERIPHPREGIONR uses [31:12], and assuming the analogy would have been wrong by one bit in the same way the PRBAR shift was. The boot image reports all of it and flags any size that disagrees with the reference manual, so a part configured differently says so rather than being silently assumed to match this one. Assisted-by: Claude Code (Opus 5) --- .../example_build/s32z280_evb/CMakeLists.txt | 5 + .../gnu/example_build/s32z280_evb/bsp_boot.c | 52 ++++++ .../gnu/example_build/s32z280_evb/platform.h | 26 ++- .../s32z280_evb/readme_s32z280.txt | 21 ++- .../gnu/example_build/s32z280_evb/tcm.c | 154 ++++++++++++++++++ .../gnu/example_build/s32z280_evb/tcm.h | 117 +++++++++++++ 6 files changed, 365 insertions(+), 10 deletions(-) create mode 100644 ports/cortex_r52/gnu/example_build/s32z280_evb/tcm.c create mode 100644 ports/cortex_r52/gnu/example_build/s32z280_evb/tcm.h diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/CMakeLists.txt b/ports/cortex_r52/gnu/example_build/s32z280_evb/CMakeLists.txt index f36ee715e..2545b3d06 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/CMakeLists.txt +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/CMakeLists.txt @@ -35,6 +35,7 @@ add_executable(s32z280_boot.elf EXCLUDE_FROM_ALL ${EVB_DIR}/gicv3.c ${EVB_DIR}/irq_dispatch.c ${EVB_DIR}/cache.c + ${EVB_DIR}/tcm.c ) target_include_directories(s32z280_boot.elf PRIVATE ${EVB_DIR}) @@ -67,6 +68,7 @@ add_executable(s32z280_demo.elf EXCLUDE_FROM_ALL ${EVB_DIR}/irq_dispatch.c ${EVB_DIR}/gic_probe.c ${EVB_DIR}/cache.c + ${EVB_DIR}/tcm.c ${EVB_DIR}/demo_s32z280.c ) @@ -106,6 +108,7 @@ if(TX_R52_ENABLE_VFP) ${EVB_DIR}/irq_dispatch.c ${EVB_DIR}/gic_probe.c ${EVB_DIR}/cache.c + ${EVB_DIR}/tcm.c ${EVB_DIR}/demo_vfp_s32z280.c ) @@ -143,6 +146,7 @@ if(TX_R52_ENABLE_IRQ_NESTING) ${EVB_DIR}/irq_dispatch.c ${EVB_DIR}/gic_probe.c ${EVB_DIR}/cache.c + ${EVB_DIR}/tcm.c ${EVB_DIR}/demo_nesting_s32z280.c ) @@ -180,6 +184,7 @@ if(TX_R52_ENABLE_FIQ_NESTING) ${EVB_DIR}/irq_dispatch.c ${EVB_DIR}/gic_probe.c ${EVB_DIR}/cache.c + ${EVB_DIR}/tcm.c ${EVB_DIR}/demo_fiq_s32z280.c ) diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/bsp_boot.c b/ports/cortex_r52/gnu/example_build/s32z280_evb/bsp_boot.c index d97ec37a4..8968dfebd 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/bsp_boot.c +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/bsp_boot.c @@ -60,6 +60,7 @@ #include "mpu.h" #include "gicv3.h" #include "cache.h" +#include "tcm.h" /* Captured at EL2 by entry.S, before the drop to EL1. */ @@ -346,6 +347,57 @@ void bsp_main(void) linflexd_puts("P1 RTU0.GPR CFG_CNTDV via LLPP\n"); report("CFG_CNTDV", *(volatile unsigned int *)S32Z_RTU0_GPR_CFG_CNTDV); + /* --- TCM: what the hardware reports about itself --------------------- + Reads only. platform.h has recorded since bring-up that the TCM windows + fault at reset, and the Cortex-R52 TRM says why: every bit of the region + registers resets to zero apart from SIZE and WAITSTATES, so the banks sit + at base 0 with both enables clear. This confirms that on the part rather + than trusting it, and cross-checks the reported sizes against the S32Z2 + reference manual, which documents TCMA 64KB, TCMB 16KB and TCMC 16KB. + + Nothing is written here. Enabling TCM also requires initialising the ECC + bits before any read (TRM 6.2.2), with ATCM needing 64-bit aligned stores + where BTCM and CTCM accept 32-bit, so the enable belongs in its own step + once these values are known. */ + + linflexd_puts("T1 TCM configuration as reported by the core\n"); + { + static const char *const bank_name[3] = { "ATCM", "BTCM", "CTCM" }; + static const unsigned long expect_bytes[3] = { 0x10000UL, 0x4000UL, 0x4000UL }; + unsigned int i; + + for (i = 0U; i < 3U; i++) + { + tcm_bank_t bank; + + tcm_read_bank(i, &bank); + + linflexd_puts(bank_name[i]); + linflexd_puts(" raw=0x"); + linflexd_put_hex32((unsigned int) bank.raw); + linflexd_puts(" base=0x"); + linflexd_put_hex32((unsigned int) bank.base); + linflexd_puts(" size=0x"); + linflexd_put_hex32((unsigned int) bank.size_bytes); + linflexd_puts(" ws="); + linflexd_putc((char) ('0' + (char) bank.wait_states)); + linflexd_puts(" en2="); + linflexd_putc((char) ('0' + (char) bank.enable_el2)); + linflexd_puts(" en10="); + linflexd_putc((char) ('0' + (char) bank.enable_el10)); + linflexd_puts((bank.size_bytes == expect_bytes[i]) + ? " size matches the RM\n" + : " SIZE DISAGREES WITH THE RM\n"); + } + + report("MEMPROTCTLR", (unsigned int) tcm_read_memprotctlr()); + linflexd_puts("ECC implemented = "); + linflexd_putc((char) ('0' + (char) tcm_ecc_implemented())); + linflexd_puts(", enabled = "); + linflexd_putc((char) ('0' + (char) tcm_ecc_enabled())); + linflexd_putc('\n'); + } + /* --- MPU, then the GIC ------------------------------------------------ The GIC needs its region mapped Device nGnRnE (Cortex-R52 TRM), which needs the MPU on. Markers around the enable: if the console survives it, diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/platform.h b/ports/cortex_r52/gnu/example_build/s32z280_evb/platform.h index b9bca7dfa..64034344c 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/platform.h +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/platform.h @@ -47,11 +47,27 @@ /* self-booting image loaded from flash would still need the data */ /* alias, since the core's own data side may not write through AXI-F. */ /* */ -/* The TCMs (0x30000000, 0x30100000, 0x30200000) are NOT accessible */ -/* at reset -- reads fault -- because nothing has programmed the TCM */ -/* region registers yet. They are therefore unusable for early boot */ -/* and are deliberately absent from this map. The DDR window at */ -/* 0x7A000000 is likewise dark until DDR is initialised. */ +/* The TCMs need care, and the earlier note here was wrong about why. */ +/* Reads of 0x30000000, 0x30100000 and 0x30200000 do fault, but not */ +/* because the TCMs are disabled. Reading the region registers on */ +/* this part gives: */ +/* */ +/* ATCM 0x0000011F 64KB, 1 wait state, ENABLED at EL2 and EL1/0 */ +/* BTCM 0x00000014 16KB, 0 wait states, disabled */ +/* CTCM 0x00000114 16KB, 1 wait state, disabled */ +/* */ +/* Every BASEADDRESS field is zero, so ATCM is live as 64KB at address */ +/* 0x00000000 -- not at 0x30000000. The faulting reads were of an */ +/* address the TCM is not at. ATCM's enables reset set because */ +/* CFGTCMBOOTx is tied high on this part (Cortex-R52 TRM r1p3 3.3.94). */ +/* The sizes and wait states match the S32Z2 reference manual exactly. */ +/* */ +/* ECC is implemented and enabled: IMP_MEMPROTCTLR reads 0x00000011, */ +/* so RAMPROTIMP and RAMPROTEN are both set. TRM 6.2.2 therefore */ +/* applies -- a TCM location must be written before it is read, and */ +/* ATCM needs 64-bit aligned stores where BTCM and CTCM accept 32-bit. */ +/* */ +/* The DDR window at 0x7A000000 is dark until DDR is initialised. */ /* */ /**************************************************************************/ diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/readme_s32z280.txt b/ports/cortex_r52/gnu/example_build/s32z280_evb/readme_s32z280.txt index f2a3d1b05..d46dfa721 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/readme_s32z280.txt +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/readme_s32z280.txt @@ -73,11 +73,22 @@ model and not an R52 at all. Data, bss and the per-mode stacks live in RTU-local data SRAM at 0x31780000 (256 KB); 0x31800000 gives 2 MB if an image outgrows it. - The TCMs at 0x30000000/0x30100000/0x30200000 are NOT accessible at reset -- - reads fault -- until their region registers are programmed, so nothing - needed for early boot can live there. The DDR window at 0x7A000000 is - likewise dark until DDR is initialised. Both are absent from link.lds on - purpose. + Reads of 0x30000000/0x30100000/0x30200000 do fault, but the earlier note + here had the reason wrong. Reading the region registers on this part shows + ATCM already ENABLED at both exception levels, 64 KB with one wait state, + and every BASEADDRESS field zero -- so ATCM is live at address 0x00000000, + not at 0x30000000. The faulting reads were of an address the TCM is not + at. ATCM's enables reset set because CFGTCMBOOTx is tied high here. BTCM + (16 KB, 0 wait states) and CTCM (16 KB, 1 wait state) really are disabled. + Sizes and wait states agree with the S32Z2 reference manual exactly. + + ECC is implemented and enabled -- IMP_MEMPROTCTLR reads 0x11 -- so per + Cortex-R52 TRM 6.2.2 a TCM location must be written before it is read, and + ATCM needs 64-bit aligned stores where BTCM and CTCM accept 32-bit. Using + TCM therefore takes more than setting an enable bit. + + The DDR window at 0x7A000000 is dark until DDR is initialised. Both TCM + and DDR are absent from link.lds for now. 5. What this image reports diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/tcm.c b/ports/cortex_r52/gnu/example_build/s32z280_evb/tcm.c new file mode 100644 index 000000000..44f140e91 --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/tcm.c @@ -0,0 +1,154 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* BOARD SUPPORT RELEASE */ +/* */ +/* tcm.c Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frederic Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Reads what the TCM hardware reports about itself. See tcm.h for */ +/* the register layouts and where they come from; nothing here is */ +/* inferred from a neighbouring register's shape. */ +/* */ +/* Reading only. Programming a base address and setting the enables */ +/* comes after these values have been seen and agree with both the */ +/* Cortex-R52 TRM and the S32Z2 reference manual, because a disagreement*/ +/* would mean one of the two documents does not describe this part and */ +/* guessing which would be the whole PRBAR mistake again. */ +/* */ +/* MISRA C:2012 deviations (justified) */ +/* */ +/* Dir 4.3 -- assembly encapsulated one operation per function. */ +/* */ +/**************************************************************************/ + +#include "tcm.h" + +#define TCM_SIZE_SHIFT 2U +#define TCM_SIZE_MASK 0x1FUL +#define TCM_WAITSTATES_SHIFT 8U +#define TCM_ENABLE_EL2 (1UL << 1) +#define TCM_ENABLE_EL10 (1UL << 0) +#define TCM_BASE_SHIFT 13U /* TRM table 3-136: [31:13] */ + +#define MEMPROT_RAMPROTIMP (1UL << 4) +#define MEMPROT_RAMPROTEN (1UL << 0) + + +static unsigned long read_atcmregionr(void) +{ + unsigned long value; + __asm volatile ("mrc p15, 0, %0, c9, c1, 0" : "=r" (value)); + return value; +} + +static unsigned long read_btcmregionr(void) +{ + unsigned long value; + __asm volatile ("mrc p15, 0, %0, c9, c1, 1" : "=r" (value)); + return value; +} + +static unsigned long read_ctcmregionr(void) +{ + unsigned long value; + __asm volatile ("mrc p15, 0, %0, c9, c1, 2" : "=r" (value)); + return value; +} + + +/* SIZE is an encoding, not a shift count: 4 means 8KB and each step doubles, + so 8KB << (field - 4). Anything outside the documented range yields 0 + rather than a plausible-looking wrong number. */ + +static unsigned long decode_size(unsigned int field) +{ + unsigned long bytes = 0UL; + + if ((field >= 4U) && (field <= 11U)) + { + bytes = 0x2000UL << (field - 4U); + } + + return bytes; +} + + +void tcm_read_bank(unsigned int index, tcm_bank_t *bank_ptr) +{ + unsigned long raw; + + if (bank_ptr == 0) + { + return; + } + + switch (index) + { + case 0U: raw = read_atcmregionr(); break; + case 1U: raw = read_btcmregionr(); break; + case 2U: raw = read_ctcmregionr(); break; + default: raw = 0UL; break; + } + + bank_ptr->raw = raw; + bank_ptr->base = raw & ~((1UL << TCM_BASE_SHIFT) - 1UL); + bank_ptr->size_field = (unsigned int) ((raw >> TCM_SIZE_SHIFT) & TCM_SIZE_MASK); + bank_ptr->size_bytes = decode_size(bank_ptr->size_field); + bank_ptr->wait_states = (unsigned int) ((raw >> TCM_WAITSTATES_SHIFT) & 1UL); + bank_ptr->enable_el2 = ((raw & TCM_ENABLE_EL2) != 0UL) ? 1U : 0U; + bank_ptr->enable_el10 = ((raw & TCM_ENABLE_EL10) != 0UL) ? 1U : 0U; +} + + +unsigned long tcm_read_memprotctlr(void) +{ + unsigned long value; + + /* Note opc1 is 1 here, not 0 as for the region registers. */ + + __asm volatile ("mrc p15, 1, %0, c9, c1, 2" : "=r" (value)); + return value; +} + + +unsigned int tcm_ecc_implemented(void) +{ + return ((tcm_read_memprotctlr() & MEMPROT_RAMPROTIMP) != 0UL) ? 1U : 0U; +} + + +unsigned int tcm_ecc_enabled(void) +{ + unsigned long ctlr = tcm_read_memprotctlr(); + + /* RAMPROTEN is ignored when RAMPROTIMP is 0: the TRM says the design + behaves as if it were 0, so report it that way rather than echoing a + bit that has no effect. */ + + if ((ctlr & MEMPROT_RAMPROTIMP) == 0UL) + { + return 0U; + } + + return ((ctlr & MEMPROT_RAMPROTEN) != 0UL) ? 1U : 0U; +} diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/tcm.h b/ports/cortex_r52/gnu/example_build/s32z280_evb/tcm.h new file mode 100644 index 000000000..0c90f71e0 --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/tcm.h @@ -0,0 +1,117 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* BOARD SUPPORT RELEASE */ +/* */ +/* tcm.h Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frederic Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Tightly-coupled memory on the S32Z280. This header is the reading */ +/* half: what the hardware reports about itself. Enabling comes next */ +/* and depends on what these reads say. */ +/* */ +/* WHERE THE FACTS COME FROM */ +/* */ +/* Cortex-R52 TRM r1p3 (100026_0103_00_en), section 3.3.94, table */ +/* 3-136. IMP_ATCMREGIONR, IMP_BTCMREGIONR and IMP_CTCMREGIONR are */ +/* at MRC/MCR p15, 0, , c9, c1, {0,1,2} and are laid out: */ +/* */ +/* [31:13] BASEADDRESS bits [31:13] of the TCM base address */ +/* [12:9] RES0 */ +/* [8] WAITSTATES wait states for TCM accesses */ +/* [7] RES0 */ +/* [6:2] SIZE size indicator, read-only in effect */ +/* [1] ENABLEEL2 enable at EL2 */ +/* [0] ENABLEEL10 enable at EL1 and EL0 */ +/* */ +/* ⚠ BASEADDRESS is [31:13], not [31:12]. IMP_PERIPHPREGIONR uses */ +/* [31:12] and inferring the same here would be wrong by one bit -- */ +/* the same class of mistake that made PRBAR silently drop XN. The */ +/* base is therefore 8KB-aligned, not 4KB. */ +/* */ +/* SIZE encodings: 0 none, 4 8KB, 5 16KB, 6 32KB, 7 64KB, 8 128KB, */ +/* 9 256KB, 10 512KB, 11 1MB. */ +/* */ +/* "At reset all bits are 0 apart from SIZE and WAITSTATES", unless */ +/* CFGTCMBOOTx is high, which resets the ATCM enables to 1. So a */ +/* part that has not been told otherwise has every TCM based at 0 with */ +/* both enables clear, which is exactly why reads of the documented */ +/* TCM windows fault on this board. */ +/* */ +/* IMP_MEMPROTCTLR is at p15, 1, , c9, c1, 2 (TRM 3.3.76, table */ +/* 3-114): RAMPROTIMP [4] says whether RAM protection exists at all, */ +/* RAMPROTEN [0] whether it is on, and RAMPROTEN is ignored when */ +/* RAMPROTIMP is 0. */ +/* */ +/* S32Z2 reference manual: TCMA 64KB with 1 wait state, TCMB 16KB with */ +/* 0, TCMC 16KB with 1, per core. Those give expected SIZE values of */ +/* 7, 5 and 5, which is a cross-check between the two documents and */ +/* the silicon rather than a restatement of either. */ +/* */ +/* WHY ENABLING IS NOT ENOUGH */ +/* */ +/* TRM section 6.2.2: the ECC bits in TCM RAM are not initialised by */ +/* the processor, and a location must be written before it is read */ +/* with ECC enabled. An uninitialised read reports an error, which */ +/* looks exactly like "the TCM is not accessible" and would send the */ +/* reader back to these region registers, which were already right. */ +/* */ +/* The preload widths are not uniform: BTCM and CTCM take STR, STRD */ +/* or STM at 32-bit alignment, but ATCM needs STRD or STM at 64-bit */ +/* alignment. A C loop storing 32-bit words would leave ATCM's check */ +/* bits invalid. */ +/* */ +/**************************************************************************/ + +#ifndef TCM_H +#define TCM_H + +/* One bank's reported configuration, decoded from its region register. */ + +typedef struct +{ + unsigned long raw; /* register as read */ + unsigned long base; /* BASEADDRESS << 13 */ + unsigned int size_field; /* SIZE, as encoded */ + unsigned long size_bytes; /* decoded, 0 if the encoding is unknown */ + unsigned int wait_states; + unsigned int enable_el2; + unsigned int enable_el10; +} tcm_bank_t; + +/* Read and decode one bank. Index 0 is ATCM, 1 BTCM, 2 CTCM; any other + index yields a zeroed structure. */ + +void tcm_read_bank(unsigned int index, tcm_bank_t *bank_ptr); + +/* IMP_MEMPROTCTLR, raw. */ + +unsigned long tcm_read_memprotctlr(void); + +/* Whether RAM protection is implemented, and whether it is enabled. Both are + decoded from IMP_MEMPROTCTLR, and the second is meaningless when the first + is zero -- the TRM says the design behaves as if RAMPROTEN were 0. */ + +unsigned int tcm_ecc_implemented(void); +unsigned int tcm_ecc_enabled(void); + +#endif From ba5e5897f43d4a5d097f16e6861047c5f61af9d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Fri, 14 Aug 2026 14:45:55 -0400 Subject: [PATCH 043/181] Made the basic processing counter visible to the reporting thread (#616) The thread-metric basic processing test reports 0 for every period when built with optimisation, and additionally claims "Basic processing thread died!" because the counter never differs from the previous reading. tm_basic_processing_counter is written by the processing thread and read by the reporting thread, but it was a plain global. The processing loop calls nothing, so nothing forces the compiler to write the counter back to memory, and in an infinite loop there is no exit path where it must. At -O2 with arm-none-eabi-gcc 13.2.1 the counter is loaded once before the loop, incremented in a register, and never stored: 28: ldr ip, [r3] counter loaded once ... inner loop over the volatile array 50: add ip, ip, #1 increment stays in the register 54: b 2c and around again The reporting thread reads the memory location, which stays 0 for the life of the program. This is not specific to the Armv8-R target it was reported on: the same shape appears for Cortex-M4 in Thumb state, and at -O1, -O2, -O3 and -Os. Only -O0 happens to work. Declare the counter volatile so the increment becomes a real store. Read it into a local once per pass and use the local inside the 1024-iteration loop, rather than letting every iteration re-read the volatile: that would add a memory access to each iteration and change the amount of work the test performs. This test is the baseline the rest of the suite is scaled against, per the readme, so its throughput has to stay comparable with previously published figures and with other RTOSes. The array was already volatile, which is why the arithmetic itself survives optimisation; only the counter was missing. Verified by disassembly rather than by inspection. After the change the inner loop is instruction-for-instruction identical to what dev generates today, ldr/ldr/add/eor/str/add/cmp/bne, with one volatile read hoisted above the loop and one store below it: 30: ldr ip, [lr] one read per pass, outside the loop 34: ... inner loop unchanged, back edge targets 34 54: add ip, ip, #1 58: str ip, [lr] the counter is now published 5c: b 2c Confirmed for cortex-r52 in Arm state and cortex-m4 in Thumb state. Reported by @hotislandn in #480, which identified the cause correctly. Assisted-by: Claude Code (Opus 5) --- .../thread_metric/tm_basic_processing_test.c | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/utility/benchmarks/thread_metric/tm_basic_processing_test.c b/utility/benchmarks/thread_metric/tm_basic_processing_test.c index f1c4fa228..40ad8f534 100644 --- a/utility/benchmarks/thread_metric/tm_basic_processing_test.c +++ b/utility/benchmarks/thread_metric/tm_basic_processing_test.c @@ -41,7 +41,13 @@ /* Define the counters used in the demo application... */ -unsigned long tm_basic_processing_counter; +/* volatile because the reporting thread reads this while the processing thread + below increments it. The processing loop calls nothing, so without volatile + the compiler is free to keep the counter in a register for the lifetime of an + infinite loop and never write it back: at -O2 it does exactly that, and the + report reads 0 forever. */ + +volatile unsigned long tm_basic_processing_counter; /* Test array. We will just do a series of calculations on the @@ -98,7 +104,8 @@ void tm_basic_processing_initialize(void) void tm_basic_processing_thread_0_entry(void) { -int i; +int i; +unsigned long snapshot; /* Initialize the test array. */ for (i = 0; i < 1024; i++) @@ -111,6 +118,15 @@ int i; while(1) { + /* Read the counter once per pass and use the copy in the loop below. + Reading the volatile counter inside the loop instead would add a + memory access to every one of the 1024 iterations and so change the + amount of work this test performs. That matters more here than + elsewhere in the suite: this test is the baseline the other results + are scaled against, so its throughput has to stay comparable with + previously published figures and with other RTOSes. */ + snapshot = tm_basic_processing_counter; + /* Loop through the basic processing array, add the previous contents with the contents of the tm_basic_processing_counter and xor the result with the previous value... just to eat @@ -119,11 +135,11 @@ int i; { /* Update each array entry. */ - tm_basic_processing_array[i] = (tm_basic_processing_array[i] + tm_basic_processing_counter) ^ tm_basic_processing_array[i]; + tm_basic_processing_array[i] = (tm_basic_processing_array[i] + snapshot) ^ tm_basic_processing_array[i]; } /* Increment the basic processing counter. */ - tm_basic_processing_counter++; + tm_basic_processing_counter = snapshot + 1; } } From b1a48824ea8437cfd1c41089302d216a1bba31db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Fri, 14 Aug 2026 16:14:24 -0400 Subject: [PATCH 044/181] Enabled ATCM on S32Z280, and left the other two banks off for a measured reason (#617) entry.S programs ATCM to 0x30000000 and enables it at both exception levels. This happens at EL2 deliberately: writing ENABLEEL2 from EL1 is silently ignored, which was measured on BTCM and CTCM -- the base took and ENABLEEL10 took while ENABLEEL2 stayed clear -- and the same write from EL2 sticks. tcm_enable() keeps ENABLEEL10 as its success criterion for the same reason, since requiring both would report failure for a bank that is usable at the level the caller runs at. Programming ATCM also moves it off address 0, where CFGTCMBOOTx leaves it, so a null-pointer write now faults instead of quietly landing in tightly-coupled memory. The boot image verifies rather than programs, preloads ATCM because ECC is enabled and the check bits are not initialised by the core, and proves the bank holds data both before the MPU is enabled and after. One MPU region covers it: the TRM requires a region before an enabled TCM can be used, and an enabled TCM always behaves as Non-cacheable Non-shareable Normal memory whatever the region says, so only the permissions there matter. BTCM and CTCM are left disabled, and that is a measurement rather than caution. Enabling any second bank removes all measurable data-cache benefit: ATCM only cache gain 24% ATCM + BTCM cache gain 0% ATCM + BTCM + CTCM cache gain 0% ATCM + BTCM at another base cache gain 0% ATCM + CTCM, BTCM disabled cache gain 0% Five configurations, one variable. Not a particular bank, not its address, and not the ECC preload: enabling a second bank at all. The benchmark buffer is in non-RTU-local SRAM at 0x31800000, outside every TCM window, and CCSIDR reports the same 16KB four-way cache throughout. I was wrong twice while narrowing this -- first blaming the preload, then blaming BTCM specifically -- and each was settled by a run rather than by argument. No erratum covers it. Checked the Cortex-R52 errata notice SDEN-857344 issue 19, all twenty-five entries, and the S32Z2 0P91J mask set errata, whose RTU and R52 entries are ERR050509, ERR051107, ERR051153, ERR051441, ERR051613, ERR051614 and ERR052126. A RAM pool shared between the RTU's last-level cache and the TCMs would explain it, the LLC being documented as allocating ways to specific domains, but that is a guess and it belongs with the other questions for NXP. Little is lost meanwhile. The reference manual describes TCM_A as the bank "optimized for small, regularly executed code such as interrupt service routines or OS kernels", which is what a TCM is wanted for here, and enabling the other two is one line each in entry.S once there is an answer. Two checks were also wrong and are fixed. T5 reported every bank accessible while two were disabled, because a disabled TCM's address range is serviced through AXIM and memory answering there says nothing about the TCM; it now requires the bank to be enabled as well. And T2 called tcm_enable() from EL1 for all three banks, which would have switched on the very banks entry.S leaves off. Verified on S32Z280 silicon: ATCM enabled and holding data before and after the MPU, the cache benchmark back to 24%, protection checks X2 and X4 unchanged, and the ThreadX demo still reporting 100 ticks with 20 preemptions. Assisted-by: Claude Code (Opus 5) --- .../gnu/example_build/s32z280_evb/bsp_boot.c | 109 ++++++++++++++++++ .../gnu/example_build/s32z280_evb/entry.S | 59 ++++++++++ .../gnu/example_build/s32z280_evb/mpu.c | 29 ++++- .../gnu/example_build/s32z280_evb/platform.h | 15 +++ .../s32z280_evb/readme_s32z280.txt | 36 +++++- .../gnu/example_build/s32z280_evb/tcm.c | 108 +++++++++++++++++ .../gnu/example_build/s32z280_evb/tcm.h | 34 ++++++ 7 files changed, 387 insertions(+), 3 deletions(-) diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/bsp_boot.c b/ports/cortex_r52/gnu/example_build/s32z280_evb/bsp_boot.c index 8968dfebd..0d555caad 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/bsp_boot.c +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/bsp_boot.c @@ -398,6 +398,78 @@ void bsp_main(void) linflexd_putc('\n'); } + /* --- TCM: enable, preload, prove ------------------------------------ + Done before the MPU goes on, so a failure here is not confused with a + missing MPU region. The preload is not optional: ECC is enabled on this + part, so a location read before it has been written reports an error, and + that error would look exactly like an inaccessible TCM. */ + + MARK(0x20); + linflexd_puts("T2 TCM state as entry.S left it\n"); + { + static const char *const bank_name[3] = { "ATCM", "BTCM", "CTCM" }; + unsigned int i; + unsigned int atcm_ok; + + /* Verification only. Nothing is programmed here: ENABLEEL2 is ignored + when written from EL1, so TCM setup belongs at EL2 in entry.S, and + calling tcm_enable() from here would additionally switch on the banks + entry.S deliberately leaves off. */ + + for (i = 0U; i < 3U; i++) + { + tcm_bank_t bank; + + tcm_read_bank(i, &bank); + + linflexd_puts(bank_name[i]); + linflexd_puts(" base=0x"); + linflexd_put_hex32((unsigned int) bank.base); + linflexd_puts(" en2="); + linflexd_putc((char) ('0' + (char) bank.enable_el2)); + linflexd_puts(" en10="); + linflexd_putc((char) ('0' + (char) bank.enable_el10)); + linflexd_puts((bank.enable_el10 != 0U) + ? " enabled\n" + : " off on purpose, see entry.S\n"); + } + + tcm_read_bank(0U, &(tcm_bank_t){0}); + { + tcm_bank_t atcm; + + tcm_read_bank(0U, &atcm); + atcm_ok = ((atcm.base == S32Z_ATCM_BASE) && + (atcm.enable_el2 != 0U) && (atcm.enable_el10 != 0U)) ? 1U : 0U; + } + + if (atcm_ok != 0U) + { + MARK(0x21); + linflexd_puts("T3 preloading ATCM to establish ECC check bits\n"); + tcm_preload(0U, S32Z_ATCM_BASE, S32Z_ATCM_SIZE); + + MARK(0x22); + linflexd_puts("T4 write and read back ATCM\n"); + { + volatile unsigned int *first = (volatile unsigned int *) S32Z_ATCM_BASE; + volatile unsigned int *last = + (volatile unsigned int *) (S32Z_ATCM_BASE + S32Z_ATCM_SIZE - 4UL); + + *first = 0xA5A5A5A5U; + *last = 0x5A5A5A5AU; + + linflexd_puts(((*first == 0xA5A5A5A5U) && (*last == 0x5A5A5A5AU)) + ? "ATCM PASS first and last word hold\n" + : "ATCM FAIL readback mismatch\n"); + } + } + else + { + linflexd_puts("T3 skipped: ATCM is not enabled as expected\n"); + } + } + /* --- MPU, then the GIC ------------------------------------------------ The GIC needs its region mapped Device nGnRnE (Cortex-R52 TRM), which needs the MPU on. Markers around the enable: if the console survives it, @@ -453,6 +525,43 @@ void bsp_main(void) MARK(0x16); linflexd_puts("M4 GIC reachable\n"); + /* TCM again, now that the MPU is enforcing. The TRM requires an MPU + region per TCM before it can be used, so this is the check that those + three regions are right -- an enabled TCM with no region faults here + and nowhere earlier. */ + + MARK(0x23); + linflexd_puts("T5 ATCM still reachable with the MPU on\n"); + { + volatile unsigned int *p = (volatile unsigned int *) S32Z_ATCM_BASE; + tcm_bank_t atcm; + unsigned int answers; + + tcm_read_bank(0U, &atcm); + + *p = 0x5A5A0000U; + answers = (*p == 0x5A5A0000U) ? 1U : 0U; + + /* Both halves matter. A disabled TCM's range is serviced through + AXIM, so memory answering there says nothing about the TCM: an + earlier version of this check reported every bank accessible while + two of them were disabled. */ + + if ((answers != 0U) && (atcm.enable_el10 != 0U)) + { + linflexd_puts("ATCM PASS enabled and holding data under MPU\n"); + } + else if (answers != 0U) + { + linflexd_puts("ATCM NOT TCM: address answers but the bank is\n" + " disabled, so this is AXIM behind it\n"); + } + else + { + linflexd_puts("ATCM FAIL address does not answer\n"); + } + } + /* --- interrupts ------------------------------------------------- Bring up the GIC properly, enable the timer PPI, arm a 10 ms one-shot and unmask IRQ at EL1. Then wait and see whether the diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/entry.S b/ports/cortex_r52/gnu/example_build/s32z280_evb/entry.S index bd7bdac10..7b48ef459 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/entry.S +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/entry.S @@ -235,6 +235,65 @@ start_a32: mcr p15, 4, r0, c1, c1, 0 isb + /* TCM: program the bases and enable all three banks, here at EL2. + * + * This is at EL2 deliberately. Writing ENABLEEL10 from EL1 works, but + * ENABLEEL2 is silently ignored there -- measured, on both BTCM and CTCM: + * the base took and bit 0 took while bit 1 stayed clear. The TRM does not + * say so outright, but EL1 being unable to change what EL2 can see is the + * sensible reading, and doing the whole job at EL2 avoids the question. + * + * ATCM boots enabled at address 0 because CFGTCMBOOTx is tied high here, so + * this also moves it off zero, which makes a null-pointer write fault rather + * than quietly land in tightly-coupled memory. Each base must be + * size-aligned (TRM r1p3 6.2); 64KB at 0x30000000 and 16KB at 0x30100000 + * and 0x30200000 satisfy that. + * + * SIZE and WAITSTATES are read-only descriptions of the hardware, so the + * values written here keep the bits the banks already report: ATCM 64KB with + * one wait state, BTCM 16KB with none, CTCM 16KB with one. + * + * Nothing may READ the TCMs after this until they have been written, because + * ECC is enabled on this part and the check bits are not initialised by the + * core (TRM 6.2.2). bsp_main preloads them. + */ + + ldr r0, =(0x30000000 | (0x07 << 2) | (1 << 8) | (1 << 1) | (1 << 0)) + mcr p15, 0, r0, c9, c1, 0 /* IMP_ATCMREGIONR */ + /* BTCM and CTCM are deliberately NOT enabled, and this costs nothing that + * matters: the reference manual describes TCM_A as the bank "optimized for + * small, regularly executed code such as interrupt service routines or OS + * kernels", which is what a TCM is wanted for here. + * + * Enabling a second bank on this part removes all measurable data-cache + * benefit. Measured, five configurations, one variable: + * + * ATCM only cache gain 24% + * ATCM + BTCM cache gain 0% + * ATCM + BTCM + CTCM cache gain 0% + * ATCM + BTCM at another base cache gain 0% + * ATCM + CTCM, BTCM disabled cache gain 0% + * + * So it is not a particular bank, not the bank's address, and not the ECC + * preload -- it is enabling a second bank at all. The benchmark buffer sits + * in non-RTU-local SRAM at 0x31800000, outside every TCM window, and the + * cache still reports 16KB with 4 ways and 64 sets throughout. + * + * No erratum covers it. Checked the Cortex-R52 errata notice + * (SDEN-857344 issue 19, all 25 entries) and the S32Z2 mask set errata for + * 0P91J; the RTU and R52 entries there are ERR050509, ERR051107, ERR051153, + * ERR051441, ERR051613, ERR051614 and ERR052126, none of which describes + * this. A shared RAM pool between the LLC and the TCMs would explain it, + * since the RTU has a last-level cache that "allocates ways to specific + * domains", but that is a guess and it is NXP's to confirm. + * + * Enabling them is one uncommented line each if that answer arrives. Until + * then, shipping them would trade a 24% cache regression for TCM this + * example does not use. + */ + + isb + /* Let EL1 reach the FPU: clear HCPTR.TCP10/TCP11. The R52 always has at least a single-precision FPU, so this matters even for a soft-float kernel if application code uses it. */ diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/mpu.c b/ports/cortex_r52/gnu/example_build/s32z280_evb/mpu.c index 33d909c25..097b2dd0f 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/mpu.c +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/mpu.c @@ -352,7 +352,34 @@ static void build_table(void) mpu_regions[5].mpu_region_attr_index = MPU_ATTR_NORMAL_WB; mpu_regions[5].mpu_region_name = "ext RW NX normal-wb"; - mpu_regions_used = 6U; + /* One region per TCM bank. The TRM is explicit that an enabled TCM still + needs an MPU region before it can be used, and that an enabled TCM always + behaves as Non-cacheable Non-shareable Normal memory whatever attributes + the MPU carries -- so the attribute index below does not describe the TCM, + only the permissions do. Kept as three regions rather than one spanning + 0x30000000 to 0x30203FFF, because a single region would also make the + 1MB gaps between banks accessible, and those are not TCM. + + Left executable on purpose: the point of TCM is deterministic access for + code as much as data, so an image that wants a TCM-resident handler can + have one. That makes these regions writable and executable, which for + tightly-coupled memory is the normal arrangement rather than an + oversight. */ + + mpu_regions[6].mpu_region_base = S32Z_ATCM_BASE; + mpu_regions[6].mpu_region_limit = S32Z_ATCM_BASE + S32Z_ATCM_SIZE - 1UL; + mpu_regions[6].mpu_region_ap = MPU_AP_RW_EL1; + mpu_regions[6].mpu_region_execute_never = 0U; + mpu_regions[6].mpu_region_shareability = MPU_SH_NON; + mpu_regions[6].mpu_region_attr_index = MPU_ATTR_NORMAL_WB; + mpu_regions[6].mpu_region_name = "atcm RW X tcm"; + + /* No regions for BTCM and CTCM: entry.S leaves those banks disabled, and a + region covering a disabled TCM would map its address range to whatever + AXIM provides there, which is not TCM and would read as success. See the + measurement in entry.S. */ + + mpu_regions_used = 7U; } diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/platform.h b/ports/cortex_r52/gnu/example_build/s32z280_evb/platform.h index 64034344c..984b4370b 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/platform.h +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/platform.h @@ -74,6 +74,21 @@ #ifndef PLATFORM_H #define PLATFORM_H +/* TCM bases. The values the S32Z2 reference manual documents, which the core + does not use until they are programmed -- ATCM boots at 0x00000000 and the + other two boot disabled with an UNKNOWN base. Each must be size-aligned + (Cortex-R52 TRM r1p3 6.2), which these are: 64KB, 16KB and 16KB banks at + 64KB, 1MB and 1MB alignment respectively. Programming ATCM here also moves + it off address 0, so a null-pointer write faults instead of quietly landing + in tightly-coupled memory. */ + +#define S32Z_ATCM_BASE 0x30000000UL +#define S32Z_ATCM_SIZE 0x00010000UL /* 64 KB, 1 wait state */ +#define S32Z_BTCM_BASE 0x30100000UL +#define S32Z_BTCM_SIZE 0x00004000UL /* 16 KB, 0 wait states */ +#define S32Z_CTCM_BASE 0x30200000UL +#define S32Z_CTCM_SIZE 0x00004000UL /* 16 KB, 1 wait state */ + /* Memory-mapped register access. Kept here rather than per-driver so that every peripheral in this BSP goes through one definition. MISRA C:2012 Rule 11.4/11.6 deviation: casting an integer address to a diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/readme_s32z280.txt b/ports/cortex_r52/gnu/example_build/s32z280_evb/readme_s32z280.txt index d46dfa721..47723c165 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/readme_s32z280.txt +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/readme_s32z280.txt @@ -87,8 +87,40 @@ model and not an R52 at all. ATCM needs 64-bit aligned stores where BTCM and CTCM accept 32-bit. Using TCM therefore takes more than setting an enable bit. - The DDR window at 0x7A000000 is dark until DDR is initialised. Both TCM - and DDR are absent from link.lds for now. + entry.S now programs ATCM to 0x30000000 and enables it at both exception + levels, at EL2 -- writing ENABLEEL2 from EL1 is silently ignored, measured on + two banks. The boot image preloads it (ECC check bits are not initialised by + the core) and proves it holds data both before and after the MPU is enabled. + + BTCM and CTCM are left disabled on purpose, and that is a measurement rather + than caution. Enabling any second bank removes all measurable data-cache + benefit on this part: + + ATCM only cache gain 24% + ATCM + BTCM cache gain 0% + ATCM + BTCM + CTCM cache gain 0% + ATCM + BTCM at another base cache gain 0% + ATCM + CTCM, BTCM disabled cache gain 0% + + Five configurations, one variable. Not a particular bank, not its address, + not the ECC preload -- enabling a second bank at all. The benchmark buffer is + in non-RTU-local SRAM at 0x31800000, outside every TCM window, and CCSIDR + reports the same 16 KB four-way cache throughout. + + No erratum covers this. Checked SDEN-857344 issue 19 (all 25 Cortex-R52 + entries) and the S32Z2 0P91J mask set errata, whose RTU and R52 entries are + ERR050509, ERR051107, ERR051153, ERR051441, ERR051613, ERR051614 and + ERR052126. A RAM pool shared between the RTU's last-level cache and the TCMs + would explain it -- the LLC "allocates ways to specific domains" -- but that is + a guess for NXP to confirm, and worth raising with the other RTU questions. + + Losing nothing by this: the reference manual describes TCM_A as the bank + "optimized for small, regularly executed code such as interrupt service + routines or OS kernels", which is what a TCM is wanted for here. Enabling the + other two is one line each in entry.S when there is an answer. + + The DDR window at 0x7A000000 is dark until DDR is initialised. TCM is still + absent from link.lds: nothing is placed there yet. 5. What this image reports diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/tcm.c b/ports/cortex_r52/gnu/example_build/s32z280_evb/tcm.c index 44f140e91..a2b9dd68a 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/tcm.c +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/tcm.c @@ -152,3 +152,111 @@ unsigned int tcm_ecc_enabled(void) return ((ctlr & MEMPROT_RAMPROTEN) != 0UL) ? 1U : 0U; } + + +static void write_regionr(unsigned int index, unsigned long value) +{ + switch (index) + { + case 0U: + __asm volatile ("mcr p15, 0, %0, c9, c1, 0" :: "r" (value) : "memory"); + break; + case 1U: + __asm volatile ("mcr p15, 0, %0, c9, c1, 1" :: "r" (value) : "memory"); + break; + case 2U: + __asm volatile ("mcr p15, 0, %0, c9, c1, 2" :: "r" (value) : "memory"); + break; + default: + return; + } + + __asm volatile ("isb sy" ::: "memory"); +} + + +unsigned int tcm_enable(unsigned int index, unsigned long base) +{ + tcm_bank_t bank; + unsigned long value; + + if (index > 2U) + { + return 0U; + } + + tcm_read_bank(index, &bank); + + if (bank.size_bytes == 0UL) + { + return 0U; /* not implemented; nothing to enable */ + } + + /* Size-aligned, per TRM 6.2. Rejecting a misaligned base is better than + programming it and discovering later that the bank answers somewhere + unexpected. */ + + if ((base & (bank.size_bytes - 1UL)) != 0UL) + { + return 0U; + } + + /* Preserve the read-only SIZE and WAITSTATES fields as read: they describe + the hardware and writing a different value there would be meaningless. */ + + value = (base & ~((1UL << TCM_BASE_SHIFT) - 1UL)) + | (bank.raw & ((TCM_SIZE_MASK << TCM_SIZE_SHIFT) | (1UL << TCM_WAITSTATES_SHIFT))) + | TCM_ENABLE_EL2 + | TCM_ENABLE_EL10; + + write_regionr(index, value); + + /* Read back rather than trusting the write. */ + + tcm_read_bank(index, &bank); + + /* ENABLEEL10 is the criterion, not both enables. Writing ENABLEEL2 from + EL1 is ignored -- measured on BTCM and CTCM, where the base and bit 0 took + while bit 1 stayed clear -- so requiring it here would report failure for + a bank that is perfectly usable at the level this code runs at. EL2 + access is arranged in entry.S, before the drop. */ + + return ((bank.base == (base & ~((1UL << TCM_BASE_SHIFT) - 1UL))) && + (bank.enable_el10 != 0U)) ? 1U : 0U; +} + + +void tcm_preload(unsigned int index, unsigned long base, unsigned long bytes) +{ + if (index == 0U) + { + /* ATCM: 64-bit stores at 64-bit alignment. TRM 6.2.2 is explicit that + STR of a word is not sufficient here, so this writes unsigned long + long and the generated code is checked to be STRD or STM rather than + two word stores. */ + + volatile unsigned long long *p = (volatile unsigned long long *) base; + unsigned long count = bytes / 8UL; + unsigned long i; + + for (i = 0UL; i < count; i++) + { + p[i] = 0ULL; + } + } + else + { + /* BTCM and CTCM: 32-bit stores at 32-bit alignment are enough. */ + + volatile unsigned int *p = (volatile unsigned int *) base; + unsigned long count = bytes / 4UL; + unsigned long i; + + for (i = 0UL; i < count; i++) + { + p[i] = 0U; + } + } + + __asm volatile ("dsb sy" ::: "memory"); +} diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/tcm.h b/ports/cortex_r52/gnu/example_build/s32z280_evb/tcm.h index 0c90f71e0..b47358f26 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/tcm.h +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/tcm.h @@ -114,4 +114,38 @@ unsigned long tcm_read_memprotctlr(void); unsigned int tcm_ecc_implemented(void); unsigned int tcm_ecc_enabled(void); +/**************************************************************************/ +/* ENABLING */ +/* */ +/* Constraints, all from Cortex-R52 TRM r1p3 section 6.2 and 3.3.94: */ +/* */ +/* - The base address must be SIZE-ALIGNED, not merely 8KB-aligned as */ +/* the BASEADDRESS field's width alone would suggest. */ +/* - A disabled TCM's base address is UNKNOWN, not zero, so every bank */ +/* must be programmed explicitly rather than adjusted from what it */ +/* appears to hold. */ +/* - "Before using the TCM you must program MPU regions to cover the */ +/* TCM regions to give access." An enabled TCM with no MPU region */ +/* still faults once the MPU is on. */ +/* - An enabled TCM always behaves as Non-cacheable Non-shareable */ +/* Normal memory whatever the MPU says; the MPU supplies only the */ +/* permissions. So the MPU region's attribute index is irrelevant */ +/* here and its AP and XN bits are not. */ +/* - With ECC on, every location must be written before it is read. */ +/* */ +/**************************************************************************/ + +/* Program one bank's base and enable it at both exception levels. Returns 1 on + success, 0 if the index is out of range, the bank reports no size, or the base + is not size-aligned. Verifies by reading the register back. */ + +unsigned int tcm_enable(unsigned int index, unsigned long base); + +/* Write every location of a bank so its ECC check bits become valid. The store + width is chosen from the bank: index 0 is ATCM and needs 64-bit stores, and + the others take 32-bit. Must be called while the bank is enabled and + accessible, and before anything reads it. */ + +void tcm_preload(unsigned int index, unsigned long base, unsigned long bytes); + #endif From 1491705269ecad83f01edfd28f6b2491e0ea2ff8 Mon Sep 17 00:00:00 2001 From: yf13 Date: Sun, 16 Aug 2026 04:39:37 +0800 Subject: [PATCH 045/181] Removed a few binary files in source tree. (#403) This drops a few archive files from the source tree as they belong to the toolchain. Signed-off-by: Yanfeng Liu --- .../sample_threadx_module_manager/libgcc.a | Bin 1525572 -> 0 bytes .../iar/example_build/stm32f2xx_library.a | Bin 700392 -> 0 bytes 2 files changed, 0 insertions(+), 0 deletions(-) delete mode 100644 ports_module/cortex_m0+/gnu/example_build/sample_threadx_module_manager/libgcc.a delete mode 100644 ports_module/cortex_m3/iar/example_build/stm32f2xx_library.a diff --git a/ports_module/cortex_m0+/gnu/example_build/sample_threadx_module_manager/libgcc.a b/ports_module/cortex_m0+/gnu/example_build/sample_threadx_module_manager/libgcc.a deleted file mode 100644 index b2d68d687c1bca75608bbb991eab68c73225a150..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1525572 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 z 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 z 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%0DYW z4y^ilmm`9OyunDsN3?CuDL?vyOSa~W*e%-foIqRD2_lxEHr#Jiozd1%j(4OFc?HpO z#xhg61Z6Pb5Xzwngb?U_RlGrWUeWGafntb?S1 z!jPmv+yJLiDMRS6W`z$&WV*N3W;pHp&eb7kfqhWh2Vq}g?8D*1j&r6|`R;Son>W4r}GZ5?&|2wfs)g%4%_c~?NWZ5{RZBO{MF z+0M)#9MS%vq!s@^=3jf};KNMC+!qVih{DW+g=+$6hnS0@4wWC*BNoxMA}bT+5_bv8 zQaJ~AbVb*;z%D55REeZrdpPrOp0vwEnJZLsnPFKL`8G@9X$h7wat-Cmj~mK)i{iJD zTLU}pMp?>2{U8k&W_BcH{&Hjma&oXPk)2CExi?F+mJi47)|a~~+g|QkzDJf!XEw^A zaQ4>;r?eh=CF-7(ZArk{QXfbN{FcVP%NC+2P==@4fCDWIc@e35;fZwzYN?aqiFK`Y zId5gZ{)NcA^3qt|v6jI8bE|?x0ToB%s=|<@^v{s?n>Pbmg-VnDqF*_`1?LF zHF&THb!v)k1>r-=Hc-8(LT$Bxw>Kax3(EcgpP-2LFYTwsY*S>Fnl|C)yH=6X> zgY?-89sRPcVEP>Bsz9AR&{ZjaFBIPfYUsrfY?g~)A}A@_2d332NGthV`}Nn@QmxE8 z;6An14R|XDDMfdrRB#b`fR!@NCS~pZ<9a*Y_N3E)*eN$V!B7Sd<;#9yB>M%V3Vmj} z(2cEuYEiQUTLbgly-%DKJXngD9>X!*}j z-hS3qvFBfnxB)aECgygqkIU|0`#yW!jpa`?-cwq5bbLsTjcnR6|H;Nd}#+L8E$9BX8CnA&AV8?ld+@k%n^RHxN6!&t^|F{Gh=e>}%z+ z(8?LNYY$qtM4cmJ8HI)fw#E^(#?Zx38+2W! zNf!Z^h;+$tUB;_-!V!!f_)ge$87W=b;gTm^GF_Kk^-g9)w&r{*%XM?mrZR^EQ9RXh zRQdK2Ou(ZgV0CkB-kNP)mx#(W_n>Y0?3yWqo_&2=UL^kP>oYALWIy!oN)zLwD2U-qNvf@Xr2VM{5h01=^l8?I= zBTdrwjPJkRo>$TI{nuOaTJamrJAhxThinv1#l}4JZ^46k=-)2s*d5F}9<7el+y>+b z?&`foL~0Io6}49#9o1O%=FM;CHoSlkW|ZaDyzu(>L}b$_+&5gYDQ~UFZQs}a`n=&c zZ)$)2`ivJg%@@Nv!x_1ohp!!*^M`$Bh=HF#2!@X<8@M^Qp>C8I_uW^AF6el5=#_!7 z13&S|sE4C}Jo)~&!Z&8Tm33$4Tj4w5dShVRr~es=emOd@o^rYC#5ljitVAAqo#GCJ zRb*rgKYs1-Twhq1AI%*r?U+i7tKPij-?nctuf)sZ4l#DkJ@ysdlv5P9NW_m zj1-%5>w}4jGQXI96`NOxyv|RE*3Gwd6=84E&7Tmv+mX5%WjAjYyLrp?fz8X;jve%e zeb2x)a`iK>&&{jA@Aabf>OFWfR~)$d!)vGH{&n9^wlcTFWk0$4S>(tz)?;T|SAjUG zGa$BgjS-iuotg9Zea``9Th|%lIrzP;Yb+>b$AJpa@u1rvJwc2>Y1!6QC~oV*@=zPY zR1SWk2sqm?o^M+#2DR^_{Whc)IOG>O5j?O1Tn@Sa`jpt6RrX&yZtE(Q2qGM*J*eM{ ztQB9XJen1iHu7C<<3wtIw)VW7?tPK9rDc)Y+q$rOQ2H`m9O{a?`EY!9qmeH1oWwwRysBXw=+tUzf3#Ir1 z<~L!^-uTl+kMBTepqj!FZMo>x{oj=8dpWm2`Q5%R6W_Av4a@GvcdHmb@WE&Sdy!bV zfF`o`SFwsXL5v%C3`(i>Xs4mvd}SrS7566sUmVfdvN?d#EaKrZ=!)okq=i1`rRY)2 z7{h$kW{Kp8;xlqYk%dr4+N$v-8^qTHc3|O)BDXEe{i0>-7;Fp6p2VPqQ+#ta>MuBq zQ1K-&%=68ORG*UNe!(t6{a82Z4f*}>ha<$~INkgGxIm-%zaM8Cd*Aot6l34x`_WP3 zCZYWCe?k5bzVkcB`vrM-*IcMB54<$N$w1a(iS)#~QGVUDfF za)fG+2p&pAQ6^H26N~itx=8kc_AJA#iTD~Eg=(9HlGISHXOE3rH%*a9I>jC6S{;`Zm z-RMsFT~B$|xm@PMHr|SyF;3N~fcW9QjER8`%v~jZxUU;eK}RG4P6_JSu_d?d#r%}4 zoq>mj?q>d=B`pjbY~OcPB5>z-U*9$aw=UdS5a%r9tmg)X zb%fvx=W)zT%$o9$o_Vor*kl>52?w7>h-0f_sFi`XY#l!HX3tO!F`-(eL$ykWs#b@p zmTgHE`hZUK8)0mG!EUz+;`S`W-rsYmdXS}SEqjhm_8fC}GA-4-6=t&JoG0dO&_-h> zK&5R!rhxf|Wyl~<`8s#PQ0LG-I0LQPH;<^$WWIQ+Oi}ufnTU%3zDEjIkqgWA=Gi&j-7NPQbI7)v zEm4WiL$ogwFpJwU9;MmQ?Kj)q)cKjJ70%S*a;k~Td@hn&U#pI{6z9k0tv!@Iv@;MC z6SEJBNm(8FXe-;Z^Ev|}C>D)={fL+tM485Wa&GFh*n_f+QPU?ix=tLcP@-$|Iu{HM z91NgsL~Sh`&_TRYVoTQ!wd@y-K6Zq5w?&kX0r;4CFyv&68y$PR7V`-S`W{8QE}W>g z3nW;kr3P7~5Y`pO^P7&oy?KyNQS=r-C>Rs_G!WwI8x3{=C!p4)b%2|}CKwf1#3lgoMInLa~0nh=?If+Oha5&eQ zou~jE=*&nQ03GBMCnCYX;la+7Li@ z1wF|*DRBUFgfk=&$p{=i*%_Fq0L^!@6Rn^l(ep&I0*6m=)Qm^`=|FdPi`HE0rbQ%~ z7H8zf?n7Fr9D~-{+B~Enb<@7{JA)I%X;iXX^FG^D6MPZ7(7~LZ; zh8(Y6lG%aXZMj7)oM##+(_t9WgXxmT^Z*@<^q}i&Psbl`MQbOVMw!`@a}pTs z2$lhRbW(y@iD+ob;W%2~AljCmvn8sHOf^Cpj(I>cW>r#QwivfDx%evP>cd}Bj4tP=7+s#7 zVsu%Qa&$RPmRyb<@g;p{c5uk?t$~Y=LdV^1XmdWkH5w=ryDvVPS948uV0XZB54i3D z={~!fZQLN)7sMami4hOmIgWa&<;Y+l(!k%3>6Owx>fg>3_3v6;{|0i#2W7L_SNHhs zuEte`aj_eEX?2TOjqw)BHQL0>Ir5UN;w5-$k?rEecxsm|^* z&H&2cX`~aTtJQ9XQ4fXK)5348yp~9!`(Nn8JpV94dEZTDKxCB$h424-shcyY)iZNN zkoWev|M6D1Iw*YqVVhAI6z=~Ne85r2AnGY28Wiq-ypZ%0I(!J=hD?XaeKXvKQ9`Oe zyp;)M7WRKw1@e@>(YOi#IBlUw&~KsTGYf+lCMN$gh>FKkq$o(WK0W^@{R_D-(@v>O zl^Rto50&my`5Vj+3jBv`hK-tvuk@z0*CQb{w5Io4h(eaG>ct6Gf&3<(wIa$}0&|Bo ztr)gp!LX*d{4F1L9cCj%Fkc^^JXya78sOtT9{7U!x;{aNW*#F;sZa)w++WWBQhBC4 z0d=?5p>x01n~GyO_%C=SQ|fmZqIKeYL+ivDh3=Q`j|(x8bidY{ib3sJbUhOZ)%8u?@h383Yu!l!_6t(H|7%jb z_ghlL_xGfGguE7#@BfMX93hU7B5;2p9VEnGNzcVmRMJOqM1&N$$4R3?yg{0+t})|X zXa6Gq6(RmjIuBKgGzUQlfIf&XF4FlZ|D*%(pA_#6B1K{iCM`$Skme!@NxzDtW~3-| zCzB#vqezECXB6rAI95!G%5w&3CW-`U7Ro>A7m#J7i1%5f_dp*R>4nfEOgaqZpA_jd zoAe&2n<8BdJ;J1@j8W1Mj?s`t5JXbQFCq;CiWG%n2`T(pO8O;~f6{xPw~Q2(;!;x7 z*OjCwG#@2JCE@X8#;2APxT{Hl(?EKUIwnJfL~F?-9C6Z*2*G2_49{j#RIaN@@&2`> zpNF1cQsA_ZRtd3<6ye=Tx(Y|4Ns(SRlh&d9lOo-2BgOllCB^%9kgi7gCq?UA-6AlF z2>KN21L?<6A4pN(c?_G4$6rWMu8)y!!_jHd2ca{cbh{8-U}gFJ7wImPe^Qj&LXdR3 z7ZgL+peUewN$R#dRd*$)^bc~P3y9V;h#EO;^Y-i=k)2t)!mXJ%X519|WRShrn$W<& zu&dE5iQsA4qf!0yXtL!Ik399_QS;nku~3=u>vZkc=>GY|G&ROSI?o$+b*e};20y9e zRG|HFPTZfRefe|0_U8=k&zS!CgJf{c^?0JX=*W(&o#9=Xtr<6lZbBBxtQn`_$DTO+ z&3(X6(D38?2XE&F5A*es8}Z;?ok}Q^(-DjyUOds-!QRrY9cOCDN&SOFxp2)MG^+E4 zZR%N&WYSO39-x@_C(I}iuDJzImeOMk8L!cU#cQP(7@5grnc6=u&@i}$?^|QiEtl$X zXt9QdKm7?k%9(4PlsS9N_N*P@ote8bT0=L=hGS*$=fkd%!Jnr6DCwUcs4A}E(Mq2( z>$$_$2fsD!W73DSwGXrV=L0$)*Pv+2JirA9x=x*=LFe=jl*woePptOR+|>nJbfG^_ z`*Uvp{ILU%R?-*vxf(Qj;-DBx`9RAw=)4mL?HSSq8g%}NgZ2#RLJeBpKTwQbT*D%+ z8xqt_Sc}x)|u1Utx63S8LF!69=u3$pBDZVj)9Xt3g-w4|JrJ0BsWV zW66plf$KGJUH^dDq8W299;}p|JFGdlShpQlYIJ-k^(WubL~qdOvHqdk)tlP2dUUak z!SCoU7PBp~+~Gs)M8nSySx@S04nC|?XPriG>>qlrNqEp8{$xIG)L8hm>rY5iVr|w~ zo8AMgYcv)YOGJZ2Uyo@tZnZB)((xe{XM{H)mZrap381hE6$&c z$21k^vjLTA^D&boEVcRIavqcSD2bf=<-C{3xm$G$Iq1)>pgUecri+}fWAcO)U-N7! zD35snDgP8HCV#$1`VBQ{m2;1ptfIavP73ARsdS9co|81R|4-6AP|~mYL8u1gFC^WM z$w197#y1S#lS=aO-u0SqBL#n#rqsL}=eV8;O#pKv=?f$lQpNcRs-X)+jKMEZ3c>jD-yx&5K z@{)_PM@qeRLBwr7DZ;pt_DGNIqBmFF|h_ z>2BzI)AlkiA)m)QMcpbT1%ECn%3z)58%cq8ujaq1`F7BmaZEyL`#+JQPW+n`;f$UP z`b8l=Mhe{PNr7_*DctYK2mL(4OA3BJ=*+9IzH*APKbI8tt(tzG6y@kAq`>%^`(+oD}j~Na?@kzo_}YX#Tk7hmTV7qevltAt}nwN^M`K?QbSU`B`(C zlE0Vq^H_%>y$kgcbO7Qb0`@H!>TV2alaWCpfAp_(45D4cl7XBsmrG^{gS>76Wk6~o zMH-{EkrUo>H41qpSD8>ZP}|`-X`x)GkgGy+_<;TdX(3mAP{!qWWH4!ooQRfv5b6bT zK(FG>Qa45L7Cw|uxjKV#BUf9HzjAd2L6p4;@(s0Duky{;t9<1+^-B8+eN)Ey`lgHv zl`>VXQpgX)N*NWo%1}W056dXYYYfgH{}CBAxk@mO{6}RJ<*L90@~c!A%vFGib!_A&&|%l@tZ{EK+1p5or^Dyk@$Wb-4hZP+wd_xffh6`G9s)$hzI%tZ%L7H9>%mLpB3LprwU8!EPx@`l#mI=ydOT1rV?k`WKOuw8GcQ@RSj)-s zgy(T1v501k>Seiuy0_B+T;NmCBmpwhxSrx&>;2!~y+7CA6PW>*N^vRR5nL+_833jvbjmTQ?z6%yjsYu^dKq5kM|u54}Fd_sqp>_ zax1jEP5gKh<|V^ts(UKDS&&Ny?^X-X(H^J5`x4|>hWy4KzQ0*`W3+H8ynm;OcTrg~ zzHA$5QsI3Ra_PkPaSIRKtu(3do`oF#_b~qWM&>8OSE!{^;pIc_;vQ%{>rsP+H>nT2 zYaq8Q4ZIgDyvcpw{Tgx?q=7eKK{CFwFUC8m;yVj+%hSO7q=hH@@?P-10J)`U;QiIY z!|+I&RN?y<A8Q@YSV>_mG7*rw_a*(!~3>g?DZrc!Mg`WQi7Wi9dgrL(arE+6P`8 z=uHSw*~(y8#ygIqfKvE9Nm z#&bx{%qYvzkV6voF!#VF+p=whTx+KK9t>-H){n2@FJQ?X$J`Ru(5P@% zPZ0J^T9|ma`Ds?aZhk5*DVkO6(7f}_Pd^(geaf6J96S_aJ`Evwk8XbQ-``{@3x+b? z|95YE!hD{UNyoZ3f**)nWGe6mq@AF@K<0AbO#VxtPk?tc&&(^%QWb;lhrq7`f30>u z0{SZW5+o7<^tv(*0$R`zX1E_+HEX4UhY1oO{HI3-ZI@4|K!I@Ht`>_M$7%j9`_>gYw)jF?tk>Smx$xwN4c#JZmjX~Y!MyH zJsbR3iysP}w=|gWo$BT_(;w=hkzcm^B#(QRDE9C(edRk#L_O{ivCzYp`s5>W71x9& zgl6@l9{IC<^4X%%6rkC-LOCF!K@P@+S0Uy85$N#{`{~G+` zc#j{#yfNb#counP8*dO9h`R6%lt)$xx{t-fBj8zt$bSetZ$;uxCi2Vi%=g(wkiSy% z3NK4+1wRq_r}(h=EO;I-F!EmmKLmfb>Gz+-GjHhFsrlc4PlhjByaoQRa66#ghazm7 z5Qn=o&l`;ztoIj!Pri?C?mfT3V;!`y*FxcU?-zMoG8|CMFV*)mr)D6QVQ=1rhfg>nug{j>&qK!uKe)& z=7z@Q4eRPRY-(0FIC!=HL*2c5pN3EKy;hW81$FmUH_U4&)zDhzrq8sO5PjY=_ZB!S9qBC`mXSBFIITxD?F@No68rxIbiPR@P^3T z&f!geb2o?YiUnTH;ky~3SSq5YhJMe@2GFCwyrFijbX;0iM!ou#WfxvhT;5cFmEW?& zwM^EA`Id@)x8!@(%S+Amt{Xg1wX=t{x+%eH?bprk!X#DjyH-9;{kDAyXPX4n|;b^8XH&PI#i#dX#;w(PU`D-{V{Ktt0$64?YlnV{nXk&vutYf zy0}yLJ~rbYDDVG3d4I3U`>9eD=TDT@kUd#vcV#*yLX z8;l2Hgx?DMQW0xcSs3SiPvTY<=Z>yLZBHBvKq>kY$Hol47^yyhRkAbg=W5=;+R!AHvYHr9i2l zp=y|rb4FrM`Ti~;+B4e+7RM^8>qhY{=NZ`&s(F};ftpK;TB5)f_xH?sEgJAb(o zYAfsTmQM8>bgGjIDV48F)@iXA{c@KHg-SCOiZSrt6AF}76$(|>O^8_58KPt;UVA)~8zG#}b}gz7Ohsx;o!fz9 z-B8eSKdx_JdYqm3teYOwksdo({&pAEKD_fUNRe0S@TN|Y9XdrwsgQhPqf$pcv9Yyo zL;3ws#9J5(o;EvH*hpnaTRWp-VvK6tSO;71T!C;&beTr4J?#(M(5Z8LVVhxv?JPHJ z57s`6R8k>RsiZF z4LRO&)mvGE4nx)WLD;ty#c%{1zbKVZWz*Tn^zN(!-$0dSPg1fFk_F<^#j)%de;46b z+vQ zETt{30Wr4EKsK7O#UtAZwThVsRsC0T$DVFOO2!wqH^vv@bog2^=J}mDv84?qolrm; zyR0TBb||*AGm7V5R>v1ArHaUrT};^`neP=fEH`XlhRR%FU1jbl<#tAGBj3T_&OGF% z*Il(cgVBDD5>ObG%{aA`Q_<}iP{AZ(rP2NK<{cc4HuWC|#pKL`bl>~uh}b^we-0I) zo))3R6{DqB&yIYyTey%j7D|^C&ghPJgCi0`wvZ9a$S46{$UdHv7QN18BbobVPJ0b7P5WK35{$_^j%#RH%mjlD!#Il)V=FOs41< z+1Er8?A_P~vDZ^Qmg*VV|HRqXI(VaU%oK!XN=e59YauUN)1sC=2+f|_1X|w2t^``) zf)3>mdqDP%?BS^LoX<%=jQ>NW|IAU@AL>3Zh;(4v7k`=x+(dyw%oSr|2Z0i7C^;Tq zbzeiGAyfv{$7KnenqPKY)SiMqK8XG|)G+OMbQx{&4F1_zcSUCOftb?}F001h4A?&_ zLsN7-8Xq5vL#BK2-gzOY>FZw9I&W$RO90dZ<2NjSM;0t8tBKtxzV+6zV|8O5ee1Q? zMiwlVHs5^f*y|$;D&#ZO;nx-5_gI}H-WoD3KTuL6`A(|;tUMab!-%7LO5*)QKlU`# zki6R64ILp-F+31Ws*MsbnI0`l5vBIX@erklNc}2xLjkRI2*mvlApGzJ*hu{2>=5cAjN8qoR7s^R5tmgdPnmhy`%X8 zwR*&@P($dR$B8wVOXa3%DV$Fpme|lLw>ZgNZaI3#F?&kde*`;TNwJG|JSkR(&LqXl zlSx_8MWE-AA`%Nov-B>53-#(Y0&_m? zv9yI(WMB|wse}kYzz_*XVMsHz-l4I2mmum}4ejB$iWGsaCB@`kj1>3{q{yE&q=@eZ z(h9w#Hc4)Fmf_n>dqnbTQiPL>CAj@u=^dJ?^$sE2H_#sbZ6_@fVh1Vm$RX#;} zzScW5Q;1v1BfoAZMdEyx6#4Xd(m7J4jr3;^c_h|7q`-fG6p8i~Qp5vMIH4j|iuddy zHdq%i6rKJ+p2lEka{!d8Ej%g&kQ5?_!Z)21o@i3smJ;|>4UCF?qQL6BvOmNq zKQhE<8Ttd9i%=SaN~w;F;>%KEq18B1EHoSnt3YEpCys?z71kLV3$0au!iD1J8pex< zZj*W~&>qXkqRBf^P^Smz1PwaAf1q|Fun(ZA8-a-$9Kk)&5Tm_BGT2+B9gN-Ec%T8z}n3e7uRn?+H5NM6ca2r1vCtvU zMVg(!iDc%lJdw-+nsp*MfEH2Ypul6yAkP@SM2Z1|JVTs=GlD1#IiS?~Mfw5;H#0C0 zdWjT&NAZ`l5U0G*rp>_LdQ#YJ2c>-svOGKa2~rHiZYM=s`T!{g7GXT+V8Ah+6#N|0 z3iz+-{hHPRBL@SbpOZpTdjPSZ7-K1GTF()TnypsBFW z0%oWKfI&%-5F7y`E>cq<;v+}42)7)`B3$yY3&JButiY2aRm4$_Op#V{Bnk+5z)n^K zN1ypa8;uc=JV=KTksLW<&>~9;Gl-fahmua#XZ}!|hm%L`k?l1iK7u?VE*k_y9G$T| zD@bA+h@>>gR~0wyO1WoJNHYAaxW;thf!7HzT^4FfhMjGlOe<~oAQGrvCYH9)1bw{v zs?hvEB+Om52iktDPwpWkm>kV(cSF!FNj#Y!czy+PlVm0+37Kzr^vexJg4y1hXTRL= zH04I5DVN`i9NI)rx|{+z6L!YLJTuLicgBo{+{1>k=%skJ<(`LJndNRC>+oPDml%kq zg89kx7^sC1-y3lCW>O{(cnCtTcwbBt?}&vbXA^*!D!%`K+#KznP5k*W4In1IjuuRX zR|dIs@U~ibWBS0mHBG!9S$Jdn!21>C7HD^y_~Yx~JI2I!d>?p4kV^+|lZ98<2i^|I zrBi zkTZBiS}+yf?;w{>eVbH}#KUkwnpAjaLoS{2yxGDtV~SLGJJZDbo`pBFkMJEz6K@bI znMuFWKJZ3EE}i&ZX5rx*Lz-0aU6Ur>0~Vg~pLjRo596k|@&U?8AXjM^i{6RnY>N+{ z0VbgOUo-Y0-hIm2l?OdYz{(jH~@EGe#{@b7*vG^CkUt{sFfxjE0pr31bEJuiu z;IG&GNbm)aXT_m^)4_iMwdrq~KOg+F2;XweF9-h>e7QWJdG4XV2=a?H-wgf{;L%^= z-3s0q?%|hez_mpPiw0k|+&TaKAo!cj3*h%!?%ab9DJx&Of9K0<1^x``!Ony~nd z$30*C75sATDL~4mfC6)m#VF8M{5PC zwgIW7*2?dD?(*i|H`1>@uxko;S6+k`*?M+-hHqD5i$4&!(izYwIkms`+@NH<%Dt@ye zKY^_S|FS0EV#ueko52r7|55SpGUO+-$HCvG$)7Rgh3uE$TkN-k@R2d()7XdL1L!{r zpWd>l%Zu+G{0saUn%rZzWon-@`Tq2vCLddI0Pch_k*qPuT z(d0`F`8>7){2lyF1zGK57aH;scDcbPv8@Kbz%d>qu^$?8KfBN17diC(jD8AN7x_Fq zXYflL`n}k%40$qp%izy&=qIy}40&(1$KcO$==Wy-GUO@v;Z|8k^;PQ7PhqKsybl{{ z@aH=8`>^8-d0%$C!IwMq`?8Y_Ieu~1c>4auLXD?pT;brG9X!3=dmQ5lE#%0j;u`R~ zH2zNTM`OG=S;`*=e--YtB;O96hG-fl(lD$27X01l|5R**w+sC3;Ax>lJRLT3Ht?n) z67jtup!hUr5IV%h{L}5xT&Ul?~#((Wm$7-8md<=SUr2; z0=5u5_JC_nAZow3k~B9rHY>H_in?V|F1$!YYzkJ}xw{LG5-mzlG!zx)RL6ewy2h2& z+Rk}0Ih-wQBab3qWM?}L2bIa)IjGn!C#Khi?Q&u|ZP+d+rq71$a$>qi*e)lge}wIE zVme5K9Znn$Dz@W?!$HM%{BSs^D8~-zpVTThlt6_%|Gp{*zx@Km>4ku=AbL@1@ z?Ai_|4hI$GQc~u0P*Lf^K}EM;xs{Yr-RQ0DYqU9T1|ts>CnT2X*`cAQbVzw zk_vEI;0QM?amqA{lqjmc?I;8r9WFwu+!n3w-t^VoWOoq+5wX5YpQ9O5zayU`n)d(a zZS+5HBNyIAC&Sz5H2kD3yp2kj*dVABgt|)~20DOhEaepDJ{LY$QDgCjdzg+kam4|AD7g9Ssl2|$RO;@l$c{S~iM!JR< zQU8#hqS~)rUQM1uq`Toj36DXZ2*P{l283JbgS&|9w4B7)|FO(~f)Lmqb2F13ON{LzHKv z?wxc&C{lO#E@4@|N|{@h849P+3n{QRzMp@2>+p=qa2kW6q%i|&L~8Gnso44BshAcf zb~M$KA6QehH;@)Oky)B=l`b0;+K$}&;k`!QAnn{Iq?P-GP)$%BP<=oe@&xw57wqe) zsy6B4*Q!SQuG4EY>BDf1S|5rUC0{8~qfbh=kZUJSs#=c^$>3d(bh)Ml4$gxau+q95nLDS)r)+5L>foH z_iPYvRfL;CqYZjnRxq`k?y2X|y{H8%kQmZi&hxv!T!#;*&sx7diH`*%*dGq0x3U2F z!`yh_v~AD8`^DSw3_J=8yKYBYO6VX@pQm=PN#xgc{f9T&BgEBcPn*FZ7RC$@dL5q4CW5t20r{y@2FRd*=?&zMZRrl03co=d|VF##W8VkGH zT31sYbgbsBET!`R#)n>=`RI=Y7#s3YtNE1&;01GF(*cYSBRWM|iJbz!mE#x9q_&mM zTcYr3ob+Kn+Qm=NE}jO$)0GF%x(;ma2oXkZ2kCnZ{Ubi?F2!ChQ~XCLT8gjkqTCgB zUEdmM;|Eb=TpH5Lqc<-PKgwh3@B)mNR3_olILf7M_p6keL^;gi<&Yhv9IgvRPswd5 zG>4vsr9Z7K;C))8wv(5^fX>JgI6I2AsNaDO?Zl4N7-v0fHOAROo|{Jx;OnILS2UBx zTvhi%FTnLCV3wm+n{W3pfjta8Y^aSV!g}-eL_O^U^e)l1#69EvK=d@~5n_x+PuraO zgqMAv_m49Tf6;~T7gaOuT-b0KxB>V}NSGk!=(v%5T0QuC)=ykJmZ{Wd~($w=9vC`{_Bf10L>-IauzY? zkTIb{%|zr!S<+RG(X$vipm~VKMCYs{^49cx6Me)59&M+USQGsn(5cddx*gk4Ym_DNy&Dug?b?^X?qXq<&bMR*}lXq z;%?@r{AJeps{|FkyP5Ei{o?A3VCvo!Pv-Ir?jPHIU5Fa<$Ql#gerAhXWwf|Pt;N+u zv^dq)XodRi+grgQ+Z*M3h0Om7=^?y=@_)^a<-7!}CRh2ljQnGUo~q_&7QhVK`ZVU{ z6gdMHc5Q8an$H$Iv$1FhUc|sJ9m{;?7 zo`U81vJ@#F`Lb6KEs<*lf$5Q$)QX7H>Zo^)n)7mH>W6^p#I%~*7*LjYdSo{j*wwVdCV^ZS5I6JE9G@ghyS4?oS3Z}PgC z=-VS%+WQAs#t(x-x~wF+J3ILEFItBV?XvvD-4?v3*Pt#dfgRtgv2^2oUl1I^MAu`@J^f>W!MqbEl zE6xz%_LSGN^!}YR3uNIrLDZ;-oq`s}-v{tjXQIIk5^wJM@~ zM%SU1(C-~8FAt;g5-SUy8c&(dDM8A-%nI#tWWFq;9K~$f2eYYoz9CA_HyjV`gfPB+ z*=N*`}iDP@776hf2c3g4Hy#jD-)p$f=$qpUhD>XL`#X11t1a+uK!3 zr=Ciws}@bElLvn65yBI5G@#Zm&q+Wjh47pk+C1=iy$({}7Uke3k0PGX&wO6h<)L_L zD^x=&g%acot&ER0new!tXs2CdW8K}#PrF#!?P(X(QbT-A!rw2TZMb<4q`#^12693w zok`uEhH*I3VIgr^M)-^ab;odFH=rd?9gswvW8evR82%@5x*+0&f>gnz@KX&0;{lPu zBCc^HaQv)@s!lEdbb^Q(jxUtE36^$x?MTrOgdv8GCBmYUNTUqvHDev&=_tIO z9K1l=RCKTS0n)#(Kh*{

bjVV#fBrqlBdao7cP^oTJ?+-Qut_Om*_?E^BwEt7Iw%_p>QO6Dp7=&5JmWDL{YvAh&Ia4 zRgIIMV`<`Fo#V!xOY#-+;DtK){SiM2u4hEg=TMBTKTQ<) z&k}{5&k-%e+a03VY4j4&1jb$=3jLi#q5mtQu;ChR?9(k~TaQwxptNg_obP=b6E`Jn_O>bC zb0p4f9vUBXng&f9<_OxqF=>-;b7EV<<=!oTpE~gT3}|^^1y5mEd?_HW_Vp_6xO2a! zLV5QeEm4QZhl-N4uitT0(-j{>EH`#Ue6X;>zFy$4m(YO>n=H>cbY{q_ydXwO>_B|j zhcbDTghiFa(>Qcknz^(Ow{vU9NZ8Tw!Rl>}c1}9JIM1PvlhDV;2aS=`zA%c5V+qDe zEMz^N+(*S4FR?IX#e+4_wn}W4)mI4Fled~&iHiOi52{`}n2QuDhny@S(VF6c z)D8Vx7*ZKpAW`$F9KlvrmR2CPzvb@pMvDw9~}9tNzX6071cU{y=3 zs>6U4lvsFjnMy-XMRmo}8fHzxZBf>w%nX)Tgl)~$t0&IQX1?U4xxGAntp3)3grU}v z)-Y?hHw|Yz)3ZkRX9}$m-l55>;gy3`M{+7-_(6!%NoeN8pCV~K7X8VsI75gi!XJ`! zx1K9487h^r08$~E#$TB5w_hkk{+0_B$vZD9fgkdO3gd6FPze03 z6_Vr=01A@7okBtIj*1L$=Q=*Sp}+F=2o`Ys!3(Rdp(MvbiMk{!!>4FcbQ5jHvd6|nK)`kN80WV}3APGGgQrhY|8U=TQo`4jL2G#X`j0CW*jJPtT9&BY-QYJX{u6L<-gG;@eTGD3^4c-js&4$c*RUtsP?`jQCJ)=ak?+)ml>I4Jt#QRjk z<6{bRqT&4udJA0OothEO?=Yz!4exB|&2)ixr-rBAlSRXO9D3A-oR>4d2Q<79QaKu) z9~~OQWW?pfTLisSXi<9!NbP8NRnT)|-@_VSS`55rUE+DN!uE}hfj0npZraN^8s4!n z@amz5X)5A!mfwRKUV03?pSr~RhlYotfnU+;BQe`u|1E}|s^1AQ@XmnVTq)OyGr#w0 zco;(X70tdUq35Rj_G)-&+TG$=n5f<0odi9VUle7xcypoWrvH9l!^3U2cy~isB;`7B zmft5DUY=BpR(@YX&y9Uka>Mz>GK*i)@a90zjeXZ>c=R5Qu4s5abcy$ohNtQ;8s0wW z%@D~Mf1TwA4_>=|v3%rLG`v~RbAxxKhF2H^?>6YUsgI8|ylFA;_PMlgG8Q1JJx`B; zHw${M@~h#g{6s6i+g##(sNogIuy3zRJa~ZH`NeXdU(xKF2|YLYy+XrN^I z{M)VJ&5L2*0qCjrF4Z`3w&$FJaDGc-;7x~~8@yHxZ$S*atuFC?t>G<-f%kz+yrCFW zRC`_$11}wVZt`2D;hhl!uf-+ab`9^W71 z_@n+4uA{vN8+b8@KXeA(DuYiEpLDUqe6$$_Cqt%P%pL|-2vKahxx=OTO?0s z>OG13c1`}geNXWR@*O`Zwt+se!$<0Pam@IiaX&|s|J8^;gnb46CQZ(FEM3{o=l+NG>lRQ489i|g0ejaveEcQXJ{PdzxOv&ktzU7Ed^E&At{xiIqE9$#F#ETys zgrje?lW=g1PIuo>$2mp(AS3hW9Qr;u4>pf6qEnW5unA9xDe++Qcpy46i3gkK1JTh) zJlH%SC`%=YpRjb>vs9XnBZBBeBMw8Et5WwWNykw@bexe;HZzp1Y{@iplx-VhW+_`5 zV}|BPQ_Otk$TZDt<{(AKp+p&M=EAu}W%K4QSh!&7+%owsaU*QT>Xzz;s_Lq;MK$#` z4d;m?fD8?OtXNuCZ5rXwnbE*i=p>zpZ>I~R zah}o{%c`3r4+i2{lF}%LAZa<~=kySdQ<1bokSHX4pb>G7Gmm7Dsk5NEqN*%2Z>czp zh*Wq;c9t_F-x*+k^qe9&%0ZQtZK^}Al@l)(E;h{&L53Y7NH;`;kR{*YSwl1P^1q|A zhWPOGzr%+9ci2$3hYiu^R{PM8q5PA|qv3jf5`JD42M$eP!l7-@UcVIxk_+Tr!Ldx- zjaq(JFq4(@&_M9cV99}zaOtEEmfsbedLWI##g#iB3WU3Y6+sb?T+WdK{^H>h2MlGv zIld3v+ov#bB+#G`xid~-bjT6(#wT{9uTE`RFuZ>F*(3hBi)7*0;$zh!{z)tWM+#Yi zVaP%ESgEViU0`(|KfNur^}6AY9v)lT(qmwyqFiF-#E;`41{~e%=*UvxAK>M&U6u)4 zB)dmCAlt_=nl(d>IyzW963*51x2@_#_=BK@aCc<0uJ-Yd>rzW2BxTtMt+ryJj>FH! z(NVFo;}sUc*jyl5Hk+*ghjGOe~fSXuK66bowZPs87q zWXQK4_;oCW!n35G6nZbc^`S*|f1-H1h(QFeLF5h!ymc8yJYJ0)MHE{G0z{Ls;wOq% zrN^j}ST*H>$n;Brcj_ zJoXNTjq0KYUhW}7{wBO|(MfpWqSN#gl%8@qXr%%jC_&LF;sHHUnF%UDogaHeUbwY` zdJepVTk8bIaKwSpJ>#($8MQBZ8KC=g4407T**%3MlXS>qBqRofcp%Xb?F*e#Y(vIq z$8#L$ITqev2&_>O3xiNk?Xt1PNGyyl-x>=5JdYUszBSf(iG_jl@NcU{C9q@+-2i9F zn9|7VWK3y=MA1)|5|u-FGN!U=D6ZZZ;EIW2K3f8sjH%=%8GeThe?*42gL*LZ(@Rqi zhWw8x9Elu(X*HSVF>TwV{7@zW@h*}6=aXpyQ9t+FL=^dx1sWCxeLgut#3x1mlLY!b zRQUEv46=L%=4}ubV{qg%Fa|L`>0waglN`n$KB@6ZJB=9gq7sRASqS7dN+IdJ97U1r zK&I{M0PdQQDT<2%fWjMm`lCKyU|0VG4lIk=qa1X4s}1vq4yK$ttJJ> zbvk&eJ9Qn8!l$^-s|o?UO-aG|(4%^yeDXF0N^Nfy{^@#~pj3_oNRPKcspm}h6EwIY z$efom-LYuXDqUoWUzDyBuK;?*Qmzvx-Z~ABw|OW>!@Jfc-uoJ!nw6sAed-b~6Cf(T zY6TGu4{NcS9OxD=8+vZ+Yt-<@#=u+a67N|J4@-@1?faEW zyd-oomEVaP-sQOWYTFftKyQJR>%_TTp$2-bP@wTt%{^2fcjKQvj(-Y03^5Vc;|S5m z=YMN>G*{6@c=#q^PJTeU4z*u_K3FKePI&133Qym_)3Ns}d_kuFKd@inbYweRN#dJ? z?~fKI%Fs9bHbMTm##7~=nJ(Uxko;lrQ^8~Xh6do{-!`()D;p%=0on-ue93z>tq+$Af=Eljj@q@oW}& zpB?67CH6fH4ii}!c=F&AmyZSQdy*f|E&w0)$?>sPL!Qa50Y3nvjEYZ>CF=6BY<53* z@&ptYz5!{-bJ@?pHz$PUI}Q0{_AdAr62tP4AunKm2Y;m+rBJ>H4Ec#H32DEq$y04x zD1RrhW5D~9!uaWi{CjLN_(ht$(2!5Xf#%pBqsh-O=d%6af33;?W60;T6x1zwR*K8V2HSN_<$oF*4Suv*-NXKghI}EL0)DF| zpJB)svqj*^6I0=zW5`cub>JuPCs5K5<)ibfAkWa`mx3qHOmSiVmVtLBFCSfg1LQAg z`sOzd&t^Y@ysvtSK>9y1@Xq1iFI}L?e`CnY*dM{`-{9P3$Sc^F;L~XK=a-KiG~|`6 zFZ#{~O-}7Y=Z8SvrpW`~uhjUlcHg7=s^-!w!2JhlM*ZcTo+A+KS} z!B4PP5kA&p$d|JX;4jqVR~hnpc02fxCcn>+H?pU|ljo``pPw1>73??QztrUK8S<5E zH+WhYtN6TsY5ZQu=V<&_M*LO0ymWao#-fik{ekw_MCE${8wLI>ESOY!6AbwpHU<2v zntX;Kzlbdce;ZBS{PHpS2BNyWI4Y}wu+EU&}Uwe}eyPLa}^ot07;Up=*<{OB8x>hj{8xrN|A z(d4Cu{3=!l-ZN6g!2VK0ehu3Qez+#T+K^w%?f_q_$?rGh-)BDo|FkA=H{?HH9pF>a z!s)+n$Zuqyf*+vC_Zjk=nFn*-P)*+3p8KdgZ)Hb;r;oRb%g06=^4nPs_|cmDBt!l~ zHW&OjO}@mC-^u7SfDBFEXvptoYrzj66;8j+kl)L00)LApztfQ4&mIRqbaXiWGlu*@ z_8RzdP5zc4f0+Fle2XUk%#c6Iz6Sq{CQr2222_5JvBBWq)8r!z`QvO7_|G)?WJCUA zHjDT%Vf#xA`ID?1e1j&hG2}mCYruc3$=4h5pR((~7atqO=i{Zu-wOF0jlTzciN-$) zev!sM1^x_;{~7pFjsGS1a*clre3i!k0en#7cY&|d_`TqpH2&YNB-_Kr) zQGGni#|K@04CLdE3+I2Vq5nK90KY(!7a8)Ov4!BT*W~9I@)ub>_!l(!1%~|RY%}<8 zH2JlL{1tX5_`>wCeGeP*U$AGvpP|WLG338w?|^UC}b=jzhmU zt1{#%tj^%yb?B$Ciw$`nw!z@vcj#kVk|FQQZZr7bJM{aqM+|vC_JqOz!J*%ey==%+ zwY5Cu|4$D6RQ7?P-=BSK@Ed-%e)fw_3ti|9zcjymc8w~kS z{`{uwqqi_OXmVQS-s9k(bnve`_`f>%1UxGh0B1V>(SG!y;QL^{^hushud#4X?@UNu zD0vU~H1yZg!LLOB7rc+vfxiSYS`v}|TJU24&>;C6z;|l$N5J0-K2OSD0RMgHPm%oF z;Qy}4KLx)F>m@qbmGHfI*6IcRk5Yd)c<)H@{)*(;;D3(wBb`=6{5e~RZ7RX$IFAFq|qZ-|Hd1&Q}DcqApuqd)t`;8WQVc($8}ikm0( zCxHJao;Maq`(}dw5b{f5#D zztfNp;-?G!0?!Y>mGVS9>s^jMsq#An{4rX7$Ado&a@8JA1RqYX4=XYF6jllTb?65q zehc`)sKcQ$zn6m_gEm`47N94E>#w|2z2G@qDJrt1sF@Kh&Yh&#~ag zX!aL^{~5}wM8;nNKAhivY=y!1Wm~{61l}o9|4#6uP=-q-|19|1A>SnVPViSjeuw1u zkbEc@nO{03>JTz|%8! z`*CwCo<~&s@uBS>4PK2Ghuxp3rKWp#qD8aek}`K{Np*8gW7Ukhil&v-RpjNtq+n5V z&3Weu#}6JfW6^@Lh1D%ZjSb6c&f_7o7cE%r2%2A%84;2l5t8EwSy)$bel^@$s+%2x zMYA)@M1r#$npTnX$a&Q~=|!`%x)+#ME}HE$V9{*d0Pa6zdI@Fab>~)PJ1v=RRkqKP z!wX4yCzuPS?z9uF9*!<0{uq*UW9MovxYPTsvJezj-R%EHl4(DqV6`)9lYv>1LUq zn$J_|k{6qk~?V-=^iFwEw&pY)&9m5_D^Bg&|-8JprnWx&F-7j%KibQo-79KVo zme~U*^;N?TRcn(Sb)XzO%cvLYG3?eh*todu4Z+hZpUQF;t}@GNlToHESYw>@|jsMcx^ zTLr4M+5=W*22ADA!Xr~=hUzNeK`Ao>$w@txP-ccofDc86m8zX(W;hCu%1q)oO3xmo zGabIynf5Tv2QWPyJFl7Wzc$Lr&T}S>ZAKj10*8BcmOVD}VNZ*br3PoSiDapv+00{> z8ko%tW~pJ>k-aQ6Dm&IdS!z&rWGzdL$&QR=sgc;3Ej18RJUvrt9CoaMveYn4c!s{L z_)JH3)jERGG4y3YJJvv1YQS}@fwI(i>sSM2siD-d2Fjw5)O2FUYDhVUPhE=hr)>^v z@#dDY*^77p9vNn=E}Pa|U9r5VqONXfMdflWyr{9hepL&1O1GsV2A)53Aw7LiYV-s$ ztzu=ha+x>63@371({>WKLriCKJvdUAXU0rgRXZv;qJosbD0dYYSxuTGY7Em(r5#ycrbH|CupmmN zs49($)3vqsUKV-g0kyGN)eUt1LiLREs~f_Nd3I4*QAJbBs^)6D1E^9X5r3pE3RW~U zRM*)x3W1}55fV|h2r~)^d}N7=K&PHrj?jrLLOW0^JszeNoaBu%Q(=0v1*a8PG*s19 zhnw>J?y?SnBkMe*u42s$`JTct$do}IQ8WlMvJ5`5Xhfh>&nz0~L>7%5sO6D|X+ zqi9r^9<8CeWK|u8yXXyJz7jjjM1@D@TuID)sn95;poyZ#ag>PC7v&NyFUF8)XMy)F zO}*swx!vTNB#sPIP()rS&@h<-B6BE1BQ$xz&#Y;vSsBFZFK4r&SZ2=c5TjDVp^m&6 zr69B%!;2lL$28u_IgO(8PUL7(wWOkMRd~|i@6kjfTDYd6GT7YMP;()lckNN7dlh|b zQ}6y%()R3WzFI3PS}jMdqWUWJ-cSv6+N;Fr)#$psr1ck!d;sOK<`-o}dGQxc>$^KE zWkyCu-gk3W3V-$bzoSzAcT`HZN2SoA5#pGXK{&PozvIedQu3KNk#6nZ=>Uwm1G?MVet?gv@%PR68?Zx;6sz}r=NeEze;3Isx)z$S#39Y|n%Yj#!& z+E(@Gj`1ubn7VfYw&8Wv(2+A4WaIwUrc8Xdp1u-I_R?3Pks3;cY|MZ(Iq1&DaGCu# zYm>gj-G^Ce>M)%^5cyASo0ia_?&v5R7Gi<+9cX0;Evzfq&k9Edi>uIXcp1=_?O7m; ze+?Wz@w&w753KImU}0TGIE_QL({S3@kdW@{NJ#J9;ZINPNJ$^uaa1V4TNZuYd}sL} z$t7^EkL3KE^GS}rmAR6GjVO7sF8(S*VNRjlECz$_LFYg#D3NkZmSqk%83(g6}^IUqOC$!BHHTz{WhWIlq^1{ z{I}+!|38dg;gS@&>8@Rr7-L0=F;3yM=bX6}dWz*1LuF6f1IV60LU&?LzBND--?6WZ(1H*H*|9tisr{3sx52 zYSnS*ItuqXVTo8X9OL5om7X)iYS>>+_vuB{#>04raUnJaD3tHiaU$G@R4OSQLp0k&I~LE)BQ^U)xM+2QHGMrV?RZ}yV(QwFc}%2(rY7|6q&%ea z=e=~TB&yq%&_ zp|+gF+GY-hmxb@P8}0X6H;3rnN{798qs1mAbl$TA?Hup6uEb2Y8M4BeEIk3WKe}UR z`t*+0(81yY`P5s0mE%1-M&TTee7x(*vGVy-Z$7;P8vFUx3zaoLhZg-J(yH8l&?jy_T z{guDMuVNoE?e?T(p6~V~A7ayS-u?=iL*xtJG3Qd|BWbHcS}3K3T*}{OYjInpw3SN( zTHMsk)ojO1 z1X^(t#-o9en)?gUMoF`^=J8<39xFiHaUp*MYP&?;3EdYZ>WdWvLT1{~;)tZxZX@nQ zTNL9H*-dZ4BTKL)Y6;RabtX!1X2&^p8Bv=S?=spj7gBDi#nSz{n)Dir=E;hgrZ#^g zCbjvyGI2k)hH^}CCu#ca5`8BSDc5|q!2OF7{l$tQrnY$BCbT)ah^f$bRz%in*OQyK z(~5(R7k^uPNcx1|e>lE8SdH5jzEJ`nV5-5vC9O|MDZ8m#ecr8Y)$bz(=aP|ZxS z9!;?C4(_5it0W)OF*`KAc2CWNSeMW{Nl{`cvcy`k9&4g|tSnkFf|uC$YIP&ReLQ@0 zBob;{l)V$FJSLK}L>Tg%w7rYZUi1!m>&)TIcYF9(nWyA4njgQ)c=-%w1s;)4XoWMk z|D$#7fR63|U~ALxx3w{g?i;7kec1xKFI!6Y^P4+1gdW=`e!&s6t!g|wD*5c;^c&6` zdY{XG!&$+#=p8g^(Hk67OFZSB%eCmuGilMA8&gX>-JQy{=zTM3(Hk36OFY%(3%jHi zy{R#^#M9gu@m^`Uv}?IjD`Pp;@Bm?#)LIdt)x@<9?pnMj3BOFW;mvb<@Qgk1M8Z67 z@n5;ryk|ZWhD&)Mm1g50D%r-tbYFG^-Iooa`}srhdrF9x1KaC%2vDYAy5MXbs{SdX5#lH7KpvtwCwUZVgH+c56^tv0H=E zirpHNmiyN5_16ave(}Y@gZ=s)JjigVcLo3V+l7Z+XU~RxF>!N7zcl3D4FTUGdBK_?m};pUTfKsQG&^W}nfReX=`>LKuhfTtuU1313OH zRbVZ}XP;IY=_;~x4gR~Nts%LQwg$~G6l*8PpgBfxsk#P_Wot;zIc}<%l#LAMZoQGa zKyXtquj>L|-u|_iB{r2)K9+Q(rk~jnNH6WkNH6Os#A?4JeNsnxdR|9UdLQ1Oy|OG^eFtC}wQs*%Q~J>+lhGzq zI{JlDgN68nU2o7<&?L}yP%kK}^D=sVp_oJQ8IY~$5r_Jl`UFe!((jao+ooYQ-P=09 zUkA9r)@i*ZO_J0rDSpjN!>|5nZ|=Zn5j(QGn!Kk32hv*(#2LpCj+2_BBt1sbqa+<7 z=|D;2OmTnV%GZ#hw|q z(ZyX>Vs2Mg;&5wFS69NAqP(tTU;nP;gky^~R``~7iPY2RU6Z#qyDQb}U7AokBY0U& z_Wn>&HgeQ?fVD5&lQJr&E0EB6z~8=TPs$)+9a27J>omR8Q#+_-zZP7y$1^CWt1uyV ze`|H_epY=-&Eh@l6SwfcGs-WkI3>8gGJ&Tp#_fBTixqi#?S^TdPAiaperhPl?>)Fr z4n4r{6L6mp+Kqdw(~tXf-YXdHGVx}Q`jCyoC7JwJYdfsR*iEP%Ys^)J-r9$Yyi0wx z1HQ7p7*XU~+Jv%mk*>4_bu8ZJrFd!=_!lsbDrdCQTm83UchSJ2oGwqomf)ZwD%Z%; z?SsFE^eqKYp!cJ{JYuQ3|H9C5F zsLlPXir41ooc*m;NO3VzTuim;8BDe589bx>=cvt>!l|m3w7+$sXh}%Z*^>6NMY1L3 zbk~v+I*{57-fm-QNhz3<0+^FV zV@{f2%+6ylC$ZWj%s8x8{&Kri%*0)cKXaw>*{C8AOj_D6G_FR?SG}}*Z^#p}LM(J} z7ro&@dmF{Z_-YestNc|gVd;jN9Q0i3Q`C3+7HvSkrM8DU9?gzTtj+C8O{7sHsWx|i z;VRV1nB4tMGs^aOrwrfUG^cb=V&dekZAoQ&tl`7EwxyKrNlMySk;HqSNGYKi>~ETmlydUAw)vLqv5tsH3#~43=_^P}j4?E_ASEDo0U0Un51faTCJf&nsH2o# zktx}>q78}o-P*c8FbfE1P|=2R8at7P(Hn!g``6A` zu*ZVU-eYr%HkMQQxcQIT5260?N(zZx4RNF)8a zP0}=zXqLyNED}gUoXG!C3<<&p+mb`_86IZ;PsM1Irh{WvxS*ZDmiT%Y5)SJ)z7a+O z0TKCE#uf=^$(V&^r9>0yk?7tl8imY>jKY=l`&1qx(iP#6R(&@i_&K9TAKk+19^;ch z{pDwAQmMb;0=0a2a@1OA&ZSA3Z-#G$64ZYDglds8VIkw@QFNJ z6D@wa6C24tIfmm{EOE>}?E4f7qA+R+(X%XeHc^C^5*;tTEX~fb_~|wjUP<8-#cAd2Obf4* zaUq;e4`RqiJ<;RE=~b-MVk?PQ1(aAU&hiJ3Kt|N-@?-Rv??)5}hSnOt^2)~8siQ?oe)?%@3 z#3TGpq9-wS7ttn*-A@$Z4-rLv9wv%He}w2ti#<*h@*PB{GxlSmvn=*BQRL@YqO&db z98s*xo+moPVlNRbw%E^!&X%9uImKeXBp!IL5j~Z$UlE;ai4)Ng-pP5!-Xw}6lHMhX z@b`$KGT-Oa;-`60_@9VBjj<5XQ!Vxvq6ptj6#4m-C@Omo(Rmg>DU9S@#GlF7UZNEi z`;sW~^Dm;67XQjUHI9E1Uxr?T|JhQEPDIaP%tN%wVo5}S=OeX?J@M=Dr2(Qr^dF+Yznv)Xw-E*Y-9&+Z577;be+_`0 zi~d7AjChnN;%z62ct0kJ^qwHP2`9-B&9T@sL<8tQM6Y1{s{vG5FA{$Y`VY~oaWWmz zEQ{?V3jJRa{Q+aI5zV&PZ-_#_gXm2-IgcnR^S4AX2+)`2S%$?vAezY7ABf(D)9{F* zvHY26Z=5hp6hCEuN)(gBXGEd@IZ+(t^*5rK7W;zeHpcc7y#W1%Xfk785yhbLZ=$R5 z$0NcmqW6F$dOrFK(fd%8M8{aH577ru6+{n#MuUi=Q5;DWgV8XeGc9%u(I25G zh?ZMy4AJeF(uhvB*m$BCtR@geBgrKC1d5PotHmZ0eF|NRDC+4Xq8Q9hCW^*XL=^3B zI?-n^lo7qu5??%+YVniYXt0|@;TK!%G@?ZoTR`*$G-09_S?mm=?HFQ+dU2vSQ8Zrq zdIAlOiY`qQ?XH>VPIOJ8Xn(7TVsKnT6y<*@QPkr) zqNv9WL{WbmiT(~vPs*<#`TbF_D&r=z_S#bEpr(Ipo9 z1<@~%RiYRSUMGsd`3<6&AKxO1LHcc?7@XcG`Zcmhv>5XN(SyhW(Mrq*L_HS!gy>R> z{gr5<#Xci?g2na{^;>KoQH-PiB-+~&Uxh$@{fGFz7W;{Ps?!lq|JvgqxwIRIQjP->HEdraaF>C9 zo+BjI;GSdUDXgIq3roarZPze~b!5-6Y`ca_tfS(?LN@HH0e8+X5u*%q5bQZRK3KgP zrXW7AhJeI6CO#~*0Q<_vo!&~)B;?4RLpmGYXbCwgK1j4J`jq!3lK0eS`?KDe5X7(J?*-l|1w=z3ENImP3?G(ca2hHs{==zBAM5pDT zlY0&t*-lT8pane#jclhFs<@>m#s{jmQ!K@!w9}I%Fdj_fnKksvifpHa67+lVfyQd5 zGbAJ$TRe8^kj{2mEFovb2dQU05YePgk)X4C4l1S+eUL_X;I)5h&q3=VES)Do=k^?Q zLj-7v1f3rrsNPP8Ms24HBrsk$#8dxzWo?PD_H+rlr01Z>uw$M&OM;#mA84$WS}Gy& zR-~tyN4s>`d9DP-E0vytZi)acm!Nnb(^Jr;5uga+&A+1Opm#)oo+m+<#RrO2tbM(J zyJ?vDeH#-uC2aP#sWnxtgszDXI#vrn_vJ;fJU&Rh`J=x(T0nyYt?xM~O3wk>BtaW{ z4ti+>XtM;xYqOp^ceC+H+XO3*h1nI_zZ< z7VE=!tPQ|Ib%{Caq78`~6E=A_qZpN5(0?M)pNbD%A0%c<^zh5LpGwfDdk#7%0`yr4`b^J3BQ1Si zf<6}?s6Lww=aybVZ%sE@b9mA6di$A#ejz?+y<{T`;YA7BemFsYEt!-dH+*5(@IOiDKgI{G8(wG{ zjt@rLhJPs0Lp?{2Q7nI!=pV(0u6OsL+;&VYr@(4HhWtf>ejFdDUe;m>CmRVZ<6e1{ zL+_H%pTq~PFONL1mt%b@v34H@tiMXEJ%<77ZxZYC!+^C{Vs#w`to;(}i^G8RPl@&A zVZi!IV*TqdVEsp8eSH|P@LZmQw&po_7_ht&3wsaZS*%5E_dbb*eGA_jtCz&Wo`-LZ zl_IgQU*cP1VWS)`d+fFN)>s217WQd;YplT%3wu1iH5Ojb@H}FF$hXEiN@8Je$<%x_ z+KTFmr8Uf&gxjL5Ntqceu?Sz%s9rsBZZ=LpNSfQr)5q#>4M-Sj9cc}-hI`Yj3D%KN z#+Nvl)t_3uC&BW2l0AK`K^Cnwld*e;CeUQ;q6!kl?j3BizdqSy^p3YxbN8y<-+#zrw2{(ubMA;W9ELca-=^e-d|eNTc2 z_k&XS0HO$gnrJ09S`jV6H%dXtp4~DWZu>mkmng!Af|7oKDD?AWc(DvGk>Sf^_@zW) z{{{+2x>plLx<~j#_;64PKb9!MAE0pTT6&5o%3(iI>{=R>B=m=YlKyC-&@Y$a%Vco|`t)sk(m$Cf^k0?Xzn0;@mEjlnf*kqU0NNY*x(SrZ;UO8mLx#U9!{3wPAsN13 zhWnBQPG3;MNdqOE6NsW53P}!oP9X|=-jw0*$?%V4cyVvknHRg{h+_9#9cVIkYh6eb zH039~@1e7aL z*x3r2w-vkih+c>KC;ENt(jNdhcC}3>3cM0YOC?<<>2;FcA?ZVsJ|XD=NmB<3oODUE zByEs%i==l+`iP{3gHRu+$C;pc*JJzurSiX&DD2t*O7bnBB;Q8ikiSF}@|~b0e*=`{ zA5%EwyJh&_WO%}05k8D4;*FNH7}SH^nx&FoE$LQCZ;><=Z(x$Kt8XY#?DiW$6ubK7 z$?zpIyi|r?DZ{Uq;kU@}*JSvcGW!EBBE*7)lU>-z->ga zJM})I=;PaoqL1z)+KS!cSi&cxEf*6-TWuhUw)Qqr#P?uir}$Y!5x<-$;{S~(1Oyw|WXRfg}E;a?GtG2DX*iR>8$%G(W5?0ViL>D7|nAn6^F-Y4mgBprP; zaFD+VM1eOQl<-a=9_?d+46l{pO)`A74BsllZ;;`4$nd9R_;WJ+Wf}f~4F3p}^0!BZ zd+;bp>H0w_f2l-aPr3{*1*LJ|2I7&=J0!hN(jQ6sl%y|6`l_UP#~>c&s?va<7fX6Q zQH-^>5yjl}08xy!+a>>;l)o(bHza*e(vKwlOwyA_B7QP<6HA(xhJ5}S8}5m|j`5%9 z8`#)Q^f$1FXa~kkqR`t!6na+^h29NBp?3#S=-o%O6C1vXzKLDLMBlhk|eWe@+ ziuxH!G=;(I#M8}{kRS!>Mo}!|G)V%k2m}h_!6a2zSPRLL`vro%moQ1#gHEj`&5^DJ;rB2*Rk970y$Stgzo$s=ei z@nzD}t%7F_JJ2!KP2M0^d;D);2cAikbwnS1JF5x;_GoqOWs5WfoJ1JMi6 zeu%D-o^lt%lY#h4d6B@w0h`*1U(bt%d#FqyeiJVu#;}GsnfNWdsJQ1zA@Nu9B7<8D z`UvsY@uGu!4Ei$h*TWNn=nuqq$jQ?LMaex(iizIFoxHfG$SK5c<3-CoLgo;E4=-Zw z`7w|92c&1-LvRWr{t;f}+_Pf=@!NUPb5D*%#6JPgBBD?6D&QU)rxX7Soc@SD$E$>U zV4OvKJFgnwhstGZ~EskDP>YTu(qMk9O$&Bty1ADOV&@>iJ~Am(XiTS5i41fpzNDo@wSw znc&o`bE((hQm@ISUb9QR7MFVGyVP6lQtv{SdKbIYyVRv#t4qE0F7-CJ)Z64zug#_2 zmTvSW%l52V@RiU@Pzbl92)m@y@xTt6-k*+s=)9$SqAi>XH>EM0-_v5?&4Hd9`>xgS7RJE4(?d9Llb5p-3uMFq6CI;R-=()-7_cc6BiQU?Fw@bX;8Xkt=Zt)Jd#5<`a zoL_YLZt>)9}#5y2ZN-dT#3Xa}5t!>K5-mF72C!2SnAL=~Y_B1YA_Sd!eW1XQ{@Cvps*N;jM{*_q9vBqVvP~y(k9WLg=}%?-mX3k{EaoL9ay0 zb>htLR~p{h7Po~qxgV&GLl&rSI~sNr1` z1MjCU@xIaUu8o1$_d<8}Erg!R@AqTiRYK2A{r*tH`#}u6$6Vt5Rl~b62HwA2;!VaN zrSf}o47^#;bCci8G`w45;C8~4(4W8mH367Nk7@BJ8fAGyREu_>J2-^ak41U)zTt<~`U5CiW*mv~QUcz=q4 z_o_=g&*pG`Ka7Dl0D5lnJ5R&=a}2z5UERz0IE`!+bptnFV8l`8dUK&3E5!L<(pA7ed z-i?2jruW2k*tewd>Xz1cI$k;+Qn$ho55o6KCBi$tAg>^xU75KVIr-TcdAZqvKn4#N zfAey3IF~s&CpVMdl_#&AF=wV_g{>ifqcDd9c5`_`i8(BQn{;ergmlu%;L4WfmWrjg zTT?Hn#G}D*d%xhO=@nbZ>*}WW0T-rB!bG$Ushcftgfi4ZWbylTPiA-uUc7g zUNxIkRlRi8d1cF*E9${CSJy=b5U3tw>VmnGDq32aYnHBRsa`1}*=bDz(s?xv%Nj*E z#kE6tru090p7F)UgJ(e)4%>T>Dt~bwu}9Q{YD z+U96qUL2Q9>+e)ML7zA+Uut;qZH3oxKS`6nX~(9vIgot_zDkpSYRCt(1K_XLyqFpuzkHf4l>Sltboecr90zdQmlr!~7lVIFlb>tI zkKw1e4?x=%myZqrw=XXn$xmm$L6e8`Lg|m`$bP*HsBJ|q4ZewzCF#IXDYLw+24 z9ejrBq^Qr|8uGF1FW^fx`QHrrc=jLgPiu0YomaANA{z{TN>Vue5r+JDHWB>Snmo^t zXY$j<)9t~)$L1OGY<3R#-)eI5pHr6?JAzk%|5B6lQ^2Ky7oUr`3i1WXDu&P4m+8f4 zBkqNKizfe(fqx=<9{e|&{8dAK5_<=Huy+{$kB0nv>~rvc)Z||p@~JElbzhYdj^Ee8 z_Xi);wg?V%X*0T>^=7)uVKz1K>9H26QE{ce!_Z16SU z@e>T!uLu7+?x#!sa_}dj{%FV`y!*jZ`oEU^i;@@iB(V_q70?&FkNpQcoR--LsXr7z zo#6440LPmQz8d^E$u9pPTeJ8N0i>eXd+HA|Z-n%9(uLxL4`Wi2)JW!0-ERkE@&tX#@gu36bq zUB7blXaUX^&7NCURJ3|tQLv(+p}MZ9zDlgJ@{DCvW)>Tbg%>S}%Cb#Kt_;pGgD1;i zh_&TdW`PVg;j=PjFk)%iSxAZ}nQsQGBmt&tt0Xfs%y5-vCQ{M#vsI$VoDr^4%`|hG zt&+_&vzl$EYvwiEPS?zAj-9TV+Z;PxGrKuVe{zDhUC%x|upu9@FlJ6$usd3L&He)H^f&HU!s=@zijvNe`vBafo>DYR@e7kSF6 zY%>>m%BpNL7n5xqGZ&MURoP}PCM&C`y0uc8Y^Q7HVzNxv)XtZwn!5QiO+?X<^N}L; z*zl7M8g}v2Ic3x5PAyy5QqkN}HhU58ztbvKR+lZTZYgSPSXOhM>e5<|rcRDnMHNjg ztD38en(A7(5`v~z*Hx@3Syi{v2%XW~+}O-j<`-o-kQdF))I!J}pwC!cHVtFe@}i2m zx}|s!<93ShB0R{gYN=?cX>5opC6jsF=@|1C)!>mWj43jtAghwxTc{p*xcAqb0M#CErIz(^F*_a7UoFK z)-@9n!G_r?C@O%{(D@D3ysbwu#FRLa)r4l^hQN$ea{AoJWWs?Cdo_Vkv@+aC)eeh} z;mq`c>iUYN@X&y+iUy?=!DY6E32DVmaeR9Y-uT-+SD|?qNSpAPGe<7UFo9g z`liwur_ackmOZJZzA2FYU9D^a6B`5H9(y{yG%B6Hv^FqtVnbtD<;rStv#O!Fv93tEfZNG@K{+m6gG2tmFh=-B49i(Qr~-O-oB1 zK~*-bI>|maCoqwMmLX_fBTuLbi@LH(KCTDSkjawf#`ExAD=-t4voesrIzMl0DOKG< zv8*edQNOghs;aswaC&3&@}<@2ivdxAr4`NfrL*T1l~$Hcp94(MAj;-7HrH3wO$w$3 zCeA(#g?M;SsBtznlm;fwZy1YZtH>LSrqwMY>k-HcW*JJMtg3otWphna3udegB{(0A z5*34|l#C}gZ%-gk@Co>SdEo4jC$ItEqz~|Kb&otc5Ip$LZw@{j^rnpsihJ=z=M*+F z*j5n;uB!9xdF$tg2DnZ=ha*Nx`0!iC5o=?S>&!zqN2KCf^{rmf; z_3jMN_o(+xpX#5MNcX`)KUw217kOkd{)Pj10t%#Z3@eR|RH-tgWO02Z#baw&ddO5% zEPPQLNFE^VEO(FJjy#Jvl#4^7Cq@!rzemRqI)a7S0|g0(D~>N ze4w(!3XDNbZ=!JICWF^9zCg}0Yj;)(+E(@Gj`7H9Mlf}6j+IeM?I45lu%9($A`clT zNh+C4lq3r@@p98k29`sUa_iP|`fhz6mXJ1Ua7xV(=UX6m!{uZLih)FC8QOg|A?L=+Hxk^ve|R? z$+p~WUCUl1>w14{dAPlyWphrnw~YO*B_unz%dG3@qegsnszzDWJK|}@hu<0&PO-|)aOcZFJ{WDE=sZKu3sXn$3IbI&BJXkz@`L-%< z!+uucw1F9yhh1lv_h{I&9-Ie%3s@>I!zMN`ct&|@uqfycdW%4D-^$l01A{l={<2^( z55KIO;uc`dP6$|m&eD;OGLU=oIBkfx6aV}*-lAgsYr{X_SH;5VEpbwVR<%=aD^hQo zMXT0(ms^32;L`b1Q|9wcPq5JmW3DRn);?V1UFxeH@Rjw&h$7$8CbR?fAH#*igA>v{ z%>Exd&U>ZcSj3a+VfbIul3X<68R}v9pOmAC&A_;ntptlu^}mdVME;d2r*tDm??Yj@ z{RH!HDmi)4k9hJJeEPJ~`JT#wmt-K!gCD?hh~kGcet}waQzH*cTP`>J;8!>N_Qp@1 z>PNI(Y@A~FL8?FT=ivZGqP6^-H6Cdw@pba>va{vkWxeI$WsUN1GK7yIJv^fvOSC~A zK8A4m;fy}pJ(1`N9851D+EH~P& z#6hscd*w#iAvo}lc>Fqgnhak+^hkM_*D85f7xd4h@T0^Jk@V|k8Sw}&CwjCzjH^W+ zwuNvMC69!n;h9H~^25+*0}sVR))@Aaux6r{aMAx^?@Pezs>-$3IVZzOI;CmoM1a$D zAf3~6M!=J#Lpq1HKxN8Fn!q_7Lz`kjgcO?6B480j@FG?~1w=2#35Whv0WDWACJ0vq z(dgw0)G1)A1(f{n`|Y*%S$pRsoD<6b{Lgb)PjbHft@Z79eQVrnui@L`4`?w$cO_|y z^ZgUbW3Reo8oY#QC58VU($kf?f%G~UHYA1r&7>2>PMUz+rv2|AMPlS2&tw>0CBF-w zO((^D_mCp2XNny(e0Cm- zp4$I=q}a^$ebNSJVH5j4)DOvDDqoP7!u<*PM!i|-!_J~LGwT`pSBf1oIj#IWc@*-m zNUs+=Wpe7}x8&nupG;QE|A+i;`LerMO#35wRE9s1Lf_X(Q5oJKMPdDebR`UrlA;j* zMT$!D4rx7ZVS`xitZ`5sZ8Z65xv*}Ux&4RaTD%RJuOYFl++Qu{ z_#g*r$N~L_oaBQXtRV;W9}?BVlkfr!iS8tmgriq*9h;;76Y7N;c4%g>cB%U{Ez*#X z$wX81Yp$E3HBEkO2wgLK%OIrs3(9Q?Onwq{qy|MM^%oSa&<8qNgO2Jy=%F51lTUDul3M2qCrpVKWNVyP@+M{^dGcm4H&0E$Mzqz zXAQtGK=O2a|3MG+$WxS#fa39(NkP4P4M5)|z<9o90^D~EK=BFadz|3)M*26wiL-DZV|l-F$lp4?_W+ z-G9(43@E?Yh3r&8WQc%bD3pn&=;K}Iv?_jpFKSTF(5Uk>L&f9Wbr;}DG>mF248}6i z(8j7ZSXCMe&%yp;@jlUOp~hO!f2q%r3eD!&%{>dB)!8I4gz{)O06swqB)A^e@1a?d`)^Fil)2>VJ& z&qC_y{}Jqu*Wq`N;??CxnqGlx@_*6v?kwDQHsUA6{oe!S{Xf(G&uaf8+W(*0KP%gj z9}Pjh2EL^C2E*R&Y#FywF7v@-1AEG30LF;L=f)Baa!|NYwk zUhV&o_CKWkpV9s=Xn!o}2~HRosF{fyhVLwMi2%Z@+?FnzY%N08yj zjvfwKEOJu*xV{r|+oVt((JXz3UoIaRYDa6X{c;1-lpEZO9E#eLjsnOTov50*UhI=A zf*iil*2A6elRE`ZtkaY6O55rMuLyEg2=luJc-Z=#Z{eZph+{hZ`dyYL-a{51>o8p^yzixn_b&_2 z3}8~>4Ju79y)}?C05ij`(~PWZ(4X`fJGO^zrX(FO-e7lD4W6>lJ(feUrGP5k^#%_^hH!m4Dw&Q@?jCJPcFB zrNSGG%t)tv*FesscXl6m>(j)0z`~o`2i~J;;{D6Q!|+R7s`L)R98WswT@5*tUJT=U z#j8&f@5>e*M$f(CeJ4%4e_D8E{FExa15r5_>G*8oZ@;S{XVP1t1ykYGL+(r)NMHN$ z?y>O9^FI~d*V4p0V&R$cONIAVns{@{lIbdryV;DaaZ9?QHbt z-!Cn^Wqp*#E08ncec|DJnp?gr`oOD%TsrB!#==|G2i`4d;{At(cTOL8FQkb#95bW^ zz~OjzO&@p@AeT;h>n*%>yFe zwKFn`s%LCxq<;H$=e(i+2;TqS#zqoId$Ocn@4i;@!ug?bkyeXm8Sl0D5au&J>EZL8 zy#%gbuKEJ5@3i;_-D}pkLF!TP54nE1>X3WQ@FD!R8NZvRT`s>><~kZD`2)BgyFR(< zFYYz(A0}(~?XF+0q{rs5VTa#E(=JyH0{^^Wk-p*Je{J#R<74y+VQk~gpRg)}ym5uN zIMc_k^6^Q-Db6eoz6a|%-oM|+-|OQa_3=LiPcPv;a>sIR!nS${{#F% zT<2?^#zKB#@e|p!;n=$jWgCC*$EJE5HgBxwX;hv%$2s$+O*kys>)G>ZXl8TVGrr!F zvN-GNo;dfO+~u)sISTAOxI4of(Dk0%ong-B`rys6V4TDiFvIikxOniixcB(&JUO_y zWXt-s34OwK<#|i0Y8P&)tKZbPWc4``EM7Q^TeB^(bz7qOO7UD>RaJ|lqg9)>uHUFn z;_*nP_O7W~zHG*#ZHiGE2bJil#>bflrIH#voOEkN>t!~`DV{@a+ zuGz7@2}jRdo=1Xfa7Jxw!@^BPqI5*hqxxuNgbye(rB%33h3EZ1KC&F_s&ac8bzV2$C*eX!nOTsZ;7vLJF z`|b=p7<_<|*>|fcp$=Z zI2fH5j7BSma0D7f?=KFI%ba;Z<@@8VS7mKwP43t&#a-!ckt@-0knr(UIqa(4Ijz}y zvTg|N4RSN5!!qKKQu4 zA=96j!;_^Ej4@^Ua*SU3z|&Bs_ad~&12<4FZGd5lC_IsLu>O)R=EkOz$2v(SDF&?T zsF$P-ic8v{(|g7mps|piOt8#UGnM1Oz}{Ji!Lq0a-7|q4N-XU(Uz|cTp*2uu9!0146s3gFm!*f>!SjJe7!&dS9 z;NSprG#@o!Bq@F(paan4s5U8MAmz{|A2nnVDQ1aRYPy!;0Ku}L8h|W`krv4gQ=ywQ z->m6XnqH%63ur!S+Fs4yNFLRSb(=W%YWk3--_-OFXg<<(So8lu9yRONpuutYan>aH zP3#~ze)AgdZZgr9MT+c|c7YO-#(<2?r9YAyCPk8@aUe+$)!(k>MbgbmUV5(B$RsZ9 zOSz{!5)OlUC+~13=wG;~fwH_;8X73n>9H=i0s^xnQ3$l0e_d`D68Jz0ImsRCzKKY% znOCyB<+HrZ3zL>O7*+%0Bp<=BJ~GXckD!$61U1gc@m|Uq$Mr=MMn7}C9M`toa>$jL zn=E>fPwr~St+v9=Wdauna^2Hln6JzlDO*sclU37}`wf`=@S~jZr<_0DEda6e1tQ`S z_%-*@;~~hIc%8RtCtg3^_tM1syM-qmH{wX8Uk)l-6&3I~zkW*~XY?~YQ7XKTK(4}v zMb?k^Sqsl}mc+XS|EN<V6L;c>g=#|B70&Q-=?M{~++c*Zkz9vZ$;% zs@%g5Q56=?u5ST&w?>0sZiR>NG`SG`AAs$+9JSsPUZl2xZ+8816!$(E7sB{!A9$RH z(k@5c>IomI4uC(?3V*;8K3aVT{4CRxL%+v7;l=7{@bgR$jBu}g)lX)o=uYJ{s z*jMF#D97a}uYJ`Lv9H>0g?sI*juZQ;8_W{~@q6v7P7wR5&syPL`>Lg4U-eScE8u>w zebq@~U-f<~+-qNTir7~zcY6oFebs4VUo~!pd+n>1iG9_3tZ=V=)pD_~`m7c1wXZr$ z?5h@_KAZgW+E<+;_Enc#;kJFw5Uensg0i*k!%lF^nw{+#YBuu-fV2*ZSnc z>IP4Ep1Q@upXZa$Q?@-;+K2t3M}D18K3{#)6Fxxwz{6kQlOLdd>IomHe&OLS^2rZW zzxRX>lJYS5$z6m;t#H2MxNpI@CO^#WiyZzmAJ09V#!;U3Vuzysa-c_hrk8<#4(-|S zd%<6huq$-<-QZurH3vJCe-Qjk$aAnv{`=q)7XNGTpSSpbg5QBUakrK)Lf^L${~I(v z0oTvr|5KWukL%0Ozn!i5rQnC+c`!xu7l3D%&qqWFUezxLPy4ORChBuN_!Zzmg#R=y zz6d<`?OEjgNna^?)rPt1NqO3ct&XqO&e!qzD(!qk=v`$)?d94SI-%N%dYHR*InU}BR@2<2tdz@W zmS?%Uw#F`N!H%X)jXU+Ko$h&@<+C24rsIJvN72F(a2My6FIidZVPHkJLG0PeEh~0x zYEHmt)2*r7vE4y3KF-3QfEzE@)T`r> zG;k}tboTD@A2VOPk;Tqq!1h5QXzRBk<6D4q{EYQn;k=e_jh8nWx)hQsn+F0aK~GO@ zA61}M@8rX#r|zrWr%ul>Q>sa16>Qhnj&N-+5w7hS;rqB!I%CHBv{LE}4n9~I z{a|6V*M(6oE;`0k%Q_DvRB3m|?KD$Vn%zNDqw|zwcGQ?Dg|RD`OrqI7#~%DN^g7{J8!A)4M4Nfqf_Zw&G|21}jzW_G@}m`Zd^(L{|Hk?bp0$5^Km z@7eu`mxc@dDO8D?qb)k+$c3&5^r4JOlvX)csq>&5Mo(!vbhys<1^v(`RgPmKJWmCT z4u5V-YGDj7vQ)~T8%nR2^3jG-#klU^PTROHOVMw9cIs=#s~q#KrzsVI+1CBveLXNF z*#6zuONJz1zBSk`=36@gk@Ya9Y0Q>g+!=r=*Lk?3YduZ9mS9=DT#UO0I}3$=Yxl9; zT{o%HsqI}iMNjS8{Yd>snYPYbgFdudqy*2ToZ8 zMeCkDhQY7z}IkLygDsXG-2G%Po&{9nH zJF%5WY>xT2mL|pnb9m@O0*EtSXKNAhY4OIlviV_`$fu9bj|HY7)zcPsV8ysJ*nWST z>03VS*7JEtcPs17ou%~;@BR}~{_1+%sZ&k^Y)m;R4bx5BczC@-!wnAI+pu-f{cU4a zX*_t!{CMd`ZUMQrE2<{KgmI~8+=An zqoI>qj)obTp%ue$4{vRyS{^Al_ZzZbj+~OLIEH z^6Y3)`SF^%(Vg@yaebrWJ4AfTO9yylo%N6p`GE z$#qPwlg~_UUb^m)mPOEU%=5=pq%dCC6$s+0?8W%7qb=Ljq{4PJxuBhCfG?K99qOdx z`Qv9Q*6zcgPG~e-03O!`OA}3w(#J234QM{gKsOSwY+%aY8>8 zHt}DW7}gaCr4xV9ivLhQ;t#v=7sVU$in;<>)aAMONnMd_7z%I4N=|!p5!(p-RZjfx zdBeK`IlTT!d_-4EE@o=m)pT1XJO0(Ylez-glzAdv)D_KAQz3(=mchX!YiV|SAhH+r z(eXR@>fd(Rb*oUBM$n=TWeXk4gRE#_XA&bDjB&Hd^3RBi2k*#aB`r% zeDd^;y)w2M+7aFWGo5=mk{Ae6uwjf4Lhx%T4%g>(hBrh(vq2XW53E-^DRCGhv%|X& zW0b}o*-86Am~(a7KveM>{Sih?Vop~2KT5IBI~?Q4pJi7fpEKYXBl#HzC7%VrTS){` zu@XFI%cq^!aX|DO-f>_VN4_*Oq3suuI`Kn@!^Re-VYv+cUOm^UyMf**;O(8cjA9C!XA%B;tLbA zk4ASKfDf+gIunl^Q>z-G6*iGp!oaW4X?hzfYhR9xg-4B9RaF;XqQ3L?>#sMIeEsb= z-WWAzrTBdN?brV{YD~3UKl1kLT@7RK`+7q}y*+g1$Uu3S@LdI6LsZR?U;#gFahq&z z%@y1ekKTY>OeZb-dZcBaN~UF>N-r%_dr8ZQL4W<=-xA&3_&RS?6$PTkP_9E2Ty{VO zvDwzyZ);s)I|cq2>Rw?}q}aTTct}`w?K;2OD6S^XeqP6xt#fM@Zgu~F?b-5cZ~yIi z?I`0lt?T2oUUr09!m`2J6FHSnDRL&=O~+>U7ITvefc93`!Fo@QSvv;}Q0^MNArNbd zSZ!0PMLC=83iReI;NVg`1s>rT(sS|7*>!xmHn@WOWtTC+Ph~iS@RBQ5FUFA~{B+V5 zXU{6%<|mTB65FasuhqMbN9s+4Sa6g>&DaaTwOCqpku6!foV8r;Vm^!h#oA=r-+;}Vq$S#9?sZC?r~S_-g|h2NufTULNhdgaX4OZwZ2MmkI)5K^{IZzTP=-d{98sqN&kQw>m(xk#$)UgQQwF8F?obem*}WCD^VH*u|% z8>FDJe327f7Msi=<2Sk+nP}-{z(szo-9l zrT&{VANy5EH!1Z;(#_f=?rNp}Ouj{%#Kj5GzmZ2hJ5IVzsW(Xx&pV_SqM4B*{ag#@ zMrm{llJ0!cIy0qgdpNM|WXf0`)kh22Dl>L!ZzmI9A#l#m-5NBjHM9q37f>_BCM#;73Zj{3qARp<-4tBe$w!m|IXp8+>2)+HOSW>@ z&fU4KIeW5i$l4p)XY?JV!AJHVoYf*V_{kc4bY|et#dT=LPG+)p~e>NrXSPhJBI}?r3 z>$q+Mt|VK>YpijZVcB)}Q^0~zO`PFzAWzqj6Z#K{4%gEhCTd6|H#qzk1~uz2<5x6h?osvJBRIjWsVbEc^Mxba|gYAJU*_^dEF^574tTD2gYORNI=e zWWAbxSc9S=_7}9LrWG1A+J8`VQ$9_rG$_VgnP_T1DLIBp{V-do!53r(Zs+Yz(HMq& zuQGOg7i&U%( z%z*7)G6;R8_gCRe^}F3HQk+!7j`_BZX(6Yq(?|>DmLG^Y=c)3UO+mDR#V`nNK`UqAssZjq$2ubY$Q(s3<8FeM~#-=7UPMLN9l!^9x02%&$DFp4I3DeEEja!e5 z{fr%f4q&=$xwjAj#wk7A3@s<+j_dg-kfl<1j%b#?!!LI|GSH6JT>Ir()0Dd*O}Tw( z%6%eDxtn{D!|>RXf1iY$$qQzQxnAs(yA5)*mgINm`{W)(0af{hz&GGu+L{jg6XaMw zn7^i2*d}-2-}fmD+k`M-ybbJ>9cyl zdpk|MYV@I|Jc@PvsnWX+a@A?*cfi6kZ~m$99)aAFH1OWE@FIQamp3^*yw#91=`HC4 zuRcw@uUL3!D&kV5_xq6J8=l|!%l97^-UKb23NIJWymac{QplO~miB>nL7I4;WqK7_iYOgm*P_44Vao<{w;=_N$<2i@Xk*Y?=}mstPi~V(!~3%g@@sZ zxK!!=YnphIkw}wXGp0y|_aVroQ~y3{;qe84E*0JlY2rO@;bGV%E*0J{(!?8r`8bna z4BvXiI}LK_JU<#NJd;1E^lMHN@4FTrhLgSO_f(pAgHh>BdZT^doeH^h(!1WmtLy`B zdzyHUT6hckz&i}N6*}A|{{G-34D<>hz;OwN+u~A{$9Tx4lim#$UUeUMS3xeF{`8=Q zx3mwu|AbsR8dTVSkhMQny0Rl)v#Ky$k<&mdEcP_bA>|*nZ8sAKUMJ__tqQ?!v>x zjBl*ld)O>~3~~{T7t?~oqph9Uvm#07+S-9l-vG~8ct)1IvOH8h< zor|gZ{{mY(m@Tym>Gkfd;CZ%x94KwyTm$+PN_(5;Zv#CG;e$2*WzZc6=YxRq2SL9J z-h_96|KR|cuaWRSfd4c2r?vb)Kz}(16+;RW08 z&D-XGX?y29gc}z^vuU(=R?j&2ON;>cCM%rgjjsiNhZTNiq(<51tT!teEjPgP$BZ`;=So+o^|dJ6m&w|B}>&v?RTsNaEaw!)8i z!e^>C!9Qw+2i>w_`Oa2D!5_B5M|;BOs)^vwME!IeY(aU#=c@|vwr!rJp70N;kAQEo z?yvWRpQSDbzZ&hq;9unl|FGHz{*V>^DNlHX`U3brS>X?P!mHGG!G90!&*1;a6TVP& zfd4PFR}=n%Cw#Gb4g5dZ_{HU@H+(#8>$tN|s9&_LlQl$(gU?0X4qJSITi2QYOQb#9 z;iq}RbJYY7zs%SEb7lJ9#71-DXL{sU_~gTCnI}9?t@iM%eDZm!&J&)m5+42>pM1X0 z_Rav+;*nqDlOLcy=?NdGKI7rf^~n!ZNjqH3zd`D29{KZq@`KbtPxxRdKa*eV)qie< z7b4&#AO9C0|CWy*;`Tkx1pYYi6Vcu$0gJX+=7L{i@yoz}96VpF7=AH$tfaw;mBViV z&n}S7xCH6j1AZ&oC!?kOUEpauhg}-^hrx3){A;+0{15g0d?t{m-LWKIu6h}K9_pim zpQHW`p3fBSzoUE@z_-HhQGNfZ;Ik3=PR-8*pTx_TrKTi5KqV0V8OZW^NW81T??7bp zH2xjnm*Brshkp~-9|!&(&3AwgA^ux5|0;Oe$Kt?~c<+Eu#urv2koF{>r)GJ0H2f28 z>t=hO#%|Vlt=$+_TOV-D*tnkV0e^L_@iP_zypl;%09w*-@*MOcSZkvnt~3Z(?V;@p@A`%Z=BY+*xkC-t^8k@%ruIn0Wp6a7?^@dpIUuzdaliuiqYy8?QIL zbKH2n>7C=o>rL+*H(qag=eY5D(>vG13wt<8do`}7YZb>^YIC(#-ni##oxCy6)f)NY z)%y6V)jS=u&tAVF$T|HBCl_xdLR%*6bsi9pGq-M{KJx#Z$(sk`kw;(lp9J?fwQ`lpv z>5RV7T|f&f*e6}$wL4PTi_MY_pUsk|QrK-7*V!FOjXJ_-&Ez4EHIw^ZVacS-kHxt- z!*vo4_q}vH(()N8;b_-QEyk9>x7*Y-S~9u5^D}Nae;he;gOu~Uh7w$zrOw`ScI!2* z*X-GevTkhOiL&0=x)XV{bI+r4UU^nW)glF(HS^>=tz)z1g3fyveebvun>F*1Q}b{} znKo-wXG1ZiBOd9h&IcD!BDZ6nKJWY>?)@sPwvgv(XY!ki55CefrtzpNj3E{7h)$wr z32JH6=Hkx@9<9KTy94>g^eLTQU5{=kfYq1VB(F+57Fdd5fyK0j;mD=y!F{BDbn6AJ zDl!sn;(EcNud(k^>^&du;+A`Gr&zcXH14nJNAI~{4{>S9g*qm2BZ|1jwu^J^*mfz7 z$Ld%&L1XAl&=>GrdKv5mv(E{X&PTji?P^l6{omTuWS0C4^hPF4lMy$2hTqqZ-LrmA zUH#bB^+;Kyq1@^-Lc4ea4u1!mZc4ZiU(2c(+{&LvZl{q&-%P?vR?BY!A-L4Mf z59|1&9JjR7R?J!2R*YkZ<_eD;nh5OB41^t;{PsH`N6Tl9U728~u{ne3#`w#|zKwbk z_HA0A2kx2b+(X+;J@3hlKbAM5E0D`Le;gm)70pr8(VI;(wrps(Wnyaa z5^rU@DJ&h<;aFI4+LvvmB?oPX62T5*EhV*u6^zhe@nt+Q_wbIA(t#S&X}|2j&cX=@ zTCX^z(}^wFvRU8Q%5AB9iJ5uj+?BK!V=TlNjSSDYnWoZBwC_@i(O@#p85r5oYTf@k zD=%jB@qSr(N#d(c$I1(P3YJyUx=Xcd-DN<0own{$4XY{Du$H=<$Md2wu`n6W!Y)vPmo-jA!#jzZd4FLNu8>VAyDUW#=%Vdqm zKcKa6Zq(LnJQ5ijigENPMJDve76sSf?9-K4cEi>p6*SAqpaJmQi-J`xYzWf(kecOE z4hG4}_GV|l6m6djrQ9$sg~45=&jMljdL(%q6q2(*H~?`fdHA13Izpkdfcuzo&ho&2 z0(l6ZPKpz0Q%Fz7XC+8KD#woG;1ITSiTRazqyU>wdW|*@bE!TzGe)T>{jbpb8R5T( z{8+tz@M<|;gm2X7{gdPMzUmG7oApp)E#)`jGgqV&m6Cm7o1CRl)u>dA{*%RGhiht|Xljr7CXd<@e2DESs`KBhvOkHNC=WAukUhe)fm z`55HKkI6&7pO7xp=3`Lb{*!!MsdiFiW(Vmqoctq2ru~w1rT*eMGV>+!=P30X(iUwl z28H)BdF0P)q~|MjgcN%Gl@x{9MT&elMtZSQee1bSHip}E+e3VOJPMnld-YqU$(ah;uK(8H~{dvb2b z-kY^AbfYmOGE&2j$P6CZxNaS;V54JqV1qe@K3ap0>OUyzi392$Z7d2kEVbv(XeAOgSE4vQ($-c zOv;SYz+*E5Mn~kjNw|{sFhOIDKLJ?CJSm>jGs8ktbluswvU>vPDUcI0gG5Df9rxDw znrp={$K=ZtjXpUubUPz+5RYW!G>wI4a3+<=#>z5S0F+eYQI`pp-P9KV%WKS|T!Z3y z*sm+dH zCQkAe1B^@x%&t*e04}u??MkrD$_&eHnrJMZrWw_c7}sQ?o?S_w7Ral2hg!`;u2O?m z^dFSw8@x3iZ9x)`5mhFd+8yx(0rlJVTBLz7B+CTYE}@_)q2(G2!?*X0wMt{HJONm% zH5P`A?^&;NHP+e_fQ7M)6zcgW0P8}Hg`w_yPU9sS3&Z61j8&(xVyMyR6i=iv6pYbS zezT(^jh$RWe!EgfN%1N(4i%oXQqv!4`WsD0qvA50pK~YugQi6xhv$)f`ft*70bZwQ z3}rbfUdh&yA`Ej|D*saK;wFy=;BQFr{|8cp^J|g}ABcNNZwIB^-J}S+pA`QOlLD7J zQhDDGG<^n?_r0v?UdZG(0!Pzl!{FIX;`NKhRl=lr<(fr`hI*#vW2BI6BW=Me8tE>) z3Xx(6T#P)-zYeeBq~K?1egWx~NGB=cX(7E#sRNqwb(j3hq`-X$aq|8jBkzbea4_D8 z7vq(lbO|hmkS@h5J1C9AEYftjruUG>kuRD)q^SycY^RV(+D}OuP=PcuPi88R$ue1i zOqR(BWS~q&Ame260hu9_4#)tRY(Ro!k^u>U(Q0|`l}Q97L}o4kEi)EFNGIw^k;!^e zWU8JN!H7qmIT)lAQ4Zq@d0=2DfY&QAcq_whJa9*n$FotoX*}2PDkCr1c8QsGni$zY#71ygEmoJ6m zh)Vh6(l7Us5^uVU3Vyi@)0De7O}W}MR_RAh*m3_WU-0v-R6y;YpkC1+O(tymkvu`ix%iIw7~pqnX3_^_yOr zOs^Rlrb_RJA&2g!hx6m@w(z9S!X2sbZch{MR~DXm!AOPo8syOZ^>BXu$|ok%D}81! z`c*=1aSybfhGX_wcw@ADD*f(C6R*?4L)8|S3a<-tOLVwR{OO%PDVg5!S}+yf63F4z ztcUaCwOV+nV&YQaeL79N4hs)S>J{&IkgL++Hu38>4$ofGZ{Si~D*a|5aHS2Tul;z} zS$KGyi%W&~DafUhe@|O@7#8%3_nS2FMo&qmm(MD?RQgSVTsrM{tA#hyflG;ZZJKyb zSa=xjh)bp4vuWauLLr#)<+F+|72ZV1rIX$*79NIQ;!@#VlP2Ed79NIiz2f}>aw~MW zP5kvQGA)^23D0eX7M>YDrNX-!a_O|U$1J>xKJ@!J3rVqT&riu4o z7Tπ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%0Ab%6 z{Dk62%w5!Xb40#)X1>RTvP-sb*`dIjcSMBegC)MH5xrV}PX+Ic1rj;0W<-CVVj7|+ zT|1NJ>l7Sj4jbXTvL+o#9`!v&r;jJa>qovqraVE4d=`>I2{WjYj{AjBW^EYWO;v(& zeM=R2ysutJig!%QG+jjs@C};oAjNfWAjP|*8%fWUFE^@Tc=vOg=Im$YW|EAMvM%3qX>oB}4;{F6uuE!;vMEW5# zFDcAo7HI-)L|T9~J*23l^GPS**^jgc!*tS#&VGVnsJvz5C&TR+DQtz$sl%pXJqGDC zJhPEb$Fmygd6>E+oq=aFQdIgbQcMfAlFq_27-^_$iCX7>MsRcT-EVTfHEVV#Sl%*DclBE_S zNnwJ3lzsw8S!yA@872ZNl%*Dcl>UR>AWJRK8>Anh7syfzSgoRKELfdP2Le+17rP!; zhrsIOb^=IQB_cN?m`H*=Or(GmCQ?WW6M@xJeBS>{PFGfQbN7)|w&aFbQI&qZ+NZA?$NSU^U)yb+8Se<-!1Xd@jPhfR& zKY-QY9ww0J56-QE)6syG`vj~ly4tmv= z+(cUukv^vro`4?9!7L)H64*CCfy35&3VOIxiJtUT#Hkm&F8lgQqz6Orx+|e)t_x@h zsqpHdR}%ySAH@5Tg=gA@c%R1sGiosqUC>)*7>j-dal5?lL61{etQX=ikUoaPuIK%u c_4ZFHSm8T}+j!4F? Date: Sat, 15 Aug 2026 16:40:19 -0400 Subject: [PATCH 046/181] Removed generated build output and per-user IDE state, and fixed two stale link lines (#618) * Removed generated build output and stopped two scripts naming deleted archives Three kinds of file in the tree are produced by a build rather than written by hand, and one pair of scripts still links archives that were deleted years ago. Keil writes ThreadX_Library.plg on every build; the two committed copies are HTML build logs from someone's machine. Code Composer generates the makefiles under ports/c667x/ccs/example_build/tx/Release from the project files beside them, so makefile, objects.mk, sources.mk, subdir_rules.mk, subdir_vars.mk and ccsObjs.opt are all regenerated output. The arm9 and arm11 sample builds link libc.a, libgcc.a and, for arm11, libnosys.a from their own example_build directories. Those archives were removed in 6.1.10 under "Removal of unneeded files", and libnosys.a in #594, but the link lines were never updated, so both examples fail immediately with arm-none-eabi-ld: cannot find libc.a: No such file or directory Link through the compiler driver instead, the shape every other example in the tree uses since #594: the driver supplies libc and libgcc, and SYSCALL_LIB is already defined in both scripts. That does not make either example link, and the fix stops short of that on purpose. With the archives no longer named, both now fail on undefined reference to `_fini' because their linker scripts define the .init and .fini sections but not the _init and _fini symbols, which live in crti.o and crtn.o and are omitted by -nostartfiles. Making those two old cores build is a separate question from removing a stale reference, so they stay in EXAMPLES_EXPECTED_TO_FAIL, with the comment there corrected: it blamed newlib multilib packaging, which is true of cortex_r4 and cortex_r5 but was never the reason for arm9 and arm11. Reproduced throughout with arm-none-eabi-gcc 13.2.1. Assisted-by: Claude Code (Opus 5) * Removed the Keil per-user state files and ignored them Every Keil project in the tree carried a second file holding per-user state: 25 .uvoptx beside the 25 .uvprojx, 9 .uvopt beside the 9 .uvproj, and 3 .uvgui multi-project workspace files. uVision rewrites all of them whenever a project is opened, so they record whoever last had it open rather than anything about the port: debugger selection, breakpoints, watch windows, window geometry. Nothing in the tree references them, and every affected directory keeps its .uvprojx or .uvproj, which is the file that actually describes the project. Add ignore rules so they do not come back the next time someone opens a project and commits. 1.4 MB across 37 files. Assisted-by: Claude Code (Opus 5) --- .gitignore | 7 + .../gnu/example_build/build_threadx_sample.sh | 2 +- .../gnu/example_build/build_threadx_sample.sh | 2 +- .../ccs/example_build/tx/Release/ccsObjs.opt | 1 - .../ccs/example_build/tx/Release/makefile | 351 -- .../ccs/example_build/tx/Release/objects.mk | 8 - .../ccs/example_build/tx/Release/sources.mk | 110 - .../example_build/tx/Release/subdir_rules.mk | 22 - .../example_build/tx/Release/subdir_vars.mk | 1174 ------- .../keil/example_build/ThreadX_Demo.uvoptx | 224 -- .../keil/example_build/ThreadX_Library.uvoptx | 2672 --------------- .../ac6/example_build/ThreadX_Library.uvoptx | 2576 -------------- .../demo_secure_zone/demo_secure_zone.uvoptx | 328 -- .../ThreadX_Demo.uvopt | 305 -- .../demo_threadx_non-secure_zone.uvoptx | 373 --- .../keil/example_build/ThreadX_Demo.uvopt | 300 -- .../keil/example_build/ThreadX_Demo.uvoptx | 300 -- .../keil/example_build/ThreadX_Library.plg | 9 - .../keil/example_build/ThreadX_Library.uvopt | 2664 --------------- .../keil/example_build/ThreadX_Library.uvoptx | 2664 --------------- .../ac6/example_build/RTOS.uvmpw.uvgui | 1777 ---------- .../ac6/example_build/ThreadX_Library.uvoptx | 2576 -------------- .../demo_secure_zone/demo_secure_zone.uvoptx | 328 -- .../ThreadX_Demo.uvopt | 305 -- .../demo_threadx_non-secure_zone.uvoptx | 342 -- .../keil/example_build/ThreadX_Demo.uvopt | 305 -- .../keil/example_build/ThreadX_Demo.uvoptx | 305 -- .../keil/example_build/ThreadX_Library.plg | 203 -- .../keil/example_build/ThreadX_Library.uvopt | 2664 --------------- .../keil/example_build/ThreadX_Library.uvoptx | 2664 --------------- .../ac6/example_build/RTOS.uvmpw.uvgui | 1777 ---------- .../ac6/example_build/ThreadX_Library.uvoptx | 2576 -------------- .../demo_secure_zone/demo_secure_zone.uvoptx | 366 -- .../ThreadX_Demo.uvopt | 305 -- .../demo_threadx_non-secure_zone.uvoptx | 342 -- .../ac6/example_build/ThreadX_Library.uvoptx | 2972 ----------------- .../demo_secure_zone/demo_secure_zone.uvoptx | 467 --- .../ThreadX_Demo.uvopt | 305 -- .../demo_threadx_non-secure_zone.uvoptx | 335 -- .../sample_threadx_module.uvoptx | 236 -- .../ac6/example_build/txm/txm.uvoptx | 1412 -------- .../ac6/example_build/RTOS.uvmpw.uvgui | 1777 ---------- .../ac6/example_build/ThreadX_Library.uvoptx | 2972 ----------------- .../demo_secure_zone/demo_secure_zone.uvoptx | 440 --- .../ThreadX_Demo.uvopt | 305 -- .../demo_threadx_non-secure_zone.uvoptx | 342 -- .../sample_threadx_module.uvoptx | 236 -- .../ac6/example_build/txm/txm.uvoptx | 1412 -------- scripts/check_clang.sh | 8 +- 49 files changed, 15 insertions(+), 44131 deletions(-) delete mode 100644 ports/c667x/ccs/example_build/tx/Release/ccsObjs.opt delete mode 100644 ports/c667x/ccs/example_build/tx/Release/makefile delete mode 100644 ports/c667x/ccs/example_build/tx/Release/objects.mk delete mode 100644 ports/c667x/ccs/example_build/tx/Release/sources.mk delete mode 100644 ports/c667x/ccs/example_build/tx/Release/subdir_rules.mk delete mode 100644 ports/c667x/ccs/example_build/tx/Release/subdir_vars.mk delete mode 100644 ports/cortex_m0/keil/example_build/ThreadX_Demo.uvoptx delete mode 100644 ports/cortex_m0/keil/example_build/ThreadX_Library.uvoptx delete mode 100644 ports/cortex_m23/ac6/example_build/ThreadX_Library.uvoptx delete mode 100644 ports/cortex_m23/ac6/example_build/demo_secure_zone/demo_secure_zone.uvoptx delete mode 100644 ports/cortex_m23/ac6/example_build/demo_threadx_non-secure_zone/ThreadX_Demo.uvopt delete mode 100644 ports/cortex_m23/ac6/example_build/demo_threadx_non-secure_zone/demo_threadx_non-secure_zone.uvoptx delete mode 100644 ports/cortex_m3/keil/example_build/ThreadX_Demo.uvopt delete mode 100644 ports/cortex_m3/keil/example_build/ThreadX_Demo.uvoptx delete mode 100644 ports/cortex_m3/keil/example_build/ThreadX_Library.plg delete mode 100644 ports/cortex_m3/keil/example_build/ThreadX_Library.uvopt delete mode 100644 ports/cortex_m3/keil/example_build/ThreadX_Library.uvoptx delete mode 100644 ports/cortex_m33/ac6/example_build/RTOS.uvmpw.uvgui delete mode 100644 ports/cortex_m33/ac6/example_build/ThreadX_Library.uvoptx delete mode 100644 ports/cortex_m33/ac6/example_build/demo_secure_zone/demo_secure_zone.uvoptx delete mode 100644 ports/cortex_m33/ac6/example_build/demo_threadx_non-secure_zone/ThreadX_Demo.uvopt delete mode 100644 ports/cortex_m33/ac6/example_build/demo_threadx_non-secure_zone/demo_threadx_non-secure_zone.uvoptx delete mode 100644 ports/cortex_m4/keil/example_build/ThreadX_Demo.uvopt delete mode 100644 ports/cortex_m4/keil/example_build/ThreadX_Demo.uvoptx delete mode 100644 ports/cortex_m4/keil/example_build/ThreadX_Library.plg delete mode 100644 ports/cortex_m4/keil/example_build/ThreadX_Library.uvopt delete mode 100644 ports/cortex_m4/keil/example_build/ThreadX_Library.uvoptx delete mode 100644 ports/cortex_m55/ac6/example_build/RTOS.uvmpw.uvgui delete mode 100644 ports/cortex_m55/ac6/example_build/ThreadX_Library.uvoptx delete mode 100644 ports/cortex_m55/ac6/example_build/demo_secure_zone/demo_secure_zone.uvoptx delete mode 100644 ports/cortex_m55/ac6/example_build/demo_threadx_non-secure_zone/ThreadX_Demo.uvopt delete mode 100644 ports/cortex_m55/ac6/example_build/demo_threadx_non-secure_zone/demo_threadx_non-secure_zone.uvoptx delete mode 100644 ports_module/cortex_m23/ac6/example_build/ThreadX_Library.uvoptx delete mode 100644 ports_module/cortex_m23/ac6/example_build/demo_secure_zone/demo_secure_zone.uvoptx delete mode 100644 ports_module/cortex_m23/ac6/example_build/demo_threadx_non-secure_zone/ThreadX_Demo.uvopt delete mode 100644 ports_module/cortex_m23/ac6/example_build/demo_threadx_non-secure_zone/demo_threadx_non-secure_zone.uvoptx delete mode 100644 ports_module/cortex_m23/ac6/example_build/sample_threadx_module/sample_threadx_module.uvoptx delete mode 100644 ports_module/cortex_m23/ac6/example_build/txm/txm.uvoptx delete mode 100644 ports_module/cortex_m33/ac6/example_build/RTOS.uvmpw.uvgui delete mode 100644 ports_module/cortex_m33/ac6/example_build/ThreadX_Library.uvoptx delete mode 100644 ports_module/cortex_m33/ac6/example_build/demo_secure_zone/demo_secure_zone.uvoptx delete mode 100644 ports_module/cortex_m33/ac6/example_build/demo_threadx_non-secure_zone/ThreadX_Demo.uvopt delete mode 100644 ports_module/cortex_m33/ac6/example_build/demo_threadx_non-secure_zone/demo_threadx_non-secure_zone.uvoptx delete mode 100644 ports_module/cortex_m33/ac6/example_build/sample_threadx_module/sample_threadx_module.uvoptx delete mode 100644 ports_module/cortex_m33/ac6/example_build/txm/txm.uvoptx diff --git a/.gitignore b/.gitignore index 6054dbead..cadb24438 100644 --- a/.gitignore +++ b/.gitignore @@ -34,3 +34,10 @@ build_r52_vfp/ build_r52_uart/ build_r52_mpu/ build_r52_all/ + +# Keil uVision per-user state, regenerated when a project is opened. +# The .uvprojx / .uvproj project files are the ones worth tracking. +*.uvoptx +*.uvopt +*.uvgui +*.uvgui.* diff --git a/ports/arm11/gnu/example_build/build_threadx_sample.sh b/ports/arm11/gnu/example_build/build_threadx_sample.sh index 89c55c1d4..93287d531 100755 --- a/ports/arm11/gnu/example_build/build_threadx_sample.sh +++ b/ports/arm11/gnu/example_build/build_threadx_sample.sh @@ -61,5 +61,5 @@ esac "${CC}" ${TARGET_FLAGS} -c -g -mcpu=arm1136j-s crt0.S "${CC}" ${TARGET_FLAGS} -c -g -mcpu=arm1136j-s tx_initialize_low_level.S "${CC}" ${TARGET_FLAGS} -c -g -mcpu=arm1136j-s -I../../../../common/inc -I../inc sample_threadx.c -arm-none-eabi-ld -A arm1136j-s -T sample_threadx.ld reset.o crt0.o tx_initialize_low_level.o sample_threadx.o tx.a libc.a libnosys.a libgcc.a -o sample_threadx.out -M > sample_threadx.map +"${CC}" ${TARGET_FLAGS} -g -nostartfiles -mcpu=arm1136j-s -T sample_threadx.ld ${SYSCALL_LIB} -o sample_threadx.out -Wl,-Map=sample_threadx.map reset.o crt0.o tx_initialize_low_level.o sample_threadx.o tx.a diff --git a/ports/arm9/gnu/example_build/build_threadx_sample.sh b/ports/arm9/gnu/example_build/build_threadx_sample.sh index 3908a75e1..78b3ac7fa 100755 --- a/ports/arm9/gnu/example_build/build_threadx_sample.sh +++ b/ports/arm9/gnu/example_build/build_threadx_sample.sh @@ -61,5 +61,5 @@ esac "${CC}" ${TARGET_FLAGS} -c -g -mcpu=arm9 crt0.S "${CC}" ${TARGET_FLAGS} -c -g -mcpu=arm9 tx_initialize_low_level.S "${CC}" ${TARGET_FLAGS} -c -g -mcpu=arm9 -I../../../../common/inc -I../inc sample_threadx.c -arm-none-eabi-ld -A arm9 -T sample_threadx.ld reset.o crt0.o tx_initialize_low_level.o sample_threadx.o tx.a libc.a libgcc.a -o sample_threadx.out -M > sample_threadx.map +"${CC}" ${TARGET_FLAGS} -g -nostartfiles -mcpu=arm9 -T sample_threadx.ld ${SYSCALL_LIB} -o sample_threadx.out -Wl,-Map=sample_threadx.map reset.o crt0.o tx_initialize_low_level.o sample_threadx.o tx.a diff --git a/ports/c667x/ccs/example_build/tx/Release/ccsObjs.opt b/ports/c667x/ccs/example_build/tx/Release/ccsObjs.opt deleted file mode 100644 index 98982c105..000000000 --- a/ports/c667x/ccs/example_build/tx/Release/ccsObjs.opt +++ /dev/null @@ -1 +0,0 @@ -"./tx_block_allocate.obj" "./tx_block_pool_cleanup.obj" "./tx_block_pool_create.obj" "./tx_block_pool_delete.obj" "./tx_block_pool_info_get.obj" "./tx_block_pool_initialize.obj" "./tx_block_pool_performance_info_get.obj" "./tx_block_pool_performance_system_info_get.obj" "./tx_block_pool_prioritize.obj" "./tx_block_release.obj" "./tx_byte_allocate.obj" "./tx_byte_pool_cleanup.obj" "./tx_byte_pool_create.obj" "./tx_byte_pool_delete.obj" "./tx_byte_pool_info_get.obj" "./tx_byte_pool_initialize.obj" "./tx_byte_pool_performance_info_get.obj" "./tx_byte_pool_performance_system_info_get.obj" "./tx_byte_pool_prioritize.obj" "./tx_byte_pool_search.obj" "./tx_byte_release.obj" "./tx_event_flags_cleanup.obj" "./tx_event_flags_create.obj" "./tx_event_flags_delete.obj" "./tx_event_flags_get.obj" "./tx_event_flags_info_get.obj" "./tx_event_flags_initialize.obj" "./tx_event_flags_performance_info_get.obj" "./tx_event_flags_performance_system_info_get.obj" "./tx_event_flags_set.obj" "./tx_event_flags_set_notify.obj" "./tx_initialize_high_level.obj" "./tx_initialize_kernel_enter.obj" "./tx_initialize_kernel_setup.obj" "./tx_mutex_cleanup.obj" "./tx_mutex_create.obj" "./tx_mutex_delete.obj" "./tx_mutex_get.obj" "./tx_mutex_info_get.obj" "./tx_mutex_initialize.obj" "./tx_mutex_performance_info_get.obj" "./tx_mutex_performance_system_info_get.obj" "./tx_mutex_prioritize.obj" "./tx_mutex_priority_change.obj" "./tx_mutex_put.obj" "./tx_queue_cleanup.obj" "./tx_queue_create.obj" "./tx_queue_delete.obj" "./tx_queue_flush.obj" "./tx_queue_front_send.obj" "./tx_queue_info_get.obj" "./tx_queue_initialize.obj" "./tx_queue_performance_info_get.obj" "./tx_queue_performance_system_info_get.obj" "./tx_queue_prioritize.obj" "./tx_queue_receive.obj" "./tx_queue_send.obj" "./tx_queue_send_notify.obj" "./tx_semaphore_ceiling_put.obj" "./tx_semaphore_cleanup.obj" "./tx_semaphore_create.obj" "./tx_semaphore_delete.obj" "./tx_semaphore_get.obj" "./tx_semaphore_info_get.obj" "./tx_semaphore_initialize.obj" "./tx_semaphore_performance_info_get.obj" "./tx_semaphore_performance_system_info_get.obj" "./tx_semaphore_prioritize.obj" "./tx_semaphore_put.obj" "./tx_semaphore_put_notify.obj" "./tx_thread_context_restore.obj" "./tx_thread_context_save.obj" "./tx_thread_create.obj" "./tx_thread_delete.obj" "./tx_thread_entry_exit_notify.obj" "./tx_thread_identify.obj" "./tx_thread_info_get.obj" "./tx_thread_initialize.obj" "./tx_thread_interrupt_control.obj" "./tx_thread_performance_info_get.obj" "./tx_thread_performance_system_info_get.obj" "./tx_thread_preemption_change.obj" "./tx_thread_priority_change.obj" "./tx_thread_relinquish.obj" "./tx_thread_reset.obj" "./tx_thread_resume.obj" "./tx_thread_schedule.obj" "./tx_thread_shell_entry.obj" "./tx_thread_sleep.obj" "./tx_thread_stack_analyze.obj" "./tx_thread_stack_build.obj" "./tx_thread_stack_error_handler.obj" "./tx_thread_stack_error_notify.obj" "./tx_thread_suspend.obj" "./tx_thread_system_preempt_check.obj" "./tx_thread_system_resume.obj" "./tx_thread_system_return.obj" "./tx_thread_system_suspend.obj" "./tx_thread_terminate.obj" "./tx_thread_time_slice.obj" "./tx_thread_time_slice_change.obj" "./tx_thread_timeout.obj" "./tx_thread_wait_abort.obj" "./tx_time_get.obj" "./tx_time_set.obj" "./tx_timer_activate.obj" "./tx_timer_change.obj" "./tx_timer_create.obj" "./tx_timer_deactivate.obj" "./tx_timer_delete.obj" "./tx_timer_expiration_process.obj" "./tx_timer_info_get.obj" "./tx_timer_initialize.obj" "./tx_timer_interrupt.obj" "./tx_timer_performance_info_get.obj" "./tx_timer_performance_system_info_get.obj" "./tx_timer_system_activate.obj" "./tx_timer_system_deactivate.obj" "./tx_timer_thread_entry.obj" "./tx_trace_buffer_full_notify.obj" "./tx_trace_disable.obj" "./tx_trace_enable.obj" "./tx_trace_event_filter.obj" "./tx_trace_event_unfilter.obj" "./tx_trace_initialize.obj" "./tx_trace_interrupt_control.obj" "./tx_trace_isr_enter_insert.obj" "./tx_trace_isr_exit_insert.obj" "./tx_trace_object_register.obj" "./tx_trace_object_unregister.obj" "./tx_trace_user_event_insert.obj" "./txe_block_allocate.obj" "./txe_block_pool_create.obj" "./txe_block_pool_delete.obj" "./txe_block_pool_info_get.obj" "./txe_block_pool_prioritize.obj" "./txe_block_release.obj" "./txe_byte_allocate.obj" "./txe_byte_pool_create.obj" "./txe_byte_pool_delete.obj" "./txe_byte_pool_info_get.obj" "./txe_byte_pool_prioritize.obj" "./txe_byte_release.obj" "./txe_event_flags_create.obj" "./txe_event_flags_delete.obj" "./txe_event_flags_get.obj" "./txe_event_flags_info_get.obj" "./txe_event_flags_set.obj" "./txe_event_flags_set_notify.obj" "./txe_mutex_create.obj" "./txe_mutex_delete.obj" "./txe_mutex_get.obj" "./txe_mutex_info_get.obj" "./txe_mutex_prioritize.obj" "./txe_mutex_put.obj" "./txe_queue_create.obj" "./txe_queue_delete.obj" "./txe_queue_flush.obj" "./txe_queue_front_send.obj" "./txe_queue_info_get.obj" "./txe_queue_prioritize.obj" "./txe_queue_receive.obj" "./txe_queue_send.obj" "./txe_queue_send_notify.obj" "./txe_semaphore_ceiling_put.obj" "./txe_semaphore_create.obj" "./txe_semaphore_delete.obj" "./txe_semaphore_get.obj" "./txe_semaphore_info_get.obj" "./txe_semaphore_prioritize.obj" "./txe_semaphore_put.obj" "./txe_semaphore_put_notify.obj" "./txe_thread_create.obj" "./txe_thread_delete.obj" "./txe_thread_entry_exit_notify.obj" "./txe_thread_info_get.obj" "./txe_thread_preemption_change.obj" "./txe_thread_priority_change.obj" "./txe_thread_relinquish.obj" "./txe_thread_reset.obj" "./txe_thread_resume.obj" "./txe_thread_suspend.obj" "./txe_thread_terminate.obj" "./txe_thread_time_slice_change.obj" "./txe_thread_wait_abort.obj" "./txe_timer_activate.obj" "./txe_timer_change.obj" "./txe_timer_create.obj" "./txe_timer_deactivate.obj" "./txe_timer_delete.obj" "./txe_timer_info_get.obj" \ No newline at end of file diff --git a/ports/c667x/ccs/example_build/tx/Release/makefile b/ports/c667x/ccs/example_build/tx/Release/makefile deleted file mode 100644 index 10d8815d5..000000000 --- a/ports/c667x/ccs/example_build/tx/Release/makefile +++ /dev/null @@ -1,351 +0,0 @@ -################################################################################ -# Automatically-generated file. Do not edit! -################################################################################ - -SHELL = cmd.exe - -CG_TOOL_ROOT := C:/ti/ccsv8/tools/compiler/ti-cgt-c6000_8.2.4 - -GEN_OPTS__FLAG := -GEN_CMDS__FLAG := - -ORDERED_OBJS += \ -"./tx_block_allocate.obj" \ -"./tx_block_pool_cleanup.obj" \ -"./tx_block_pool_create.obj" \ -"./tx_block_pool_delete.obj" \ -"./tx_block_pool_info_get.obj" \ -"./tx_block_pool_initialize.obj" \ -"./tx_block_pool_performance_info_get.obj" \ -"./tx_block_pool_performance_system_info_get.obj" \ -"./tx_block_pool_prioritize.obj" \ -"./tx_block_release.obj" \ -"./tx_byte_allocate.obj" \ -"./tx_byte_pool_cleanup.obj" \ -"./tx_byte_pool_create.obj" \ -"./tx_byte_pool_delete.obj" \ -"./tx_byte_pool_info_get.obj" \ -"./tx_byte_pool_initialize.obj" \ -"./tx_byte_pool_performance_info_get.obj" \ -"./tx_byte_pool_performance_system_info_get.obj" \ -"./tx_byte_pool_prioritize.obj" \ -"./tx_byte_pool_search.obj" \ -"./tx_byte_release.obj" \ -"./tx_event_flags_cleanup.obj" \ -"./tx_event_flags_create.obj" \ -"./tx_event_flags_delete.obj" \ -"./tx_event_flags_get.obj" \ -"./tx_event_flags_info_get.obj" \ -"./tx_event_flags_initialize.obj" \ -"./tx_event_flags_performance_info_get.obj" \ -"./tx_event_flags_performance_system_info_get.obj" \ -"./tx_event_flags_set.obj" \ -"./tx_event_flags_set_notify.obj" \ -"./tx_initialize_high_level.obj" \ -"./tx_initialize_kernel_enter.obj" \ -"./tx_initialize_kernel_setup.obj" \ -"./tx_mutex_cleanup.obj" \ -"./tx_mutex_create.obj" \ -"./tx_mutex_delete.obj" \ -"./tx_mutex_get.obj" \ -"./tx_mutex_info_get.obj" \ -"./tx_mutex_initialize.obj" \ -"./tx_mutex_performance_info_get.obj" \ -"./tx_mutex_performance_system_info_get.obj" \ -"./tx_mutex_prioritize.obj" \ -"./tx_mutex_priority_change.obj" \ -"./tx_mutex_put.obj" \ -"./tx_queue_cleanup.obj" \ -"./tx_queue_create.obj" \ -"./tx_queue_delete.obj" \ -"./tx_queue_flush.obj" \ -"./tx_queue_front_send.obj" \ -"./tx_queue_info_get.obj" \ -"./tx_queue_initialize.obj" \ -"./tx_queue_performance_info_get.obj" \ -"./tx_queue_performance_system_info_get.obj" \ -"./tx_queue_prioritize.obj" \ -"./tx_queue_receive.obj" \ -"./tx_queue_send.obj" \ -"./tx_queue_send_notify.obj" \ -"./tx_semaphore_ceiling_put.obj" \ -"./tx_semaphore_cleanup.obj" \ -"./tx_semaphore_create.obj" \ -"./tx_semaphore_delete.obj" \ -"./tx_semaphore_get.obj" \ -"./tx_semaphore_info_get.obj" \ -"./tx_semaphore_initialize.obj" \ -"./tx_semaphore_performance_info_get.obj" \ -"./tx_semaphore_performance_system_info_get.obj" \ -"./tx_semaphore_prioritize.obj" \ -"./tx_semaphore_put.obj" \ -"./tx_semaphore_put_notify.obj" \ -"./tx_thread_context_restore.obj" \ -"./tx_thread_context_save.obj" \ -"./tx_thread_create.obj" \ -"./tx_thread_delete.obj" \ -"./tx_thread_entry_exit_notify.obj" \ -"./tx_thread_identify.obj" \ -"./tx_thread_info_get.obj" \ -"./tx_thread_initialize.obj" \ -"./tx_thread_interrupt_control.obj" \ -"./tx_thread_performance_info_get.obj" \ -"./tx_thread_performance_system_info_get.obj" \ -"./tx_thread_preemption_change.obj" \ -"./tx_thread_priority_change.obj" \ -"./tx_thread_relinquish.obj" \ -"./tx_thread_reset.obj" \ -"./tx_thread_resume.obj" \ -"./tx_thread_schedule.obj" \ -"./tx_thread_shell_entry.obj" \ -"./tx_thread_sleep.obj" \ -"./tx_thread_stack_analyze.obj" \ -"./tx_thread_stack_build.obj" \ -"./tx_thread_stack_error_handler.obj" \ -"./tx_thread_stack_error_notify.obj" \ -"./tx_thread_suspend.obj" \ -"./tx_thread_system_preempt_check.obj" \ -"./tx_thread_system_resume.obj" \ -"./tx_thread_system_return.obj" \ -"./tx_thread_system_suspend.obj" \ -"./tx_thread_terminate.obj" \ -"./tx_thread_time_slice.obj" \ -"./tx_thread_time_slice_change.obj" \ -"./tx_thread_timeout.obj" \ -"./tx_thread_wait_abort.obj" \ -"./tx_time_get.obj" \ -"./tx_time_set.obj" \ -"./tx_timer_activate.obj" \ -"./tx_timer_change.obj" \ -"./tx_timer_create.obj" \ -"./tx_timer_deactivate.obj" \ -"./tx_timer_delete.obj" \ -"./tx_timer_expiration_process.obj" \ -"./tx_timer_info_get.obj" \ -"./tx_timer_initialize.obj" \ -"./tx_timer_interrupt.obj" \ -"./tx_timer_performance_info_get.obj" \ -"./tx_timer_performance_system_info_get.obj" \ -"./tx_timer_system_activate.obj" \ -"./tx_timer_system_deactivate.obj" \ -"./tx_timer_thread_entry.obj" \ -"./tx_trace_buffer_full_notify.obj" \ -"./tx_trace_disable.obj" \ -"./tx_trace_enable.obj" \ -"./tx_trace_event_filter.obj" \ -"./tx_trace_event_unfilter.obj" \ -"./tx_trace_initialize.obj" \ -"./tx_trace_interrupt_control.obj" \ -"./tx_trace_isr_enter_insert.obj" \ -"./tx_trace_isr_exit_insert.obj" \ -"./tx_trace_object_register.obj" \ -"./tx_trace_object_unregister.obj" \ -"./tx_trace_user_event_insert.obj" \ -"./txe_block_allocate.obj" \ -"./txe_block_pool_create.obj" \ -"./txe_block_pool_delete.obj" \ -"./txe_block_pool_info_get.obj" \ -"./txe_block_pool_prioritize.obj" \ -"./txe_block_release.obj" \ -"./txe_byte_allocate.obj" \ -"./txe_byte_pool_create.obj" \ -"./txe_byte_pool_delete.obj" \ -"./txe_byte_pool_info_get.obj" \ -"./txe_byte_pool_prioritize.obj" \ -"./txe_byte_release.obj" \ -"./txe_event_flags_create.obj" \ -"./txe_event_flags_delete.obj" \ -"./txe_event_flags_get.obj" \ -"./txe_event_flags_info_get.obj" \ -"./txe_event_flags_set.obj" \ -"./txe_event_flags_set_notify.obj" \ -"./txe_mutex_create.obj" \ -"./txe_mutex_delete.obj" \ -"./txe_mutex_get.obj" \ -"./txe_mutex_info_get.obj" \ -"./txe_mutex_prioritize.obj" \ -"./txe_mutex_put.obj" \ -"./txe_queue_create.obj" \ -"./txe_queue_delete.obj" \ -"./txe_queue_flush.obj" \ -"./txe_queue_front_send.obj" \ -"./txe_queue_info_get.obj" \ -"./txe_queue_prioritize.obj" \ -"./txe_queue_receive.obj" \ -"./txe_queue_send.obj" \ -"./txe_queue_send_notify.obj" \ -"./txe_semaphore_ceiling_put.obj" \ -"./txe_semaphore_create.obj" \ -"./txe_semaphore_delete.obj" \ -"./txe_semaphore_get.obj" \ -"./txe_semaphore_info_get.obj" \ -"./txe_semaphore_prioritize.obj" \ -"./txe_semaphore_put.obj" \ -"./txe_semaphore_put_notify.obj" \ -"./txe_thread_create.obj" \ -"./txe_thread_delete.obj" \ -"./txe_thread_entry_exit_notify.obj" \ -"./txe_thread_info_get.obj" \ -"./txe_thread_preemption_change.obj" \ -"./txe_thread_priority_change.obj" \ -"./txe_thread_relinquish.obj" \ -"./txe_thread_reset.obj" \ -"./txe_thread_resume.obj" \ -"./txe_thread_suspend.obj" \ -"./txe_thread_terminate.obj" \ -"./txe_thread_time_slice_change.obj" \ -"./txe_thread_wait_abort.obj" \ -"./txe_timer_activate.obj" \ -"./txe_timer_change.obj" \ -"./txe_timer_create.obj" \ -"./txe_timer_deactivate.obj" \ -"./txe_timer_delete.obj" \ -"./txe_timer_info_get.obj" \ - --include ../makefile.init - -RM := DEL /F -RMDIR := RMDIR /S/Q - -# All of the sources participating in the build are defined here --include sources.mk --include subdir_vars.mk --include subdir_rules.mk --include objects.mk - -ifneq ($(MAKECMDGOALS),clean) -ifneq ($(strip $(C55_DEPS)),) --include $(C55_DEPS) -endif -ifneq ($(strip $(C_UPPER_DEPS)),) --include $(C_UPPER_DEPS) -endif -ifneq ($(strip $(S67_DEPS)),) --include $(S67_DEPS) -endif -ifneq ($(strip $(S62_DEPS)),) --include $(S62_DEPS) -endif -ifneq ($(strip $(S_DEPS)),) --include $(S_DEPS) -endif -ifneq ($(strip $(OPT_DEPS)),) --include $(OPT_DEPS) -endif -ifneq ($(strip $(C??_DEPS)),) --include $(C??_DEPS) -endif -ifneq ($(strip $(ASM_UPPER_DEPS)),) --include $(ASM_UPPER_DEPS) -endif -ifneq ($(strip $(S??_DEPS)),) --include $(S??_DEPS) -endif -ifneq ($(strip $(C64_DEPS)),) --include $(C64_DEPS) -endif -ifneq ($(strip $(CXX_DEPS)),) --include $(CXX_DEPS) -endif -ifneq ($(strip $(S64_DEPS)),) --include $(S64_DEPS) -endif -ifneq ($(strip $(INO_DEPS)),) --include $(INO_DEPS) -endif -ifneq ($(strip $(CLA_DEPS)),) --include $(CLA_DEPS) -endif -ifneq ($(strip $(S55_DEPS)),) --include $(S55_DEPS) -endif -ifneq ($(strip $(SV7A_DEPS)),) --include $(SV7A_DEPS) -endif -ifneq ($(strip $(C62_DEPS)),) --include $(C62_DEPS) -endif -ifneq ($(strip $(C67_DEPS)),) --include $(C67_DEPS) -endif -ifneq ($(strip $(PDE_DEPS)),) --include $(PDE_DEPS) -endif -ifneq ($(strip $(K_DEPS)),) --include $(K_DEPS) -endif -ifneq ($(strip $(C_DEPS)),) --include $(C_DEPS) -endif -ifneq ($(strip $(CC_DEPS)),) --include $(CC_DEPS) -endif -ifneq ($(strip $(C++_DEPS)),) --include $(C++_DEPS) -endif -ifneq ($(strip $(C43_DEPS)),) --include $(C43_DEPS) -endif -ifneq ($(strip $(S43_DEPS)),) --include $(S43_DEPS) -endif -ifneq ($(strip $(ASM_DEPS)),) --include $(ASM_DEPS) -endif -ifneq ($(strip $(S_UPPER_DEPS)),) --include $(S_UPPER_DEPS) -endif -ifneq ($(strip $(CPP_DEPS)),) --include $(CPP_DEPS) -endif -ifneq ($(strip $(SA_DEPS)),) --include $(SA_DEPS) -endif -endif - --include ../makefile.defs - -# Add inputs and outputs from these tool invocations to the build variables -LIB_OUTPUTS += \ -tx.lib \ - -LIB_OUTPUTS__QUOTED += \ -"tx.lib" \ - - -# All Target -all: tx.lib - -# Tool invocations -tx.lib: $(OBJS) $(OBJ_SRCS) $(LIB_SRCS) -ifneq ($(strip $(ORDERED_OBJS)),) - @echo 'Building target: "$@"' - @echo 'Invoking: C6000 Archiver' - "C:/ti/ccsv8/tools/compiler/ti-cgt-c6000_8.2.4/bin/ar6x" r "tx.lib" $(ORDERED_OBJS) - @echo 'Finished building target: "$@"' - @echo ' ' -endif - -# Other Targets -clean: - -$(RM) $(LIB_OUTPUTS__QUOTED) - -$(RM) "tx_block_allocate.obj" "tx_block_pool_cleanup.obj" "tx_block_pool_create.obj" "tx_block_pool_delete.obj" "tx_block_pool_info_get.obj" "tx_block_pool_initialize.obj" "tx_block_pool_performance_info_get.obj" "tx_block_pool_performance_system_info_get.obj" "tx_block_pool_prioritize.obj" "tx_block_release.obj" "tx_byte_allocate.obj" "tx_byte_pool_cleanup.obj" "tx_byte_pool_create.obj" "tx_byte_pool_delete.obj" "tx_byte_pool_info_get.obj" "tx_byte_pool_initialize.obj" "tx_byte_pool_performance_info_get.obj" "tx_byte_pool_performance_system_info_get.obj" "tx_byte_pool_prioritize.obj" "tx_byte_pool_search.obj" "tx_byte_release.obj" "tx_event_flags_cleanup.obj" "tx_event_flags_create.obj" "tx_event_flags_delete.obj" "tx_event_flags_get.obj" "tx_event_flags_info_get.obj" "tx_event_flags_initialize.obj" "tx_event_flags_performance_info_get.obj" "tx_event_flags_performance_system_info_get.obj" "tx_event_flags_set.obj" "tx_event_flags_set_notify.obj" "tx_initialize_high_level.obj" "tx_initialize_kernel_enter.obj" - -$(RM) "tx_initialize_kernel_setup.obj" "tx_mutex_cleanup.obj" "tx_mutex_create.obj" "tx_mutex_delete.obj" "tx_mutex_get.obj" "tx_mutex_info_get.obj" "tx_mutex_initialize.obj" "tx_mutex_performance_info_get.obj" "tx_mutex_performance_system_info_get.obj" "tx_mutex_prioritize.obj" "tx_mutex_priority_change.obj" "tx_mutex_put.obj" "tx_queue_cleanup.obj" "tx_queue_create.obj" "tx_queue_delete.obj" "tx_queue_flush.obj" "tx_queue_front_send.obj" "tx_queue_info_get.obj" "tx_queue_initialize.obj" "tx_queue_performance_info_get.obj" "tx_queue_performance_system_info_get.obj" "tx_queue_prioritize.obj" "tx_queue_receive.obj" "tx_queue_send.obj" "tx_queue_send_notify.obj" "tx_semaphore_ceiling_put.obj" "tx_semaphore_cleanup.obj" "tx_semaphore_create.obj" "tx_semaphore_delete.obj" "tx_semaphore_get.obj" "tx_semaphore_info_get.obj" "tx_semaphore_initialize.obj" "tx_semaphore_performance_info_get.obj" "tx_semaphore_performance_system_info_get.obj" "tx_semaphore_prioritize.obj" "tx_semaphore_put.obj" "tx_semaphore_put_notify.obj" - -$(RM) "tx_thread_context_restore.obj" "tx_thread_context_save.obj" "tx_thread_create.obj" "tx_thread_delete.obj" "tx_thread_entry_exit_notify.obj" "tx_thread_identify.obj" "tx_thread_info_get.obj" "tx_thread_initialize.obj" "tx_thread_interrupt_control.obj" "tx_thread_performance_info_get.obj" "tx_thread_performance_system_info_get.obj" "tx_thread_preemption_change.obj" "tx_thread_priority_change.obj" "tx_thread_relinquish.obj" "tx_thread_reset.obj" "tx_thread_resume.obj" "tx_thread_schedule.obj" "tx_thread_shell_entry.obj" "tx_thread_sleep.obj" "tx_thread_stack_analyze.obj" "tx_thread_stack_build.obj" "tx_thread_stack_error_handler.obj" "tx_thread_stack_error_notify.obj" "tx_thread_suspend.obj" "tx_thread_system_preempt_check.obj" "tx_thread_system_resume.obj" "tx_thread_system_return.obj" "tx_thread_system_suspend.obj" "tx_thread_terminate.obj" "tx_thread_time_slice.obj" "tx_thread_time_slice_change.obj" "tx_thread_timeout.obj" "tx_thread_wait_abort.obj" "tx_time_get.obj" "tx_time_set.obj" - -$(RM) "tx_timer_activate.obj" "tx_timer_change.obj" "tx_timer_create.obj" "tx_timer_deactivate.obj" "tx_timer_delete.obj" "tx_timer_expiration_process.obj" "tx_timer_info_get.obj" "tx_timer_initialize.obj" "tx_timer_interrupt.obj" "tx_timer_performance_info_get.obj" "tx_timer_performance_system_info_get.obj" "tx_timer_system_activate.obj" "tx_timer_system_deactivate.obj" "tx_timer_thread_entry.obj" "tx_trace_buffer_full_notify.obj" "tx_trace_disable.obj" "tx_trace_enable.obj" "tx_trace_event_filter.obj" "tx_trace_event_unfilter.obj" "tx_trace_initialize.obj" "tx_trace_interrupt_control.obj" "tx_trace_isr_enter_insert.obj" "tx_trace_isr_exit_insert.obj" "tx_trace_object_register.obj" "tx_trace_object_unregister.obj" "tx_trace_user_event_insert.obj" "txe_block_allocate.obj" "txe_block_pool_create.obj" "txe_block_pool_delete.obj" "txe_block_pool_info_get.obj" "txe_block_pool_prioritize.obj" "txe_block_release.obj" "txe_byte_allocate.obj" "txe_byte_pool_create.obj" "txe_byte_pool_delete.obj" "txe_byte_pool_info_get.obj" - -$(RM) "txe_byte_pool_prioritize.obj" "txe_byte_release.obj" "txe_event_flags_create.obj" "txe_event_flags_delete.obj" "txe_event_flags_get.obj" "txe_event_flags_info_get.obj" "txe_event_flags_set.obj" "txe_event_flags_set_notify.obj" "txe_mutex_create.obj" "txe_mutex_delete.obj" "txe_mutex_get.obj" "txe_mutex_info_get.obj" "txe_mutex_prioritize.obj" "txe_mutex_put.obj" "txe_queue_create.obj" "txe_queue_delete.obj" "txe_queue_flush.obj" "txe_queue_front_send.obj" "txe_queue_info_get.obj" "txe_queue_prioritize.obj" "txe_queue_receive.obj" "txe_queue_send.obj" "txe_queue_send_notify.obj" "txe_semaphore_ceiling_put.obj" "txe_semaphore_create.obj" "txe_semaphore_delete.obj" "txe_semaphore_get.obj" "txe_semaphore_info_get.obj" "txe_semaphore_prioritize.obj" "txe_semaphore_put.obj" "txe_semaphore_put_notify.obj" "txe_thread_create.obj" "txe_thread_delete.obj" "txe_thread_entry_exit_notify.obj" "txe_thread_info_get.obj" "txe_thread_preemption_change.obj" "txe_thread_priority_change.obj" "txe_thread_relinquish.obj" - -$(RM) "txe_thread_reset.obj" "txe_thread_resume.obj" "txe_thread_suspend.obj" "txe_thread_terminate.obj" "txe_thread_time_slice_change.obj" "txe_thread_wait_abort.obj" "txe_timer_activate.obj" "txe_timer_change.obj" "txe_timer_create.obj" "txe_timer_deactivate.obj" "txe_timer_delete.obj" "txe_timer_info_get.obj" - -$(RM) "tx_block_allocate.d" "tx_block_pool_cleanup.d" "tx_block_pool_create.d" "tx_block_pool_delete.d" "tx_block_pool_info_get.d" "tx_block_pool_initialize.d" "tx_block_pool_performance_info_get.d" "tx_block_pool_performance_system_info_get.d" "tx_block_pool_prioritize.d" "tx_block_release.d" "tx_byte_allocate.d" "tx_byte_pool_cleanup.d" "tx_byte_pool_create.d" "tx_byte_pool_delete.d" "tx_byte_pool_info_get.d" "tx_byte_pool_initialize.d" "tx_byte_pool_performance_info_get.d" "tx_byte_pool_performance_system_info_get.d" "tx_byte_pool_prioritize.d" "tx_byte_pool_search.d" "tx_byte_release.d" "tx_event_flags_cleanup.d" "tx_event_flags_create.d" "tx_event_flags_delete.d" "tx_event_flags_get.d" "tx_event_flags_info_get.d" "tx_event_flags_initialize.d" "tx_event_flags_performance_info_get.d" "tx_event_flags_performance_system_info_get.d" "tx_event_flags_set.d" "tx_event_flags_set_notify.d" "tx_initialize_high_level.d" "tx_initialize_kernel_enter.d" "tx_initialize_kernel_setup.d" "tx_mutex_cleanup.d" - -$(RM) "tx_mutex_create.d" "tx_mutex_delete.d" "tx_mutex_get.d" "tx_mutex_info_get.d" "tx_mutex_initialize.d" "tx_mutex_performance_info_get.d" "tx_mutex_performance_system_info_get.d" "tx_mutex_prioritize.d" "tx_mutex_priority_change.d" "tx_mutex_put.d" "tx_queue_cleanup.d" "tx_queue_create.d" "tx_queue_delete.d" "tx_queue_flush.d" "tx_queue_front_send.d" "tx_queue_info_get.d" "tx_queue_initialize.d" "tx_queue_performance_info_get.d" "tx_queue_performance_system_info_get.d" "tx_queue_prioritize.d" "tx_queue_receive.d" "tx_queue_send.d" "tx_queue_send_notify.d" "tx_semaphore_ceiling_put.d" "tx_semaphore_cleanup.d" "tx_semaphore_create.d" "tx_semaphore_delete.d" "tx_semaphore_get.d" "tx_semaphore_info_get.d" "tx_semaphore_initialize.d" "tx_semaphore_performance_info_get.d" "tx_semaphore_performance_system_info_get.d" "tx_semaphore_prioritize.d" "tx_semaphore_put.d" "tx_semaphore_put_notify.d" "tx_thread_create.d" "tx_thread_delete.d" "tx_thread_entry_exit_notify.d" "tx_thread_identify.d" "tx_thread_info_get.d" - -$(RM) "tx_thread_initialize.d" "tx_thread_performance_info_get.d" "tx_thread_performance_system_info_get.d" "tx_thread_preemption_change.d" "tx_thread_priority_change.d" "tx_thread_relinquish.d" "tx_thread_reset.d" "tx_thread_resume.d" "tx_thread_shell_entry.d" "tx_thread_sleep.d" "tx_thread_stack_analyze.d" "tx_thread_stack_error_handler.d" "tx_thread_stack_error_notify.d" "tx_thread_suspend.d" "tx_thread_system_preempt_check.d" "tx_thread_system_resume.d" "tx_thread_system_suspend.d" "tx_thread_terminate.d" "tx_thread_time_slice.d" "tx_thread_time_slice_change.d" "tx_thread_timeout.d" "tx_thread_wait_abort.d" "tx_time_get.d" "tx_time_set.d" "tx_timer_activate.d" "tx_timer_change.d" "tx_timer_create.d" "tx_timer_deactivate.d" "tx_timer_delete.d" "tx_timer_expiration_process.d" "tx_timer_info_get.d" "tx_timer_initialize.d" "tx_timer_performance_info_get.d" "tx_timer_performance_system_info_get.d" "tx_timer_system_activate.d" "tx_timer_system_deactivate.d" "tx_timer_thread_entry.d" "tx_trace_buffer_full_notify.d" - -$(RM) "tx_trace_disable.d" "tx_trace_enable.d" "tx_trace_event_filter.d" "tx_trace_event_unfilter.d" "tx_trace_initialize.d" "tx_trace_interrupt_control.d" "tx_trace_isr_enter_insert.d" "tx_trace_isr_exit_insert.d" "tx_trace_object_register.d" "tx_trace_object_unregister.d" "tx_trace_user_event_insert.d" "txe_block_allocate.d" "txe_block_pool_create.d" "txe_block_pool_delete.d" "txe_block_pool_info_get.d" "txe_block_pool_prioritize.d" "txe_block_release.d" "txe_byte_allocate.d" "txe_byte_pool_create.d" "txe_byte_pool_delete.d" "txe_byte_pool_info_get.d" "txe_byte_pool_prioritize.d" "txe_byte_release.d" "txe_event_flags_create.d" "txe_event_flags_delete.d" "txe_event_flags_get.d" "txe_event_flags_info_get.d" "txe_event_flags_set.d" "txe_event_flags_set_notify.d" "txe_mutex_create.d" "txe_mutex_delete.d" "txe_mutex_get.d" "txe_mutex_info_get.d" "txe_mutex_prioritize.d" "txe_mutex_put.d" "txe_queue_create.d" "txe_queue_delete.d" "txe_queue_flush.d" "txe_queue_front_send.d" "txe_queue_info_get.d" - -$(RM) "txe_queue_prioritize.d" "txe_queue_receive.d" "txe_queue_send.d" "txe_queue_send_notify.d" "txe_semaphore_ceiling_put.d" "txe_semaphore_create.d" "txe_semaphore_delete.d" "txe_semaphore_get.d" "txe_semaphore_info_get.d" "txe_semaphore_prioritize.d" "txe_semaphore_put.d" "txe_semaphore_put_notify.d" "txe_thread_create.d" "txe_thread_delete.d" "txe_thread_entry_exit_notify.d" "txe_thread_info_get.d" "txe_thread_preemption_change.d" "txe_thread_priority_change.d" "txe_thread_relinquish.d" "txe_thread_reset.d" "txe_thread_resume.d" "txe_thread_suspend.d" "txe_thread_terminate.d" "txe_thread_time_slice_change.d" "txe_thread_wait_abort.d" "txe_timer_activate.d" "txe_timer_change.d" "txe_timer_create.d" "txe_timer_deactivate.d" "txe_timer_delete.d" "txe_timer_info_get.d" - -$(RM) "tx_thread_context_restore.d" "tx_thread_context_save.d" "tx_thread_interrupt_control.d" "tx_thread_schedule.d" "tx_thread_stack_build.d" "tx_thread_system_return.d" "tx_timer_interrupt.d" - -@echo 'Finished clean' - -@echo ' ' - -.PHONY: all clean dependents -.SECONDARY: - --include ../makefile.targets - diff --git a/ports/c667x/ccs/example_build/tx/Release/objects.mk b/ports/c667x/ccs/example_build/tx/Release/objects.mk deleted file mode 100644 index 742c2da04..000000000 --- a/ports/c667x/ccs/example_build/tx/Release/objects.mk +++ /dev/null @@ -1,8 +0,0 @@ -################################################################################ -# Automatically-generated file. Do not edit! -################################################################################ - -USER_OBJS := - -LIBS := - diff --git a/ports/c667x/ccs/example_build/tx/Release/sources.mk b/ports/c667x/ccs/example_build/tx/Release/sources.mk deleted file mode 100644 index 95c7e8c3e..000000000 --- a/ports/c667x/ccs/example_build/tx/Release/sources.mk +++ /dev/null @@ -1,110 +0,0 @@ -################################################################################ -# Automatically-generated file. Do not edit! -################################################################################ - -C55_SRCS := -A_SRCS := -ASM_UPPER_SRCS := -LDS_UPPER_SRCS := -CPP_SRCS := -CMD_SRCS := -O_SRCS := -C??_SRCS := -C64_SRCS := -C67_SRCS := -SA_SRCS := -S64_SRCS := -OPT_SRCS := -CXX_SRCS := -S67_SRCS := -S??_SRCS := -PDE_SRCS := -SV7A_SRCS := -K_SRCS := -CLA_SRCS := -S55_SRCS := -LD_UPPER_SRCS := -INO_SRCS := -LIB_SRCS := -ASM_SRCS := -S_UPPER_SRCS := -S43_SRCS := -LD_SRCS := -CMD_UPPER_SRCS := -C_UPPER_SRCS := -C++_SRCS := -C43_SRCS := -OBJ_SRCS := -LDS_SRCS := -S_SRCS := -CC_SRCS := -S62_SRCS := -C62_SRCS := -C_SRCS := -C55_DEPS := -C_UPPER_DEPS := -S67_DEPS := -S62_DEPS := -S_DEPS := -OPT_DEPS := -C??_DEPS := -ASM_UPPER_DEPS := -S??_DEPS := -C64_DEPS := -CXX_DEPS := -S64_DEPS := -INO_DEPS := -CLA_DEPS := -S55_DEPS := -SV7A_DEPS := -C62_DEPS := -C67_DEPS := -PDE_DEPS := -K_DEPS := -C_DEPS := -LIB_OUTPUTS := -CC_DEPS := -C++_DEPS := -C43_DEPS := -S43_DEPS := -OBJS := -ASM_DEPS := -S_UPPER_DEPS := -CPP_DEPS := -SA_DEPS := -C++_DEPS__QUOTED := -OPT_DEPS__QUOTED := -S_UPPER_DEPS__QUOTED := -SA_DEPS__QUOTED := -C??_DEPS__QUOTED := -S67_DEPS__QUOTED := -C55_DEPS__QUOTED := -CC_DEPS__QUOTED := -ASM_UPPER_DEPS__QUOTED := -SV7A_DEPS__QUOTED := -S??_DEPS__QUOTED := -OBJS__QUOTED := -C67_DEPS__QUOTED := -LIB_OUTPUTS__QUOTED := -K_DEPS__QUOTED := -S55_DEPS__QUOTED := -INO_DEPS__QUOTED := -C62_DEPS__QUOTED := -C_DEPS__QUOTED := -C_UPPER_DEPS__QUOTED := -C43_DEPS__QUOTED := -CPP_DEPS__QUOTED := -C64_DEPS__QUOTED := -CXX_DEPS__QUOTED := -CLA_DEPS__QUOTED := -S_DEPS__QUOTED := -ASM_DEPS__QUOTED := -S43_DEPS__QUOTED := -S64_DEPS__QUOTED := -S62_DEPS__QUOTED := -PDE_DEPS__QUOTED := - -# Every subdirectory with source files must be described here -SUBDIRS := \ -. \ - diff --git a/ports/c667x/ccs/example_build/tx/Release/subdir_rules.mk b/ports/c667x/ccs/example_build/tx/Release/subdir_rules.mk deleted file mode 100644 index 6ceea2dd3..000000000 --- a/ports/c667x/ccs/example_build/tx/Release/subdir_rules.mk +++ /dev/null @@ -1,22 +0,0 @@ -################################################################################ -# Automatically-generated file. Do not edit! -################################################################################ - -SHELL = cmd.exe - -# Each subdirectory must supply rules for building sources it contributes -%.obj: ../%.c $(GEN_OPTS) | $(GEN_FILES) - @echo 'Building file: "$<"' - @echo 'Invoking: C6000 Compiler' - "C:/ti/ccsv8/tools/compiler/ti-cgt-c6000_8.2.4/bin/cl6x" -mv6600 --abi=eabi -O2 --include_path="C:/ti/ccsv8/tools/compiler/ti-cgt-c6000_8.2.4/include" --display_error_number --diag_warning=225 --preproc_with_compile --preproc_dependency="$(basename $( - - - 1.0 - -

### uVision Project, (C) Keil Software
- - - *.c - *.s*; *.src; *.a* - *.obj; *.o - *.lib - *.txt; *.h; *.inc; *.md - *.plm - *.cpp - 0 - - - - 0 - 0 - - - - ThreadX_Demo - 0x4 - ARM-ADS - - 12000000 - - 0 - 1 - 0 - 1 - 0 - - - 1 - 65535 - 0 - 0 - 0 - - - 79 - 66 - 8 - .\Listings\ - - - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - - - 0 - 0 - 1 - - 0 - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 1 - 1 - 0 - 0 - 1 - 0 - 0 - 0 - - - - - - - - - - - BIN\UL2CM3.DLL - - - - 0 - UL2CM3 - UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000) - - - - - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - - - - - - - - - - - - - src - 1 - 0 - 0 - 0 - - 1 - 1 - 1 - 0 - 0 - 0 - .\sample_threadx.c - sample_threadx.c - 0 - 0 - - - 1 - 2 - 2 - 0 - 0 - 0 - .\tx_initialize_low_level.s - tx_initialize_low_level.s - 0 - 0 - - - - - lib - 1 - 0 - 0 - 0 - - 2 - 3 - 4 - 0 - 0 - 0 - .\Objects\tx.lib - tx.lib - 0 - 0 - - - - diff --git a/ports/cortex_m0/keil/example_build/ThreadX_Library.uvoptx b/ports/cortex_m0/keil/example_build/ThreadX_Library.uvoptx deleted file mode 100644 index f4611e5cc..000000000 --- a/ports/cortex_m0/keil/example_build/ThreadX_Library.uvoptx +++ /dev/null @@ -1,2672 +0,0 @@ - - - - 1.0 - -
### uVision Project, (C) Keil Software
- - - *.c - *.s*; *.src; *.a* - *.obj; *.o - *.lib - *.txt; *.h; *.inc; *.md - *.plm - *.cpp - 0 - - - - 0 - 0 - - - - ThreadX_Library_Project - 0x4 - ARM-ADS - - 12000000 - - 0 - 1 - 0 - 1 - 0 - - - 1 - 65535 - 0 - 0 - 0 - - - 79 - 66 - 8 - .\Listings\ - - - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - - - 0 - 0 - 1 - - 0 - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 1 - 1 - 0 - 0 - 1 - 0 - 0 - 0 - - - - - - - - - - - BIN\UL2CM3.DLL - - - - 0 - UL2CM3 - UL2CM3(-S0 -C0 -P0 -FD20000000 -FC1000) - - - - - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - - - - - - - - - - - - - inc - 0 - 0 - 0 - 0 - - 1 - 1 - 5 - 0 - 0 - 0 - ..\inc\tx_port.h - tx_port.h - 0 - 0 - - - 1 - 2 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_api.h - tx_api.h - 0 - 0 - - - 1 - 3 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_block_pool.h - tx_block_pool.h - 0 - 0 - - - 1 - 4 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_byte_pool.h - tx_byte_pool.h - 0 - 0 - - - 1 - 5 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_event_flags.h - tx_event_flags.h - 0 - 0 - - - 1 - 6 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_initialize.h - tx_initialize.h - 0 - 0 - - - 1 - 7 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_mutex.h - tx_mutex.h - 0 - 0 - - - 1 - 8 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_queue.h - tx_queue.h - 0 - 0 - - - 1 - 9 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_semaphore.h - tx_semaphore.h - 0 - 0 - - - 1 - 10 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_thread.h - tx_thread.h - 0 - 0 - - - 1 - 11 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_timer.h - tx_timer.h - 0 - 0 - - - 1 - 12 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_trace.h - tx_trace.h - 0 - 0 - - - 1 - 13 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_user_sample.h - tx_user_sample.h - 0 - 0 - - - - - src - 0 - 0 - 0 - 0 - - 2 - 14 - 2 - 0 - 0 - 0 - ..\src\tx_thread_context_restore.s - tx_thread_context_restore.s - 0 - 0 - - - 2 - 15 - 2 - 0 - 0 - 0 - ..\src\tx_thread_context_save.s - tx_thread_context_save.s - 0 - 0 - - - 2 - 16 - 2 - 0 - 0 - 0 - ..\src\tx_thread_interrupt_control.s - tx_thread_interrupt_control.s - 0 - 0 - - - 2 - 17 - 2 - 0 - 0 - 0 - ..\src\tx_thread_interrupt_disable.s - tx_thread_interrupt_disable.s - 0 - 0 - - - 2 - 18 - 2 - 0 - 0 - 0 - ..\src\tx_thread_interrupt_restore.s - tx_thread_interrupt_restore.s - 0 - 0 - - - 2 - 19 - 2 - 0 - 0 - 0 - ..\src\tx_thread_schedule.s - tx_thread_schedule.s - 0 - 0 - - - 2 - 20 - 2 - 0 - 0 - 0 - ..\src\tx_thread_stack_build.s - tx_thread_stack_build.s - 0 - 0 - - - 2 - 21 - 2 - 0 - 0 - 0 - ..\src\tx_thread_system_return.s - tx_thread_system_return.s - 0 - 0 - - - 2 - 22 - 2 - 0 - 0 - 0 - ..\src\tx_timer_interrupt.s - tx_timer_interrupt.s - 0 - 0 - - - 2 - 23 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_allocate.c - tx_block_allocate.c - 0 - 0 - - - 2 - 24 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_cleanup.c - tx_block_pool_cleanup.c - 0 - 0 - - - 2 - 25 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_create.c - tx_block_pool_create.c - 0 - 0 - - - 2 - 26 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_delete.c - tx_block_pool_delete.c - 0 - 0 - - - 2 - 27 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_info_get.c - tx_block_pool_info_get.c - 0 - 0 - - - 2 - 28 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_initialize.c - tx_block_pool_initialize.c - 0 - 0 - - - 2 - 29 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_performance_info_get.c - tx_block_pool_performance_info_get.c - 0 - 0 - - - 2 - 30 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_performance_system_info_get.c - tx_block_pool_performance_system_info_get.c - 0 - 0 - - - 2 - 31 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_prioritize.c - tx_block_pool_prioritize.c - 0 - 0 - - - 2 - 32 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_release.c - tx_block_release.c - 0 - 0 - - - 2 - 33 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_allocate.c - tx_byte_allocate.c - 0 - 0 - - - 2 - 34 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_cleanup.c - tx_byte_pool_cleanup.c - 0 - 0 - - - 2 - 35 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_create.c - tx_byte_pool_create.c - 0 - 0 - - - 2 - 36 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_delete.c - tx_byte_pool_delete.c - 0 - 0 - - - 2 - 37 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_info_get.c - tx_byte_pool_info_get.c - 0 - 0 - - - 2 - 38 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_initialize.c - tx_byte_pool_initialize.c - 0 - 0 - - - 2 - 39 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_performance_info_get.c - tx_byte_pool_performance_info_get.c - 0 - 0 - - - 2 - 40 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_performance_system_info_get.c - tx_byte_pool_performance_system_info_get.c - 0 - 0 - - - 2 - 41 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_prioritize.c - tx_byte_pool_prioritize.c - 0 - 0 - - - 2 - 42 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_search.c - tx_byte_pool_search.c - 0 - 0 - - - 2 - 43 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_release.c - tx_byte_release.c - 0 - 0 - - - 2 - 44 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_cleanup.c - tx_event_flags_cleanup.c - 0 - 0 - - - 2 - 45 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_create.c - tx_event_flags_create.c - 0 - 0 - - - 2 - 46 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_delete.c - tx_event_flags_delete.c - 0 - 0 - - - 2 - 47 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_get.c - tx_event_flags_get.c - 0 - 0 - - - 2 - 48 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_info_get.c - tx_event_flags_info_get.c - 0 - 0 - - - 2 - 49 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_initialize.c - tx_event_flags_initialize.c - 0 - 0 - - - 2 - 50 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_performance_info_get.c - tx_event_flags_performance_info_get.c - 0 - 0 - - - 2 - 51 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_performance_system_info_get.c - tx_event_flags_performance_system_info_get.c - 0 - 0 - - - 2 - 52 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_set.c - tx_event_flags_set.c - 0 - 0 - - - 2 - 53 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_set_notify.c - tx_event_flags_set_notify.c - 0 - 0 - - - 2 - 54 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_initialize_high_level.c - tx_initialize_high_level.c - 0 - 0 - - - 2 - 55 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_initialize_kernel_enter.c - tx_initialize_kernel_enter.c - 0 - 0 - - - 2 - 56 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_initialize_kernel_setup.c - tx_initialize_kernel_setup.c - 0 - 0 - - - 2 - 57 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_misra.c - tx_misra.c - 0 - 0 - - - 2 - 58 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_cleanup.c - tx_mutex_cleanup.c - 0 - 0 - - - 2 - 59 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_create.c - tx_mutex_create.c - 0 - 0 - - - 2 - 60 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_delete.c - tx_mutex_delete.c - 0 - 0 - - - 2 - 61 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_get.c - tx_mutex_get.c - 0 - 0 - - - 2 - 62 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_info_get.c - tx_mutex_info_get.c - 0 - 0 - - - 2 - 63 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_initialize.c - tx_mutex_initialize.c - 0 - 0 - - - 2 - 64 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_performance_info_get.c - tx_mutex_performance_info_get.c - 0 - 0 - - - 2 - 65 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_performance_system_info_get.c - tx_mutex_performance_system_info_get.c - 0 - 0 - - - 2 - 66 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_prioritize.c - tx_mutex_prioritize.c - 0 - 0 - - - 2 - 67 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_priority_change.c - tx_mutex_priority_change.c - 0 - 0 - - - 2 - 68 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_put.c - tx_mutex_put.c - 0 - 0 - - - 2 - 69 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_cleanup.c - tx_queue_cleanup.c - 0 - 0 - - - 2 - 70 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_create.c - tx_queue_create.c - 0 - 0 - - - 2 - 71 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_delete.c - tx_queue_delete.c - 0 - 0 - - - 2 - 72 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_flush.c - tx_queue_flush.c - 0 - 0 - - - 2 - 73 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_front_send.c - tx_queue_front_send.c - 0 - 0 - - - 2 - 74 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_info_get.c - tx_queue_info_get.c - 0 - 0 - - - 2 - 75 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_initialize.c - tx_queue_initialize.c - 0 - 0 - - - 2 - 76 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_performance_info_get.c - tx_queue_performance_info_get.c - 0 - 0 - - - 2 - 77 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_performance_system_info_get.c - tx_queue_performance_system_info_get.c - 0 - 0 - - - 2 - 78 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_prioritize.c - tx_queue_prioritize.c - 0 - 0 - - - 2 - 79 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_receive.c - tx_queue_receive.c - 0 - 0 - - - 2 - 80 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_send.c - tx_queue_send.c - 0 - 0 - - - 2 - 81 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_send_notify.c - tx_queue_send_notify.c - 0 - 0 - - - 2 - 82 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_ceiling_put.c - tx_semaphore_ceiling_put.c - 0 - 0 - - - 2 - 83 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_cleanup.c - tx_semaphore_cleanup.c - 0 - 0 - - - 2 - 84 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_create.c - tx_semaphore_create.c - 0 - 0 - - - 2 - 85 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_delete.c - tx_semaphore_delete.c - 0 - 0 - - - 2 - 86 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_get.c - tx_semaphore_get.c - 0 - 0 - - - 2 - 87 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_info_get.c - tx_semaphore_info_get.c - 0 - 0 - - - 2 - 88 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_initialize.c - tx_semaphore_initialize.c - 0 - 0 - - - 2 - 89 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_performance_info_get.c - tx_semaphore_performance_info_get.c - 0 - 0 - - - 2 - 90 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_performance_system_info_get.c - tx_semaphore_performance_system_info_get.c - 0 - 0 - - - 2 - 91 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_prioritize.c - tx_semaphore_prioritize.c - 0 - 0 - - - 2 - 92 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_put.c - tx_semaphore_put.c - 0 - 0 - - - 2 - 93 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_put_notify.c - tx_semaphore_put_notify.c - 0 - 0 - - - 2 - 94 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_create.c - tx_thread_create.c - 0 - 0 - - - 2 - 95 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_delete.c - tx_thread_delete.c - 0 - 0 - - - 2 - 96 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_entry_exit_notify.c - tx_thread_entry_exit_notify.c - 0 - 0 - - - 2 - 97 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_identify.c - tx_thread_identify.c - 0 - 0 - - - 2 - 98 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_info_get.c - tx_thread_info_get.c - 0 - 0 - - - 2 - 99 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_initialize.c - tx_thread_initialize.c - 0 - 0 - - - 2 - 100 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_performance_info_get.c - tx_thread_performance_info_get.c - 0 - 0 - - - 2 - 101 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_performance_system_info_get.c - tx_thread_performance_system_info_get.c - 0 - 0 - - - 2 - 102 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_preemption_change.c - tx_thread_preemption_change.c - 0 - 0 - - - 2 - 103 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_priority_change.c - tx_thread_priority_change.c - 0 - 0 - - - 2 - 104 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_relinquish.c - tx_thread_relinquish.c - 0 - 0 - - - 2 - 105 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_reset.c - tx_thread_reset.c - 0 - 0 - - - 2 - 106 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_resume.c - tx_thread_resume.c - 0 - 0 - - - 2 - 107 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_shell_entry.c - tx_thread_shell_entry.c - 0 - 0 - - - 2 - 108 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_sleep.c - tx_thread_sleep.c - 0 - 0 - - - 2 - 109 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_stack_analyze.c - tx_thread_stack_analyze.c - 0 - 0 - - - 2 - 110 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_stack_error_handler.c - tx_thread_stack_error_handler.c - 0 - 0 - - - 2 - 111 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_stack_error_notify.c - tx_thread_stack_error_notify.c - 0 - 0 - - - 2 - 112 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_suspend.c - tx_thread_suspend.c - 0 - 0 - - - 2 - 113 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_system_preempt_check.c - tx_thread_system_preempt_check.c - 0 - 0 - - - 2 - 114 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_system_resume.c - tx_thread_system_resume.c - 0 - 0 - - - 2 - 115 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_system_suspend.c - tx_thread_system_suspend.c - 0 - 0 - - - 2 - 116 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_terminate.c - tx_thread_terminate.c - 0 - 0 - - - 2 - 117 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_time_slice.c - tx_thread_time_slice.c - 0 - 0 - - - 2 - 118 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_time_slice_change.c - tx_thread_time_slice_change.c - 0 - 0 - - - 2 - 119 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_timeout.c - tx_thread_timeout.c - 0 - 0 - - - 2 - 120 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_wait_abort.c - tx_thread_wait_abort.c - 0 - 0 - - - 2 - 121 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_time_get.c - tx_time_get.c - 0 - 0 - - - 2 - 122 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_time_set.c - tx_time_set.c - 0 - 0 - - - 2 - 123 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_activate.c - tx_timer_activate.c - 0 - 0 - - - 2 - 124 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_change.c - tx_timer_change.c - 0 - 0 - - - 2 - 125 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_create.c - tx_timer_create.c - 0 - 0 - - - 2 - 126 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_deactivate.c - tx_timer_deactivate.c - 0 - 0 - - - 2 - 127 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_delete.c - tx_timer_delete.c - 0 - 0 - - - 2 - 128 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_expiration_process.c - tx_timer_expiration_process.c - 0 - 0 - - - 2 - 129 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_info_get.c - tx_timer_info_get.c - 0 - 0 - - - 2 - 130 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_initialize.c - tx_timer_initialize.c - 0 - 0 - - - 2 - 131 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_performance_info_get.c - tx_timer_performance_info_get.c - 0 - 0 - - - 2 - 132 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_performance_system_info_get.c - tx_timer_performance_system_info_get.c - 0 - 0 - - - 2 - 133 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_system_activate.c - tx_timer_system_activate.c - 0 - 0 - - - 2 - 134 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_system_deactivate.c - tx_timer_system_deactivate.c - 0 - 0 - - - 2 - 135 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_thread_entry.c - tx_timer_thread_entry.c - 0 - 0 - - - 2 - 136 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_buffer_full_notify.c - tx_trace_buffer_full_notify.c - 0 - 0 - - - 2 - 137 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_disable.c - tx_trace_disable.c - 0 - 0 - - - 2 - 138 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_enable.c - tx_trace_enable.c - 0 - 0 - - - 2 - 139 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_event_filter.c - tx_trace_event_filter.c - 0 - 0 - - - 2 - 140 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_event_unfilter.c - tx_trace_event_unfilter.c - 0 - 0 - - - 2 - 141 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_initialize.c - tx_trace_initialize.c - 0 - 0 - - - 2 - 142 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_interrupt_control.c - tx_trace_interrupt_control.c - 0 - 0 - - - 2 - 143 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_isr_enter_insert.c - tx_trace_isr_enter_insert.c - 0 - 0 - - - 2 - 144 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_isr_exit_insert.c - tx_trace_isr_exit_insert.c - 0 - 0 - - - 2 - 145 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_object_register.c - tx_trace_object_register.c - 0 - 0 - - - 2 - 146 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_object_unregister.c - tx_trace_object_unregister.c - 0 - 0 - - - 2 - 147 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_user_event_insert.c - tx_trace_user_event_insert.c - 0 - 0 - - - 2 - 148 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_allocate.c - txe_block_allocate.c - 0 - 0 - - - 2 - 149 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_pool_create.c - txe_block_pool_create.c - 0 - 0 - - - 2 - 150 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_pool_delete.c - txe_block_pool_delete.c - 0 - 0 - - - 2 - 151 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_pool_info_get.c - txe_block_pool_info_get.c - 0 - 0 - - - 2 - 152 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_pool_prioritize.c - txe_block_pool_prioritize.c - 0 - 0 - - - 2 - 153 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_release.c - txe_block_release.c - 0 - 0 - - - 2 - 154 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_allocate.c - txe_byte_allocate.c - 0 - 0 - - - 2 - 155 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_pool_create.c - txe_byte_pool_create.c - 0 - 0 - - - 2 - 156 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_pool_delete.c - txe_byte_pool_delete.c - 0 - 0 - - - 2 - 157 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_pool_info_get.c - txe_byte_pool_info_get.c - 0 - 0 - - - 2 - 158 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_pool_prioritize.c - txe_byte_pool_prioritize.c - 0 - 0 - - - 2 - 159 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_release.c - txe_byte_release.c - 0 - 0 - - - 2 - 160 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_create.c - txe_event_flags_create.c - 0 - 0 - - - 2 - 161 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_delete.c - txe_event_flags_delete.c - 0 - 0 - - - 2 - 162 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_get.c - txe_event_flags_get.c - 0 - 0 - - - 2 - 163 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_info_get.c - txe_event_flags_info_get.c - 0 - 0 - - - 2 - 164 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_set.c - txe_event_flags_set.c - 0 - 0 - - - 2 - 165 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_set_notify.c - txe_event_flags_set_notify.c - 0 - 0 - - - 2 - 166 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_create.c - txe_mutex_create.c - 0 - 0 - - - 2 - 167 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_delete.c - txe_mutex_delete.c - 0 - 0 - - - 2 - 168 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_get.c - txe_mutex_get.c - 0 - 0 - - - 2 - 169 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_info_get.c - txe_mutex_info_get.c - 0 - 0 - - - 2 - 170 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_prioritize.c - txe_mutex_prioritize.c - 0 - 0 - - - 2 - 171 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_put.c - txe_mutex_put.c - 0 - 0 - - - 2 - 172 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_create.c - txe_queue_create.c - 0 - 0 - - - 2 - 173 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_delete.c - txe_queue_delete.c - 0 - 0 - - - 2 - 174 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_flush.c - txe_queue_flush.c - 0 - 0 - - - 2 - 175 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_front_send.c - txe_queue_front_send.c - 0 - 0 - - - 2 - 176 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_info_get.c - txe_queue_info_get.c - 0 - 0 - - - 2 - 177 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_prioritize.c - txe_queue_prioritize.c - 0 - 0 - - - 2 - 178 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_receive.c - txe_queue_receive.c - 0 - 0 - - - 2 - 179 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_send.c - txe_queue_send.c - 0 - 0 - - - 2 - 180 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_send_notify.c - txe_queue_send_notify.c - 0 - 0 - - - 2 - 181 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_ceiling_put.c - txe_semaphore_ceiling_put.c - 0 - 0 - - - 2 - 182 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_create.c - txe_semaphore_create.c - 0 - 0 - - - 2 - 183 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_delete.c - txe_semaphore_delete.c - 0 - 0 - - - 2 - 184 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_get.c - txe_semaphore_get.c - 0 - 0 - - - 2 - 185 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_info_get.c - txe_semaphore_info_get.c - 0 - 0 - - - 2 - 186 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_prioritize.c - txe_semaphore_prioritize.c - 0 - 0 - - - 2 - 187 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_put.c - txe_semaphore_put.c - 0 - 0 - - - 2 - 188 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_put_notify.c - txe_semaphore_put_notify.c - 0 - 0 - - - 2 - 189 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_create.c - txe_thread_create.c - 0 - 0 - - - 2 - 190 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_delete.c - txe_thread_delete.c - 0 - 0 - - - 2 - 191 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_entry_exit_notify.c - txe_thread_entry_exit_notify.c - 0 - 0 - - - 2 - 192 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_info_get.c - txe_thread_info_get.c - 0 - 0 - - - 2 - 193 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_preemption_change.c - txe_thread_preemption_change.c - 0 - 0 - - - 2 - 194 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_priority_change.c - txe_thread_priority_change.c - 0 - 0 - - - 2 - 195 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_relinquish.c - txe_thread_relinquish.c - 0 - 0 - - - 2 - 196 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_reset.c - txe_thread_reset.c - 0 - 0 - - - 2 - 197 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_resume.c - txe_thread_resume.c - 0 - 0 - - - 2 - 198 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_suspend.c - txe_thread_suspend.c - 0 - 0 - - - 2 - 199 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_terminate.c - txe_thread_terminate.c - 0 - 0 - - - 2 - 200 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_time_slice_change.c - txe_thread_time_slice_change.c - 0 - 0 - - - 2 - 201 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_wait_abort.c - txe_thread_wait_abort.c - 0 - 0 - - - 2 - 202 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_activate.c - txe_timer_activate.c - 0 - 0 - - - 2 - 203 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_change.c - txe_timer_change.c - 0 - 0 - - - 2 - 204 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_create.c - txe_timer_create.c - 0 - 0 - - - 2 - 205 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_deactivate.c - txe_timer_deactivate.c - 0 - 0 - - - 2 - 206 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_delete.c - txe_timer_delete.c - 0 - 0 - - - 2 - 207 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_info_get.c - txe_timer_info_get.c - 0 - 0 - - - -
diff --git a/ports/cortex_m23/ac6/example_build/ThreadX_Library.uvoptx b/ports/cortex_m23/ac6/example_build/ThreadX_Library.uvoptx deleted file mode 100644 index dcb75d537..000000000 --- a/ports/cortex_m23/ac6/example_build/ThreadX_Library.uvoptx +++ /dev/null @@ -1,2576 +0,0 @@ - - - - 1.0 - -
### uVision Project, (C) Keil Software
- - - *.c - *.s*; *.src; *.a* - *.obj; *.o - *.lib - *.txt; *.h; *.inc - *.plm - *.cpp - 0 - - - - 0 - 0 - - - - ThreadX_Library_Project - 0x4 - ARM-ADS - - 12000000 - - 1 - 1 - 0 - 1 - 0 - - - 1 - 65535 - 0 - 0 - 0 - - - 79 - 66 - 8 - .\ - - - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - - - 1 - 0 - 1 - - 7 - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 1 - 1 - 0 - 0 - 1 - 0 - 0 - 13 - - - - - - - - - - - BIN\UL2V8M.DLL - - - - 0 - UL2V8M - UL2V8M(-S0 -C0 -P0 -FD20000000 -FC1000) - - - - - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - - - - - - - - - - - - - Source Group - 1 - 0 - 0 - 0 - - 1 - 1 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_allocate.c - tx_block_allocate.c - 0 - 0 - - - 1 - 2 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_cleanup.c - tx_block_pool_cleanup.c - 0 - 0 - - - 1 - 3 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_create.c - tx_block_pool_create.c - 0 - 0 - - - 1 - 4 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_delete.c - tx_block_pool_delete.c - 0 - 0 - - - 1 - 5 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_info_get.c - tx_block_pool_info_get.c - 0 - 0 - - - 1 - 6 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_initialize.c - tx_block_pool_initialize.c - 0 - 0 - - - 1 - 7 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_performance_info_get.c - tx_block_pool_performance_info_get.c - 0 - 0 - - - 1 - 8 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_performance_system_info_get.c - tx_block_pool_performance_system_info_get.c - 0 - 0 - - - 1 - 9 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_prioritize.c - tx_block_pool_prioritize.c - 0 - 0 - - - 1 - 10 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_release.c - tx_block_release.c - 0 - 0 - - - 1 - 11 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_allocate.c - tx_byte_allocate.c - 0 - 0 - - - 1 - 12 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_cleanup.c - tx_byte_pool_cleanup.c - 0 - 0 - - - 1 - 13 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_create.c - tx_byte_pool_create.c - 0 - 0 - - - 1 - 14 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_delete.c - tx_byte_pool_delete.c - 0 - 0 - - - 1 - 15 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_info_get.c - tx_byte_pool_info_get.c - 0 - 0 - - - 1 - 16 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_initialize.c - tx_byte_pool_initialize.c - 0 - 0 - - - 1 - 17 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_performance_info_get.c - tx_byte_pool_performance_info_get.c - 0 - 0 - - - 1 - 18 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_performance_system_info_get.c - tx_byte_pool_performance_system_info_get.c - 0 - 0 - - - 1 - 19 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_prioritize.c - tx_byte_pool_prioritize.c - 0 - 0 - - - 1 - 20 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_search.c - tx_byte_pool_search.c - 0 - 0 - - - 1 - 21 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_release.c - tx_byte_release.c - 0 - 0 - - - 1 - 22 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_cleanup.c - tx_event_flags_cleanup.c - 0 - 0 - - - 1 - 23 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_create.c - tx_event_flags_create.c - 0 - 0 - - - 1 - 24 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_delete.c - tx_event_flags_delete.c - 0 - 0 - - - 1 - 25 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_get.c - tx_event_flags_get.c - 0 - 0 - - - 1 - 26 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_info_get.c - tx_event_flags_info_get.c - 0 - 0 - - - 1 - 27 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_initialize.c - tx_event_flags_initialize.c - 0 - 0 - - - 1 - 28 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_performance_info_get.c - tx_event_flags_performance_info_get.c - 0 - 0 - - - 1 - 29 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_performance_system_info_get.c - tx_event_flags_performance_system_info_get.c - 0 - 0 - - - 1 - 30 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_set.c - tx_event_flags_set.c - 0 - 0 - - - 1 - 31 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_set_notify.c - tx_event_flags_set_notify.c - 0 - 0 - - - 1 - 32 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_initialize_high_level.c - tx_initialize_high_level.c - 0 - 0 - - - 1 - 33 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_initialize_kernel_enter.c - tx_initialize_kernel_enter.c - 0 - 0 - - - 1 - 34 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_initialize_kernel_setup.c - tx_initialize_kernel_setup.c - 0 - 0 - - - 1 - 35 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_cleanup.c - tx_mutex_cleanup.c - 0 - 0 - - - 1 - 36 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_create.c - tx_mutex_create.c - 0 - 0 - - - 1 - 37 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_delete.c - tx_mutex_delete.c - 0 - 0 - - - 1 - 38 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_get.c - tx_mutex_get.c - 0 - 0 - - - 1 - 39 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_info_get.c - tx_mutex_info_get.c - 0 - 0 - - - 1 - 40 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_initialize.c - tx_mutex_initialize.c - 0 - 0 - - - 1 - 41 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_performance_info_get.c - tx_mutex_performance_info_get.c - 0 - 0 - - - 1 - 42 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_performance_system_info_get.c - tx_mutex_performance_system_info_get.c - 0 - 0 - - - 1 - 43 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_prioritize.c - tx_mutex_prioritize.c - 0 - 0 - - - 1 - 44 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_priority_change.c - tx_mutex_priority_change.c - 0 - 0 - - - 1 - 45 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_put.c - tx_mutex_put.c - 0 - 0 - - - 1 - 46 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_cleanup.c - tx_queue_cleanup.c - 0 - 0 - - - 1 - 47 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_create.c - tx_queue_create.c - 0 - 0 - - - 1 - 48 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_delete.c - tx_queue_delete.c - 0 - 0 - - - 1 - 49 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_flush.c - tx_queue_flush.c - 0 - 0 - - - 1 - 50 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_front_send.c - tx_queue_front_send.c - 0 - 0 - - - 1 - 51 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_info_get.c - tx_queue_info_get.c - 0 - 0 - - - 1 - 52 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_initialize.c - tx_queue_initialize.c - 0 - 0 - - - 1 - 53 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_performance_info_get.c - tx_queue_performance_info_get.c - 0 - 0 - - - 1 - 54 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_performance_system_info_get.c - tx_queue_performance_system_info_get.c - 0 - 0 - - - 1 - 55 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_prioritize.c - tx_queue_prioritize.c - 0 - 0 - - - 1 - 56 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_receive.c - tx_queue_receive.c - 0 - 0 - - - 1 - 57 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_send.c - tx_queue_send.c - 0 - 0 - - - 1 - 58 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_send_notify.c - tx_queue_send_notify.c - 0 - 0 - - - 1 - 59 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_ceiling_put.c - tx_semaphore_ceiling_put.c - 0 - 0 - - - 1 - 60 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_cleanup.c - tx_semaphore_cleanup.c - 0 - 0 - - - 1 - 61 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_create.c - tx_semaphore_create.c - 0 - 0 - - - 1 - 62 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_delete.c - tx_semaphore_delete.c - 0 - 0 - - - 1 - 63 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_get.c - tx_semaphore_get.c - 0 - 0 - - - 1 - 64 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_info_get.c - tx_semaphore_info_get.c - 0 - 0 - - - 1 - 65 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_initialize.c - tx_semaphore_initialize.c - 0 - 0 - - - 1 - 66 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_performance_info_get.c - tx_semaphore_performance_info_get.c - 0 - 0 - - - 1 - 67 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_performance_system_info_get.c - tx_semaphore_performance_system_info_get.c - 0 - 0 - - - 1 - 68 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_prioritize.c - tx_semaphore_prioritize.c - 0 - 0 - - - 1 - 69 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_put.c - tx_semaphore_put.c - 0 - 0 - - - 1 - 70 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_put_notify.c - tx_semaphore_put_notify.c - 0 - 0 - - - 1 - 71 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_create.c - tx_thread_create.c - 0 - 0 - - - 1 - 72 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_delete.c - tx_thread_delete.c - 0 - 0 - - - 1 - 73 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_entry_exit_notify.c - tx_thread_entry_exit_notify.c - 0 - 0 - - - 1 - 74 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_identify.c - tx_thread_identify.c - 0 - 0 - - - 1 - 75 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_info_get.c - tx_thread_info_get.c - 0 - 0 - - - 1 - 76 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_initialize.c - tx_thread_initialize.c - 0 - 0 - - - 1 - 77 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_performance_info_get.c - tx_thread_performance_info_get.c - 0 - 0 - - - 1 - 78 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_performance_system_info_get.c - tx_thread_performance_system_info_get.c - 0 - 0 - - - 1 - 79 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_preemption_change.c - tx_thread_preemption_change.c - 0 - 0 - - - 1 - 80 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_priority_change.c - tx_thread_priority_change.c - 0 - 0 - - - 1 - 81 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_relinquish.c - tx_thread_relinquish.c - 0 - 0 - - - 1 - 82 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_reset.c - tx_thread_reset.c - 0 - 0 - - - 1 - 83 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_resume.c - tx_thread_resume.c - 0 - 0 - - - 1 - 84 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_shell_entry.c - tx_thread_shell_entry.c - 0 - 0 - - - 1 - 85 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_sleep.c - tx_thread_sleep.c - 0 - 0 - - - 1 - 86 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_stack_analyze.c - tx_thread_stack_analyze.c - 0 - 0 - - - 1 - 87 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_suspend.c - tx_thread_suspend.c - 0 - 0 - - - 1 - 88 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_system_preempt_check.c - tx_thread_system_preempt_check.c - 0 - 0 - - - 1 - 89 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_system_resume.c - tx_thread_system_resume.c - 0 - 0 - - - 1 - 90 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_system_suspend.c - tx_thread_system_suspend.c - 0 - 0 - - - 1 - 91 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_terminate.c - tx_thread_terminate.c - 0 - 0 - - - 1 - 92 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_time_slice.c - tx_thread_time_slice.c - 0 - 0 - - - 1 - 93 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_time_slice_change.c - tx_thread_time_slice_change.c - 0 - 0 - - - 1 - 94 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_timeout.c - tx_thread_timeout.c - 0 - 0 - - - 1 - 95 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_wait_abort.c - tx_thread_wait_abort.c - 0 - 0 - - - 1 - 96 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_time_get.c - tx_time_get.c - 0 - 0 - - - 1 - 97 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_time_set.c - tx_time_set.c - 0 - 0 - - - 1 - 98 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_activate.c - tx_timer_activate.c - 0 - 0 - - - 1 - 99 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_change.c - tx_timer_change.c - 0 - 0 - - - 1 - 100 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_create.c - tx_timer_create.c - 0 - 0 - - - 1 - 101 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_deactivate.c - tx_timer_deactivate.c - 0 - 0 - - - 1 - 102 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_delete.c - tx_timer_delete.c - 0 - 0 - - - 1 - 103 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_expiration_process.c - tx_timer_expiration_process.c - 0 - 0 - - - 1 - 104 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_info_get.c - tx_timer_info_get.c - 0 - 0 - - - 1 - 105 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_initialize.c - tx_timer_initialize.c - 0 - 0 - - - 1 - 106 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_performance_info_get.c - tx_timer_performance_info_get.c - 0 - 0 - - - 1 - 107 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_performance_system_info_get.c - tx_timer_performance_system_info_get.c - 0 - 0 - - - 1 - 108 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_system_activate.c - tx_timer_system_activate.c - 0 - 0 - - - 1 - 109 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_system_deactivate.c - tx_timer_system_deactivate.c - 0 - 0 - - - 1 - 110 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_thread_entry.c - tx_timer_thread_entry.c - 0 - 0 - - - 1 - 111 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_disable.c - tx_trace_disable.c - 0 - 0 - - - 1 - 112 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_enable.c - tx_trace_enable.c - 0 - 0 - - - 1 - 113 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_initialize.c - tx_trace_initialize.c - 0 - 0 - - - 1 - 114 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_interrupt_control.c - tx_trace_interrupt_control.c - 0 - 0 - - - 1 - 115 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_isr_enter_insert.c - tx_trace_isr_enter_insert.c - 0 - 0 - - - 1 - 116 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_isr_exit_insert.c - tx_trace_isr_exit_insert.c - 0 - 0 - - - 1 - 117 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_object_register.c - tx_trace_object_register.c - 0 - 0 - - - 1 - 118 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_object_unregister.c - tx_trace_object_unregister.c - 0 - 0 - - - 1 - 119 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_user_event_insert.c - tx_trace_user_event_insert.c - 0 - 0 - - - 1 - 120 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_allocate.c - txe_block_allocate.c - 0 - 0 - - - 1 - 121 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_pool_create.c - txe_block_pool_create.c - 0 - 0 - - - 1 - 122 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_pool_delete.c - txe_block_pool_delete.c - 0 - 0 - - - 1 - 123 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_pool_info_get.c - txe_block_pool_info_get.c - 0 - 0 - - - 1 - 124 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_pool_prioritize.c - txe_block_pool_prioritize.c - 0 - 0 - - - 1 - 125 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_release.c - txe_block_release.c - 0 - 0 - - - 1 - 126 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_allocate.c - txe_byte_allocate.c - 0 - 0 - - - 1 - 127 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_pool_create.c - txe_byte_pool_create.c - 0 - 0 - - - 1 - 128 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_pool_delete.c - txe_byte_pool_delete.c - 0 - 0 - - - 1 - 129 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_pool_info_get.c - txe_byte_pool_info_get.c - 0 - 0 - - - 1 - 130 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_pool_prioritize.c - txe_byte_pool_prioritize.c - 0 - 0 - - - 1 - 131 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_release.c - txe_byte_release.c - 0 - 0 - - - 1 - 132 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_create.c - txe_event_flags_create.c - 0 - 0 - - - 1 - 133 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_delete.c - txe_event_flags_delete.c - 0 - 0 - - - 1 - 134 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_get.c - txe_event_flags_get.c - 0 - 0 - - - 1 - 135 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_info_get.c - txe_event_flags_info_get.c - 0 - 0 - - - 1 - 136 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_set.c - txe_event_flags_set.c - 0 - 0 - - - 1 - 137 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_set_notify.c - txe_event_flags_set_notify.c - 0 - 0 - - - 1 - 138 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_create.c - txe_mutex_create.c - 0 - 0 - - - 1 - 139 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_delete.c - txe_mutex_delete.c - 0 - 0 - - - 1 - 140 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_get.c - txe_mutex_get.c - 0 - 0 - - - 1 - 141 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_info_get.c - txe_mutex_info_get.c - 0 - 0 - - - 1 - 142 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_prioritize.c - txe_mutex_prioritize.c - 0 - 0 - - - 1 - 143 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_put.c - txe_mutex_put.c - 0 - 0 - - - 1 - 144 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_create.c - txe_queue_create.c - 0 - 0 - - - 1 - 145 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_delete.c - txe_queue_delete.c - 0 - 0 - - - 1 - 146 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_flush.c - txe_queue_flush.c - 0 - 0 - - - 1 - 147 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_front_send.c - txe_queue_front_send.c - 0 - 0 - - - 1 - 148 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_info_get.c - txe_queue_info_get.c - 0 - 0 - - - 1 - 149 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_prioritize.c - txe_queue_prioritize.c - 0 - 0 - - - 1 - 150 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_receive.c - txe_queue_receive.c - 0 - 0 - - - 1 - 151 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_send.c - txe_queue_send.c - 0 - 0 - - - 1 - 152 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_send_notify.c - txe_queue_send_notify.c - 0 - 0 - - - 1 - 153 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_ceiling_put.c - txe_semaphore_ceiling_put.c - 0 - 0 - - - 1 - 154 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_create.c - txe_semaphore_create.c - 0 - 0 - - - 1 - 155 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_delete.c - txe_semaphore_delete.c - 0 - 0 - - - 1 - 156 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_get.c - txe_semaphore_get.c - 0 - 0 - - - 1 - 157 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_info_get.c - txe_semaphore_info_get.c - 0 - 0 - - - 1 - 158 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_prioritize.c - txe_semaphore_prioritize.c - 0 - 0 - - - 1 - 159 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_put.c - txe_semaphore_put.c - 0 - 0 - - - 1 - 160 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_put_notify.c - txe_semaphore_put_notify.c - 0 - 0 - - - 1 - 161 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_create.c - txe_thread_create.c - 0 - 0 - - - 1 - 162 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_delete.c - txe_thread_delete.c - 0 - 0 - - - 1 - 163 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_entry_exit_notify.c - txe_thread_entry_exit_notify.c - 0 - 0 - - - 1 - 164 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_info_get.c - txe_thread_info_get.c - 0 - 0 - - - 1 - 165 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_preemption_change.c - txe_thread_preemption_change.c - 0 - 0 - - - 1 - 166 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_priority_change.c - txe_thread_priority_change.c - 0 - 0 - - - 1 - 167 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_relinquish.c - txe_thread_relinquish.c - 0 - 0 - - - 1 - 168 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_reset.c - txe_thread_reset.c - 0 - 0 - - - 1 - 169 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_resume.c - txe_thread_resume.c - 0 - 0 - - - 1 - 170 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_suspend.c - txe_thread_suspend.c - 0 - 0 - - - 1 - 171 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_terminate.c - txe_thread_terminate.c - 0 - 0 - - - 1 - 172 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_time_slice_change.c - txe_thread_time_slice_change.c - 0 - 0 - - - 1 - 173 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_wait_abort.c - txe_thread_wait_abort.c - 0 - 0 - - - 1 - 174 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_activate.c - txe_timer_activate.c - 0 - 0 - - - 1 - 175 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_change.c - txe_timer_change.c - 0 - 0 - - - 1 - 176 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_create.c - txe_timer_create.c - 0 - 0 - - - 1 - 177 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_deactivate.c - txe_timer_deactivate.c - 0 - 0 - - - 1 - 178 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_delete.c - txe_timer_delete.c - 0 - 0 - - - 1 - 179 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_info_get.c - txe_timer_info_get.c - 0 - 0 - - - 1 - 180 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_buffer_full_notify.c - tx_trace_buffer_full_notify.c - 0 - 0 - - - 1 - 181 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_event_filter.c - tx_trace_event_filter.c - 0 - 0 - - - 1 - 182 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_event_unfilter.c - tx_trace_event_unfilter.c - 0 - 0 - - - 1 - 183 - 1 - 0 - 0 - 0 - ..\src\txe_thread_secure_stack_allocate.c - txe_thread_secure_stack_allocate.c - 0 - 0 - - - 1 - 184 - 1 - 0 - 0 - 0 - ..\src\txe_thread_secure_stack_free.c - txe_thread_secure_stack_free.c - 0 - 0 - - - 1 - 185 - 2 - 0 - 0 - 0 - ..\src\tx_thread_context_restore.S - tx_thread_context_restore.S - 0 - 0 - - - 1 - 186 - 2 - 0 - 0 - 0 - ..\src\tx_thread_context_save.S - tx_thread_context_save.S - 0 - 0 - - - 1 - 187 - 2 - 0 - 0 - 0 - ..\src\tx_thread_interrupt_control.S - tx_thread_interrupt_control.S - 0 - 0 - - - 1 - 188 - 2 - 0 - 0 - 0 - ..\src\tx_thread_interrupt_disable.S - tx_thread_interrupt_disable.S - 0 - 0 - - - 1 - 189 - 2 - 0 - 0 - 0 - ..\src\tx_thread_interrupt_restore.S - tx_thread_interrupt_restore.S - 0 - 0 - - - 1 - 190 - 2 - 0 - 0 - 0 - ..\src\tx_thread_schedule.S - tx_thread_schedule.S - 0 - 0 - - - 1 - 191 - 2 - 0 - 0 - 0 - ..\src\tx_thread_secure_stack_allocate.S - tx_thread_secure_stack_allocate.S - 0 - 0 - - - 1 - 192 - 2 - 0 - 0 - 0 - ..\src\tx_thread_secure_stack_free.S - tx_thread_secure_stack_free.S - 0 - 0 - - - 1 - 193 - 2 - 0 - 0 - 0 - ..\src\tx_thread_stack_build.S - tx_thread_stack_build.S - 0 - 0 - - - 1 - 194 - 2 - 0 - 0 - 0 - ..\src\tx_thread_system_return.S - tx_thread_system_return.S - 0 - 0 - - - 1 - 195 - 2 - 0 - 0 - 0 - ..\src\tx_timer_interrupt.S - tx_timer_interrupt.S - 0 - 0 - - - 1 - 196 - 2 - 0 - 0 - 0 - .\tx_initialize_low_level.S - tx_initialize_low_level.S - 0 - 0 - - - 1 - 197 - 2 - 0 - 0 - 0 - ..\src\tx_thread_secure_stack_initialize.S - tx_thread_secure_stack_initialize.S - 0 - 0 - - - 1 - 198 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_stack_error_handler.c - tx_thread_stack_error_handler.c - 0 - 0 - - - 1 - 199 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_stack_error_notify.c - tx_thread_stack_error_notify.c - 0 - 0 - - - - - ::CMSIS - 0 - 0 - 0 - 1 - - -
diff --git a/ports/cortex_m23/ac6/example_build/demo_secure_zone/demo_secure_zone.uvoptx b/ports/cortex_m23/ac6/example_build/demo_secure_zone/demo_secure_zone.uvoptx deleted file mode 100644 index 3933a1714..000000000 --- a/ports/cortex_m23/ac6/example_build/demo_secure_zone/demo_secure_zone.uvoptx +++ /dev/null @@ -1,328 +0,0 @@ - - - - 1.0 - -
### uVision Project, (C) Keil Software
- - - *.c - *.s*; *.src; *.a* - *.obj; *.o - *.lib - *.txt; *.h; *.inc - *.plm - *.cpp - 0 - - - - 0 - 0 - - - - FVP Simulation Model - 0x4 - ARM-ADS - - 12000000 - - 1 - 1 - 0 - 1 - 0 - - - 1 - 65535 - 0 - 0 - 0 - - - 79 - 66 - 8 - .\Listings\ - - - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - - - 1 - 0 - 1 - - 7 - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 1 - 1 - 0 - 0 - 1 - 0 - 0 - 15 - - - - - - - - - - ..\Debug.ini - BIN\DbgFMv8M.DLL - - - - 0 - UL2V8M - UL2V8M(-S0 -C0 -P0 -FC1000 -FD20000000 - - - 0 - DbgFMv8M - -I -S -L"cpu0" -O4102 -C0 -MC".\FVP\MPS2_Cortex-M\FVP_MPS2_Cortex-M23_MDK.exe" -MF"..\ARMCM23_TZ_config.txt" -PF -MA - - - 0 - DLGTARM - (6010=1818,430,2295,1026,0)(6018=2033,530,2222,879,0)(6019=-1,-1,-1,-1,0)(6008=1845,239,2139,424,0)(6009=-1,-1,-1,-1,0)(6014=1836,-490,2094,241,0)(6015=-1,-1,-1,-1,0)(6003=-1,-1,-1,-1,0)(6000=75,104,528,436,0) - - - 0 - ARMDBGFLAGS - - - - 0 - DLGUARM - (105=-1,-1,-1,-1,0)(106=-1,-1,-1,-1,0)(107=-1,-1,-1,-1,0) - - - - - - 0 - 1 - _tx_thread_current_ptr - - - 1 - 1 - thread_0_counter - - - 2 - 1 - thread_1_counter - - - 3 - 1 - thread_2_counter - - - 4 - 1 - thread_3_counter - - - 5 - 1 - thread_4_counter - - - 6 - 1 - thread_5_counter - - - 7 - 1 - thread_6_counter - - - 8 - 1 - thread_7_counter - - - 9 - 1 - _tx_timer_system_clock - - - - - 1 - 2 - 0 - 0 - - - - - 2 - 2 - 0xE000ED28 - 0 - - - - 0 - - - 0 - 1 - 1 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - - - - - - - - - - - - - Secure Code - 1 - 0 - 0 - 0 - - 1 - 1 - 1 - 0 - 0 - 0 - ..\..\src\tx_thread_secure_stack.c - tx_thread_secure_stack.c - 0 - 0 - - - 1 - 2 - 1 - 0 - 0 - 0 - .\main_s.c - main_s.c - 0 - 0 - - - - - Interface - 1 - 0 - 0 - 0 - - 2 - 3 - 1 - 0 - 0 - 0 - .\interface.c - interface.c - 0 - 0 - - - - - ::CMSIS - 0 - 0 - 0 - 1 - - - - ::Device - 0 - 0 - 0 - 1 - - -
diff --git a/ports/cortex_m23/ac6/example_build/demo_threadx_non-secure_zone/ThreadX_Demo.uvopt b/ports/cortex_m23/ac6/example_build/demo_threadx_non-secure_zone/ThreadX_Demo.uvopt deleted file mode 100644 index 7ec4b36b6..000000000 --- a/ports/cortex_m23/ac6/example_build/demo_threadx_non-secure_zone/ThreadX_Demo.uvopt +++ /dev/null @@ -1,305 +0,0 @@ - - - - 1.0 - -
### uVision Project, (C) Keil Software
- - - *.c - *.s*; *.src; *.a* - *.obj; *.o - *.lib - *.txt; *.h; *.inc - *.plm - *.cpp - 0 - - - - 0 - 0 - - - - ThreadX_Demo - 0x4 - ARM-ADS - - 12000000 - - 1 - 1 - 1 - 0 - 0 - - - 1 - 65535 - 0 - 0 - 0 - - - 79 - 66 - 8 - .\ - - - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - - - 1 - 0 - 1 - - 255 - - 1 - 0 - 1 - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 1 - 0 - 1 - 0 - 1 - 1 - 0 - 0 - 1 - 0 - 0 - -1 - - - - - - - - - - - - - - - 0 - ARMRTXEVENTFLAGS - -L70 -Z18 -C0 -M0 -T1 - - - 0 - DLGDARM - (1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0) - - - 0 - DLGUARM - (105=-1,-1,-1,-1,0)(106=-1,-1,-1,-1,0)(107=-1,-1,-1,-1,0) - - - 0 - DLGTARM - (1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0)(110=-1,-1,-1,-1,0)(100=-1,-1,-1,-1,0)(101=-1,-1,-1,-1,0)(102=-1,-1,-1,-1,0)(103=-1,-1,-1,-1,0)(104=-1,-1,-1,-1,0)(105=-1,-1,-1,-1,0)(106=-1,-1,-1,-1,0)(107=-1,-1,-1,-1,0)(161=-1,-1,-1,-1,0)(162=-1,-1,-1,-1,0)(163=-1,-1,-1,-1,0)(164=-1,-1,-1,-1,0)(150=-1,-1,-1,-1,0)(151=-1,-1,-1,-1,0)(152=-1,-1,-1,-1,0)(1011=-1,-1,-1,-1,0)(1012=-1,-1,-1,-1,0)(1013=-1,-1,-1,-1,0)(171=-1,-1,-1,-1,0)(172=-1,-1,-1,-1,0)(173=-1,-1,-1,-1,0)(1014=-1,-1,-1,-1,0)(1016=-1,-1,-1,-1,0)(136=-1,-1,-1,-1,0) - - - 0 - ARMDBGFLAGS - -T5F - - - 0 - UL2CM3 - -UV0289BJE -O14 -S0 -C0 -N00("ARM CoreSight JTAG-DP") -D00(3BA00477) -L00(4) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO7 -FD20000000 -FC800 -FN1 -FF0LM3S_16 -FS00 -FL04000 - - - - - - 0 - 1 - thread_0_counter - - - 1 - 1 - thread_1_counter - - - 2 - 1 - thread_2_counter - - - 3 - 1 - thread_3_counter - - - 4 - 1 - thread_4_counter - - - 5 - 1 - thread_5_counter - - - 6 - 1 - _tx_thread_current_ptr - - - - 0 - - - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - - - - - - - - - - - - - Source Group - 1 - 0 - 0 - 0 - - 1 - 1 - 2 - 0 - 0 - 0 - .\tx_initialize_low_level.s - tx_initialize_low_level.s - 0 - 0 - - - 1 - 2 - 1 - 1 - 0 - 0 - .\demo_threadx.c - demo_threadx.c - 0 - 0 - - 44 - 0 - 1 - - -1 - -1 - - - -1 - -1 - - - 56 - 12 - 1633 - 671 - - - - - - - Library_Group - 1 - 0 - 0 - 0 - - 2 - 3 - 4 - 0 - 0 - 0 - .\ThreadX_Library.lib - ThreadX_Library.lib - 0 - 0 - - - -
diff --git a/ports/cortex_m23/ac6/example_build/demo_threadx_non-secure_zone/demo_threadx_non-secure_zone.uvoptx b/ports/cortex_m23/ac6/example_build/demo_threadx_non-secure_zone/demo_threadx_non-secure_zone.uvoptx deleted file mode 100644 index ea78cfd68..000000000 --- a/ports/cortex_m23/ac6/example_build/demo_threadx_non-secure_zone/demo_threadx_non-secure_zone.uvoptx +++ /dev/null @@ -1,373 +0,0 @@ - - - - 1.0 - -
### uVision Project, (C) Keil Software
- - - *.c - *.s*; *.src; *.a* - *.obj; *.o - *.lib - *.txt; *.h; *.inc - *.plm - *.cpp - 0 - - - - 0 - 0 - - - - FVP Simulation Model - 0x4 - ARM-ADS - - 12000000 - - 1 - 1 - 0 - 1 - 0 - - - 1 - 65535 - 0 - 0 - 0 - - - 79 - 66 - 8 - .\Listings\ - - - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - - - 1 - 0 - 1 - - 7 - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 1 - 1 - 0 - 0 - 1 - 0 - 0 - 15 - - - - - - - - - - ..\Debug.ini - BIN\DbgFMv8M.DLL - - - - 0 - UL2V8M - UL2V8M(-S0 -C0 -P0 -FC1000 -FD20000000 - - - 0 - DbgFMv8M - -I -S -L"cpu0" -O4102 -C0 -MC".\FVP\MPS2_Cortex-M\FVP_MPS2_Cortex-M23_MDK.exe" -MF"..\ARMCM23_TZ_config.txt" -PF -MA - - - 0 - PWSTATINFO - 200,50,700 - - - 0 - DLGTARM - (6010=1830,250,2307,846,0)(6018=1284,352,1473,701,0)(6019=1328,34,1517,370,0)(6008=1865,39,2159,224,0)(6009=1860,848,2154,1033,0)(6014=1111,129,1369,860,0)(6015=872,146,1130,768,0)(6003=-1,-1,-1,-1,0)(6000=-1,-1,-1,-1,0) - - - 0 - ARMDBGFLAGS - - - - 0 - DLGUARM - (105=150,186,829,544,0)(106=511,345,1277,659,0)(107=-1,-1,-1,-1,0) - - - - - 0 - 0 - 89 - 1 -
1046
- 0 - 0 - 0 - 0 - 0 - 1 - <1>RTE\Device\ARMCM23_TZ\system_ARMCM23.c - - \\demo_secure_zone\RTE/Device/ARMCM23_TZ/system_ARMCM23.c\89 -
- - 1 - 0 - 0 - 1 -
2107412
- 0 - 0 - 0 - 0 - 0 - 1 - - - -
-
- - - 0 - 1 - thread_0_counter - - - 1 - 1 - thread_1_counter - - - 2 - 1 - thread_2_counter - - - 3 - 1 - thread_3_counter - - - 4 - 1 - thread_4_counter - - - 5 - 1 - thread_5_counter - - - 6 - 1 - thread_6_counter - - - 7 - 1 - thread_7_counter - - - 8 - 1 - _tx_thread_current_ptr - - - - - 1 - 2 - 0x2023ffb8 - 0 - - - - - 2 - 2 - 0xE000ED28 - 0 - - - - 0 - - - 0 - 1 - 1 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - - - - - - - - -
-
- - - Non-secure Code - 1 - 0 - 0 - 0 - - 1 - 1 - 4 - 0 - 0 - 0 - ..\ThreadX_Library.lib - ThreadX_Library.lib - 0 - 0 - - - 1 - 2 - 1 - 0 - 0 - 0 - .\demo_threadx.c - demo_threadx.c - 0 - 0 - - - - - CMSE Library - 0 - 0 - 0 - 0 - - 2 - 3 - 5 - 0 - 0 - 0 - ..\demo_secure_zone\interface.h - interface.h - 0 - 0 - - - 2 - 4 - 3 - 0 - 0 - 0 - ..\demo_secure_zone\Objects\demo_secure_zone_CMSE_Lib.o - demo_secure_zone_CMSE_Lib.o - 0 - 0 - - - - - ::CMSIS - 1 - 0 - 0 - 1 - - - - ::Device - 0 - 0 - 0 - 1 - - -
diff --git a/ports/cortex_m3/keil/example_build/ThreadX_Demo.uvopt b/ports/cortex_m3/keil/example_build/ThreadX_Demo.uvopt deleted file mode 100644 index 703846828..000000000 --- a/ports/cortex_m3/keil/example_build/ThreadX_Demo.uvopt +++ /dev/null @@ -1,300 +0,0 @@ - - - - 1.0 - -
### uVision Project, (C) Keil Software
- - - *.c - *.s*; *.src; *.a* - *.obj - *.lib - *.txt; *.h; *.inc; *.md - *.plm - *.cpp - 0 - - - - 0 - 0 - - - - ThreadX_Demo - 0x4 - ARM-ADS - - 12000000 - - 1 - 1 - 1 - 0 - 0 - - - 1 - 65535 - 0 - 0 - 0 - - - 79 - 66 - 8 - .\ - - - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - - - 0 - 0 - 1 - - 255 - - 1 - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 1 - 0 - 1 - 0 - 1 - 1 - 0 - 0 - 1 - 0 - 0 - -1 - - - - - - - - - - - - - - - 0 - ARMRTXEVENTFLAGS - -L70 -Z18 -C0 -M0 -T1 - - - 0 - DLGDARM - (1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0) - - - 0 - DLGUARM - (105=-1,-1,-1,-1,0)(106=-1,-1,-1,-1,0)(107=-1,-1,-1,-1,0) - - - 0 - DLGTARM - (1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0)(110=-1,-1,-1,-1,0)(100=-1,-1,-1,-1,0)(101=-1,-1,-1,-1,0)(102=-1,-1,-1,-1,0)(103=-1,-1,-1,-1,0)(104=-1,-1,-1,-1,0)(105=-1,-1,-1,-1,0)(106=-1,-1,-1,-1,0)(107=-1,-1,-1,-1,0)(161=-1,-1,-1,-1,0)(162=-1,-1,-1,-1,0)(163=-1,-1,-1,-1,0)(164=-1,-1,-1,-1,0)(150=-1,-1,-1,-1,0)(151=-1,-1,-1,-1,0)(152=-1,-1,-1,-1,0)(1011=-1,-1,-1,-1,0)(1012=-1,-1,-1,-1,0)(1013=-1,-1,-1,-1,0)(171=-1,-1,-1,-1,0)(172=-1,-1,-1,-1,0)(173=-1,-1,-1,-1,0)(1014=-1,-1,-1,-1,0)(1016=-1,-1,-1,-1,0)(136=-1,-1,-1,-1,0) - - - 0 - ARMDBGFLAGS - -T5F - - - 0 - UL2CM3 - -UV0289BJE -O14 -S0 -C0 -N00("ARM CoreSight JTAG-DP") -D00(3BA00477) -L00(4) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO7 -FD20000000 -FC800 -FN1 -FF0LM3S_16 -FS00 -FL04000 - - - - - - 0 - 1 - thread_0_counter - - - 1 - 1 - thread_1_counter - - - 2 - 1 - thread_2_counter - - - 3 - 1 - thread_3_counter - - - 4 - 1 - thread_4_counter - - - 5 - 1 - thread_5_counter - - - - 0 - - - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - - - - - - - - - - - - - Source Group - 0 - 0 - 0 - 0 - - 1 - 1 - 2 - 0 - 0 - 0 - .\tx_initialize_low_level.s - tx_initialize_low_level.s - 0 - 0 - - - 1 - 2 - 1 - 0 - 0 - 0 - .\sample_threadx.c - sample_threadx.c - 0 - 0 - - 44 - 0 - 1 - - -1 - -1 - - - -1 - -1 - - - 56 - 12 - 1633 - 671 - - - - - - - Library_Group - 0 - 0 - 0 - 0 - - 2 - 3 - 4 - 0 - 0 - 0 - .\ThreadX_Library.lib - ThreadX_Library.lib - 0 - 0 - - - -
diff --git a/ports/cortex_m3/keil/example_build/ThreadX_Demo.uvoptx b/ports/cortex_m3/keil/example_build/ThreadX_Demo.uvoptx deleted file mode 100644 index 253c0c3c7..000000000 --- a/ports/cortex_m3/keil/example_build/ThreadX_Demo.uvoptx +++ /dev/null @@ -1,300 +0,0 @@ - - - - 1.0 - -
### uVision Project, (C) Keil Software
- - - *.c - *.s*; *.src; *.a* - *.obj - *.lib - *.txt; *.h; *.inc; *.md - *.plm - *.cpp - 0 - - - - 0 - 0 - - - - ThreadX_Demo - 0x4 - ARM-ADS - - 12000000 - - 1 - 1 - 1 - 0 - 0 - - - 1 - 65535 - 0 - 0 - 0 - - - 79 - 66 - 8 - .\ - - - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - - - 0 - 0 - 1 - - 255 - - 1 - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 1 - 0 - 1 - 0 - 1 - 1 - 0 - 0 - 1 - 0 - 0 - -1 - - - - - - - - - - - - - - - 0 - ARMRTXEVENTFLAGS - -L70 -Z18 -C0 -M0 -T1 - - - 0 - DLGDARM - (1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0) - - - 0 - DLGUARM - (105=-1,-1,-1,-1,0)(106=-1,-1,-1,-1,0)(107=-1,-1,-1,-1,0) - - - 0 - DLGTARM - (1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0)(110=-1,-1,-1,-1,0)(100=-1,-1,-1,-1,0)(101=-1,-1,-1,-1,0)(102=-1,-1,-1,-1,0)(103=-1,-1,-1,-1,0)(104=-1,-1,-1,-1,0)(105=-1,-1,-1,-1,0)(106=-1,-1,-1,-1,0)(107=-1,-1,-1,-1,0)(161=-1,-1,-1,-1,0)(162=-1,-1,-1,-1,0)(163=-1,-1,-1,-1,0)(164=-1,-1,-1,-1,0)(150=-1,-1,-1,-1,0)(151=-1,-1,-1,-1,0)(152=-1,-1,-1,-1,0)(1011=-1,-1,-1,-1,0)(1012=-1,-1,-1,-1,0)(1013=-1,-1,-1,-1,0)(171=-1,-1,-1,-1,0)(172=-1,-1,-1,-1,0)(173=-1,-1,-1,-1,0)(1014=-1,-1,-1,-1,0)(1016=-1,-1,-1,-1,0)(136=-1,-1,-1,-1,0) - - - 0 - ARMDBGFLAGS - -T5F - - - 0 - UL2CM3 - -UV0289BJE -O14 -S0 -C0 -N00("ARM CoreSight JTAG-DP") -D00(3BA00477) -L00(4) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO7 -FD20000000 -FC800 -FN1 -FF0LM3S_16 -FS00 -FL04000 - - - - - - 0 - 1 - thread_0_counter - - - 1 - 1 - thread_1_counter - - - 2 - 1 - thread_2_counter - - - 3 - 1 - thread_3_counter - - - 4 - 1 - thread_4_counter - - - 5 - 1 - thread_5_counter - - - - 0 - - - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - - - - - - - - - - - - - Source Group - 0 - 0 - 0 - 0 - - 1 - 1 - 2 - 0 - 0 - 0 - .\tx_initialize_low_level.s - tx_initialize_low_level.s - 0 - 0 - - - 1 - 2 - 1 - 0 - 0 - 0 - .\sample_threadx.c - sample_threadx.c - 0 - 0 - - 44 - 0 - 1 - - -1 - -1 - - - -1 - -1 - - - 56 - 12 - 1633 - 671 - - - - - - - Library_Group - 0 - 0 - 0 - 0 - - 2 - 3 - 4 - 0 - 0 - 0 - .\ThreadX_Library.lib - ThreadX_Library.lib - 0 - 0 - - - -
diff --git a/ports/cortex_m3/keil/example_build/ThreadX_Library.plg b/ports/cortex_m3/keil/example_build/ThreadX_Library.plg deleted file mode 100644 index 6b87c5cfd..000000000 --- a/ports/cortex_m3/keil/example_build/ThreadX_Library.plg +++ /dev/null @@ -1,9 +0,0 @@ - - -
-

µVision Build Log

-

Project:

-C:\threadx\cortex-m3\keil\ThreadX_Library.uvproj -Project File Date: 07/19/2012 - -

Output:

diff --git a/ports/cortex_m3/keil/example_build/ThreadX_Library.uvopt b/ports/cortex_m3/keil/example_build/ThreadX_Library.uvopt deleted file mode 100644 index f85946182..000000000 --- a/ports/cortex_m3/keil/example_build/ThreadX_Library.uvopt +++ /dev/null @@ -1,2664 +0,0 @@ - - - - 1.0 - -
### uVision Project, (C) Keil Software
- - - *.c - *.s*; *.src; *.a* - *.obj; *.o - *.lib - *.txt; *.h; *.inc; *.md - *.plm - *.cpp - 0 - - - - 0 - 0 - - - - ThreadX_Library_Project - 0x4 - ARM-ADS - - 12000000 - - 1 - 1 - 1 - 0 - 0 - - - 1 - 65535 - 0 - 0 - 0 - - - 79 - 66 - 8 - .\ - - - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - - - 1 - 0 - 1 - - 255 - - 1 - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 1 - 0 - 1 - 0 - 1 - 1 - 0 - 0 - 1 - 0 - 0 - 1 - - - - - - - - - - - BIN\UL2CM3.DLL - - - - 0 - UL2CM3 - -UU0101L5E -O14 -S0 -C0 -N00("ARM Cortex-M3") -D00(1BA00477) -L00(4) -FO7 -FD20000000 -FC800 -FN1 -FF0LM3S_16 -FS00 -FL04000 - - - - - 0 - - - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - - - - - - - - - - - - - Source Group - 0 - 0 - 0 - 0 - - 1 - 1 - 2 - 0 - 0 - 0 - ..\src\tx_thread_interrupt_disable.s - tx_thread_interrupt_disable.s - 0 - 0 - - - 1 - 2 - 2 - 0 - 0 - 0 - ..\src\tx_thread_interrupt_control.s - tx_thread_interrupt_control.s - 0 - 0 - - - 1 - 3 - 2 - 0 - 0 - 0 - ..\src\tx_thread_context_restore.s - tx_thread_context_restore.s - 0 - 0 - - - 1 - 4 - 2 - 0 - 0 - 0 - ..\src\tx_thread_context_save.s - tx_thread_context_save.s - 0 - 0 - - - 1 - 5 - 2 - 0 - 0 - 0 - ..\src\tx_thread_interrupt_restore.s - tx_thread_interrupt_restore.s - 0 - 0 - - - 1 - 6 - 2 - 0 - 0 - 0 - ..\src\tx_thread_schedule.s - tx_thread_schedule.s - 0 - 0 - - - 1 - 7 - 2 - 0 - 0 - 0 - ..\src\tx_thread_stack_build.s - tx_thread_stack_build.s - 0 - 0 - - - 1 - 8 - 2 - 0 - 0 - 0 - ..\src\tx_thread_system_return.s - tx_thread_system_return.s - 0 - 0 - - - 1 - 9 - 2 - 0 - 0 - 0 - ..\src\tx_timer_interrupt.s - tx_timer_interrupt.s - 0 - 0 - - - 1 - 10 - 5 - 0 - 0 - 0 - ..\inc\tx_port.h - tx_port.h - 0 - 0 - - - 1 - 11 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_api.h - tx_api.h - 0 - 0 - - - 1 - 12 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_block_pool.h - tx_block_pool.h - 0 - 0 - - - 1 - 13 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_byte_pool.h - tx_byte_pool.h - 0 - 0 - - - 1 - 14 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_event_flags.h - tx_event_flags.h - 0 - 0 - - - 1 - 15 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_initialize.h - tx_initialize.h - 0 - 0 - - - 1 - 16 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_mutex.h - tx_mutex.h - 0 - 0 - - - 1 - 17 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_queue.h - tx_queue.h - 0 - 0 - - - 1 - 18 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_semaphore.h - tx_semaphore.h - 0 - 0 - - - 1 - 19 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_thread.h - tx_thread.h - 0 - 0 - - - 1 - 20 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_timer.h - tx_timer.h - 0 - 0 - - - 1 - 21 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_trace.h - tx_trace.h - 0 - 0 - - - 1 - 22 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_user.h - tx_user.h - 0 - 0 - - - 1 - 23 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_allocate.c - tx_block_allocate.c - 0 - 0 - - - 1 - 24 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_cleanup.c - tx_block_pool_cleanup.c - 0 - 0 - - - 1 - 25 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_create.c - tx_block_pool_create.c - 0 - 0 - - - 1 - 26 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_delete.c - tx_block_pool_delete.c - 0 - 0 - - - 1 - 27 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_info_get.c - tx_block_pool_info_get.c - 0 - 0 - - - 1 - 28 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_initialize.c - tx_block_pool_initialize.c - 0 - 0 - - - 1 - 29 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_performance_info_get.c - tx_block_pool_performance_info_get.c - 0 - 0 - - - 1 - 30 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_performance_system_info_get.c - tx_block_pool_performance_system_info_get.c - 0 - 0 - - - 1 - 31 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_prioritize.c - tx_block_pool_prioritize.c - 0 - 0 - - - 1 - 32 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_release.c - tx_block_release.c - 0 - 0 - - - 1 - 33 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_allocate.c - tx_byte_allocate.c - 0 - 0 - - - 1 - 34 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_cleanup.c - tx_byte_pool_cleanup.c - 0 - 0 - - - 1 - 35 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_create.c - tx_byte_pool_create.c - 0 - 0 - - - 1 - 36 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_delete.c - tx_byte_pool_delete.c - 0 - 0 - - - 1 - 37 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_info_get.c - tx_byte_pool_info_get.c - 0 - 0 - - - 1 - 38 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_initialize.c - tx_byte_pool_initialize.c - 0 - 0 - - - 1 - 39 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_performance_info_get.c - tx_byte_pool_performance_info_get.c - 0 - 0 - - - 1 - 40 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_performance_system_info_get.c - tx_byte_pool_performance_system_info_get.c - 0 - 0 - - - 1 - 41 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_prioritize.c - tx_byte_pool_prioritize.c - 0 - 0 - - - 1 - 42 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_search.c - tx_byte_pool_search.c - 0 - 0 - - - 1 - 43 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_release.c - tx_byte_release.c - 0 - 0 - - - 1 - 44 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_cleanup.c - tx_event_flags_cleanup.c - 0 - 0 - - - 1 - 45 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_create.c - tx_event_flags_create.c - 0 - 0 - - - 1 - 46 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_delete.c - tx_event_flags_delete.c - 0 - 0 - - - 1 - 47 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_get.c - tx_event_flags_get.c - 0 - 0 - - - 1 - 48 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_info_get.c - tx_event_flags_info_get.c - 0 - 0 - - - 1 - 49 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_initialize.c - tx_event_flags_initialize.c - 0 - 0 - - - 1 - 50 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_performance_info_get.c - tx_event_flags_performance_info_get.c - 0 - 0 - - - 1 - 51 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_performance_system_info_get.c - tx_event_flags_performance_system_info_get.c - 0 - 0 - - - 1 - 52 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_set.c - tx_event_flags_set.c - 0 - 0 - - - 1 - 53 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_set_notify.c - tx_event_flags_set_notify.c - 0 - 0 - - - 1 - 54 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_initialize_high_level.c - tx_initialize_high_level.c - 0 - 0 - - - 1 - 55 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_initialize_kernel_enter.c - tx_initialize_kernel_enter.c - 0 - 0 - - - 1 - 56 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_initialize_kernel_setup.c - tx_initialize_kernel_setup.c - 0 - 0 - - - 1 - 57 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_misra.c - tx_misra.c - 0 - 0 - - - 1 - 58 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_cleanup.c - tx_mutex_cleanup.c - 0 - 0 - - - 1 - 59 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_create.c - tx_mutex_create.c - 0 - 0 - - - 1 - 60 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_delete.c - tx_mutex_delete.c - 0 - 0 - - - 1 - 61 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_get.c - tx_mutex_get.c - 0 - 0 - - - 1 - 62 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_info_get.c - tx_mutex_info_get.c - 0 - 0 - - - 1 - 63 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_initialize.c - tx_mutex_initialize.c - 0 - 0 - - - 1 - 64 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_performance_info_get.c - tx_mutex_performance_info_get.c - 0 - 0 - - - 1 - 65 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_performance_system_info_get.c - tx_mutex_performance_system_info_get.c - 0 - 0 - - - 1 - 66 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_prioritize.c - tx_mutex_prioritize.c - 0 - 0 - - - 1 - 67 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_priority_change.c - tx_mutex_priority_change.c - 0 - 0 - - - 1 - 68 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_put.c - tx_mutex_put.c - 0 - 0 - - - 1 - 69 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_cleanup.c - tx_queue_cleanup.c - 0 - 0 - - - 1 - 70 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_create.c - tx_queue_create.c - 0 - 0 - - - 1 - 71 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_delete.c - tx_queue_delete.c - 0 - 0 - - - 1 - 72 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_flush.c - tx_queue_flush.c - 0 - 0 - - - 1 - 73 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_front_send.c - tx_queue_front_send.c - 0 - 0 - - - 1 - 74 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_info_get.c - tx_queue_info_get.c - 0 - 0 - - - 1 - 75 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_initialize.c - tx_queue_initialize.c - 0 - 0 - - - 1 - 76 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_performance_info_get.c - tx_queue_performance_info_get.c - 0 - 0 - - - 1 - 77 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_performance_system_info_get.c - tx_queue_performance_system_info_get.c - 0 - 0 - - - 1 - 78 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_prioritize.c - tx_queue_prioritize.c - 0 - 0 - - - 1 - 79 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_receive.c - tx_queue_receive.c - 0 - 0 - - - 1 - 80 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_send.c - tx_queue_send.c - 0 - 0 - - - 1 - 81 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_send_notify.c - tx_queue_send_notify.c - 0 - 0 - - - 1 - 82 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_ceiling_put.c - tx_semaphore_ceiling_put.c - 0 - 0 - - - 1 - 83 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_cleanup.c - tx_semaphore_cleanup.c - 0 - 0 - - - 1 - 84 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_create.c - tx_semaphore_create.c - 0 - 0 - - - 1 - 85 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_delete.c - tx_semaphore_delete.c - 0 - 0 - - - 1 - 86 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_get.c - tx_semaphore_get.c - 0 - 0 - - - 1 - 87 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_info_get.c - tx_semaphore_info_get.c - 0 - 0 - - - 1 - 88 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_initialize.c - tx_semaphore_initialize.c - 0 - 0 - - - 1 - 89 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_performance_info_get.c - tx_semaphore_performance_info_get.c - 0 - 0 - - - 1 - 90 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_performance_system_info_get.c - tx_semaphore_performance_system_info_get.c - 0 - 0 - - - 1 - 91 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_prioritize.c - tx_semaphore_prioritize.c - 0 - 0 - - - 1 - 92 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_put.c - tx_semaphore_put.c - 0 - 0 - - - 1 - 93 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_put_notify.c - tx_semaphore_put_notify.c - 0 - 0 - - - 1 - 94 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_create.c - tx_thread_create.c - 0 - 0 - - - 1 - 95 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_delete.c - tx_thread_delete.c - 0 - 0 - - - 1 - 96 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_entry_exit_notify.c - tx_thread_entry_exit_notify.c - 0 - 0 - - - 1 - 97 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_identify.c - tx_thread_identify.c - 0 - 0 - - - 1 - 98 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_info_get.c - tx_thread_info_get.c - 0 - 0 - - - 1 - 99 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_initialize.c - tx_thread_initialize.c - 0 - 0 - - - 1 - 100 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_performance_info_get.c - tx_thread_performance_info_get.c - 0 - 0 - - - 1 - 101 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_performance_system_info_get.c - tx_thread_performance_system_info_get.c - 0 - 0 - - - 1 - 102 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_preemption_change.c - tx_thread_preemption_change.c - 0 - 0 - - - 1 - 103 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_priority_change.c - tx_thread_priority_change.c - 0 - 0 - - - 1 - 104 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_relinquish.c - tx_thread_relinquish.c - 0 - 0 - - - 1 - 105 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_reset.c - tx_thread_reset.c - 0 - 0 - - - 1 - 106 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_resume.c - tx_thread_resume.c - 0 - 0 - - - 1 - 107 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_shell_entry.c - tx_thread_shell_entry.c - 0 - 0 - - - 1 - 108 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_sleep.c - tx_thread_sleep.c - 0 - 0 - - - 1 - 109 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_stack_analyze.c - tx_thread_stack_analyze.c - 0 - 0 - - - 1 - 110 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_stack_error_handler.c - tx_thread_stack_error_handler.c - 0 - 0 - - - 1 - 111 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_stack_error_notify.c - tx_thread_stack_error_notify.c - 0 - 0 - - - 1 - 112 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_suspend.c - tx_thread_suspend.c - 0 - 0 - - - 1 - 113 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_system_preempt_check.c - tx_thread_system_preempt_check.c - 0 - 0 - - - 1 - 114 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_system_resume.c - tx_thread_system_resume.c - 0 - 0 - - - 1 - 115 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_system_suspend.c - tx_thread_system_suspend.c - 0 - 0 - - - 1 - 116 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_terminate.c - tx_thread_terminate.c - 0 - 0 - - - 1 - 117 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_time_slice.c - tx_thread_time_slice.c - 0 - 0 - - - 1 - 118 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_time_slice_change.c - tx_thread_time_slice_change.c - 0 - 0 - - - 1 - 119 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_timeout.c - tx_thread_timeout.c - 0 - 0 - - - 1 - 120 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_wait_abort.c - tx_thread_wait_abort.c - 0 - 0 - - - 1 - 121 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_time_get.c - tx_time_get.c - 0 - 0 - - - 1 - 122 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_time_set.c - tx_time_set.c - 0 - 0 - - - 1 - 123 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_activate.c - tx_timer_activate.c - 0 - 0 - - - 1 - 124 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_change.c - tx_timer_change.c - 0 - 0 - - - 1 - 125 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_create.c - tx_timer_create.c - 0 - 0 - - - 1 - 126 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_deactivate.c - tx_timer_deactivate.c - 0 - 0 - - - 1 - 127 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_delete.c - tx_timer_delete.c - 0 - 0 - - - 1 - 128 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_expiration_process.c - tx_timer_expiration_process.c - 0 - 0 - - - 1 - 129 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_info_get.c - tx_timer_info_get.c - 0 - 0 - - - 1 - 130 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_initialize.c - tx_timer_initialize.c - 0 - 0 - - - 1 - 131 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_performance_info_get.c - tx_timer_performance_info_get.c - 0 - 0 - - - 1 - 132 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_performance_system_info_get.c - tx_timer_performance_system_info_get.c - 0 - 0 - - - 1 - 133 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_system_activate.c - tx_timer_system_activate.c - 0 - 0 - - - 1 - 134 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_system_deactivate.c - tx_timer_system_deactivate.c - 0 - 0 - - - 1 - 135 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_thread_entry.c - tx_timer_thread_entry.c - 0 - 0 - - - 1 - 136 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_buffer_full_notify.c - tx_trace_buffer_full_notify.c - 0 - 0 - - - 1 - 137 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_disable.c - tx_trace_disable.c - 0 - 0 - - - 1 - 138 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_enable.c - tx_trace_enable.c - 0 - 0 - - - 1 - 139 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_event_filter.c - tx_trace_event_filter.c - 0 - 0 - - - 1 - 140 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_event_unfilter.c - tx_trace_event_unfilter.c - 0 - 0 - - - 1 - 141 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_initialize.c - tx_trace_initialize.c - 0 - 0 - - - 1 - 142 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_interrupt_control.c - tx_trace_interrupt_control.c - 0 - 0 - - - 1 - 143 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_isr_enter_insert.c - tx_trace_isr_enter_insert.c - 0 - 0 - - - 1 - 144 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_isr_exit_insert.c - tx_trace_isr_exit_insert.c - 0 - 0 - - - 1 - 145 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_object_register.c - tx_trace_object_register.c - 0 - 0 - - - 1 - 146 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_object_unregister.c - tx_trace_object_unregister.c - 0 - 0 - - - 1 - 147 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_user_event_insert.c - tx_trace_user_event_insert.c - 0 - 0 - - - 1 - 148 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_allocate.c - txe_block_allocate.c - 0 - 0 - - - 1 - 149 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_pool_create.c - txe_block_pool_create.c - 0 - 0 - - - 1 - 150 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_pool_delete.c - txe_block_pool_delete.c - 0 - 0 - - - 1 - 151 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_pool_info_get.c - txe_block_pool_info_get.c - 0 - 0 - - - 1 - 152 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_pool_prioritize.c - txe_block_pool_prioritize.c - 0 - 0 - - - 1 - 153 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_release.c - txe_block_release.c - 0 - 0 - - - 1 - 154 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_allocate.c - txe_byte_allocate.c - 0 - 0 - - - 1 - 155 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_pool_create.c - txe_byte_pool_create.c - 0 - 0 - - - 1 - 156 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_pool_delete.c - txe_byte_pool_delete.c - 0 - 0 - - - 1 - 157 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_pool_info_get.c - txe_byte_pool_info_get.c - 0 - 0 - - - 1 - 158 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_pool_prioritize.c - txe_byte_pool_prioritize.c - 0 - 0 - - - 1 - 159 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_release.c - txe_byte_release.c - 0 - 0 - - - 1 - 160 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_create.c - txe_event_flags_create.c - 0 - 0 - - - 1 - 161 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_delete.c - txe_event_flags_delete.c - 0 - 0 - - - 1 - 162 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_get.c - txe_event_flags_get.c - 0 - 0 - - - 1 - 163 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_info_get.c - txe_event_flags_info_get.c - 0 - 0 - - - 1 - 164 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_set.c - txe_event_flags_set.c - 0 - 0 - - - 1 - 165 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_set_notify.c - txe_event_flags_set_notify.c - 0 - 0 - - - 1 - 166 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_create.c - txe_mutex_create.c - 0 - 0 - - - 1 - 167 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_delete.c - txe_mutex_delete.c - 0 - 0 - - - 1 - 168 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_get.c - txe_mutex_get.c - 0 - 0 - - - 1 - 169 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_info_get.c - txe_mutex_info_get.c - 0 - 0 - - - 1 - 170 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_prioritize.c - txe_mutex_prioritize.c - 0 - 0 - - - 1 - 171 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_put.c - txe_mutex_put.c - 0 - 0 - - - 1 - 172 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_create.c - txe_queue_create.c - 0 - 0 - - - 1 - 173 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_delete.c - txe_queue_delete.c - 0 - 0 - - - 1 - 174 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_flush.c - txe_queue_flush.c - 0 - 0 - - - 1 - 175 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_front_send.c - txe_queue_front_send.c - 0 - 0 - - - 1 - 176 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_info_get.c - txe_queue_info_get.c - 0 - 0 - - - 1 - 177 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_prioritize.c - txe_queue_prioritize.c - 0 - 0 - - - 1 - 178 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_receive.c - txe_queue_receive.c - 0 - 0 - - - 1 - 179 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_send.c - txe_queue_send.c - 0 - 0 - - - 1 - 180 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_send_notify.c - txe_queue_send_notify.c - 0 - 0 - - - 1 - 181 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_ceiling_put.c - txe_semaphore_ceiling_put.c - 0 - 0 - - - 1 - 182 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_create.c - txe_semaphore_create.c - 0 - 0 - - - 1 - 183 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_delete.c - txe_semaphore_delete.c - 0 - 0 - - - 1 - 184 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_get.c - txe_semaphore_get.c - 0 - 0 - - - 1 - 185 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_info_get.c - txe_semaphore_info_get.c - 0 - 0 - - - 1 - 186 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_prioritize.c - txe_semaphore_prioritize.c - 0 - 0 - - - 1 - 187 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_put.c - txe_semaphore_put.c - 0 - 0 - - - 1 - 188 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_put_notify.c - txe_semaphore_put_notify.c - 0 - 0 - - - 1 - 189 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_create.c - txe_thread_create.c - 0 - 0 - - - 1 - 190 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_delete.c - txe_thread_delete.c - 0 - 0 - - - 1 - 191 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_entry_exit_notify.c - txe_thread_entry_exit_notify.c - 0 - 0 - - - 1 - 192 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_info_get.c - txe_thread_info_get.c - 0 - 0 - - - 1 - 193 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_preemption_change.c - txe_thread_preemption_change.c - 0 - 0 - - - 1 - 194 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_priority_change.c - txe_thread_priority_change.c - 0 - 0 - - - 1 - 195 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_relinquish.c - txe_thread_relinquish.c - 0 - 0 - - - 1 - 196 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_reset.c - txe_thread_reset.c - 0 - 0 - - - 1 - 197 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_resume.c - txe_thread_resume.c - 0 - 0 - - - 1 - 198 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_suspend.c - txe_thread_suspend.c - 0 - 0 - - - 1 - 199 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_terminate.c - txe_thread_terminate.c - 0 - 0 - - - 1 - 200 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_time_slice_change.c - txe_thread_time_slice_change.c - 0 - 0 - - - 1 - 201 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_wait_abort.c - txe_thread_wait_abort.c - 0 - 0 - - - 1 - 202 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_activate.c - txe_timer_activate.c - 0 - 0 - - - 1 - 203 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_change.c - txe_timer_change.c - 0 - 0 - - - 1 - 204 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_create.c - txe_timer_create.c - 0 - 0 - - - 1 - 205 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_deactivate.c - txe_timer_deactivate.c - 0 - 0 - - - 1 - 206 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_delete.c - txe_timer_delete.c - 0 - 0 - - - 1 - 207 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_info_get.c - txe_timer_info_get.c - 0 - 0 - - - -
diff --git a/ports/cortex_m3/keil/example_build/ThreadX_Library.uvoptx b/ports/cortex_m3/keil/example_build/ThreadX_Library.uvoptx deleted file mode 100644 index beae910cd..000000000 --- a/ports/cortex_m3/keil/example_build/ThreadX_Library.uvoptx +++ /dev/null @@ -1,2664 +0,0 @@ - - - - 1.0 - -
### uVision Project, (C) Keil Software
- - - *.c - *.s*; *.src; *.a* - *.obj; *.o - *.lib - *.txt; *.h; *.inc; *.md - *.plm - *.cpp - 0 - - - - 0 - 0 - - - - ThreadX_Library_Project - 0x4 - ARM-ADS - - 12000000 - - 1 - 1 - 1 - 0 - 0 - - - 1 - 65535 - 0 - 0 - 0 - - - 79 - 66 - 8 - .\ - - - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - - - 1 - 0 - 1 - - 255 - - 1 - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 1 - 0 - 1 - 0 - 1 - 1 - 0 - 0 - 1 - 0 - 0 - 1 - - - - - - - - - - - BIN\UL2CM3.DLL - - - - 0 - UL2CM3 - -UU0101L5E -O14 -S0 -C0 -N00("ARM Cortex-M3") -D00(1BA00477) -L00(4) -FO7 -FD20000000 -FC800 -FN1 -FF0LM3S_16 -FS00 -FL04000 - - - - - 0 - - - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - - - - - - - - - - - - - Source Group - 0 - 0 - 0 - 0 - - 1 - 1 - 5 - 0 - 0 - 0 - ..\inc\tx_port.h - tx_port.h - 0 - 0 - - - 1 - 2 - 2 - 0 - 0 - 0 - ..\src\tx_thread_context_restore.s - tx_thread_context_restore.s - 0 - 0 - - - 1 - 3 - 2 - 0 - 0 - 0 - ..\src\tx_thread_context_save.s - tx_thread_context_save.s - 0 - 0 - - - 1 - 4 - 2 - 0 - 0 - 0 - ..\src\tx_thread_interrupt_control.s - tx_thread_interrupt_control.s - 0 - 0 - - - 1 - 5 - 2 - 0 - 0 - 0 - ..\src\tx_thread_interrupt_disable.s - tx_thread_interrupt_disable.s - 0 - 0 - - - 1 - 6 - 2 - 0 - 0 - 0 - ..\src\tx_thread_interrupt_restore.s - tx_thread_interrupt_restore.s - 0 - 0 - - - 1 - 7 - 2 - 0 - 0 - 0 - ..\src\tx_thread_schedule.s - tx_thread_schedule.s - 0 - 0 - - - 1 - 8 - 2 - 0 - 0 - 0 - ..\src\tx_thread_stack_build.s - tx_thread_stack_build.s - 0 - 0 - - - 1 - 9 - 2 - 0 - 0 - 0 - ..\src\tx_thread_system_return.s - tx_thread_system_return.s - 0 - 0 - - - 1 - 10 - 2 - 0 - 0 - 0 - ..\src\tx_timer_interrupt.s - tx_timer_interrupt.s - 0 - 0 - - - 1 - 11 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_api.h - tx_api.h - 0 - 0 - - - 1 - 12 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_block_pool.h - tx_block_pool.h - 0 - 0 - - - 1 - 13 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_byte_pool.h - tx_byte_pool.h - 0 - 0 - - - 1 - 14 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_event_flags.h - tx_event_flags.h - 0 - 0 - - - 1 - 15 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_initialize.h - tx_initialize.h - 0 - 0 - - - 1 - 16 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_mutex.h - tx_mutex.h - 0 - 0 - - - 1 - 17 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_queue.h - tx_queue.h - 0 - 0 - - - 1 - 18 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_semaphore.h - tx_semaphore.h - 0 - 0 - - - 1 - 19 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_thread.h - tx_thread.h - 0 - 0 - - - 1 - 20 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_timer.h - tx_timer.h - 0 - 0 - - - 1 - 21 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_trace.h - tx_trace.h - 0 - 0 - - - 1 - 22 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_user.h - tx_user.h - 0 - 0 - - - 1 - 23 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_allocate.c - tx_block_allocate.c - 0 - 0 - - - 1 - 24 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_cleanup.c - tx_block_pool_cleanup.c - 0 - 0 - - - 1 - 25 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_create.c - tx_block_pool_create.c - 0 - 0 - - - 1 - 26 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_delete.c - tx_block_pool_delete.c - 0 - 0 - - - 1 - 27 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_info_get.c - tx_block_pool_info_get.c - 0 - 0 - - - 1 - 28 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_initialize.c - tx_block_pool_initialize.c - 0 - 0 - - - 1 - 29 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_performance_info_get.c - tx_block_pool_performance_info_get.c - 0 - 0 - - - 1 - 30 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_performance_system_info_get.c - tx_block_pool_performance_system_info_get.c - 0 - 0 - - - 1 - 31 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_prioritize.c - tx_block_pool_prioritize.c - 0 - 0 - - - 1 - 32 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_release.c - tx_block_release.c - 0 - 0 - - - 1 - 33 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_allocate.c - tx_byte_allocate.c - 0 - 0 - - - 1 - 34 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_cleanup.c - tx_byte_pool_cleanup.c - 0 - 0 - - - 1 - 35 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_create.c - tx_byte_pool_create.c - 0 - 0 - - - 1 - 36 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_delete.c - tx_byte_pool_delete.c - 0 - 0 - - - 1 - 37 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_info_get.c - tx_byte_pool_info_get.c - 0 - 0 - - - 1 - 38 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_initialize.c - tx_byte_pool_initialize.c - 0 - 0 - - - 1 - 39 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_performance_info_get.c - tx_byte_pool_performance_info_get.c - 0 - 0 - - - 1 - 40 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_performance_system_info_get.c - tx_byte_pool_performance_system_info_get.c - 0 - 0 - - - 1 - 41 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_prioritize.c - tx_byte_pool_prioritize.c - 0 - 0 - - - 1 - 42 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_search.c - tx_byte_pool_search.c - 0 - 0 - - - 1 - 43 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_release.c - tx_byte_release.c - 0 - 0 - - - 1 - 44 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_cleanup.c - tx_event_flags_cleanup.c - 0 - 0 - - - 1 - 45 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_create.c - tx_event_flags_create.c - 0 - 0 - - - 1 - 46 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_delete.c - tx_event_flags_delete.c - 0 - 0 - - - 1 - 47 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_get.c - tx_event_flags_get.c - 0 - 0 - - - 1 - 48 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_info_get.c - tx_event_flags_info_get.c - 0 - 0 - - - 1 - 49 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_initialize.c - tx_event_flags_initialize.c - 0 - 0 - - - 1 - 50 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_performance_info_get.c - tx_event_flags_performance_info_get.c - 0 - 0 - - - 1 - 51 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_performance_system_info_get.c - tx_event_flags_performance_system_info_get.c - 0 - 0 - - - 1 - 52 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_set.c - tx_event_flags_set.c - 0 - 0 - - - 1 - 53 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_set_notify.c - tx_event_flags_set_notify.c - 0 - 0 - - - 1 - 54 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_initialize_high_level.c - tx_initialize_high_level.c - 0 - 0 - - - 1 - 55 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_initialize_kernel_enter.c - tx_initialize_kernel_enter.c - 0 - 0 - - - 1 - 56 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_initialize_kernel_setup.c - tx_initialize_kernel_setup.c - 0 - 0 - - - 1 - 57 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_misra.c - tx_misra.c - 0 - 0 - - - 1 - 58 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_cleanup.c - tx_mutex_cleanup.c - 0 - 0 - - - 1 - 59 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_create.c - tx_mutex_create.c - 0 - 0 - - - 1 - 60 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_delete.c - tx_mutex_delete.c - 0 - 0 - - - 1 - 61 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_get.c - tx_mutex_get.c - 0 - 0 - - - 1 - 62 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_info_get.c - tx_mutex_info_get.c - 0 - 0 - - - 1 - 63 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_initialize.c - tx_mutex_initialize.c - 0 - 0 - - - 1 - 64 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_performance_info_get.c - tx_mutex_performance_info_get.c - 0 - 0 - - - 1 - 65 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_performance_system_info_get.c - tx_mutex_performance_system_info_get.c - 0 - 0 - - - 1 - 66 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_prioritize.c - tx_mutex_prioritize.c - 0 - 0 - - - 1 - 67 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_priority_change.c - tx_mutex_priority_change.c - 0 - 0 - - - 1 - 68 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_put.c - tx_mutex_put.c - 0 - 0 - - - 1 - 69 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_cleanup.c - tx_queue_cleanup.c - 0 - 0 - - - 1 - 70 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_create.c - tx_queue_create.c - 0 - 0 - - - 1 - 71 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_delete.c - tx_queue_delete.c - 0 - 0 - - - 1 - 72 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_flush.c - tx_queue_flush.c - 0 - 0 - - - 1 - 73 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_front_send.c - tx_queue_front_send.c - 0 - 0 - - - 1 - 74 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_info_get.c - tx_queue_info_get.c - 0 - 0 - - - 1 - 75 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_initialize.c - tx_queue_initialize.c - 0 - 0 - - - 1 - 76 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_performance_info_get.c - tx_queue_performance_info_get.c - 0 - 0 - - - 1 - 77 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_performance_system_info_get.c - tx_queue_performance_system_info_get.c - 0 - 0 - - - 1 - 78 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_prioritize.c - tx_queue_prioritize.c - 0 - 0 - - - 1 - 79 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_receive.c - tx_queue_receive.c - 0 - 0 - - - 1 - 80 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_send.c - tx_queue_send.c - 0 - 0 - - - 1 - 81 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_send_notify.c - tx_queue_send_notify.c - 0 - 0 - - - 1 - 82 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_ceiling_put.c - tx_semaphore_ceiling_put.c - 0 - 0 - - - 1 - 83 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_cleanup.c - tx_semaphore_cleanup.c - 0 - 0 - - - 1 - 84 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_create.c - tx_semaphore_create.c - 0 - 0 - - - 1 - 85 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_delete.c - tx_semaphore_delete.c - 0 - 0 - - - 1 - 86 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_get.c - tx_semaphore_get.c - 0 - 0 - - - 1 - 87 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_info_get.c - tx_semaphore_info_get.c - 0 - 0 - - - 1 - 88 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_initialize.c - tx_semaphore_initialize.c - 0 - 0 - - - 1 - 89 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_performance_info_get.c - tx_semaphore_performance_info_get.c - 0 - 0 - - - 1 - 90 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_performance_system_info_get.c - tx_semaphore_performance_system_info_get.c - 0 - 0 - - - 1 - 91 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_prioritize.c - tx_semaphore_prioritize.c - 0 - 0 - - - 1 - 92 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_put.c - tx_semaphore_put.c - 0 - 0 - - - 1 - 93 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_put_notify.c - tx_semaphore_put_notify.c - 0 - 0 - - - 1 - 94 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_create.c - tx_thread_create.c - 0 - 0 - - - 1 - 95 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_delete.c - tx_thread_delete.c - 0 - 0 - - - 1 - 96 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_entry_exit_notify.c - tx_thread_entry_exit_notify.c - 0 - 0 - - - 1 - 97 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_identify.c - tx_thread_identify.c - 0 - 0 - - - 1 - 98 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_info_get.c - tx_thread_info_get.c - 0 - 0 - - - 1 - 99 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_initialize.c - tx_thread_initialize.c - 0 - 0 - - - 1 - 100 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_performance_info_get.c - tx_thread_performance_info_get.c - 0 - 0 - - - 1 - 101 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_performance_system_info_get.c - tx_thread_performance_system_info_get.c - 0 - 0 - - - 1 - 102 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_preemption_change.c - tx_thread_preemption_change.c - 0 - 0 - - - 1 - 103 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_priority_change.c - tx_thread_priority_change.c - 0 - 0 - - - 1 - 104 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_relinquish.c - tx_thread_relinquish.c - 0 - 0 - - - 1 - 105 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_reset.c - tx_thread_reset.c - 0 - 0 - - - 1 - 106 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_resume.c - tx_thread_resume.c - 0 - 0 - - - 1 - 107 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_shell_entry.c - tx_thread_shell_entry.c - 0 - 0 - - - 1 - 108 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_sleep.c - tx_thread_sleep.c - 0 - 0 - - - 1 - 109 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_stack_analyze.c - tx_thread_stack_analyze.c - 0 - 0 - - - 1 - 110 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_stack_error_handler.c - tx_thread_stack_error_handler.c - 0 - 0 - - - 1 - 111 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_stack_error_notify.c - tx_thread_stack_error_notify.c - 0 - 0 - - - 1 - 112 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_suspend.c - tx_thread_suspend.c - 0 - 0 - - - 1 - 113 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_system_preempt_check.c - tx_thread_system_preempt_check.c - 0 - 0 - - - 1 - 114 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_system_resume.c - tx_thread_system_resume.c - 0 - 0 - - - 1 - 115 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_system_suspend.c - tx_thread_system_suspend.c - 0 - 0 - - - 1 - 116 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_terminate.c - tx_thread_terminate.c - 0 - 0 - - - 1 - 117 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_time_slice.c - tx_thread_time_slice.c - 0 - 0 - - - 1 - 118 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_time_slice_change.c - tx_thread_time_slice_change.c - 0 - 0 - - - 1 - 119 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_timeout.c - tx_thread_timeout.c - 0 - 0 - - - 1 - 120 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_wait_abort.c - tx_thread_wait_abort.c - 0 - 0 - - - 1 - 121 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_time_get.c - tx_time_get.c - 0 - 0 - - - 1 - 122 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_time_set.c - tx_time_set.c - 0 - 0 - - - 1 - 123 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_activate.c - tx_timer_activate.c - 0 - 0 - - - 1 - 124 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_change.c - tx_timer_change.c - 0 - 0 - - - 1 - 125 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_create.c - tx_timer_create.c - 0 - 0 - - - 1 - 126 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_deactivate.c - tx_timer_deactivate.c - 0 - 0 - - - 1 - 127 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_delete.c - tx_timer_delete.c - 0 - 0 - - - 1 - 128 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_expiration_process.c - tx_timer_expiration_process.c - 0 - 0 - - - 1 - 129 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_info_get.c - tx_timer_info_get.c - 0 - 0 - - - 1 - 130 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_initialize.c - tx_timer_initialize.c - 0 - 0 - - - 1 - 131 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_performance_info_get.c - tx_timer_performance_info_get.c - 0 - 0 - - - 1 - 132 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_performance_system_info_get.c - tx_timer_performance_system_info_get.c - 0 - 0 - - - 1 - 133 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_system_activate.c - tx_timer_system_activate.c - 0 - 0 - - - 1 - 134 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_system_deactivate.c - tx_timer_system_deactivate.c - 0 - 0 - - - 1 - 135 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_thread_entry.c - tx_timer_thread_entry.c - 0 - 0 - - - 1 - 136 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_buffer_full_notify.c - tx_trace_buffer_full_notify.c - 0 - 0 - - - 1 - 137 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_disable.c - tx_trace_disable.c - 0 - 0 - - - 1 - 138 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_enable.c - tx_trace_enable.c - 0 - 0 - - - 1 - 139 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_event_filter.c - tx_trace_event_filter.c - 0 - 0 - - - 1 - 140 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_event_unfilter.c - tx_trace_event_unfilter.c - 0 - 0 - - - 1 - 141 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_initialize.c - tx_trace_initialize.c - 0 - 0 - - - 1 - 142 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_interrupt_control.c - tx_trace_interrupt_control.c - 0 - 0 - - - 1 - 143 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_isr_enter_insert.c - tx_trace_isr_enter_insert.c - 0 - 0 - - - 1 - 144 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_isr_exit_insert.c - tx_trace_isr_exit_insert.c - 0 - 0 - - - 1 - 145 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_object_register.c - tx_trace_object_register.c - 0 - 0 - - - 1 - 146 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_object_unregister.c - tx_trace_object_unregister.c - 0 - 0 - - - 1 - 147 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_user_event_insert.c - tx_trace_user_event_insert.c - 0 - 0 - - - 1 - 148 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_allocate.c - txe_block_allocate.c - 0 - 0 - - - 1 - 149 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_pool_create.c - txe_block_pool_create.c - 0 - 0 - - - 1 - 150 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_pool_delete.c - txe_block_pool_delete.c - 0 - 0 - - - 1 - 151 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_pool_info_get.c - txe_block_pool_info_get.c - 0 - 0 - - - 1 - 152 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_pool_prioritize.c - txe_block_pool_prioritize.c - 0 - 0 - - - 1 - 153 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_release.c - txe_block_release.c - 0 - 0 - - - 1 - 154 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_allocate.c - txe_byte_allocate.c - 0 - 0 - - - 1 - 155 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_pool_create.c - txe_byte_pool_create.c - 0 - 0 - - - 1 - 156 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_pool_delete.c - txe_byte_pool_delete.c - 0 - 0 - - - 1 - 157 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_pool_info_get.c - txe_byte_pool_info_get.c - 0 - 0 - - - 1 - 158 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_pool_prioritize.c - txe_byte_pool_prioritize.c - 0 - 0 - - - 1 - 159 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_release.c - txe_byte_release.c - 0 - 0 - - - 1 - 160 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_create.c - txe_event_flags_create.c - 0 - 0 - - - 1 - 161 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_delete.c - txe_event_flags_delete.c - 0 - 0 - - - 1 - 162 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_get.c - txe_event_flags_get.c - 0 - 0 - - - 1 - 163 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_info_get.c - txe_event_flags_info_get.c - 0 - 0 - - - 1 - 164 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_set.c - txe_event_flags_set.c - 0 - 0 - - - 1 - 165 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_set_notify.c - txe_event_flags_set_notify.c - 0 - 0 - - - 1 - 166 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_create.c - txe_mutex_create.c - 0 - 0 - - - 1 - 167 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_delete.c - txe_mutex_delete.c - 0 - 0 - - - 1 - 168 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_get.c - txe_mutex_get.c - 0 - 0 - - - 1 - 169 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_info_get.c - txe_mutex_info_get.c - 0 - 0 - - - 1 - 170 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_prioritize.c - txe_mutex_prioritize.c - 0 - 0 - - - 1 - 171 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_put.c - txe_mutex_put.c - 0 - 0 - - - 1 - 172 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_create.c - txe_queue_create.c - 0 - 0 - - - 1 - 173 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_delete.c - txe_queue_delete.c - 0 - 0 - - - 1 - 174 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_flush.c - txe_queue_flush.c - 0 - 0 - - - 1 - 175 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_front_send.c - txe_queue_front_send.c - 0 - 0 - - - 1 - 176 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_info_get.c - txe_queue_info_get.c - 0 - 0 - - - 1 - 177 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_prioritize.c - txe_queue_prioritize.c - 0 - 0 - - - 1 - 178 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_receive.c - txe_queue_receive.c - 0 - 0 - - - 1 - 179 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_send.c - txe_queue_send.c - 0 - 0 - - - 1 - 180 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_send_notify.c - txe_queue_send_notify.c - 0 - 0 - - - 1 - 181 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_ceiling_put.c - txe_semaphore_ceiling_put.c - 0 - 0 - - - 1 - 182 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_create.c - txe_semaphore_create.c - 0 - 0 - - - 1 - 183 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_delete.c - txe_semaphore_delete.c - 0 - 0 - - - 1 - 184 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_get.c - txe_semaphore_get.c - 0 - 0 - - - 1 - 185 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_info_get.c - txe_semaphore_info_get.c - 0 - 0 - - - 1 - 186 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_prioritize.c - txe_semaphore_prioritize.c - 0 - 0 - - - 1 - 187 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_put.c - txe_semaphore_put.c - 0 - 0 - - - 1 - 188 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_put_notify.c - txe_semaphore_put_notify.c - 0 - 0 - - - 1 - 189 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_create.c - txe_thread_create.c - 0 - 0 - - - 1 - 190 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_delete.c - txe_thread_delete.c - 0 - 0 - - - 1 - 191 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_entry_exit_notify.c - txe_thread_entry_exit_notify.c - 0 - 0 - - - 1 - 192 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_info_get.c - txe_thread_info_get.c - 0 - 0 - - - 1 - 193 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_preemption_change.c - txe_thread_preemption_change.c - 0 - 0 - - - 1 - 194 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_priority_change.c - txe_thread_priority_change.c - 0 - 0 - - - 1 - 195 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_relinquish.c - txe_thread_relinquish.c - 0 - 0 - - - 1 - 196 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_reset.c - txe_thread_reset.c - 0 - 0 - - - 1 - 197 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_resume.c - txe_thread_resume.c - 0 - 0 - - - 1 - 198 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_suspend.c - txe_thread_suspend.c - 0 - 0 - - - 1 - 199 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_terminate.c - txe_thread_terminate.c - 0 - 0 - - - 1 - 200 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_time_slice_change.c - txe_thread_time_slice_change.c - 0 - 0 - - - 1 - 201 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_wait_abort.c - txe_thread_wait_abort.c - 0 - 0 - - - 1 - 202 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_activate.c - txe_timer_activate.c - 0 - 0 - - - 1 - 203 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_change.c - txe_timer_change.c - 0 - 0 - - - 1 - 204 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_create.c - txe_timer_create.c - 0 - 0 - - - 1 - 205 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_deactivate.c - txe_timer_deactivate.c - 0 - 0 - - - 1 - 206 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_delete.c - txe_timer_delete.c - 0 - 0 - - - 1 - 207 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_info_get.c - txe_timer_info_get.c - 0 - 0 - - - -
diff --git a/ports/cortex_m33/ac6/example_build/RTOS.uvmpw.uvgui b/ports/cortex_m33/ac6/example_build/RTOS.uvmpw.uvgui deleted file mode 100644 index 5c23c31fc..000000000 --- a/ports/cortex_m33/ac6/example_build/RTOS.uvmpw.uvgui +++ /dev/null @@ -1,1777 +0,0 @@ - - - - -6.1 - -
### uVision Project, (C) Keil Software
- - - - - 44 - 2 - 3 - - -1 - -1 - - - -1 - -1 - - - 0 - 0 - 1024 - 728 - - - - 0 - - 297 - 0100000004000000010000000100000001000000010000000000000002000000000000000100000001000000000000002800000028000000010000000100000000000000010000005F433A5C4B65696C5C41524D5C5041434B5C41524D5C434D5349535C352E322E305C434D5349535C52544F53325C5254585C4578616D706C65735C54727573745A6F6E6556384D5C52544F535C434D33335F735C41627374726163742E747874000000000C41627374726163742E74787400000000C5D4F200FFFFFFFF0100000010000000C5D4F200FFDC7800BECEA100F0A0A100BCA8E1009CC1B600F7B88600D9ADC200A5C2D700B3A6BE00EAD6A300F6FA7D00B5E99D005FC3CF00C1838300CACAD500010000000000000002000000380100006500000080070000FD030000 - - - - 0 - Build - - -1 - -1 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - F40000004F00000090050000F0000000 - - - 16 - F4000000650000009005000006010000 - - - - 1005 - 1005 - 1 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 030000006600000031010000CE030000 - - - 16 - 2100000037000000110100001A010000 - - - - 109 - 109 - 1 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 030000006600000031010000CE030000 - - - 16 - 21000000370000003D010000BD020000 - - - - 1465 - 1465 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000760200008D050000FB020000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 1466 - 1466 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000760200008D050000FB020000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 1467 - 1467 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000760200008D050000FB020000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 1468 - 1468 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000760200008D050000FB020000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 1506 - 1506 - 0 - 0 - 0 - 0 - 32767 - 0 - 16384 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 1913 - 1913 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - F7000000660000008D050000D7000000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 1935 - 1935 - 0 - 0 - 0 - 0 - 32767 - 0 - 32768 - 0 - - 16 - 03000000760200008D050000FB020000 - - - 16 - 2100000037000000110100001A010000 - - - - 1936 - 1936 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000760200008D050000FB020000 - - - 16 - 2100000037000000110100001A010000 - - - - 1937 - 1937 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000760200008D050000FB020000 - - - 16 - 2100000037000000110100001A010000 - - - - 1939 - 1939 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000760200008D050000FB020000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 1940 - 1940 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000760200008D050000FB020000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 1941 - 1941 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000760200008D050000FB020000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 1942 - 1942 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000760200008D050000FB020000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 195 - 195 - 1 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 030000006600000031010000CE030000 - - - 16 - 21000000370000003D010000BD020000 - - - - 196 - 196 - 1 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 030000006600000031010000CE030000 - - - 16 - 21000000370000003D010000BD020000 - - - - 197 - 197 - 0 - 0 - 0 - 0 - 32767 - 0 - 32768 - 0 - - 16 - 03000000390300007D070000CE030000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 198 - 198 - 0 - 0 - 0 - 0 - 32767 - 0 - 32768 - 0 - - 16 - 000000005F0200009005000014030000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 199 - 199 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000390300007D070000CE030000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 203 - 203 - 0 - 0 - 0 - 0 - 32767 - 0 - 8192 - 0 - - 16 - F7000000660000008D050000D7000000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 204 - 204 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - F7000000660000008D050000D7000000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 221 - 221 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 00000000000000000000000000000000 - - - 16 - 0A0000000A0000006E0000006E000000 - - - - 2506 - 2506 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 2507 - 2507 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000760200008D050000FB020000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 343 - 343 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - F7000000660000008D050000D7000000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 346 - 346 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - F7000000660000008D050000D7000000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 35824 - 35824 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - F7000000660000008D050000D7000000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 35885 - 35885 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35886 - 35886 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35887 - 35887 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35888 - 35888 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35889 - 35889 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35890 - 35890 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35891 - 35891 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35892 - 35892 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35893 - 35893 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35894 - 35894 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35895 - 35895 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35896 - 35896 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35897 - 35897 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35898 - 35898 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35899 - 35899 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35900 - 35900 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35901 - 35901 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35902 - 35902 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35903 - 35903 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35904 - 35904 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35905 - 35905 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 38003 - 38003 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 030000006600000031010000CE030000 - - - 16 - 21000000370000003D010000BD020000 - - - - 38007 - 38007 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000390300007D070000CE030000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 436 - 436 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000390300007D070000CE030000 - - - 16 - 21000000370000003D010000BD020000 - - - - 437 - 437 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000760200008D050000FB020000 - - - 16 - 2100000037000000110100001A010000 - - - - 440 - 440 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000760200008D050000FB020000 - - - 16 - 2100000037000000110100001A010000 - - - - 463 - 463 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 030000006E0300007D070000CE030000 - - - 16 - 21000000370000003D01000079020000 - - - - 466 - 466 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 030000006E0300007D070000CE030000 - - - 16 - 21000000370000003D01000079020000 - - - - 470 - 470 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000010000000300000003020000 - - - 16 - 2100000037000000E9020000C7000000 - - - - 50000 - 50000 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50001 - 50001 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50002 - 50002 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50003 - 50003 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50004 - 50004 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50005 - 50005 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50006 - 50006 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50007 - 50007 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50008 - 50008 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50009 - 50009 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50010 - 50010 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50011 - 50011 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50012 - 50012 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50013 - 50013 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50014 - 50014 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50015 - 50015 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50016 - 50016 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50017 - 50017 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50018 - 50018 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50019 - 50019 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 59392 - 59392 - 1 - 0 - 0 - 0 - 940 - 0 - 8192 - 0 - - 16 - 0000000000000000B70300001C000000 - - - 16 - 0A0000000A0000006E0000006E000000 - - - - 59393 - 0 - 1 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 00000000E703000080070000FA030000 - - - 16 - 0A0000000A0000006E0000006E000000 - - - - 59399 - 59399 - 1 - 0 - 0 - 0 - 303 - 0 - 8192 - 1 - - 16 - 000000001C000000E701000038000000 - - - 16 - 0A0000000A0000006E0000006E000000 - - - - 59400 - 59400 - 0 - 0 - 0 - 0 - 612 - 0 - 8192 - 2 - - 16 - 00000000380000006F02000054000000 - - - 16 - 0A0000000A0000006E0000006E000000 - - - - 824 - 824 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000010000000300000003020000 - - - 16 - 21000000370000001101000002010000 - - - - 3692 - 000000000F000000000000000020000000000000FFFFFFFFFFFFFFFFF4000000F000000090050000F4000000000000000100000004000000010000000000000000000000FFFFFFFF06000000CB00000057010000CC000000F08B00005A01000079070000FFFF02000B004354616262656450616E650020000000000000F4000000650000009005000006010000F40000004F00000090050000F00000000000000040280046060000000B446973617373656D626C7900000000CB00000001000000FFFFFFFFFFFFFFFF14506572666F726D616E636520416E616C797A6572000000005701000001000000FFFFFFFFFFFFFFFF14506572666F726D616E636520416E616C797A657200000000CC00000001000000FFFFFFFFFFFFFFFF0E4C6F67696320416E616C797A657200000000F08B000001000000FFFFFFFFFFFFFFFF0D436F646520436F766572616765000000005A01000001000000FFFFFFFFFFFFFFFF11496E737472756374696F6E205472616365000000007907000001000000FFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000000000000000000001000000FFFFFFFFCB00000001000000FFFFFFFFCB000000000000000040000000000000FFFFFFFFFFFFFFFF9C0400004F000000A00400006F020000000000000200000004000000010000000000000000000000FFFFFFFF2B000000E2050000CA0900002D8C00002E8C00002F8C0000308C0000318C0000328C0000338C0000348C0000358C0000368C0000378C0000388C0000398C00003A8C00003B8C00003C8C00003D8C00003E8C00003F8C0000408C0000418C000050C3000051C3000052C3000053C3000054C3000055C3000056C3000057C3000058C3000059C300005AC300005BC300005CC300005DC300005EC300005FC3000060C3000061C3000062C3000063C3000001800040000000000000A0040000650000009005000085020000A00400004F000000900500006F02000000000000404100462B0000000753796D626F6C7300000000E205000001000000FFFFFFFFFFFFFFFF0A5472616365204461746100000000CA09000001000000FFFFFFFFFFFFFFFF00000000002D8C000001000000FFFFFFFFFFFFFFFF00000000002E8C000001000000FFFFFFFFFFFFFFFF00000000002F8C000001000000FFFFFFFFFFFFFFFF0000000000308C000001000000FFFFFFFFFFFFFFFF0000000000318C000001000000FFFFFFFFFFFFFFFF0000000000328C000001000000FFFFFFFFFFFFFFFF0000000000338C000001000000FFFFFFFFFFFFFFFF0000000000348C000001000000FFFFFFFFFFFFFFFF0000000000358C000001000000FFFFFFFFFFFFFFFF0000000000368C000001000000FFFFFFFFFFFFFFFF0000000000378C000001000000FFFFFFFFFFFFFFFF0000000000388C000001000000FFFFFFFFFFFFFFFF0000000000398C000001000000FFFFFFFFFFFFFFFF00000000003A8C000001000000FFFFFFFFFFFFFFFF00000000003B8C000001000000FFFFFFFFFFFFFFFF00000000003C8C000001000000FFFFFFFFFFFFFFFF00000000003D8C000001000000FFFFFFFFFFFFFFFF00000000003E8C000001000000FFFFFFFFFFFFFFFF00000000003F8C000001000000FFFFFFFFFFFFFFFF0000000000408C000001000000FFFFFFFFFFFFFFFF0000000000418C000001000000FFFFFFFFFFFFFFFF000000000050C3000001000000FFFFFFFFFFFFFFFF000000000051C3000001000000FFFFFFFFFFFFFFFF000000000052C3000001000000FFFFFFFFFFFFFFFF000000000053C3000001000000FFFFFFFFFFFFFFFF000000000054C3000001000000FFFFFFFFFFFFFFFF000000000055C3000001000000FFFFFFFFFFFFFFFF000000000056C3000001000000FFFFFFFFFFFFFFFF000000000057C3000001000000FFFFFFFFFFFFFFFF000000000058C3000001000000FFFFFFFFFFFFFFFF000000000059C3000001000000FFFFFFFFFFFFFFFF00000000005AC3000001000000FFFFFFFFFFFFFFFF00000000005BC3000001000000FFFFFFFFFFFFFFFF00000000005CC3000001000000FFFFFFFFFFFFFFFF00000000005DC3000001000000FFFFFFFFFFFFFFFF00000000005EC3000001000000FFFFFFFFFFFFFFFF00000000005FC3000001000000FFFFFFFFFFFFFFFF000000000060C3000001000000FFFFFFFFFFFFFFFF000000000061C3000001000000FFFFFFFFFFFFFFFF000000000062C3000001000000FFFFFFFFFFFFFFFF000000000063C3000001000000FFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000000000000000000001000000FFFFFFFFE205000001000000FFFFFFFFE2050000000000000010000001000000FFFFFFFFFFFFFFFF340100004F00000038010000E703000001000000020000100400000001000000A7FEFFFF1C060000FFFFFFFF05000000ED0300006D000000C3000000C40000007394000001800010000001000000000000006500000034010000FD030000000000004F00000034010000E70300000000000040410056050000000750726F6A65637401000000ED03000001000000FFFFFFFFFFFFFFFF05426F6F6B73010000006D00000001000000FFFFFFFFFFFFFFFF0946756E6374696F6E7301000000C300000001000000FFFFFFFFFFFFFFFF0954656D706C6174657301000000C400000001000000FFFFFFFFFFFFFFFF09526567697374657273000000007394000001000000FFFFFFFFFFFFFFFF00000000000000000000000000000000000000000000000001000000FFFFFFFFED03000001000000FFFFFFFFED030000000000000080000000000000FFFFFFFFFFFFFFFF000000005B020000900500005F02000000000000010000000400000001000000000000000000000000000000000000000000000001000000C6000000FFFFFFFF0E0000008F070000930700009407000095070000960700009007000091070000B5010000B8010000B9050000BA050000BB050000BC050000CB090000018000800000000000000000000075020000900500002A030000000000005F020000900500001403000000000000404100460E0000001343616C6C20537461636B202B204C6F63616C73000000008F07000001000000FFFFFFFFFFFFFFFF0755415254202331000000009307000001000000FFFFFFFFFFFFFFFF0755415254202332000000009407000001000000FFFFFFFFFFFFFFFF0755415254202333000000009507000001000000FFFFFFFFFFFFFFFF15446562756720287072696E74662920566965776572000000009607000001000000FFFFFFFFFFFFFFFF0757617463682031000000009007000001000000FFFFFFFFFFFFFFFF0757617463682032000000009107000001000000FFFFFFFFFFFFFFFF10547261636520457863657074696F6E7300000000B501000001000000FFFFFFFFFFFFFFFF0E4576656E7420436F756E7465727300000000B801000001000000FFFFFFFFFFFFFFFF084D656D6F7279203100000000B905000001000000FFFFFFFFFFFFFFFF084D656D6F7279203200000000BA05000001000000FFFFFFFFFFFFFFFF084D656D6F7279203300000000BB05000001000000FFFFFFFFFFFFFFFF084D656D6F7279203400000000BC05000001000000FFFFFFFFFFFFFFFF105472616365204E617669676174696F6E00000000CB09000001000000FFFFFFFFFFFFFFFFFFFFFFFF0000000001000000000000000000000001000000FFFFFFFFC80200005F020000CC0200001403000000000000020000000400000000000000000000000000000000000000000000000000000002000000C6000000FFFFFFFF8F07000001000000FFFFFFFF8F07000001000000C6000000000000000080000000000000FFFFFFFFFFFFFFFF000000001E03000080070000220300000000000001000000040000000100000067FDFFFFF4000000FFFFFFFF04000000C5000000C7000000B40100007794000001800080000000000000000000003803000080070000FD030000000000002203000080070000E70300000000000040820046040000000C4275696C64204F757470757400000000C500000001000000FFFFFFFFFFFFFFFF0D46696E6420496E2046696C657300000000C700000001000000FFFFFFFFFFFFFFFF0A4572726F72204C69737400000000B401000001000000FFFFFFFFFFFFFFFF0742726F77736572000000007794000001000000FFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000000000000000000001000000FFFFFFFFC500000001000000FFFFFFFFC5000000000000000080000000000000FFFFFFFFFFFFFFFF0000000017020000900500001B0200000000000001000000040000000100000000000000000000000000000000000000000000000100000000000000FFFFFFFF0200000038030000D6010000018000800000000000000000000000000000010000003202000000000000EAFFFFFF010000001C02000000000000404100460200000009554C494E4B706C7573000000003803000001000000FFFFFFFFFFFFFFFF0F53797374656D20416E616C797A657200000000D601000001000000FFFFFFFFFFFFFFFFFFFFFFFF0000000001000000000000000000000001000000FFFFFFFFC80200001B020000CC020000BF02000000000000020000000400000000000000000000000000000000000000000000000000000001000000FFFFFFFF3803000001000000FFFFFFFF38030000000000000080000000000000FFFFFFFFFFFFFFFF00000000530300008007000057030000000000000100000004000000010000000000000000000000FFFFFFFF02000000D2010000CF01000001800080000000000000000000006D03000080070000FD030000000000005703000080070000E70300000000000040820046020000000E536F757263652042726F7773657200000000D201000001000000FFFFFFFFFFFFFFFF1346696E6420416C6C205265666572656E63657300000000CF01000001000000FFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000000000000000000001000000FFFFFFFFD201000001000000FFFFFFFFD2010000000000000000000000000000 - - - 59392 - File - - 2438 - 00200000010000002800FFFF01001100434D4643546F6F6C426172427574746F6E00E100000000000000000000000000000000000000000000000100000001000000018001E100000000000001000000000000000000000000000000000100000001000000018003E1000000000000020000000000000000000000000000000001000000010000000180CD7F0000000000000300000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018023E100000000040004000000000000000000000000000000000100000001000000018022E100000000040005000000000000000000000000000000000100000001000000018025E10000000000000600000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001802BE10000000004000700000000000000000000000000000000010000000100000001802CE10000000004000800000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001807A8A0000000004000900000000000000000000000000000000010000000100000001807B8A0000000004000A00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180D3B00000000000000B000000000000000000000000000000000100000001000000018015B10000000004000C0000000000000000000000000000000001000000010000000180F4B00000000004000D000000000000000000000000000000000100000001000000018036B10000000004000E00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180FF88000000000400460000000000000000000000000000000001000000010000000180FE880000000004004500000000000000000000000000000000010000000100000001800B810000000004001300000000000000000000000000000000010000000100000001800C810000000004001400000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180F0880000020000000F000000000000000000000000000000000100000001000000FFFF0100120043555646696E64436F6D626F427574746F6EE803000000000000000000000000000000000000000000000001000000010000009600000002002050000000000944657374726F796564960000000000000014000944657374726F79656406507265656D7006746872656164136F735274785468726561645265616479507574106F73527478546872656164426C6F636B15457672527478546872656164556E626C6F636B656413457672527478546872656164426C6F636B6564116F735274785468726561645377697463681545767252747854687265616444657374726F796564146F7352747854687265616457616974456E746572146F7352747854687265616444656C61795469636B0D7468726561642D3E7374617465126F73527478546872656164426C6F636B6564126F7352747854687265616457616974696E67204576745274784B65726E656C496E666F5265747269657665645F44657461696C194576745274784B65726E656C496E666F52657472696576656408546872656164437206236966646566136F735F69646C655F7468726561645F617474720E6F73546872656164417474725F740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018024E10000000000001100000000000000000000000000000000010000000100000001800A810000000000001200000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018022800000020000001500000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180C488000000000000160000000000000000000000000000000001000000010000000180C988000000000400180000000000000000000000000000000001000000010000000180C788000000000000190000000000000000000000000000000001000000010000000180C8880000000000001700000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000FFFF01001500434D4643546F6F6C4261724D656E75427574746F6E4C010000020001001A0000000F2650726F6A6563742057696E646F77000000000000000000000000010000000100000000000000000000000100000008002880DD880000000000001A0000000750726F6A656374000000000000000000000000010000000100000000000000000000000100000000002880DC8B0000000000003A00000005426F6F6B73000000000000000000000000010000000100000000000000000000000100000000002880E18B0000000000003B0000000946756E6374696F6E73000000000000000000000000010000000100000000000000000000000100000000002880E28B000000000000400000000954656D706C6174657300000000000000000000000001000000010000000000000000000000010000000000288018890000000000003D0000000E536F757263652042726F777365720000000000000000000000000100000001000000000000000000000001000000000028800000000000000400FFFFFFFF00000000000000000001000000000000000100000000000000000000000100000000002880D988000000000000390000000C4275696C64204F7574707574000000000000000000000000010000000100000000000000000000000100000000002880E38B000000000000410000000B46696E64204F75747075740000000000000000000000000100000001000000000000000000000001000000000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180FB7F0000000000001B000000000000000000000000000000000100000001000000000000000446696C65AC030000 - - - 1423 - 2800FFFF01001100434D4643546F6F6C426172427574746F6E00E1000000000000FFFFFFFF000100000000000000010000000000000001000000018001E1000000000000FFFFFFFF000100000000000000010000000000000001000000018003E1000000000000FFFFFFFF0001000000000000000100000000000000010000000180CD7F000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF000000000000000000010000000000000001000000018023E1000000000000FFFFFFFF000100000000000000010000000000000001000000018022E1000000000000FFFFFFFF000100000000000000010000000000000001000000018025E1000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001802BE1000000000000FFFFFFFF00010000000000000001000000000000000100000001802CE1000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001807A8A000000000000FFFFFFFF00010000000000000001000000000000000100000001807B8A000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF0000000000000000000100000000000000010000000180D3B0000000000000FFFFFFFF000100000000000000010000000000000001000000018015B1000000000000FFFFFFFF0001000000000000000100000000000000010000000180F4B0000000000000FFFFFFFF000100000000000000010000000000000001000000018036B1000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF0000000000000000000100000000000000010000000180FF88000000000000FFFFFFFF0001000000000000000100000000000000010000000180FE88000000000000FFFFFFFF00010000000000000001000000000000000100000001800B81000000000000FFFFFFFF00010000000000000001000000000000000100000001800C81000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF0000000000000000000100000000000000010000000180F088000000000000FFFFFFFF0001000000000000000100000000000000010000000180EE7F000000000000FFFFFFFF000100000000000000010000000000000001000000018024E1000000000000FFFFFFFF00010000000000000001000000000000000100000001800A81000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001802280000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF0000000000000000000100000000000000010000000180C488000000000000FFFFFFFF0001000000000000000100000000000000010000000180C988000000000000FFFFFFFF0001000000000000000100000000000000010000000180C788000000000000FFFFFFFF0001000000000000000100000000000000010000000180C888000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF0000000000000000000100000000000000010000000180DD88000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF0000000000000000000100000000000000010000000180FB7F000000000000FFFFFFFF000100000000000000010000000000000001000000 - - - 1423 - 2800FFFF01001100434D4643546F6F6C426172427574746F6E00E100000000000000000000000000000000000000000000000100000001000000018001E100000000000001000000000000000000000000000000000100000001000000018003E1000000000000020000000000000000000000000000000001000000010000000180CD7F0000000000000300000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018023E100000000000004000000000000000000000000000000000100000001000000018022E100000000000005000000000000000000000000000000000100000001000000018025E10000000000000600000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001802BE10000000000000700000000000000000000000000000000010000000100000001802CE10000000000000800000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001807A8A0000000000000900000000000000000000000000000000010000000100000001807B8A0000000000000A00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180D3B00000000000000B000000000000000000000000000000000100000001000000018015B10000000000000C0000000000000000000000000000000001000000010000000180F4B00000000000000D000000000000000000000000000000000100000001000000018036B10000000000000E00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180FF880000000000000F0000000000000000000000000000000001000000010000000180FE880000000000001000000000000000000000000000000000010000000100000001800B810000000000001100000000000000000000000000000000010000000100000001800C810000000000001200000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180F088000000000000130000000000000000000000000000000001000000010000000180EE7F00000000000014000000000000000000000000000000000100000001000000018024E10000000000001500000000000000000000000000000000010000000100000001800A810000000000001600000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018022800000000000001700000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180C488000000000000180000000000000000000000000000000001000000010000000180C988000000000000190000000000000000000000000000000001000000010000000180C7880000000000001A0000000000000000000000000000000001000000010000000180C8880000000000001B00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180DD880000000000001C00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180FB7F0000000000001D000000000000000000000000000000000100000001000000 - - - - 59399 - Build - - 1000 - 00200000010000001000FFFF01001100434D4643546F6F6C426172427574746F6ECF7F0000000004001C0000000000000000000000000000000001000000010000000180D07F0000000000001D000000000000000000000000000000000100000001000000018030800000000000001E000000000000000000000000000000000100000001000000FFFF01001500434D4643546F6F6C4261724D656E75427574746F6EC7040000000000006A0000000C4261746368204275696C2664000000000000000000000000010000000100000000000000000000000100000004000580C7040000000000006A0000000C4261746368204275696C266400000000000000000000000001000000010000000000000000000000010000000000058046070000000000006B0000000D42617463682052656275696C640000000000000000000000000100000001000000000000000000000001000000000005804707000000000000FFFFFFFF0B426174636820436C65616E0100000000000000000000000100000001000000000000000000000001000000000005809E8A0000000000001F0000000F4261746326682053657475702E2E2E000000000000000000000000010000000100000000000000000000000100000000000180D17F0000000004002000000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001804C8A0000000004002100000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000FFFF01001900434D4643546F6F6C426172436F6D626F426F78427574746F6EBA0000000000000000000000000000000000000000000000000100000001000000960000000300205000000000144656502053696D756C6174696F6E204D6F64656C96000000000000000100144656502053696D756C6174696F6E204D6F64656C000000000180EB880000000000002200000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180C07F000000000000230000000000000000000000000000000001000000010000000180B08A000000000000240000000000000000000000000000000001000000010000000180A8010000000000004E00000000000000000000000000000000010000000100000001807202000000000000530000000000000000000000000000000001000000010000000180BE010000000000005000000000000000000000000000000000010000000100000000000000054275696C642F010000 - - - 583 - 1000FFFF01001100434D4643546F6F6C426172427574746F6ECF7F000000000000FFFFFFFF0001000000000000000100000000000000010000000180D07F000000000000FFFFFFFF00010000000000000001000000000000000100000001803080000000000000FFFFFFFF00010000000000000001000000000000000100000001809E8A000000000000FFFFFFFF0001000000000000000100000000000000010000000180D17F000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001804C8A000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001806680000000000000FFFFFFFF0001000000000000000100000000000000010000000180EB88000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF0000000000000000000100000000000000010000000180C07F000000000000FFFFFFFF0001000000000000000100000000000000010000000180B08A000000000000FFFFFFFF0001000000000000000100000000000000010000000180A801000000000000FFFFFFFF00010000000000000001000000000000000100000001807202000000000000FFFFFFFF0001000000000000000100000000000000010000000180BE01000000000000FFFFFFFF000100000000000000010000000000000001000000 - - - 583 - 1000FFFF01001100434D4643546F6F6C426172427574746F6ECF7F000000000000000000000000000000000000000000000001000000010000000180D07F00000000000001000000000000000000000000000000000100000001000000018030800000000000000200000000000000000000000000000000010000000100000001809E8A000000000000030000000000000000000000000000000001000000010000000180D17F0000000000000400000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001804C8A0000000000000500000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001806680000000000000060000000000000000000000000000000001000000010000000180EB880000000000000700000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180C07F000000000000080000000000000000000000000000000001000000010000000180B08A000000000000090000000000000000000000000000000001000000010000000180A8010000000000000A000000000000000000000000000000000100000001000000018072020000000000000B0000000000000000000000000000000001000000010000000180BE010000000000000C000000000000000000000000000000000100000001000000 - - - - 59400 - Debug - - 2373 - 00200000000000001900FFFF01001100434D4643546F6F6C426172427574746F6ECC880000000000002500000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018017800000000000002600000000000000000000000000000000010000000100000001801D800000000000002700000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001801A800000000000002800000000000000000000000000000000010000000100000001801B80000000000000290000000000000000000000000000000001000000010000000180E57F0000000000002A00000000000000000000000000000000010000000100000001801C800000000000002B00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018000890000000000002C00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180E48B0000000000002D0000000000000000000000000000000001000000010000000180F07F0000000000002E0000000000000000000000000000000001000000010000000180E8880000000000003700000000000000000000000000000000010000000100000001803B010000000000002F0000000000000000000000000000000001000000010000000180BB8A00000000000030000000000000000000000000000000000100000001000000FFFF01001500434D4643546F6F6C4261724D656E75427574746F6E0E01000000000000310000000D57617463682057696E646F7773000000000000000000000000010000000100000000000000000000000100000003001380D88B00000000000031000000085761746368202631000000000000000000000000010000000100000000000000000000000100000000001380D98B00000000000031000000085761746368202632000000000000000000000000010000000100000000000000000000000100000000001380CE01000000000000FFFFFFFF0C576174636820416E63686F720000000000000000010000000000000001000000000000000000000001000000000013800F01000000000000320000000E4D656D6F72792057696E646F7773000000000000000000000000010000000100000000000000000000000100000004001380D28B00000000000032000000094D656D6F7279202631000000000000000000000000010000000100000000000000000000000100000000001380D38B00000000000032000000094D656D6F7279202632000000000000000000000000010000000100000000000000000000000100000000001380D48B00000000000032000000094D656D6F7279202633000000000000000000000000010000000100000000000000000000000100000000001380D58B00000000000032000000094D656D6F72792026340000000000000000000000000100000001000000000000000000000001000000000013801001000000000000330000000E53657269616C2057696E646F77730000000000000000000000000100000001000000000000000000000001000000040013809307000000000000330000000855415254202326310000000000000000000000000100000001000000000000000000000001000000000013809407000000000000330000000855415254202326320000000000000000000000000100000001000000000000000000000001000000000013809507000000000000330000000855415254202326330000000000000000000000000100000001000000000000000000000001000000000013809607000000000000330000001626446562756720287072696E746629205669657765720000000000000000000000000100000001000000000000000000000001000000000013803C010000000000003400000010416E616C797369732057696E646F7773000000000000000000000000010000000100000000000000000000000100000004001380658A000000000000340000000F264C6F67696320416E616C797A6572000000000000000000000000010000000100000000000000000000000100000000001380DC7F0000000000003E0000001526506572666F726D616E636520416E616C797A6572000000000000000000000000010000000100000000000000000000000100000000001380E788000000000000380000000E26436F646520436F766572616765000000000000000000000000010000000100000000000000000000000100000000001380CD01000000000000FFFFFFFF0F416E616C7973697320416E63686F7200000000000000000100000000000000010000000000000000000000010000000000138053010000000000003F0000000D54726163652057696E646F77730000000000000000000000000100000001000000000000000000000001000000010013805401000000000000FFFFFFFF115472616365204D656E7520416E63686F720000000000000000010000000000000001000000000000000000000001000000000013802901000000000000350000001553797374656D205669657765722057696E646F77730000000000000000000000000100000001000000000000000000000001000000010013804B01000000000000FFFFFFFF1453797374656D2056696577657220416E63686F720000000000000000010000000000000001000000000000000000000001000000000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000013800189000000000000360000000F26546F6F6C626F782057696E646F7700000000000000000000000001000000010000000000000000000000010000000300138044C5000000000000FFFFFFFF0E5570646174652057696E646F77730000000000000000010000000000000001000000000000000000000001000000000013800000000000000400FFFFFFFF000000000000000000010000000000000001000000000000000000000001000000000013805B01000000000000FFFFFFFF12546F6F6C626F78204D656E75416E63686F72000000000000000001000000000000000100000000000000000000000100000000000000000005446562756764020000 - - - 898 - 1900FFFF01001100434D4643546F6F6C426172427574746F6ECC88000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001801780000000000000FFFFFFFF00010000000000000001000000000000000100000001801D80000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001801A80000000000000FFFFFFFF00010000000000000001000000000000000100000001801B80000000000000FFFFFFFF0001000000000000000100000000000000010000000180E57F000000000000FFFFFFFF00010000000000000001000000000000000100000001801C80000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001800089000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF0000000000000000000100000000000000010000000180E48B000000000000FFFFFFFF0001000000000000000100000000000000010000000180F07F000000000000FFFFFFFF0001000000000000000100000000000000010000000180E888000000000000FFFFFFFF00010000000000000001000000000000000100000001803B01000000000000FFFFFFFF0001000000000000000100000000000000010000000180BB8A000000000000FFFFFFFF0001000000000000000100000000000000010000000180D88B000000000000FFFFFFFF0001000000000000000100000000000000010000000180D28B000000000000FFFFFFFF00010000000000000001000000000000000100000001809307000000000000FFFFFFFF0001000000000000000100000000000000010000000180658A000000000000FFFFFFFF0001000000000000000100000000000000010000000180C18A000000000000FFFFFFFF0001000000000000000100000000000000010000000180EE8B000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001800189000000000000FFFFFFFF000100000000000000010000000000000001000000 - - - 898 - 1900FFFF01001100434D4643546F6F6C426172427574746F6ECC880000000000000000000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018017800000000000000100000000000000000000000000000000010000000100000001801D800000000000000200000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001801A800000000000000300000000000000000000000000000000010000000100000001801B80000000000000040000000000000000000000000000000001000000010000000180E57F0000000000000500000000000000000000000000000000010000000100000001801C800000000000000600000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018000890000000000000700000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180E48B000000000000080000000000000000000000000000000001000000010000000180F07F000000000000090000000000000000000000000000000001000000010000000180E8880000000000000A00000000000000000000000000000000010000000100000001803B010000000000000B0000000000000000000000000000000001000000010000000180BB8A0000000000000C0000000000000000000000000000000001000000010000000180D88B0000000000000D0000000000000000000000000000000001000000010000000180D28B0000000000000E000000000000000000000000000000000100000001000000018093070000000000000F0000000000000000000000000000000001000000010000000180658A000000000000100000000000000000000000000000000001000000010000000180C18A000000000000110000000000000000000000000000000001000000010000000180EE8B0000000000001200000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180018900000000000013000000000000000000000000000000000100000001000000 - - - - 0 - 1920 - 1080 - - - - - - 1 - 0 - - 100 - 0 - - <1>.\Abstract.txt - 0 - 1 - 1 - 0 - - 0 - - - - -
diff --git a/ports/cortex_m33/ac6/example_build/ThreadX_Library.uvoptx b/ports/cortex_m33/ac6/example_build/ThreadX_Library.uvoptx deleted file mode 100644 index a408cfa30..000000000 --- a/ports/cortex_m33/ac6/example_build/ThreadX_Library.uvoptx +++ /dev/null @@ -1,2576 +0,0 @@ - - - - 1.0 - -
### uVision Project, (C) Keil Software
- - - *.c - *.s*; *.src; *.a* - *.obj; *.o - *.lib - *.txt; *.h; *.inc - *.plm - *.cpp - 0 - - - - 0 - 0 - - - - ThreadX_Library_Project - 0x4 - ARM-ADS - - 12000000 - - 1 - 1 - 0 - 1 - 0 - - - 1 - 65535 - 0 - 0 - 0 - - - 79 - 66 - 8 - .\ - - - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - - - 0 - 0 - 1 - - 7 - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 1 - 1 - 0 - 0 - 1 - 0 - 0 - 13 - - - - - - - - - - - BIN\UL2V8M.DLL - - - - 0 - UL2V8M - UL2V8M(-S0 -C0 -P0 -FD20000000 -FC1000) - - - - - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - - - - - - - - - - - - - Source Group - 1 - 0 - 0 - 0 - - 1 - 1 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_allocate.c - tx_block_allocate.c - 0 - 0 - - - 1 - 2 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_cleanup.c - tx_block_pool_cleanup.c - 0 - 0 - - - 1 - 3 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_create.c - tx_block_pool_create.c - 0 - 0 - - - 1 - 4 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_delete.c - tx_block_pool_delete.c - 0 - 0 - - - 1 - 5 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_info_get.c - tx_block_pool_info_get.c - 0 - 0 - - - 1 - 6 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_initialize.c - tx_block_pool_initialize.c - 0 - 0 - - - 1 - 7 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_performance_info_get.c - tx_block_pool_performance_info_get.c - 0 - 0 - - - 1 - 8 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_performance_system_info_get.c - tx_block_pool_performance_system_info_get.c - 0 - 0 - - - 1 - 9 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_prioritize.c - tx_block_pool_prioritize.c - 0 - 0 - - - 1 - 10 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_release.c - tx_block_release.c - 0 - 0 - - - 1 - 11 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_allocate.c - tx_byte_allocate.c - 0 - 0 - - - 1 - 12 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_cleanup.c - tx_byte_pool_cleanup.c - 0 - 0 - - - 1 - 13 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_create.c - tx_byte_pool_create.c - 0 - 0 - - - 1 - 14 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_delete.c - tx_byte_pool_delete.c - 0 - 0 - - - 1 - 15 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_info_get.c - tx_byte_pool_info_get.c - 0 - 0 - - - 1 - 16 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_initialize.c - tx_byte_pool_initialize.c - 0 - 0 - - - 1 - 17 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_performance_info_get.c - tx_byte_pool_performance_info_get.c - 0 - 0 - - - 1 - 18 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_performance_system_info_get.c - tx_byte_pool_performance_system_info_get.c - 0 - 0 - - - 1 - 19 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_prioritize.c - tx_byte_pool_prioritize.c - 0 - 0 - - - 1 - 20 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_search.c - tx_byte_pool_search.c - 0 - 0 - - - 1 - 21 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_release.c - tx_byte_release.c - 0 - 0 - - - 1 - 22 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_cleanup.c - tx_event_flags_cleanup.c - 0 - 0 - - - 1 - 23 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_create.c - tx_event_flags_create.c - 0 - 0 - - - 1 - 24 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_delete.c - tx_event_flags_delete.c - 0 - 0 - - - 1 - 25 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_get.c - tx_event_flags_get.c - 0 - 0 - - - 1 - 26 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_info_get.c - tx_event_flags_info_get.c - 0 - 0 - - - 1 - 27 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_initialize.c - tx_event_flags_initialize.c - 0 - 0 - - - 1 - 28 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_performance_info_get.c - tx_event_flags_performance_info_get.c - 0 - 0 - - - 1 - 29 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_performance_system_info_get.c - tx_event_flags_performance_system_info_get.c - 0 - 0 - - - 1 - 30 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_set.c - tx_event_flags_set.c - 0 - 0 - - - 1 - 31 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_set_notify.c - tx_event_flags_set_notify.c - 0 - 0 - - - 1 - 32 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_initialize_high_level.c - tx_initialize_high_level.c - 0 - 0 - - - 1 - 33 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_initialize_kernel_enter.c - tx_initialize_kernel_enter.c - 0 - 0 - - - 1 - 34 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_initialize_kernel_setup.c - tx_initialize_kernel_setup.c - 0 - 0 - - - 1 - 35 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_cleanup.c - tx_mutex_cleanup.c - 0 - 0 - - - 1 - 36 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_create.c - tx_mutex_create.c - 0 - 0 - - - 1 - 37 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_delete.c - tx_mutex_delete.c - 0 - 0 - - - 1 - 38 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_get.c - tx_mutex_get.c - 0 - 0 - - - 1 - 39 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_info_get.c - tx_mutex_info_get.c - 0 - 0 - - - 1 - 40 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_initialize.c - tx_mutex_initialize.c - 0 - 0 - - - 1 - 41 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_performance_info_get.c - tx_mutex_performance_info_get.c - 0 - 0 - - - 1 - 42 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_performance_system_info_get.c - tx_mutex_performance_system_info_get.c - 0 - 0 - - - 1 - 43 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_prioritize.c - tx_mutex_prioritize.c - 0 - 0 - - - 1 - 44 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_priority_change.c - tx_mutex_priority_change.c - 0 - 0 - - - 1 - 45 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_put.c - tx_mutex_put.c - 0 - 0 - - - 1 - 46 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_cleanup.c - tx_queue_cleanup.c - 0 - 0 - - - 1 - 47 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_create.c - tx_queue_create.c - 0 - 0 - - - 1 - 48 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_delete.c - tx_queue_delete.c - 0 - 0 - - - 1 - 49 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_flush.c - tx_queue_flush.c - 0 - 0 - - - 1 - 50 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_front_send.c - tx_queue_front_send.c - 0 - 0 - - - 1 - 51 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_info_get.c - tx_queue_info_get.c - 0 - 0 - - - 1 - 52 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_initialize.c - tx_queue_initialize.c - 0 - 0 - - - 1 - 53 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_performance_info_get.c - tx_queue_performance_info_get.c - 0 - 0 - - - 1 - 54 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_performance_system_info_get.c - tx_queue_performance_system_info_get.c - 0 - 0 - - - 1 - 55 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_prioritize.c - tx_queue_prioritize.c - 0 - 0 - - - 1 - 56 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_receive.c - tx_queue_receive.c - 0 - 0 - - - 1 - 57 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_send.c - tx_queue_send.c - 0 - 0 - - - 1 - 58 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_send_notify.c - tx_queue_send_notify.c - 0 - 0 - - - 1 - 59 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_ceiling_put.c - tx_semaphore_ceiling_put.c - 0 - 0 - - - 1 - 60 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_cleanup.c - tx_semaphore_cleanup.c - 0 - 0 - - - 1 - 61 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_create.c - tx_semaphore_create.c - 0 - 0 - - - 1 - 62 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_delete.c - tx_semaphore_delete.c - 0 - 0 - - - 1 - 63 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_get.c - tx_semaphore_get.c - 0 - 0 - - - 1 - 64 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_info_get.c - tx_semaphore_info_get.c - 0 - 0 - - - 1 - 65 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_initialize.c - tx_semaphore_initialize.c - 0 - 0 - - - 1 - 66 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_performance_info_get.c - tx_semaphore_performance_info_get.c - 0 - 0 - - - 1 - 67 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_performance_system_info_get.c - tx_semaphore_performance_system_info_get.c - 0 - 0 - - - 1 - 68 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_prioritize.c - tx_semaphore_prioritize.c - 0 - 0 - - - 1 - 69 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_put.c - tx_semaphore_put.c - 0 - 0 - - - 1 - 70 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_put_notify.c - tx_semaphore_put_notify.c - 0 - 0 - - - 1 - 71 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_create.c - tx_thread_create.c - 0 - 0 - - - 1 - 72 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_delete.c - tx_thread_delete.c - 0 - 0 - - - 1 - 73 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_entry_exit_notify.c - tx_thread_entry_exit_notify.c - 0 - 0 - - - 1 - 74 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_identify.c - tx_thread_identify.c - 0 - 0 - - - 1 - 75 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_info_get.c - tx_thread_info_get.c - 0 - 0 - - - 1 - 76 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_initialize.c - tx_thread_initialize.c - 0 - 0 - - - 1 - 77 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_performance_info_get.c - tx_thread_performance_info_get.c - 0 - 0 - - - 1 - 78 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_performance_system_info_get.c - tx_thread_performance_system_info_get.c - 0 - 0 - - - 1 - 79 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_preemption_change.c - tx_thread_preemption_change.c - 0 - 0 - - - 1 - 80 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_priority_change.c - tx_thread_priority_change.c - 0 - 0 - - - 1 - 81 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_relinquish.c - tx_thread_relinquish.c - 0 - 0 - - - 1 - 82 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_reset.c - tx_thread_reset.c - 0 - 0 - - - 1 - 83 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_resume.c - tx_thread_resume.c - 0 - 0 - - - 1 - 84 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_shell_entry.c - tx_thread_shell_entry.c - 0 - 0 - - - 1 - 85 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_sleep.c - tx_thread_sleep.c - 0 - 0 - - - 1 - 86 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_stack_analyze.c - tx_thread_stack_analyze.c - 0 - 0 - - - 1 - 87 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_suspend.c - tx_thread_suspend.c - 0 - 0 - - - 1 - 88 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_system_preempt_check.c - tx_thread_system_preempt_check.c - 0 - 0 - - - 1 - 89 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_system_resume.c - tx_thread_system_resume.c - 0 - 0 - - - 1 - 90 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_system_suspend.c - tx_thread_system_suspend.c - 0 - 0 - - - 1 - 91 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_terminate.c - tx_thread_terminate.c - 0 - 0 - - - 1 - 92 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_time_slice.c - tx_thread_time_slice.c - 0 - 0 - - - 1 - 93 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_time_slice_change.c - tx_thread_time_slice_change.c - 0 - 0 - - - 1 - 94 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_timeout.c - tx_thread_timeout.c - 0 - 0 - - - 1 - 95 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_wait_abort.c - tx_thread_wait_abort.c - 0 - 0 - - - 1 - 96 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_time_get.c - tx_time_get.c - 0 - 0 - - - 1 - 97 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_time_set.c - tx_time_set.c - 0 - 0 - - - 1 - 98 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_activate.c - tx_timer_activate.c - 0 - 0 - - - 1 - 99 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_change.c - tx_timer_change.c - 0 - 0 - - - 1 - 100 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_create.c - tx_timer_create.c - 0 - 0 - - - 1 - 101 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_deactivate.c - tx_timer_deactivate.c - 0 - 0 - - - 1 - 102 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_delete.c - tx_timer_delete.c - 0 - 0 - - - 1 - 103 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_expiration_process.c - tx_timer_expiration_process.c - 0 - 0 - - - 1 - 104 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_info_get.c - tx_timer_info_get.c - 0 - 0 - - - 1 - 105 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_initialize.c - tx_timer_initialize.c - 0 - 0 - - - 1 - 106 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_performance_info_get.c - tx_timer_performance_info_get.c - 0 - 0 - - - 1 - 107 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_performance_system_info_get.c - tx_timer_performance_system_info_get.c - 0 - 0 - - - 1 - 108 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_system_activate.c - tx_timer_system_activate.c - 0 - 0 - - - 1 - 109 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_system_deactivate.c - tx_timer_system_deactivate.c - 0 - 0 - - - 1 - 110 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_thread_entry.c - tx_timer_thread_entry.c - 0 - 0 - - - 1 - 111 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_disable.c - tx_trace_disable.c - 0 - 0 - - - 1 - 112 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_enable.c - tx_trace_enable.c - 0 - 0 - - - 1 - 113 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_initialize.c - tx_trace_initialize.c - 0 - 0 - - - 1 - 114 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_interrupt_control.c - tx_trace_interrupt_control.c - 0 - 0 - - - 1 - 115 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_isr_enter_insert.c - tx_trace_isr_enter_insert.c - 0 - 0 - - - 1 - 116 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_isr_exit_insert.c - tx_trace_isr_exit_insert.c - 0 - 0 - - - 1 - 117 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_object_register.c - tx_trace_object_register.c - 0 - 0 - - - 1 - 118 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_object_unregister.c - tx_trace_object_unregister.c - 0 - 0 - - - 1 - 119 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_user_event_insert.c - tx_trace_user_event_insert.c - 0 - 0 - - - 1 - 120 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_allocate.c - txe_block_allocate.c - 0 - 0 - - - 1 - 121 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_pool_create.c - txe_block_pool_create.c - 0 - 0 - - - 1 - 122 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_pool_delete.c - txe_block_pool_delete.c - 0 - 0 - - - 1 - 123 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_pool_info_get.c - txe_block_pool_info_get.c - 0 - 0 - - - 1 - 124 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_pool_prioritize.c - txe_block_pool_prioritize.c - 0 - 0 - - - 1 - 125 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_release.c - txe_block_release.c - 0 - 0 - - - 1 - 126 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_allocate.c - txe_byte_allocate.c - 0 - 0 - - - 1 - 127 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_pool_create.c - txe_byte_pool_create.c - 0 - 0 - - - 1 - 128 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_pool_delete.c - txe_byte_pool_delete.c - 0 - 0 - - - 1 - 129 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_pool_info_get.c - txe_byte_pool_info_get.c - 0 - 0 - - - 1 - 130 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_pool_prioritize.c - txe_byte_pool_prioritize.c - 0 - 0 - - - 1 - 131 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_release.c - txe_byte_release.c - 0 - 0 - - - 1 - 132 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_create.c - txe_event_flags_create.c - 0 - 0 - - - 1 - 133 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_delete.c - txe_event_flags_delete.c - 0 - 0 - - - 1 - 134 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_get.c - txe_event_flags_get.c - 0 - 0 - - - 1 - 135 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_info_get.c - txe_event_flags_info_get.c - 0 - 0 - - - 1 - 136 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_set.c - txe_event_flags_set.c - 0 - 0 - - - 1 - 137 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_set_notify.c - txe_event_flags_set_notify.c - 0 - 0 - - - 1 - 138 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_create.c - txe_mutex_create.c - 0 - 0 - - - 1 - 139 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_delete.c - txe_mutex_delete.c - 0 - 0 - - - 1 - 140 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_get.c - txe_mutex_get.c - 0 - 0 - - - 1 - 141 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_info_get.c - txe_mutex_info_get.c - 0 - 0 - - - 1 - 142 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_prioritize.c - txe_mutex_prioritize.c - 0 - 0 - - - 1 - 143 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_put.c - txe_mutex_put.c - 0 - 0 - - - 1 - 144 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_create.c - txe_queue_create.c - 0 - 0 - - - 1 - 145 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_delete.c - txe_queue_delete.c - 0 - 0 - - - 1 - 146 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_flush.c - txe_queue_flush.c - 0 - 0 - - - 1 - 147 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_front_send.c - txe_queue_front_send.c - 0 - 0 - - - 1 - 148 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_info_get.c - txe_queue_info_get.c - 0 - 0 - - - 1 - 149 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_prioritize.c - txe_queue_prioritize.c - 0 - 0 - - - 1 - 150 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_receive.c - txe_queue_receive.c - 0 - 0 - - - 1 - 151 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_send.c - txe_queue_send.c - 0 - 0 - - - 1 - 152 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_send_notify.c - txe_queue_send_notify.c - 0 - 0 - - - 1 - 153 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_ceiling_put.c - txe_semaphore_ceiling_put.c - 0 - 0 - - - 1 - 154 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_create.c - txe_semaphore_create.c - 0 - 0 - - - 1 - 155 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_delete.c - txe_semaphore_delete.c - 0 - 0 - - - 1 - 156 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_get.c - txe_semaphore_get.c - 0 - 0 - - - 1 - 157 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_info_get.c - txe_semaphore_info_get.c - 0 - 0 - - - 1 - 158 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_prioritize.c - txe_semaphore_prioritize.c - 0 - 0 - - - 1 - 159 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_put.c - txe_semaphore_put.c - 0 - 0 - - - 1 - 160 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_put_notify.c - txe_semaphore_put_notify.c - 0 - 0 - - - 1 - 161 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_create.c - txe_thread_create.c - 0 - 0 - - - 1 - 162 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_delete.c - txe_thread_delete.c - 0 - 0 - - - 1 - 163 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_entry_exit_notify.c - txe_thread_entry_exit_notify.c - 0 - 0 - - - 1 - 164 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_info_get.c - txe_thread_info_get.c - 0 - 0 - - - 1 - 165 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_preemption_change.c - txe_thread_preemption_change.c - 0 - 0 - - - 1 - 166 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_priority_change.c - txe_thread_priority_change.c - 0 - 0 - - - 1 - 167 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_relinquish.c - txe_thread_relinquish.c - 0 - 0 - - - 1 - 168 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_reset.c - txe_thread_reset.c - 0 - 0 - - - 1 - 169 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_resume.c - txe_thread_resume.c - 0 - 0 - - - 1 - 170 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_suspend.c - txe_thread_suspend.c - 0 - 0 - - - 1 - 171 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_terminate.c - txe_thread_terminate.c - 0 - 0 - - - 1 - 172 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_time_slice_change.c - txe_thread_time_slice_change.c - 0 - 0 - - - 1 - 173 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_wait_abort.c - txe_thread_wait_abort.c - 0 - 0 - - - 1 - 174 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_activate.c - txe_timer_activate.c - 0 - 0 - - - 1 - 175 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_change.c - txe_timer_change.c - 0 - 0 - - - 1 - 176 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_create.c - txe_timer_create.c - 0 - 0 - - - 1 - 177 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_deactivate.c - txe_timer_deactivate.c - 0 - 0 - - - 1 - 178 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_delete.c - txe_timer_delete.c - 0 - 0 - - - 1 - 179 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_info_get.c - txe_timer_info_get.c - 0 - 0 - - - 1 - 180 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_buffer_full_notify.c - tx_trace_buffer_full_notify.c - 0 - 0 - - - 1 - 181 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_event_filter.c - tx_trace_event_filter.c - 0 - 0 - - - 1 - 182 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_event_unfilter.c - tx_trace_event_unfilter.c - 0 - 0 - - - 1 - 183 - 1 - 0 - 0 - 0 - ..\src\txe_thread_secure_stack_allocate.c - txe_thread_secure_stack_allocate.c - 0 - 0 - - - 1 - 184 - 1 - 0 - 0 - 0 - ..\src\txe_thread_secure_stack_free.c - txe_thread_secure_stack_free.c - 0 - 0 - - - 1 - 185 - 2 - 0 - 0 - 0 - ..\src\tx_thread_context_restore.S - tx_thread_context_restore.S - 0 - 0 - - - 1 - 186 - 2 - 0 - 0 - 0 - ..\src\tx_thread_context_save.S - tx_thread_context_save.S - 0 - 0 - - - 1 - 187 - 2 - 0 - 0 - 0 - ..\src\tx_thread_interrupt_control.S - tx_thread_interrupt_control.S - 0 - 0 - - - 1 - 188 - 2 - 0 - 0 - 0 - ..\src\tx_thread_interrupt_disable.S - tx_thread_interrupt_disable.S - 0 - 0 - - - 1 - 189 - 2 - 0 - 0 - 0 - ..\src\tx_thread_interrupt_restore.S - tx_thread_interrupt_restore.S - 0 - 0 - - - 1 - 190 - 2 - 0 - 0 - 0 - ..\src\tx_thread_schedule.S - tx_thread_schedule.S - 0 - 0 - - - 1 - 191 - 2 - 0 - 0 - 0 - ..\src\tx_thread_secure_stack_allocate.S - tx_thread_secure_stack_allocate.S - 0 - 0 - - - 1 - 192 - 2 - 0 - 0 - 0 - ..\src\tx_thread_secure_stack_free.S - tx_thread_secure_stack_free.S - 0 - 0 - - - 1 - 193 - 2 - 0 - 0 - 0 - ..\src\tx_thread_stack_build.S - tx_thread_stack_build.S - 0 - 0 - - - 1 - 194 - 2 - 0 - 0 - 0 - ..\src\tx_thread_system_return.S - tx_thread_system_return.S - 0 - 0 - - - 1 - 195 - 2 - 0 - 0 - 0 - ..\src\tx_timer_interrupt.S - tx_timer_interrupt.S - 0 - 0 - - - 1 - 196 - 2 - 0 - 0 - 0 - .\tx_initialize_low_level.S - tx_initialize_low_level.S - 0 - 0 - - - 1 - 197 - 2 - 0 - 0 - 0 - ..\src\tx_thread_secure_stack_initialize.S - tx_thread_secure_stack_initialize.S - 0 - 0 - - - 1 - 198 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_stack_error_handler.c - tx_thread_stack_error_handler.c - 0 - 0 - - - 1 - 199 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_stack_error_notify.c - tx_thread_stack_error_notify.c - 0 - 0 - - - - - ::CMSIS - 0 - 0 - 0 - 1 - - -
diff --git a/ports/cortex_m33/ac6/example_build/demo_secure_zone/demo_secure_zone.uvoptx b/ports/cortex_m33/ac6/example_build/demo_secure_zone/demo_secure_zone.uvoptx deleted file mode 100644 index ec69bc696..000000000 --- a/ports/cortex_m33/ac6/example_build/demo_secure_zone/demo_secure_zone.uvoptx +++ /dev/null @@ -1,328 +0,0 @@ - - - - 1.0 - -
### uVision Project, (C) Keil Software
- - - *.c - *.s*; *.src; *.a* - *.obj; *.o - *.lib - *.txt; *.h; *.inc - *.plm - *.cpp - 0 - - - - 0 - 0 - - - - FVP Simulation Model - 0x4 - ARM-ADS - - 12000000 - - 1 - 1 - 0 - 1 - 0 - - - 1 - 65535 - 0 - 0 - 0 - - - 79 - 66 - 8 - .\Listings\ - - - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - - - 0 - 0 - 1 - - 7 - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 1 - 1 - 0 - 0 - 1 - 0 - 0 - 15 - - - - - - - - - - ..\Debug.ini - BIN\DbgFMv8M.DLL - - - - 0 - DLGTARM - (6010=1267,114,1744,710,0)(6018=-1,-1,-1,-1,0)(6019=105,137,294,473,0)(6008=1877,-377,2171,-192,0)(6009=-1,-1,-1,-1,0)(6014=1814,-131,2072,600,0)(6015=-1,-1,-1,-1,0)(6003=-1,-1,-1,-1,0)(6000=-1,-1,-1,-1,0) - - - 0 - ARMDBGFLAGS - - - - 0 - DLGUARM - (105=-1,-1,-1,-1,0)(106=-1,-1,-1,-1,0)(107=-1,-1,-1,-1,0) - - - 0 - DbgFMv8M - -I -S -L"cpu0" -O4102 -C0 -MC".\FVP\MPS2_Cortex-M\FVP_MPS2_Cortex-M33_MDK.exe" -MF"..\ARMCM33_DSP_FP_TZ_config.txt" -MA - - - 0 - UL2V8M - UL2V8M(-S0 -C0 -P0 -FD20000000 -FC1000) - - - - - - 0 - 1 - thread_0_counter - - - 1 - 1 - thread_1_counter - - - 2 - 1 - thread_2_counter - - - 3 - 1 - thread_3_counter - - - 4 - 1 - thread_4_counter - - - 5 - 1 - thread_5_counter - - - 6 - 1 - thread_6_counter - - - 7 - 1 - thread_7_counter - - - 8 - 1 - _tx_thread_current_ptr - - - 9 - 1 - _tx_thread_execute_ptr - - - - - 1 - 2 - 0x2001ffd8 - 0 - - - - - 2 - 2 - 0xE000ED28 - 0 - - - - 0 - - - 0 - 1 - 1 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - - - - - - - - - - - - - Secure Code - 1 - 0 - 0 - 0 - - 1 - 1 - 1 - 0 - 0 - 0 - .\main_s.c - main_s.c - 0 - 0 - - - 1 - 2 - 1 - 0 - 0 - 0 - ..\..\src\tx_thread_secure_stack.c - tx_thread_secure_stack.c - 0 - 0 - - - - - Interface - 1 - 0 - 0 - 0 - - 2 - 3 - 1 - 0 - 0 - 0 - .\interface.c - interface.c - 0 - 0 - - - - - ::CMSIS - 0 - 0 - 0 - 1 - - - - ::Device - 1 - 0 - 0 - 1 - - -
diff --git a/ports/cortex_m33/ac6/example_build/demo_threadx_non-secure_zone/ThreadX_Demo.uvopt b/ports/cortex_m33/ac6/example_build/demo_threadx_non-secure_zone/ThreadX_Demo.uvopt deleted file mode 100644 index 7ec4b36b6..000000000 --- a/ports/cortex_m33/ac6/example_build/demo_threadx_non-secure_zone/ThreadX_Demo.uvopt +++ /dev/null @@ -1,305 +0,0 @@ - - - - 1.0 - -
### uVision Project, (C) Keil Software
- - - *.c - *.s*; *.src; *.a* - *.obj; *.o - *.lib - *.txt; *.h; *.inc - *.plm - *.cpp - 0 - - - - 0 - 0 - - - - ThreadX_Demo - 0x4 - ARM-ADS - - 12000000 - - 1 - 1 - 1 - 0 - 0 - - - 1 - 65535 - 0 - 0 - 0 - - - 79 - 66 - 8 - .\ - - - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - - - 1 - 0 - 1 - - 255 - - 1 - 0 - 1 - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 1 - 0 - 1 - 0 - 1 - 1 - 0 - 0 - 1 - 0 - 0 - -1 - - - - - - - - - - - - - - - 0 - ARMRTXEVENTFLAGS - -L70 -Z18 -C0 -M0 -T1 - - - 0 - DLGDARM - (1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0) - - - 0 - DLGUARM - (105=-1,-1,-1,-1,0)(106=-1,-1,-1,-1,0)(107=-1,-1,-1,-1,0) - - - 0 - DLGTARM - (1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0)(110=-1,-1,-1,-1,0)(100=-1,-1,-1,-1,0)(101=-1,-1,-1,-1,0)(102=-1,-1,-1,-1,0)(103=-1,-1,-1,-1,0)(104=-1,-1,-1,-1,0)(105=-1,-1,-1,-1,0)(106=-1,-1,-1,-1,0)(107=-1,-1,-1,-1,0)(161=-1,-1,-1,-1,0)(162=-1,-1,-1,-1,0)(163=-1,-1,-1,-1,0)(164=-1,-1,-1,-1,0)(150=-1,-1,-1,-1,0)(151=-1,-1,-1,-1,0)(152=-1,-1,-1,-1,0)(1011=-1,-1,-1,-1,0)(1012=-1,-1,-1,-1,0)(1013=-1,-1,-1,-1,0)(171=-1,-1,-1,-1,0)(172=-1,-1,-1,-1,0)(173=-1,-1,-1,-1,0)(1014=-1,-1,-1,-1,0)(1016=-1,-1,-1,-1,0)(136=-1,-1,-1,-1,0) - - - 0 - ARMDBGFLAGS - -T5F - - - 0 - UL2CM3 - -UV0289BJE -O14 -S0 -C0 -N00("ARM CoreSight JTAG-DP") -D00(3BA00477) -L00(4) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO7 -FD20000000 -FC800 -FN1 -FF0LM3S_16 -FS00 -FL04000 - - - - - - 0 - 1 - thread_0_counter - - - 1 - 1 - thread_1_counter - - - 2 - 1 - thread_2_counter - - - 3 - 1 - thread_3_counter - - - 4 - 1 - thread_4_counter - - - 5 - 1 - thread_5_counter - - - 6 - 1 - _tx_thread_current_ptr - - - - 0 - - - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - - - - - - - - - - - - - Source Group - 1 - 0 - 0 - 0 - - 1 - 1 - 2 - 0 - 0 - 0 - .\tx_initialize_low_level.s - tx_initialize_low_level.s - 0 - 0 - - - 1 - 2 - 1 - 1 - 0 - 0 - .\demo_threadx.c - demo_threadx.c - 0 - 0 - - 44 - 0 - 1 - - -1 - -1 - - - -1 - -1 - - - 56 - 12 - 1633 - 671 - - - - - - - Library_Group - 1 - 0 - 0 - 0 - - 2 - 3 - 4 - 0 - 0 - 0 - .\ThreadX_Library.lib - ThreadX_Library.lib - 0 - 0 - - - -
diff --git a/ports/cortex_m33/ac6/example_build/demo_threadx_non-secure_zone/demo_threadx_non-secure_zone.uvoptx b/ports/cortex_m33/ac6/example_build/demo_threadx_non-secure_zone/demo_threadx_non-secure_zone.uvoptx deleted file mode 100644 index 5d966f5b9..000000000 --- a/ports/cortex_m33/ac6/example_build/demo_threadx_non-secure_zone/demo_threadx_non-secure_zone.uvoptx +++ /dev/null @@ -1,342 +0,0 @@ - - - - 1.0 - -
### uVision Project, (C) Keil Software
- - - *.c - *.s*; *.src; *.a* - *.obj; *.o - *.lib - *.txt; *.h; *.inc - *.plm - *.cpp - 0 - - - - 0 - 0 - - - - FVP Simulation Model - 0x4 - ARM-ADS - - 12000000 - - 1 - 1 - 0 - 1 - 0 - - - 1 - 65535 - 0 - 0 - 0 - - - 79 - 66 - 8 - .\Listings\ - - - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - - - 0 - 0 - 1 - - 7 - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 1 - 1 - 0 - 0 - 1 - 0 - 0 - 15 - - - - - - - - - - ..\Debug.ini - BIN\DbgFMv8M.DLL - - - - 0 - PWSTATINFO - 200,50,700 - - - 0 - DLGTARM - (6010=1243,118,1720,714,0)(6018=1284,352,1473,701,0)(6019=1328,34,1517,370,0)(6008=-1,-1,-1,-1,0)(6009=969,18,1263,203,0)(6014=1111,129,1369,860,0)(6015=872,146,1130,768,0)(6003=-1,-1,-1,-1,0)(6000=-1,-1,-1,-1,0) - - - 0 - ARMDBGFLAGS - - - - 0 - DLGUARM - (105=-1,-1,-1,-1,0)(106=511,345,1277,660,0)(107=-1,-1,-1,-1,0) - - - 0 - DbgFMv8M - -I -S -L"cpu0" -O4102 -C0 -MC".\FVP\MPS2_Cortex-M\FVP_MPS2_Cortex-M33_MDK.exe" -MF"..\ARMCM33_DSP_FP_TZ_config.txt" -PF -MA - - - 0 - UL2V8M - UL2V8M(-S0 -C0 -P0 -FC1000 -FD20000000 - - - - - - 0 - 1 - thread_0_counter - - - 1 - 1 - thread_1_counter - - - 2 - 1 - thread_2_counter - - - 3 - 1 - thread_3_counter - - - 4 - 1 - thread_4_counter - - - 5 - 1 - thread_5_counter - - - 6 - 1 - thread_6_counter - - - 7 - 1 - thread_7_counter - - - - - 1 - 2 - 0x20200a10 - 0 - - - - - 2 - 2 - 0xE000ED28 - 0 - - - - 0 - - - 0 - 1 - 1 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - - - - - - - - - - 1 - 0 - 0 - 1 - 10000000 - - - - - - Non-secure Code - 1 - 0 - 0 - 0 - - 1 - 1 - 1 - 0 - 0 - 0 - .\demo_threadx.c - demo_threadx.c - 0 - 0 - - - 1 - 2 - 4 - 0 - 0 - 0 - ..\ThreadX_Library.lib - ThreadX_Library.lib - 0 - 0 - - - - - CMSE Library - 1 - 0 - 0 - 0 - - 2 - 3 - 5 - 0 - 0 - 0 - ..\demo_secure_zone\interface.h - interface.h - 0 - 0 - - - 2 - 4 - 3 - 0 - 0 - 0 - ..\demo_secure_zone\Objects\demo_secure_zone_CMSE_Lib.o - demo_secure_zone_CMSE_Lib.o - 0 - 0 - - - - - ::CMSIS - 1 - 0 - 0 - 1 - - - - ::Device - 1 - 0 - 0 - 1 - - -
diff --git a/ports/cortex_m4/keil/example_build/ThreadX_Demo.uvopt b/ports/cortex_m4/keil/example_build/ThreadX_Demo.uvopt deleted file mode 100644 index 7b1000329..000000000 --- a/ports/cortex_m4/keil/example_build/ThreadX_Demo.uvopt +++ /dev/null @@ -1,305 +0,0 @@ - - - - 1.0 - -
### uVision Project, (C) Keil Software
- - - *.c - *.s*; *.src; *.a* - *.obj; *.o - *.lib - *.txt; *.h; *.inc; *.md - *.plm - *.cpp - 0 - - - - 0 - 0 - - - - ThreadX_Demo - 0x4 - ARM-ADS - - 12000000 - - 1 - 1 - 1 - 0 - 0 - - - 1 - 65535 - 0 - 0 - 0 - - - 79 - 66 - 8 - .\ - - - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - - - 1 - 0 - 1 - - 255 - - 1 - 0 - 1 - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 1 - 0 - 1 - 0 - 1 - 1 - 0 - 0 - 1 - 0 - 0 - -1 - - - - - - - - - - - - - - - 0 - ARMRTXEVENTFLAGS - -L70 -Z18 -C0 -M0 -T1 - - - 0 - DLGDARM - (1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0) - - - 0 - DLGUARM - (105=-1,-1,-1,-1,0)(106=-1,-1,-1,-1,0)(107=-1,-1,-1,-1,0) - - - 0 - DLGTARM - (1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0)(110=-1,-1,-1,-1,0)(100=-1,-1,-1,-1,0)(101=-1,-1,-1,-1,0)(102=-1,-1,-1,-1,0)(103=-1,-1,-1,-1,0)(104=-1,-1,-1,-1,0)(105=-1,-1,-1,-1,0)(106=-1,-1,-1,-1,0)(107=-1,-1,-1,-1,0)(161=-1,-1,-1,-1,0)(162=-1,-1,-1,-1,0)(163=-1,-1,-1,-1,0)(164=-1,-1,-1,-1,0)(150=-1,-1,-1,-1,0)(151=-1,-1,-1,-1,0)(152=-1,-1,-1,-1,0)(1011=-1,-1,-1,-1,0)(1012=-1,-1,-1,-1,0)(1013=-1,-1,-1,-1,0)(171=-1,-1,-1,-1,0)(172=-1,-1,-1,-1,0)(173=-1,-1,-1,-1,0)(1014=-1,-1,-1,-1,0)(1016=-1,-1,-1,-1,0)(136=-1,-1,-1,-1,0) - - - 0 - ARMDBGFLAGS - -T5F - - - 0 - UL2CM3 - -UV0289BJE -O14 -S0 -C0 -N00("ARM CoreSight JTAG-DP") -D00(3BA00477) -L00(4) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO7 -FD20000000 -FC800 -FN1 -FF0LM3S_16 -FS00 -FL04000 - - - - - - 0 - 1 - thread_0_counter - - - 1 - 1 - thread_1_counter - - - 2 - 1 - thread_2_counter - - - 3 - 1 - thread_3_counter - - - 4 - 1 - thread_4_counter - - - 5 - 1 - thread_5_counter - - - 6 - 1 - _tx_thread_current_ptr - - - - 0 - - - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - - - - - - - - - - - - - Source Group - 1 - 0 - 0 - 0 - - 1 - 1 - 2 - 0 - 0 - 0 - .\tx_initialize_low_level.s - tx_initialize_low_level.s - 0 - 0 - - - 1 - 2 - 1 - 0 - 0 - 0 - .\demo_threadx.c - demo_threadx.c - 0 - 0 - - 44 - 0 - 1 - - -1 - -1 - - - -1 - -1 - - - 56 - 12 - 1633 - 671 - - - - - - - Library_Group - 1 - 0 - 0 - 0 - - 2 - 3 - 4 - 0 - 0 - 0 - .\ThreadX_Library.lib - ThreadX_Library.lib - 0 - 0 - - - -
diff --git a/ports/cortex_m4/keil/example_build/ThreadX_Demo.uvoptx b/ports/cortex_m4/keil/example_build/ThreadX_Demo.uvoptx deleted file mode 100644 index c6d34eb64..000000000 --- a/ports/cortex_m4/keil/example_build/ThreadX_Demo.uvoptx +++ /dev/null @@ -1,305 +0,0 @@ - - - - 1.0 - -
### uVision Project, (C) Keil Software
- - - *.c - *.s*; *.src; *.a* - *.obj; *.o - *.lib - *.txt; *.h; *.inc; *.md - *.plm - *.cpp - 0 - - - - 0 - 0 - - - - ThreadX_Demo - 0x4 - ARM-ADS - - 12000000 - - 1 - 1 - 1 - 0 - 0 - - - 1 - 65535 - 0 - 0 - 0 - - - 79 - 66 - 8 - .\ - - - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - - - 1 - 0 - 1 - - 255 - - 1 - 0 - 1 - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 1 - 0 - 1 - 0 - 1 - 1 - 0 - 0 - 1 - 0 - 0 - -1 - - - - - - - - - - - - - - - 0 - ARMRTXEVENTFLAGS - -L70 -Z18 -C0 -M0 -T1 - - - 0 - DLGDARM - (1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0) - - - 0 - DLGUARM - (105=-1,-1,-1,-1,0)(106=-1,-1,-1,-1,0)(107=-1,-1,-1,-1,0) - - - 0 - DLGTARM - (1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0)(110=-1,-1,-1,-1,0)(100=-1,-1,-1,-1,0)(101=-1,-1,-1,-1,0)(102=-1,-1,-1,-1,0)(103=-1,-1,-1,-1,0)(104=-1,-1,-1,-1,0)(105=-1,-1,-1,-1,0)(106=-1,-1,-1,-1,0)(107=-1,-1,-1,-1,0)(161=-1,-1,-1,-1,0)(162=-1,-1,-1,-1,0)(163=-1,-1,-1,-1,0)(164=-1,-1,-1,-1,0)(150=-1,-1,-1,-1,0)(151=-1,-1,-1,-1,0)(152=-1,-1,-1,-1,0)(1011=-1,-1,-1,-1,0)(1012=-1,-1,-1,-1,0)(1013=-1,-1,-1,-1,0)(171=-1,-1,-1,-1,0)(172=-1,-1,-1,-1,0)(173=-1,-1,-1,-1,0)(1014=-1,-1,-1,-1,0)(1016=-1,-1,-1,-1,0)(136=-1,-1,-1,-1,0) - - - 0 - ARMDBGFLAGS - -T5F - - - 0 - UL2CM3 - -UV0289BJE -O14 -S0 -C0 -N00("ARM CoreSight JTAG-DP") -D00(3BA00477) -L00(4) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO7 -FD20000000 -FC800 -FN1 -FF0LM3S_16 -FS00 -FL04000 - - - - - - 0 - 1 - thread_0_counter - - - 1 - 1 - thread_1_counter - - - 2 - 1 - thread_2_counter - - - 3 - 1 - thread_3_counter - - - 4 - 1 - thread_4_counter - - - 5 - 1 - thread_5_counter - - - 6 - 1 - _tx_thread_current_ptr - - - - 0 - - - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - - - - - - - - - - - - - Source Group - 1 - 0 - 0 - 0 - - 1 - 1 - 2 - 0 - 0 - 0 - .\tx_initialize_low_level.s - tx_initialize_low_level.s - 0 - 0 - - - 1 - 2 - 1 - 0 - 0 - 0 - .\demo_threadx.c - demo_threadx.c - 0 - 0 - - 44 - 0 - 1 - - -1 - -1 - - - -1 - -1 - - - 56 - 12 - 1633 - 671 - - - - - - - Library_Group - 1 - 0 - 0 - 0 - - 2 - 3 - 4 - 0 - 0 - 0 - .\ThreadX_Library.lib - ThreadX_Library.lib - 0 - 0 - - - -
diff --git a/ports/cortex_m4/keil/example_build/ThreadX_Library.plg b/ports/cortex_m4/keil/example_build/ThreadX_Library.plg deleted file mode 100644 index 725a791b1..000000000 --- a/ports/cortex_m4/keil/example_build/ThreadX_Library.plg +++ /dev/null @@ -1,203 +0,0 @@ - - -
-

µVision Build Log

-

Project:

-C:\release\threadx\ThreadX_Library.uvproj -Project File Date: 06/28/2012 - -

Output:

-Build target 'ThreadX_Library_Project' -compiling txe_timer_info_get.c... -compiling tx_block_allocate.c... -compiling tx_block_pool_cleanup.c... -compiling tx_block_pool_create.c... -compiling tx_block_pool_delete.c... -compiling tx_block_pool_info_get.c... -compiling tx_block_pool_initialize.c... -compiling tx_block_pool_performance_info_get.c... -compiling tx_block_pool_performance_system_info_get.c... -compiling tx_block_pool_prioritize.c... -compiling tx_block_release.c... -compiling tx_byte_allocate.c... -compiling tx_byte_pool_cleanup.c... -compiling tx_byte_pool_create.c... -compiling tx_byte_pool_delete.c... -compiling tx_byte_pool_info_get.c... -compiling tx_byte_pool_initialize.c... -compiling tx_byte_pool_performance_info_get.c... -compiling tx_byte_pool_performance_system_info_get.c... -compiling tx_byte_pool_prioritize.c... -compiling tx_byte_pool_search.c... -compiling tx_byte_release.c... -compiling tx_event_flags_cleanup.c... -compiling tx_event_flags_create.c... -compiling tx_event_flags_delete.c... -compiling tx_event_flags_get.c... -compiling tx_event_flags_info_get.c... -compiling tx_event_flags_initialize.c... -compiling tx_event_flags_performance_info_get.c... -compiling tx_event_flags_performance_system_info_get.c... -compiling tx_event_flags_set.c... -compiling tx_event_flags_set_notify.c... -compiling tx_initialize_high_level.c... -compiling tx_initialize_kernel_enter.c... -compiling tx_initialize_kernel_setup.c... -compiling tx_mutex_cleanup.c... -compiling tx_mutex_create.c... -compiling tx_mutex_delete.c... -compiling tx_mutex_get.c... -compiling tx_mutex_info_get.c... -compiling tx_mutex_initialize.c... -compiling tx_mutex_performance_info_get.c... -compiling tx_mutex_performance_system_info_get.c... -compiling tx_mutex_prioritize.c... -compiling tx_mutex_priority_change.c... -compiling tx_mutex_put.c... -compiling tx_queue_cleanup.c... -compiling tx_queue_create.c... -compiling tx_queue_delete.c... -compiling tx_queue_flush.c... -compiling tx_queue_front_send.c... -compiling tx_queue_info_get.c... -compiling tx_queue_initialize.c... -compiling tx_queue_performance_info_get.c... -compiling tx_queue_performance_system_info_get.c... -compiling tx_queue_prioritize.c... -compiling tx_queue_receive.c... -compiling tx_queue_send.c... -compiling tx_queue_send_notify.c... -compiling tx_semaphore_ceiling_put.c... -compiling tx_semaphore_cleanup.c... -compiling tx_semaphore_create.c... -compiling tx_semaphore_delete.c... -compiling tx_semaphore_get.c... -compiling tx_semaphore_info_get.c... -compiling tx_semaphore_initialize.c... -compiling tx_semaphore_performance_info_get.c... -compiling tx_semaphore_performance_system_info_get.c... -compiling tx_semaphore_prioritize.c... -compiling tx_semaphore_put.c... -compiling tx_semaphore_put_notify.c... -compiling tx_thread_create.c... -compiling tx_thread_delete.c... -compiling tx_thread_entry_exit_notify.c... -compiling tx_thread_identify.c... -compiling tx_thread_info_get.c... -compiling tx_thread_initialize.c... -compiling tx_thread_performance_info_get.c... -compiling tx_thread_performance_system_info_get.c... -compiling tx_thread_preemption_change.c... -compiling tx_thread_priority_change.c... -compiling tx_thread_relinquish.c... -compiling tx_thread_reset.c... -compiling tx_thread_resume.c... -compiling tx_thread_shell_entry.c... -compiling tx_thread_sleep.c... -compiling tx_thread_stack_analyze.c... -compiling tx_thread_stack_error_handler.c... -compiling tx_thread_stack_error_notify.c... -compiling tx_thread_suspend.c... -compiling tx_thread_system_preempt_check.c... -compiling tx_thread_system_resume.c... -compiling tx_thread_system_suspend.c... -compiling tx_thread_terminate.c... -compiling tx_thread_time_slice.c... -compiling tx_thread_time_slice_change.c... -compiling tx_thread_timeout.c... -compiling tx_thread_wait_abort.c... -compiling tx_time_get.c... -compiling tx_time_set.c... -compiling tx_timer_activate.c... -compiling tx_timer_change.c... -compiling tx_timer_create.c... -compiling tx_timer_deactivate.c... -compiling tx_timer_delete.c... -compiling tx_timer_expiration_process.c... -compiling tx_timer_info_get.c... -compiling tx_timer_initialize.c... -compiling tx_timer_performance_info_get.c... -compiling tx_timer_performance_system_info_get.c... -compiling tx_timer_system_activate.c... -compiling tx_timer_system_deactivate.c... -compiling tx_timer_thread_entry.c... -compiling tx_trace_disable.c... -compiling tx_trace_enable.c... -compiling tx_trace_initialize.c... -compiling tx_trace_interrupt_control.c... -compiling tx_trace_isr_enter_insert.c... -compiling tx_trace_isr_exit_insert.c... -compiling tx_trace_object_register.c... -compiling tx_trace_object_unregister.c... -compiling tx_trace_user_event_insert.c... -compiling txe_block_allocate.c... -compiling txe_block_pool_create.c... -compiling txe_block_pool_delete.c... -compiling txe_block_pool_info_get.c... -compiling txe_block_pool_prioritize.c... -compiling txe_block_release.c... -compiling txe_byte_allocate.c... -compiling txe_byte_pool_create.c... -compiling txe_byte_pool_delete.c... -compiling txe_byte_pool_info_get.c... -compiling txe_byte_pool_prioritize.c... -compiling txe_byte_release.c... -compiling txe_event_flags_create.c... -compiling txe_event_flags_delete.c... -compiling txe_event_flags_get.c... -compiling txe_event_flags_info_get.c... -compiling txe_event_flags_set.c... -compiling txe_event_flags_set_notify.c... -compiling txe_mutex_create.c... -compiling txe_mutex_delete.c... -compiling txe_mutex_get.c... -compiling txe_mutex_info_get.c... -compiling txe_mutex_prioritize.c... -compiling txe_mutex_put.c... -compiling txe_queue_create.c... -compiling txe_queue_delete.c... -compiling txe_queue_flush.c... -compiling txe_queue_front_send.c... -compiling txe_queue_info_get.c... -compiling txe_queue_prioritize.c... -compiling txe_queue_receive.c... -compiling txe_queue_send.c... -compiling txe_queue_send_notify.c... -compiling txe_semaphore_ceiling_put.c... -compiling txe_semaphore_create.c... -compiling txe_semaphore_delete.c... -compiling txe_semaphore_get.c... -compiling txe_semaphore_info_get.c... -compiling txe_semaphore_prioritize.c... -compiling txe_semaphore_put.c... -compiling txe_semaphore_put_notify.c... -compiling txe_thread_create.c... -compiling txe_thread_delete.c... -compiling txe_thread_entry_exit_notify.c... -compiling txe_thread_info_get.c... -compiling txe_thread_preemption_change.c... -compiling txe_thread_priority_change.c... -compiling txe_thread_relinquish.c... -compiling txe_thread_reset.c... -compiling txe_thread_resume.c... -compiling txe_thread_suspend.c... -compiling txe_thread_terminate.c... -compiling txe_thread_time_slice_change.c... -compiling txe_thread_wait_abort.c... -compiling txe_timer_activate.c... -compiling txe_timer_change.c... -compiling txe_timer_create.c... -compiling txe_timer_deactivate.c... -compiling txe_timer_delete.c... -assembling tx_timer_interrupt.s... -assembling tx_thread_context_restore.s... -assembling tx_thread_context_save.s... -assembling tx_thread_interrupt_control.s... -assembling tx_thread_schedule.s... -assembling tx_thread_stack_build.s... -assembling tx_thread_system_return.s... -compiling tx_trace_buffer_full_notify.c... -compiling tx_trace_event_filter.c... -compiling tx_trace_event_unfilter.c... -creating Library... -"ThreadX_Library.lib" - 0 Error(s), 0 Warning(s). diff --git a/ports/cortex_m4/keil/example_build/ThreadX_Library.uvopt b/ports/cortex_m4/keil/example_build/ThreadX_Library.uvopt deleted file mode 100644 index 0eaad09f5..000000000 --- a/ports/cortex_m4/keil/example_build/ThreadX_Library.uvopt +++ /dev/null @@ -1,2664 +0,0 @@ - - - - 1.0 - -
### uVision Project, (C) Keil Software
- - - *.c - *.s*; *.src; *.a* - *.obj; *.o - *.lib - *.txt; *.h; *.inc; *.md - *.plm - *.cpp - 0 - - - - 0 - 0 - - - - ThreadX_Library_Project - 0x4 - ARM-ADS - - 12000000 - - 1 - 1 - 1 - 0 - 0 - - - 1 - 65535 - 0 - 0 - 0 - - - 79 - 66 - 8 - .\ - - - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - - - 1 - 0 - 1 - - 255 - - 1 - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 1 - 0 - 1 - 0 - 1 - 1 - 0 - 0 - 1 - 0 - 0 - 5 - - - - - - - - - - - BIN\ULP2CM3.DLL - - - - 0 - ULP2CM3 - -O2510 -S0 -C0 -FO15 -FD20000000 -FC4000 -FN1 -FF0MK_P256 -FS00 -FL040000) - - - - - 0 - - - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - - - - - - - - - - - - - Source Group - 0 - 0 - 0 - 0 - - 1 - 1 - 5 - 0 - 0 - 0 - ..\inc\tx_port.h - tx_port.h - 0 - 0 - - - 1 - 2 - 2 - 0 - 0 - 0 - ..\src\tx_thread_context_restore.s - tx_thread_context_restore.s - 0 - 0 - - - 1 - 3 - 2 - 0 - 0 - 0 - ..\src\tx_thread_context_save.s - tx_thread_context_save.s - 0 - 0 - - - 1 - 4 - 2 - 0 - 0 - 0 - ..\src\tx_thread_interrupt_control.s - tx_thread_interrupt_control.s - 0 - 0 - - - 1 - 5 - 2 - 0 - 0 - 0 - ..\src\tx_thread_interrupt_disable.s - tx_thread_interrupt_disable.s - 0 - 0 - - - 1 - 6 - 2 - 0 - 0 - 0 - ..\src\tx_thread_interrupt_restore.s - tx_thread_interrupt_restore.s - 0 - 0 - - - 1 - 7 - 2 - 0 - 0 - 0 - ..\src\tx_thread_schedule.s - tx_thread_schedule.s - 0 - 0 - - - 1 - 8 - 2 - 0 - 0 - 0 - ..\src\tx_thread_stack_build.s - tx_thread_stack_build.s - 0 - 0 - - - 1 - 9 - 2 - 0 - 0 - 0 - ..\src\tx_thread_system_return.s - tx_thread_system_return.s - 0 - 0 - - - 1 - 10 - 2 - 0 - 0 - 0 - ..\src\tx_timer_interrupt.s - tx_timer_interrupt.s - 0 - 0 - - - 1 - 11 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_api.h - tx_api.h - 0 - 0 - - - 1 - 12 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_block_pool.h - tx_block_pool.h - 0 - 0 - - - 1 - 13 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_byte_pool.h - tx_byte_pool.h - 0 - 0 - - - 1 - 14 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_event_flags.h - tx_event_flags.h - 0 - 0 - - - 1 - 15 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_initialize.h - tx_initialize.h - 0 - 0 - - - 1 - 16 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_mutex.h - tx_mutex.h - 0 - 0 - - - 1 - 17 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_queue.h - tx_queue.h - 0 - 0 - - - 1 - 18 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_semaphore.h - tx_semaphore.h - 0 - 0 - - - 1 - 19 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_thread.h - tx_thread.h - 0 - 0 - - - 1 - 20 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_timer.h - tx_timer.h - 0 - 0 - - - 1 - 21 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_trace.h - tx_trace.h - 0 - 0 - - - 1 - 22 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_user.h - tx_user.h - 0 - 0 - - - 1 - 23 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_allocate.c - tx_block_allocate.c - 0 - 0 - - - 1 - 24 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_cleanup.c - tx_block_pool_cleanup.c - 0 - 0 - - - 1 - 25 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_create.c - tx_block_pool_create.c - 0 - 0 - - - 1 - 26 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_delete.c - tx_block_pool_delete.c - 0 - 0 - - - 1 - 27 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_info_get.c - tx_block_pool_info_get.c - 0 - 0 - - - 1 - 28 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_initialize.c - tx_block_pool_initialize.c - 0 - 0 - - - 1 - 29 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_performance_info_get.c - tx_block_pool_performance_info_get.c - 0 - 0 - - - 1 - 30 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_performance_system_info_get.c - tx_block_pool_performance_system_info_get.c - 0 - 0 - - - 1 - 31 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_prioritize.c - tx_block_pool_prioritize.c - 0 - 0 - - - 1 - 32 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_release.c - tx_block_release.c - 0 - 0 - - - 1 - 33 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_allocate.c - tx_byte_allocate.c - 0 - 0 - - - 1 - 34 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_cleanup.c - tx_byte_pool_cleanup.c - 0 - 0 - - - 1 - 35 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_create.c - tx_byte_pool_create.c - 0 - 0 - - - 1 - 36 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_delete.c - tx_byte_pool_delete.c - 0 - 0 - - - 1 - 37 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_info_get.c - tx_byte_pool_info_get.c - 0 - 0 - - - 1 - 38 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_initialize.c - tx_byte_pool_initialize.c - 0 - 0 - - - 1 - 39 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_performance_info_get.c - tx_byte_pool_performance_info_get.c - 0 - 0 - - - 1 - 40 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_performance_system_info_get.c - tx_byte_pool_performance_system_info_get.c - 0 - 0 - - - 1 - 41 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_prioritize.c - tx_byte_pool_prioritize.c - 0 - 0 - - - 1 - 42 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_search.c - tx_byte_pool_search.c - 0 - 0 - - - 1 - 43 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_release.c - tx_byte_release.c - 0 - 0 - - - 1 - 44 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_cleanup.c - tx_event_flags_cleanup.c - 0 - 0 - - - 1 - 45 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_create.c - tx_event_flags_create.c - 0 - 0 - - - 1 - 46 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_delete.c - tx_event_flags_delete.c - 0 - 0 - - - 1 - 47 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_get.c - tx_event_flags_get.c - 0 - 0 - - - 1 - 48 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_info_get.c - tx_event_flags_info_get.c - 0 - 0 - - - 1 - 49 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_initialize.c - tx_event_flags_initialize.c - 0 - 0 - - - 1 - 50 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_performance_info_get.c - tx_event_flags_performance_info_get.c - 0 - 0 - - - 1 - 51 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_performance_system_info_get.c - tx_event_flags_performance_system_info_get.c - 0 - 0 - - - 1 - 52 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_set.c - tx_event_flags_set.c - 0 - 0 - - - 1 - 53 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_set_notify.c - tx_event_flags_set_notify.c - 0 - 0 - - - 1 - 54 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_initialize_high_level.c - tx_initialize_high_level.c - 0 - 0 - - - 1 - 55 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_initialize_kernel_enter.c - tx_initialize_kernel_enter.c - 0 - 0 - - - 1 - 56 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_initialize_kernel_setup.c - tx_initialize_kernel_setup.c - 0 - 0 - - - 1 - 57 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_misra.c - tx_misra.c - 0 - 0 - - - 1 - 58 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_cleanup.c - tx_mutex_cleanup.c - 0 - 0 - - - 1 - 59 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_create.c - tx_mutex_create.c - 0 - 0 - - - 1 - 60 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_delete.c - tx_mutex_delete.c - 0 - 0 - - - 1 - 61 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_get.c - tx_mutex_get.c - 0 - 0 - - - 1 - 62 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_info_get.c - tx_mutex_info_get.c - 0 - 0 - - - 1 - 63 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_initialize.c - tx_mutex_initialize.c - 0 - 0 - - - 1 - 64 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_performance_info_get.c - tx_mutex_performance_info_get.c - 0 - 0 - - - 1 - 65 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_performance_system_info_get.c - tx_mutex_performance_system_info_get.c - 0 - 0 - - - 1 - 66 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_prioritize.c - tx_mutex_prioritize.c - 0 - 0 - - - 1 - 67 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_priority_change.c - tx_mutex_priority_change.c - 0 - 0 - - - 1 - 68 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_put.c - tx_mutex_put.c - 0 - 0 - - - 1 - 69 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_cleanup.c - tx_queue_cleanup.c - 0 - 0 - - - 1 - 70 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_create.c - tx_queue_create.c - 0 - 0 - - - 1 - 71 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_delete.c - tx_queue_delete.c - 0 - 0 - - - 1 - 72 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_flush.c - tx_queue_flush.c - 0 - 0 - - - 1 - 73 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_front_send.c - tx_queue_front_send.c - 0 - 0 - - - 1 - 74 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_info_get.c - tx_queue_info_get.c - 0 - 0 - - - 1 - 75 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_initialize.c - tx_queue_initialize.c - 0 - 0 - - - 1 - 76 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_performance_info_get.c - tx_queue_performance_info_get.c - 0 - 0 - - - 1 - 77 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_performance_system_info_get.c - tx_queue_performance_system_info_get.c - 0 - 0 - - - 1 - 78 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_prioritize.c - tx_queue_prioritize.c - 0 - 0 - - - 1 - 79 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_receive.c - tx_queue_receive.c - 0 - 0 - - - 1 - 80 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_send.c - tx_queue_send.c - 0 - 0 - - - 1 - 81 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_send_notify.c - tx_queue_send_notify.c - 0 - 0 - - - 1 - 82 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_ceiling_put.c - tx_semaphore_ceiling_put.c - 0 - 0 - - - 1 - 83 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_cleanup.c - tx_semaphore_cleanup.c - 0 - 0 - - - 1 - 84 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_create.c - tx_semaphore_create.c - 0 - 0 - - - 1 - 85 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_delete.c - tx_semaphore_delete.c - 0 - 0 - - - 1 - 86 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_get.c - tx_semaphore_get.c - 0 - 0 - - - 1 - 87 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_info_get.c - tx_semaphore_info_get.c - 0 - 0 - - - 1 - 88 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_initialize.c - tx_semaphore_initialize.c - 0 - 0 - - - 1 - 89 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_performance_info_get.c - tx_semaphore_performance_info_get.c - 0 - 0 - - - 1 - 90 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_performance_system_info_get.c - tx_semaphore_performance_system_info_get.c - 0 - 0 - - - 1 - 91 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_prioritize.c - tx_semaphore_prioritize.c - 0 - 0 - - - 1 - 92 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_put.c - tx_semaphore_put.c - 0 - 0 - - - 1 - 93 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_put_notify.c - tx_semaphore_put_notify.c - 0 - 0 - - - 1 - 94 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_create.c - tx_thread_create.c - 0 - 0 - - - 1 - 95 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_delete.c - tx_thread_delete.c - 0 - 0 - - - 1 - 96 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_entry_exit_notify.c - tx_thread_entry_exit_notify.c - 0 - 0 - - - 1 - 97 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_identify.c - tx_thread_identify.c - 0 - 0 - - - 1 - 98 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_info_get.c - tx_thread_info_get.c - 0 - 0 - - - 1 - 99 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_initialize.c - tx_thread_initialize.c - 0 - 0 - - - 1 - 100 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_performance_info_get.c - tx_thread_performance_info_get.c - 0 - 0 - - - 1 - 101 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_performance_system_info_get.c - tx_thread_performance_system_info_get.c - 0 - 0 - - - 1 - 102 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_preemption_change.c - tx_thread_preemption_change.c - 0 - 0 - - - 1 - 103 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_priority_change.c - tx_thread_priority_change.c - 0 - 0 - - - 1 - 104 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_relinquish.c - tx_thread_relinquish.c - 0 - 0 - - - 1 - 105 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_reset.c - tx_thread_reset.c - 0 - 0 - - - 1 - 106 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_resume.c - tx_thread_resume.c - 0 - 0 - - - 1 - 107 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_shell_entry.c - tx_thread_shell_entry.c - 0 - 0 - - - 1 - 108 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_sleep.c - tx_thread_sleep.c - 0 - 0 - - - 1 - 109 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_stack_analyze.c - tx_thread_stack_analyze.c - 0 - 0 - - - 1 - 110 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_stack_error_handler.c - tx_thread_stack_error_handler.c - 0 - 0 - - - 1 - 111 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_stack_error_notify.c - tx_thread_stack_error_notify.c - 0 - 0 - - - 1 - 112 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_suspend.c - tx_thread_suspend.c - 0 - 0 - - - 1 - 113 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_system_preempt_check.c - tx_thread_system_preempt_check.c - 0 - 0 - - - 1 - 114 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_system_resume.c - tx_thread_system_resume.c - 0 - 0 - - - 1 - 115 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_system_suspend.c - tx_thread_system_suspend.c - 0 - 0 - - - 1 - 116 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_terminate.c - tx_thread_terminate.c - 0 - 0 - - - 1 - 117 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_time_slice.c - tx_thread_time_slice.c - 0 - 0 - - - 1 - 118 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_time_slice_change.c - tx_thread_time_slice_change.c - 0 - 0 - - - 1 - 119 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_timeout.c - tx_thread_timeout.c - 0 - 0 - - - 1 - 120 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_wait_abort.c - tx_thread_wait_abort.c - 0 - 0 - - - 1 - 121 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_time_get.c - tx_time_get.c - 0 - 0 - - - 1 - 122 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_time_set.c - tx_time_set.c - 0 - 0 - - - 1 - 123 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_activate.c - tx_timer_activate.c - 0 - 0 - - - 1 - 124 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_change.c - tx_timer_change.c - 0 - 0 - - - 1 - 125 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_create.c - tx_timer_create.c - 0 - 0 - - - 1 - 126 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_deactivate.c - tx_timer_deactivate.c - 0 - 0 - - - 1 - 127 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_delete.c - tx_timer_delete.c - 0 - 0 - - - 1 - 128 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_expiration_process.c - tx_timer_expiration_process.c - 0 - 0 - - - 1 - 129 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_info_get.c - tx_timer_info_get.c - 0 - 0 - - - 1 - 130 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_initialize.c - tx_timer_initialize.c - 0 - 0 - - - 1 - 131 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_performance_info_get.c - tx_timer_performance_info_get.c - 0 - 0 - - - 1 - 132 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_performance_system_info_get.c - tx_timer_performance_system_info_get.c - 0 - 0 - - - 1 - 133 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_system_activate.c - tx_timer_system_activate.c - 0 - 0 - - - 1 - 134 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_system_deactivate.c - tx_timer_system_deactivate.c - 0 - 0 - - - 1 - 135 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_thread_entry.c - tx_timer_thread_entry.c - 0 - 0 - - - 1 - 136 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_buffer_full_notify.c - tx_trace_buffer_full_notify.c - 0 - 0 - - - 1 - 137 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_disable.c - tx_trace_disable.c - 0 - 0 - - - 1 - 138 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_enable.c - tx_trace_enable.c - 0 - 0 - - - 1 - 139 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_event_filter.c - tx_trace_event_filter.c - 0 - 0 - - - 1 - 140 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_event_unfilter.c - tx_trace_event_unfilter.c - 0 - 0 - - - 1 - 141 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_initialize.c - tx_trace_initialize.c - 0 - 0 - - - 1 - 142 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_interrupt_control.c - tx_trace_interrupt_control.c - 0 - 0 - - - 1 - 143 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_isr_enter_insert.c - tx_trace_isr_enter_insert.c - 0 - 0 - - - 1 - 144 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_isr_exit_insert.c - tx_trace_isr_exit_insert.c - 0 - 0 - - - 1 - 145 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_object_register.c - tx_trace_object_register.c - 0 - 0 - - - 1 - 146 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_object_unregister.c - tx_trace_object_unregister.c - 0 - 0 - - - 1 - 147 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_user_event_insert.c - tx_trace_user_event_insert.c - 0 - 0 - - - 1 - 148 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_allocate.c - txe_block_allocate.c - 0 - 0 - - - 1 - 149 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_pool_create.c - txe_block_pool_create.c - 0 - 0 - - - 1 - 150 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_pool_delete.c - txe_block_pool_delete.c - 0 - 0 - - - 1 - 151 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_pool_info_get.c - txe_block_pool_info_get.c - 0 - 0 - - - 1 - 152 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_pool_prioritize.c - txe_block_pool_prioritize.c - 0 - 0 - - - 1 - 153 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_release.c - txe_block_release.c - 0 - 0 - - - 1 - 154 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_allocate.c - txe_byte_allocate.c - 0 - 0 - - - 1 - 155 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_pool_create.c - txe_byte_pool_create.c - 0 - 0 - - - 1 - 156 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_pool_delete.c - txe_byte_pool_delete.c - 0 - 0 - - - 1 - 157 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_pool_info_get.c - txe_byte_pool_info_get.c - 0 - 0 - - - 1 - 158 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_pool_prioritize.c - txe_byte_pool_prioritize.c - 0 - 0 - - - 1 - 159 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_release.c - txe_byte_release.c - 0 - 0 - - - 1 - 160 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_create.c - txe_event_flags_create.c - 0 - 0 - - - 1 - 161 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_delete.c - txe_event_flags_delete.c - 0 - 0 - - - 1 - 162 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_get.c - txe_event_flags_get.c - 0 - 0 - - - 1 - 163 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_info_get.c - txe_event_flags_info_get.c - 0 - 0 - - - 1 - 164 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_set.c - txe_event_flags_set.c - 0 - 0 - - - 1 - 165 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_set_notify.c - txe_event_flags_set_notify.c - 0 - 0 - - - 1 - 166 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_create.c - txe_mutex_create.c - 0 - 0 - - - 1 - 167 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_delete.c - txe_mutex_delete.c - 0 - 0 - - - 1 - 168 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_get.c - txe_mutex_get.c - 0 - 0 - - - 1 - 169 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_info_get.c - txe_mutex_info_get.c - 0 - 0 - - - 1 - 170 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_prioritize.c - txe_mutex_prioritize.c - 0 - 0 - - - 1 - 171 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_put.c - txe_mutex_put.c - 0 - 0 - - - 1 - 172 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_create.c - txe_queue_create.c - 0 - 0 - - - 1 - 173 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_delete.c - txe_queue_delete.c - 0 - 0 - - - 1 - 174 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_flush.c - txe_queue_flush.c - 0 - 0 - - - 1 - 175 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_front_send.c - txe_queue_front_send.c - 0 - 0 - - - 1 - 176 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_info_get.c - txe_queue_info_get.c - 0 - 0 - - - 1 - 177 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_prioritize.c - txe_queue_prioritize.c - 0 - 0 - - - 1 - 178 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_receive.c - txe_queue_receive.c - 0 - 0 - - - 1 - 179 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_send.c - txe_queue_send.c - 0 - 0 - - - 1 - 180 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_send_notify.c - txe_queue_send_notify.c - 0 - 0 - - - 1 - 181 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_ceiling_put.c - txe_semaphore_ceiling_put.c - 0 - 0 - - - 1 - 182 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_create.c - txe_semaphore_create.c - 0 - 0 - - - 1 - 183 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_delete.c - txe_semaphore_delete.c - 0 - 0 - - - 1 - 184 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_get.c - txe_semaphore_get.c - 0 - 0 - - - 1 - 185 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_info_get.c - txe_semaphore_info_get.c - 0 - 0 - - - 1 - 186 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_prioritize.c - txe_semaphore_prioritize.c - 0 - 0 - - - 1 - 187 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_put.c - txe_semaphore_put.c - 0 - 0 - - - 1 - 188 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_put_notify.c - txe_semaphore_put_notify.c - 0 - 0 - - - 1 - 189 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_create.c - txe_thread_create.c - 0 - 0 - - - 1 - 190 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_delete.c - txe_thread_delete.c - 0 - 0 - - - 1 - 191 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_entry_exit_notify.c - txe_thread_entry_exit_notify.c - 0 - 0 - - - 1 - 192 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_info_get.c - txe_thread_info_get.c - 0 - 0 - - - 1 - 193 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_preemption_change.c - txe_thread_preemption_change.c - 0 - 0 - - - 1 - 194 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_priority_change.c - txe_thread_priority_change.c - 0 - 0 - - - 1 - 195 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_relinquish.c - txe_thread_relinquish.c - 0 - 0 - - - 1 - 196 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_reset.c - txe_thread_reset.c - 0 - 0 - - - 1 - 197 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_resume.c - txe_thread_resume.c - 0 - 0 - - - 1 - 198 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_suspend.c - txe_thread_suspend.c - 0 - 0 - - - 1 - 199 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_terminate.c - txe_thread_terminate.c - 0 - 0 - - - 1 - 200 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_time_slice_change.c - txe_thread_time_slice_change.c - 0 - 0 - - - 1 - 201 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_wait_abort.c - txe_thread_wait_abort.c - 0 - 0 - - - 1 - 202 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_activate.c - txe_timer_activate.c - 0 - 0 - - - 1 - 203 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_change.c - txe_timer_change.c - 0 - 0 - - - 1 - 204 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_create.c - txe_timer_create.c - 0 - 0 - - - 1 - 205 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_deactivate.c - txe_timer_deactivate.c - 0 - 0 - - - 1 - 206 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_delete.c - txe_timer_delete.c - 0 - 0 - - - 1 - 207 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_info_get.c - txe_timer_info_get.c - 0 - 0 - - - -
diff --git a/ports/cortex_m4/keil/example_build/ThreadX_Library.uvoptx b/ports/cortex_m4/keil/example_build/ThreadX_Library.uvoptx deleted file mode 100644 index 31f5064ad..000000000 --- a/ports/cortex_m4/keil/example_build/ThreadX_Library.uvoptx +++ /dev/null @@ -1,2664 +0,0 @@ - - - - 1.0 - -
### uVision Project, (C) Keil Software
- - - *.c - *.s*; *.src; *.a* - *.obj; *.o - *.lib - *.txt; *.h; *.inc; *.md - *.plm - *.cpp - 0 - - - - 0 - 0 - - - - ThreadX_Library_Project - 0x4 - ARM-ADS - - 12000000 - - 1 - 1 - 1 - 0 - 0 - - - 1 - 65535 - 0 - 0 - 0 - - - 79 - 66 - 8 - .\ - - - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - - - 1 - 0 - 1 - - 255 - - 1 - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 1 - 0 - 1 - 0 - 1 - 1 - 0 - 0 - 1 - 0 - 0 - 5 - - - - - - - - - - - BIN\ULP2CM3.DLL - - - - 0 - ULP2CM3 - -O2510 -S0 -C0 -FO15 -FD20000000 -FC4000 -FN1 -FF0MK_P256 -FS00 -FL040000) - - - - - 0 - - - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - - - - - - - - - - - - - Source Group - 0 - 0 - 0 - 0 - - 1 - 1 - 5 - 0 - 0 - 0 - ..\inc\tx_port.h - tx_port.h - 0 - 0 - - - 1 - 2 - 2 - 0 - 0 - 0 - ..\src\tx_thread_context_restore.s - tx_thread_context_restore.s - 0 - 0 - - - 1 - 3 - 2 - 0 - 0 - 0 - ..\src\tx_thread_context_save.s - tx_thread_context_save.s - 0 - 0 - - - 1 - 4 - 2 - 0 - 0 - 0 - ..\src\tx_thread_interrupt_control.s - tx_thread_interrupt_control.s - 0 - 0 - - - 1 - 5 - 2 - 0 - 0 - 0 - ..\src\tx_thread_interrupt_disable.s - tx_thread_interrupt_disable.s - 0 - 0 - - - 1 - 6 - 2 - 0 - 0 - 0 - ..\src\tx_thread_interrupt_restore.s - tx_thread_interrupt_restore.s - 0 - 0 - - - 1 - 7 - 2 - 0 - 0 - 0 - ..\src\tx_thread_schedule.s - tx_thread_schedule.s - 0 - 0 - - - 1 - 8 - 2 - 0 - 0 - 0 - ..\src\tx_thread_stack_build.s - tx_thread_stack_build.s - 0 - 0 - - - 1 - 9 - 2 - 0 - 0 - 0 - ..\src\tx_thread_system_return.s - tx_thread_system_return.s - 0 - 0 - - - 1 - 10 - 2 - 0 - 0 - 0 - ..\src\tx_timer_interrupt.s - tx_timer_interrupt.s - 0 - 0 - - - 1 - 11 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_api.h - tx_api.h - 0 - 0 - - - 1 - 12 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_block_pool.h - tx_block_pool.h - 0 - 0 - - - 1 - 13 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_byte_pool.h - tx_byte_pool.h - 0 - 0 - - - 1 - 14 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_event_flags.h - tx_event_flags.h - 0 - 0 - - - 1 - 15 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_initialize.h - tx_initialize.h - 0 - 0 - - - 1 - 16 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_mutex.h - tx_mutex.h - 0 - 0 - - - 1 - 17 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_queue.h - tx_queue.h - 0 - 0 - - - 1 - 18 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_semaphore.h - tx_semaphore.h - 0 - 0 - - - 1 - 19 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_thread.h - tx_thread.h - 0 - 0 - - - 1 - 20 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_timer.h - tx_timer.h - 0 - 0 - - - 1 - 21 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_trace.h - tx_trace.h - 0 - 0 - - - 1 - 22 - 5 - 0 - 0 - 0 - ..\..\..\..\common\inc\tx_user.h - tx_user.h - 0 - 0 - - - 1 - 23 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_allocate.c - tx_block_allocate.c - 0 - 0 - - - 1 - 24 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_cleanup.c - tx_block_pool_cleanup.c - 0 - 0 - - - 1 - 25 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_create.c - tx_block_pool_create.c - 0 - 0 - - - 1 - 26 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_delete.c - tx_block_pool_delete.c - 0 - 0 - - - 1 - 27 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_info_get.c - tx_block_pool_info_get.c - 0 - 0 - - - 1 - 28 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_initialize.c - tx_block_pool_initialize.c - 0 - 0 - - - 1 - 29 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_performance_info_get.c - tx_block_pool_performance_info_get.c - 0 - 0 - - - 1 - 30 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_performance_system_info_get.c - tx_block_pool_performance_system_info_get.c - 0 - 0 - - - 1 - 31 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_prioritize.c - tx_block_pool_prioritize.c - 0 - 0 - - - 1 - 32 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_release.c - tx_block_release.c - 0 - 0 - - - 1 - 33 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_allocate.c - tx_byte_allocate.c - 0 - 0 - - - 1 - 34 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_cleanup.c - tx_byte_pool_cleanup.c - 0 - 0 - - - 1 - 35 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_create.c - tx_byte_pool_create.c - 0 - 0 - - - 1 - 36 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_delete.c - tx_byte_pool_delete.c - 0 - 0 - - - 1 - 37 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_info_get.c - tx_byte_pool_info_get.c - 0 - 0 - - - 1 - 38 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_initialize.c - tx_byte_pool_initialize.c - 0 - 0 - - - 1 - 39 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_performance_info_get.c - tx_byte_pool_performance_info_get.c - 0 - 0 - - - 1 - 40 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_performance_system_info_get.c - tx_byte_pool_performance_system_info_get.c - 0 - 0 - - - 1 - 41 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_prioritize.c - tx_byte_pool_prioritize.c - 0 - 0 - - - 1 - 42 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_search.c - tx_byte_pool_search.c - 0 - 0 - - - 1 - 43 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_release.c - tx_byte_release.c - 0 - 0 - - - 1 - 44 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_cleanup.c - tx_event_flags_cleanup.c - 0 - 0 - - - 1 - 45 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_create.c - tx_event_flags_create.c - 0 - 0 - - - 1 - 46 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_delete.c - tx_event_flags_delete.c - 0 - 0 - - - 1 - 47 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_get.c - tx_event_flags_get.c - 0 - 0 - - - 1 - 48 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_info_get.c - tx_event_flags_info_get.c - 0 - 0 - - - 1 - 49 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_initialize.c - tx_event_flags_initialize.c - 0 - 0 - - - 1 - 50 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_performance_info_get.c - tx_event_flags_performance_info_get.c - 0 - 0 - - - 1 - 51 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_performance_system_info_get.c - tx_event_flags_performance_system_info_get.c - 0 - 0 - - - 1 - 52 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_set.c - tx_event_flags_set.c - 0 - 0 - - - 1 - 53 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_set_notify.c - tx_event_flags_set_notify.c - 0 - 0 - - - 1 - 54 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_initialize_high_level.c - tx_initialize_high_level.c - 0 - 0 - - - 1 - 55 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_initialize_kernel_enter.c - tx_initialize_kernel_enter.c - 0 - 0 - - - 1 - 56 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_initialize_kernel_setup.c - tx_initialize_kernel_setup.c - 0 - 0 - - - 1 - 57 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_misra.c - tx_misra.c - 0 - 0 - - - 1 - 58 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_cleanup.c - tx_mutex_cleanup.c - 0 - 0 - - - 1 - 59 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_create.c - tx_mutex_create.c - 0 - 0 - - - 1 - 60 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_delete.c - tx_mutex_delete.c - 0 - 0 - - - 1 - 61 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_get.c - tx_mutex_get.c - 0 - 0 - - - 1 - 62 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_info_get.c - tx_mutex_info_get.c - 0 - 0 - - - 1 - 63 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_initialize.c - tx_mutex_initialize.c - 0 - 0 - - - 1 - 64 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_performance_info_get.c - tx_mutex_performance_info_get.c - 0 - 0 - - - 1 - 65 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_performance_system_info_get.c - tx_mutex_performance_system_info_get.c - 0 - 0 - - - 1 - 66 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_prioritize.c - tx_mutex_prioritize.c - 0 - 0 - - - 1 - 67 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_priority_change.c - tx_mutex_priority_change.c - 0 - 0 - - - 1 - 68 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_put.c - tx_mutex_put.c - 0 - 0 - - - 1 - 69 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_cleanup.c - tx_queue_cleanup.c - 0 - 0 - - - 1 - 70 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_create.c - tx_queue_create.c - 0 - 0 - - - 1 - 71 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_delete.c - tx_queue_delete.c - 0 - 0 - - - 1 - 72 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_flush.c - tx_queue_flush.c - 0 - 0 - - - 1 - 73 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_front_send.c - tx_queue_front_send.c - 0 - 0 - - - 1 - 74 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_info_get.c - tx_queue_info_get.c - 0 - 0 - - - 1 - 75 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_initialize.c - tx_queue_initialize.c - 0 - 0 - - - 1 - 76 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_performance_info_get.c - tx_queue_performance_info_get.c - 0 - 0 - - - 1 - 77 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_performance_system_info_get.c - tx_queue_performance_system_info_get.c - 0 - 0 - - - 1 - 78 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_prioritize.c - tx_queue_prioritize.c - 0 - 0 - - - 1 - 79 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_receive.c - tx_queue_receive.c - 0 - 0 - - - 1 - 80 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_send.c - tx_queue_send.c - 0 - 0 - - - 1 - 81 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_send_notify.c - tx_queue_send_notify.c - 0 - 0 - - - 1 - 82 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_ceiling_put.c - tx_semaphore_ceiling_put.c - 0 - 0 - - - 1 - 83 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_cleanup.c - tx_semaphore_cleanup.c - 0 - 0 - - - 1 - 84 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_create.c - tx_semaphore_create.c - 0 - 0 - - - 1 - 85 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_delete.c - tx_semaphore_delete.c - 0 - 0 - - - 1 - 86 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_get.c - tx_semaphore_get.c - 0 - 0 - - - 1 - 87 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_info_get.c - tx_semaphore_info_get.c - 0 - 0 - - - 1 - 88 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_initialize.c - tx_semaphore_initialize.c - 0 - 0 - - - 1 - 89 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_performance_info_get.c - tx_semaphore_performance_info_get.c - 0 - 0 - - - 1 - 90 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_performance_system_info_get.c - tx_semaphore_performance_system_info_get.c - 0 - 0 - - - 1 - 91 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_prioritize.c - tx_semaphore_prioritize.c - 0 - 0 - - - 1 - 92 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_put.c - tx_semaphore_put.c - 0 - 0 - - - 1 - 93 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_put_notify.c - tx_semaphore_put_notify.c - 0 - 0 - - - 1 - 94 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_create.c - tx_thread_create.c - 0 - 0 - - - 1 - 95 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_delete.c - tx_thread_delete.c - 0 - 0 - - - 1 - 96 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_entry_exit_notify.c - tx_thread_entry_exit_notify.c - 0 - 0 - - - 1 - 97 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_identify.c - tx_thread_identify.c - 0 - 0 - - - 1 - 98 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_info_get.c - tx_thread_info_get.c - 0 - 0 - - - 1 - 99 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_initialize.c - tx_thread_initialize.c - 0 - 0 - - - 1 - 100 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_performance_info_get.c - tx_thread_performance_info_get.c - 0 - 0 - - - 1 - 101 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_performance_system_info_get.c - tx_thread_performance_system_info_get.c - 0 - 0 - - - 1 - 102 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_preemption_change.c - tx_thread_preemption_change.c - 0 - 0 - - - 1 - 103 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_priority_change.c - tx_thread_priority_change.c - 0 - 0 - - - 1 - 104 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_relinquish.c - tx_thread_relinquish.c - 0 - 0 - - - 1 - 105 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_reset.c - tx_thread_reset.c - 0 - 0 - - - 1 - 106 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_resume.c - tx_thread_resume.c - 0 - 0 - - - 1 - 107 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_shell_entry.c - tx_thread_shell_entry.c - 0 - 0 - - - 1 - 108 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_sleep.c - tx_thread_sleep.c - 0 - 0 - - - 1 - 109 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_stack_analyze.c - tx_thread_stack_analyze.c - 0 - 0 - - - 1 - 110 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_stack_error_handler.c - tx_thread_stack_error_handler.c - 0 - 0 - - - 1 - 111 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_stack_error_notify.c - tx_thread_stack_error_notify.c - 0 - 0 - - - 1 - 112 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_suspend.c - tx_thread_suspend.c - 0 - 0 - - - 1 - 113 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_system_preempt_check.c - tx_thread_system_preempt_check.c - 0 - 0 - - - 1 - 114 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_system_resume.c - tx_thread_system_resume.c - 0 - 0 - - - 1 - 115 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_system_suspend.c - tx_thread_system_suspend.c - 0 - 0 - - - 1 - 116 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_terminate.c - tx_thread_terminate.c - 0 - 0 - - - 1 - 117 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_time_slice.c - tx_thread_time_slice.c - 0 - 0 - - - 1 - 118 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_time_slice_change.c - tx_thread_time_slice_change.c - 0 - 0 - - - 1 - 119 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_timeout.c - tx_thread_timeout.c - 0 - 0 - - - 1 - 120 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_wait_abort.c - tx_thread_wait_abort.c - 0 - 0 - - - 1 - 121 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_time_get.c - tx_time_get.c - 0 - 0 - - - 1 - 122 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_time_set.c - tx_time_set.c - 0 - 0 - - - 1 - 123 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_activate.c - tx_timer_activate.c - 0 - 0 - - - 1 - 124 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_change.c - tx_timer_change.c - 0 - 0 - - - 1 - 125 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_create.c - tx_timer_create.c - 0 - 0 - - - 1 - 126 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_deactivate.c - tx_timer_deactivate.c - 0 - 0 - - - 1 - 127 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_delete.c - tx_timer_delete.c - 0 - 0 - - - 1 - 128 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_expiration_process.c - tx_timer_expiration_process.c - 0 - 0 - - - 1 - 129 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_info_get.c - tx_timer_info_get.c - 0 - 0 - - - 1 - 130 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_initialize.c - tx_timer_initialize.c - 0 - 0 - - - 1 - 131 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_performance_info_get.c - tx_timer_performance_info_get.c - 0 - 0 - - - 1 - 132 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_performance_system_info_get.c - tx_timer_performance_system_info_get.c - 0 - 0 - - - 1 - 133 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_system_activate.c - tx_timer_system_activate.c - 0 - 0 - - - 1 - 134 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_system_deactivate.c - tx_timer_system_deactivate.c - 0 - 0 - - - 1 - 135 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_thread_entry.c - tx_timer_thread_entry.c - 0 - 0 - - - 1 - 136 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_buffer_full_notify.c - tx_trace_buffer_full_notify.c - 0 - 0 - - - 1 - 137 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_disable.c - tx_trace_disable.c - 0 - 0 - - - 1 - 138 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_enable.c - tx_trace_enable.c - 0 - 0 - - - 1 - 139 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_event_filter.c - tx_trace_event_filter.c - 0 - 0 - - - 1 - 140 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_event_unfilter.c - tx_trace_event_unfilter.c - 0 - 0 - - - 1 - 141 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_initialize.c - tx_trace_initialize.c - 0 - 0 - - - 1 - 142 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_interrupt_control.c - tx_trace_interrupt_control.c - 0 - 0 - - - 1 - 143 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_isr_enter_insert.c - tx_trace_isr_enter_insert.c - 0 - 0 - - - 1 - 144 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_isr_exit_insert.c - tx_trace_isr_exit_insert.c - 0 - 0 - - - 1 - 145 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_object_register.c - tx_trace_object_register.c - 0 - 0 - - - 1 - 146 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_object_unregister.c - tx_trace_object_unregister.c - 0 - 0 - - - 1 - 147 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_user_event_insert.c - tx_trace_user_event_insert.c - 0 - 0 - - - 1 - 148 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_allocate.c - txe_block_allocate.c - 0 - 0 - - - 1 - 149 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_pool_create.c - txe_block_pool_create.c - 0 - 0 - - - 1 - 150 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_pool_delete.c - txe_block_pool_delete.c - 0 - 0 - - - 1 - 151 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_pool_info_get.c - txe_block_pool_info_get.c - 0 - 0 - - - 1 - 152 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_pool_prioritize.c - txe_block_pool_prioritize.c - 0 - 0 - - - 1 - 153 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_release.c - txe_block_release.c - 0 - 0 - - - 1 - 154 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_allocate.c - txe_byte_allocate.c - 0 - 0 - - - 1 - 155 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_pool_create.c - txe_byte_pool_create.c - 0 - 0 - - - 1 - 156 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_pool_delete.c - txe_byte_pool_delete.c - 0 - 0 - - - 1 - 157 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_pool_info_get.c - txe_byte_pool_info_get.c - 0 - 0 - - - 1 - 158 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_pool_prioritize.c - txe_byte_pool_prioritize.c - 0 - 0 - - - 1 - 159 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_release.c - txe_byte_release.c - 0 - 0 - - - 1 - 160 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_create.c - txe_event_flags_create.c - 0 - 0 - - - 1 - 161 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_delete.c - txe_event_flags_delete.c - 0 - 0 - - - 1 - 162 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_get.c - txe_event_flags_get.c - 0 - 0 - - - 1 - 163 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_info_get.c - txe_event_flags_info_get.c - 0 - 0 - - - 1 - 164 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_set.c - txe_event_flags_set.c - 0 - 0 - - - 1 - 165 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_set_notify.c - txe_event_flags_set_notify.c - 0 - 0 - - - 1 - 166 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_create.c - txe_mutex_create.c - 0 - 0 - - - 1 - 167 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_delete.c - txe_mutex_delete.c - 0 - 0 - - - 1 - 168 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_get.c - txe_mutex_get.c - 0 - 0 - - - 1 - 169 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_info_get.c - txe_mutex_info_get.c - 0 - 0 - - - 1 - 170 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_prioritize.c - txe_mutex_prioritize.c - 0 - 0 - - - 1 - 171 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_put.c - txe_mutex_put.c - 0 - 0 - - - 1 - 172 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_create.c - txe_queue_create.c - 0 - 0 - - - 1 - 173 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_delete.c - txe_queue_delete.c - 0 - 0 - - - 1 - 174 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_flush.c - txe_queue_flush.c - 0 - 0 - - - 1 - 175 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_front_send.c - txe_queue_front_send.c - 0 - 0 - - - 1 - 176 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_info_get.c - txe_queue_info_get.c - 0 - 0 - - - 1 - 177 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_prioritize.c - txe_queue_prioritize.c - 0 - 0 - - - 1 - 178 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_receive.c - txe_queue_receive.c - 0 - 0 - - - 1 - 179 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_send.c - txe_queue_send.c - 0 - 0 - - - 1 - 180 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_send_notify.c - txe_queue_send_notify.c - 0 - 0 - - - 1 - 181 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_ceiling_put.c - txe_semaphore_ceiling_put.c - 0 - 0 - - - 1 - 182 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_create.c - txe_semaphore_create.c - 0 - 0 - - - 1 - 183 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_delete.c - txe_semaphore_delete.c - 0 - 0 - - - 1 - 184 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_get.c - txe_semaphore_get.c - 0 - 0 - - - 1 - 185 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_info_get.c - txe_semaphore_info_get.c - 0 - 0 - - - 1 - 186 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_prioritize.c - txe_semaphore_prioritize.c - 0 - 0 - - - 1 - 187 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_put.c - txe_semaphore_put.c - 0 - 0 - - - 1 - 188 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_put_notify.c - txe_semaphore_put_notify.c - 0 - 0 - - - 1 - 189 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_create.c - txe_thread_create.c - 0 - 0 - - - 1 - 190 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_delete.c - txe_thread_delete.c - 0 - 0 - - - 1 - 191 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_entry_exit_notify.c - txe_thread_entry_exit_notify.c - 0 - 0 - - - 1 - 192 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_info_get.c - txe_thread_info_get.c - 0 - 0 - - - 1 - 193 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_preemption_change.c - txe_thread_preemption_change.c - 0 - 0 - - - 1 - 194 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_priority_change.c - txe_thread_priority_change.c - 0 - 0 - - - 1 - 195 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_relinquish.c - txe_thread_relinquish.c - 0 - 0 - - - 1 - 196 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_reset.c - txe_thread_reset.c - 0 - 0 - - - 1 - 197 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_resume.c - txe_thread_resume.c - 0 - 0 - - - 1 - 198 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_suspend.c - txe_thread_suspend.c - 0 - 0 - - - 1 - 199 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_terminate.c - txe_thread_terminate.c - 0 - 0 - - - 1 - 200 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_time_slice_change.c - txe_thread_time_slice_change.c - 0 - 0 - - - 1 - 201 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_wait_abort.c - txe_thread_wait_abort.c - 0 - 0 - - - 1 - 202 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_activate.c - txe_timer_activate.c - 0 - 0 - - - 1 - 203 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_change.c - txe_timer_change.c - 0 - 0 - - - 1 - 204 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_create.c - txe_timer_create.c - 0 - 0 - - - 1 - 205 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_deactivate.c - txe_timer_deactivate.c - 0 - 0 - - - 1 - 206 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_delete.c - txe_timer_delete.c - 0 - 0 - - - 1 - 207 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_info_get.c - txe_timer_info_get.c - 0 - 0 - - - -
diff --git a/ports/cortex_m55/ac6/example_build/RTOS.uvmpw.uvgui b/ports/cortex_m55/ac6/example_build/RTOS.uvmpw.uvgui deleted file mode 100644 index 5c23c31fc..000000000 --- a/ports/cortex_m55/ac6/example_build/RTOS.uvmpw.uvgui +++ /dev/null @@ -1,1777 +0,0 @@ - - - - -6.1 - -
### uVision Project, (C) Keil Software
- - - - - 44 - 2 - 3 - - -1 - -1 - - - -1 - -1 - - - 0 - 0 - 1024 - 728 - - - - 0 - - 297 - 0100000004000000010000000100000001000000010000000000000002000000000000000100000001000000000000002800000028000000010000000100000000000000010000005F433A5C4B65696C5C41524D5C5041434B5C41524D5C434D5349535C352E322E305C434D5349535C52544F53325C5254585C4578616D706C65735C54727573745A6F6E6556384D5C52544F535C434D33335F735C41627374726163742E747874000000000C41627374726163742E74787400000000C5D4F200FFFFFFFF0100000010000000C5D4F200FFDC7800BECEA100F0A0A100BCA8E1009CC1B600F7B88600D9ADC200A5C2D700B3A6BE00EAD6A300F6FA7D00B5E99D005FC3CF00C1838300CACAD500010000000000000002000000380100006500000080070000FD030000 - - - - 0 - Build - - -1 - -1 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - F40000004F00000090050000F0000000 - - - 16 - F4000000650000009005000006010000 - - - - 1005 - 1005 - 1 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 030000006600000031010000CE030000 - - - 16 - 2100000037000000110100001A010000 - - - - 109 - 109 - 1 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 030000006600000031010000CE030000 - - - 16 - 21000000370000003D010000BD020000 - - - - 1465 - 1465 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000760200008D050000FB020000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 1466 - 1466 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000760200008D050000FB020000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 1467 - 1467 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000760200008D050000FB020000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 1468 - 1468 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000760200008D050000FB020000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 1506 - 1506 - 0 - 0 - 0 - 0 - 32767 - 0 - 16384 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 1913 - 1913 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - F7000000660000008D050000D7000000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 1935 - 1935 - 0 - 0 - 0 - 0 - 32767 - 0 - 32768 - 0 - - 16 - 03000000760200008D050000FB020000 - - - 16 - 2100000037000000110100001A010000 - - - - 1936 - 1936 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000760200008D050000FB020000 - - - 16 - 2100000037000000110100001A010000 - - - - 1937 - 1937 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000760200008D050000FB020000 - - - 16 - 2100000037000000110100001A010000 - - - - 1939 - 1939 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000760200008D050000FB020000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 1940 - 1940 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000760200008D050000FB020000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 1941 - 1941 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000760200008D050000FB020000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 1942 - 1942 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000760200008D050000FB020000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 195 - 195 - 1 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 030000006600000031010000CE030000 - - - 16 - 21000000370000003D010000BD020000 - - - - 196 - 196 - 1 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 030000006600000031010000CE030000 - - - 16 - 21000000370000003D010000BD020000 - - - - 197 - 197 - 0 - 0 - 0 - 0 - 32767 - 0 - 32768 - 0 - - 16 - 03000000390300007D070000CE030000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 198 - 198 - 0 - 0 - 0 - 0 - 32767 - 0 - 32768 - 0 - - 16 - 000000005F0200009005000014030000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 199 - 199 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000390300007D070000CE030000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 203 - 203 - 0 - 0 - 0 - 0 - 32767 - 0 - 8192 - 0 - - 16 - F7000000660000008D050000D7000000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 204 - 204 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - F7000000660000008D050000D7000000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 221 - 221 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 00000000000000000000000000000000 - - - 16 - 0A0000000A0000006E0000006E000000 - - - - 2506 - 2506 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 2507 - 2507 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000760200008D050000FB020000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 343 - 343 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - F7000000660000008D050000D7000000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 346 - 346 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - F7000000660000008D050000D7000000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 35824 - 35824 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - F7000000660000008D050000D7000000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 35885 - 35885 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35886 - 35886 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35887 - 35887 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35888 - 35888 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35889 - 35889 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35890 - 35890 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35891 - 35891 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35892 - 35892 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35893 - 35893 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35894 - 35894 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35895 - 35895 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35896 - 35896 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35897 - 35897 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35898 - 35898 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35899 - 35899 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35900 - 35900 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35901 - 35901 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35902 - 35902 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35903 - 35903 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35904 - 35904 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35905 - 35905 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 38003 - 38003 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 030000006600000031010000CE030000 - - - 16 - 21000000370000003D010000BD020000 - - - - 38007 - 38007 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000390300007D070000CE030000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 436 - 436 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000390300007D070000CE030000 - - - 16 - 21000000370000003D010000BD020000 - - - - 437 - 437 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000760200008D050000FB020000 - - - 16 - 2100000037000000110100001A010000 - - - - 440 - 440 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000760200008D050000FB020000 - - - 16 - 2100000037000000110100001A010000 - - - - 463 - 463 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 030000006E0300007D070000CE030000 - - - 16 - 21000000370000003D01000079020000 - - - - 466 - 466 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 030000006E0300007D070000CE030000 - - - 16 - 21000000370000003D01000079020000 - - - - 470 - 470 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000010000000300000003020000 - - - 16 - 2100000037000000E9020000C7000000 - - - - 50000 - 50000 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50001 - 50001 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50002 - 50002 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50003 - 50003 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50004 - 50004 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50005 - 50005 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50006 - 50006 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50007 - 50007 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50008 - 50008 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50009 - 50009 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50010 - 50010 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50011 - 50011 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50012 - 50012 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50013 - 50013 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50014 - 50014 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50015 - 50015 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50016 - 50016 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50017 - 50017 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50018 - 50018 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50019 - 50019 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 59392 - 59392 - 1 - 0 - 0 - 0 - 940 - 0 - 8192 - 0 - - 16 - 0000000000000000B70300001C000000 - - - 16 - 0A0000000A0000006E0000006E000000 - - - - 59393 - 0 - 1 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 00000000E703000080070000FA030000 - - - 16 - 0A0000000A0000006E0000006E000000 - - - - 59399 - 59399 - 1 - 0 - 0 - 0 - 303 - 0 - 8192 - 1 - - 16 - 000000001C000000E701000038000000 - - - 16 - 0A0000000A0000006E0000006E000000 - - - - 59400 - 59400 - 0 - 0 - 0 - 0 - 612 - 0 - 8192 - 2 - - 16 - 00000000380000006F02000054000000 - - - 16 - 0A0000000A0000006E0000006E000000 - - - - 824 - 824 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000010000000300000003020000 - - - 16 - 21000000370000001101000002010000 - - - - 3692 - 000000000F000000000000000020000000000000FFFFFFFFFFFFFFFFF4000000F000000090050000F4000000000000000100000004000000010000000000000000000000FFFFFFFF06000000CB00000057010000CC000000F08B00005A01000079070000FFFF02000B004354616262656450616E650020000000000000F4000000650000009005000006010000F40000004F00000090050000F00000000000000040280046060000000B446973617373656D626C7900000000CB00000001000000FFFFFFFFFFFFFFFF14506572666F726D616E636520416E616C797A6572000000005701000001000000FFFFFFFFFFFFFFFF14506572666F726D616E636520416E616C797A657200000000CC00000001000000FFFFFFFFFFFFFFFF0E4C6F67696320416E616C797A657200000000F08B000001000000FFFFFFFFFFFFFFFF0D436F646520436F766572616765000000005A01000001000000FFFFFFFFFFFFFFFF11496E737472756374696F6E205472616365000000007907000001000000FFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000000000000000000001000000FFFFFFFFCB00000001000000FFFFFFFFCB000000000000000040000000000000FFFFFFFFFFFFFFFF9C0400004F000000A00400006F020000000000000200000004000000010000000000000000000000FFFFFFFF2B000000E2050000CA0900002D8C00002E8C00002F8C0000308C0000318C0000328C0000338C0000348C0000358C0000368C0000378C0000388C0000398C00003A8C00003B8C00003C8C00003D8C00003E8C00003F8C0000408C0000418C000050C3000051C3000052C3000053C3000054C3000055C3000056C3000057C3000058C3000059C300005AC300005BC300005CC300005DC300005EC300005FC3000060C3000061C3000062C3000063C3000001800040000000000000A0040000650000009005000085020000A00400004F000000900500006F02000000000000404100462B0000000753796D626F6C7300000000E205000001000000FFFFFFFFFFFFFFFF0A5472616365204461746100000000CA09000001000000FFFFFFFFFFFFFFFF00000000002D8C000001000000FFFFFFFFFFFFFFFF00000000002E8C000001000000FFFFFFFFFFFFFFFF00000000002F8C000001000000FFFFFFFFFFFFFFFF0000000000308C000001000000FFFFFFFFFFFFFFFF0000000000318C000001000000FFFFFFFFFFFFFFFF0000000000328C000001000000FFFFFFFFFFFFFFFF0000000000338C000001000000FFFFFFFFFFFFFFFF0000000000348C000001000000FFFFFFFFFFFFFFFF0000000000358C000001000000FFFFFFFFFFFFFFFF0000000000368C000001000000FFFFFFFFFFFFFFFF0000000000378C000001000000FFFFFFFFFFFFFFFF0000000000388C000001000000FFFFFFFFFFFFFFFF0000000000398C000001000000FFFFFFFFFFFFFFFF00000000003A8C000001000000FFFFFFFFFFFFFFFF00000000003B8C000001000000FFFFFFFFFFFFFFFF00000000003C8C000001000000FFFFFFFFFFFFFFFF00000000003D8C000001000000FFFFFFFFFFFFFFFF00000000003E8C000001000000FFFFFFFFFFFFFFFF00000000003F8C000001000000FFFFFFFFFFFFFFFF0000000000408C000001000000FFFFFFFFFFFFFFFF0000000000418C000001000000FFFFFFFFFFFFFFFF000000000050C3000001000000FFFFFFFFFFFFFFFF000000000051C3000001000000FFFFFFFFFFFFFFFF000000000052C3000001000000FFFFFFFFFFFFFFFF000000000053C3000001000000FFFFFFFFFFFFFFFF000000000054C3000001000000FFFFFFFFFFFFFFFF000000000055C3000001000000FFFFFFFFFFFFFFFF000000000056C3000001000000FFFFFFFFFFFFFFFF000000000057C3000001000000FFFFFFFFFFFFFFFF000000000058C3000001000000FFFFFFFFFFFFFFFF000000000059C3000001000000FFFFFFFFFFFFFFFF00000000005AC3000001000000FFFFFFFFFFFFFFFF00000000005BC3000001000000FFFFFFFFFFFFFFFF00000000005CC3000001000000FFFFFFFFFFFFFFFF00000000005DC3000001000000FFFFFFFFFFFFFFFF00000000005EC3000001000000FFFFFFFFFFFFFFFF00000000005FC3000001000000FFFFFFFFFFFFFFFF000000000060C3000001000000FFFFFFFFFFFFFFFF000000000061C3000001000000FFFFFFFFFFFFFFFF000000000062C3000001000000FFFFFFFFFFFFFFFF000000000063C3000001000000FFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000000000000000000001000000FFFFFFFFE205000001000000FFFFFFFFE2050000000000000010000001000000FFFFFFFFFFFFFFFF340100004F00000038010000E703000001000000020000100400000001000000A7FEFFFF1C060000FFFFFFFF05000000ED0300006D000000C3000000C40000007394000001800010000001000000000000006500000034010000FD030000000000004F00000034010000E70300000000000040410056050000000750726F6A65637401000000ED03000001000000FFFFFFFFFFFFFFFF05426F6F6B73010000006D00000001000000FFFFFFFFFFFFFFFF0946756E6374696F6E7301000000C300000001000000FFFFFFFFFFFFFFFF0954656D706C6174657301000000C400000001000000FFFFFFFFFFFFFFFF09526567697374657273000000007394000001000000FFFFFFFFFFFFFFFF00000000000000000000000000000000000000000000000001000000FFFFFFFFED03000001000000FFFFFFFFED030000000000000080000000000000FFFFFFFFFFFFFFFF000000005B020000900500005F02000000000000010000000400000001000000000000000000000000000000000000000000000001000000C6000000FFFFFFFF0E0000008F070000930700009407000095070000960700009007000091070000B5010000B8010000B9050000BA050000BB050000BC050000CB090000018000800000000000000000000075020000900500002A030000000000005F020000900500001403000000000000404100460E0000001343616C6C20537461636B202B204C6F63616C73000000008F07000001000000FFFFFFFFFFFFFFFF0755415254202331000000009307000001000000FFFFFFFFFFFFFFFF0755415254202332000000009407000001000000FFFFFFFFFFFFFFFF0755415254202333000000009507000001000000FFFFFFFFFFFFFFFF15446562756720287072696E74662920566965776572000000009607000001000000FFFFFFFFFFFFFFFF0757617463682031000000009007000001000000FFFFFFFFFFFFFFFF0757617463682032000000009107000001000000FFFFFFFFFFFFFFFF10547261636520457863657074696F6E7300000000B501000001000000FFFFFFFFFFFFFFFF0E4576656E7420436F756E7465727300000000B801000001000000FFFFFFFFFFFFFFFF084D656D6F7279203100000000B905000001000000FFFFFFFFFFFFFFFF084D656D6F7279203200000000BA05000001000000FFFFFFFFFFFFFFFF084D656D6F7279203300000000BB05000001000000FFFFFFFFFFFFFFFF084D656D6F7279203400000000BC05000001000000FFFFFFFFFFFFFFFF105472616365204E617669676174696F6E00000000CB09000001000000FFFFFFFFFFFFFFFFFFFFFFFF0000000001000000000000000000000001000000FFFFFFFFC80200005F020000CC0200001403000000000000020000000400000000000000000000000000000000000000000000000000000002000000C6000000FFFFFFFF8F07000001000000FFFFFFFF8F07000001000000C6000000000000000080000000000000FFFFFFFFFFFFFFFF000000001E03000080070000220300000000000001000000040000000100000067FDFFFFF4000000FFFFFFFF04000000C5000000C7000000B40100007794000001800080000000000000000000003803000080070000FD030000000000002203000080070000E70300000000000040820046040000000C4275696C64204F757470757400000000C500000001000000FFFFFFFFFFFFFFFF0D46696E6420496E2046696C657300000000C700000001000000FFFFFFFFFFFFFFFF0A4572726F72204C69737400000000B401000001000000FFFFFFFFFFFFFFFF0742726F77736572000000007794000001000000FFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000000000000000000001000000FFFFFFFFC500000001000000FFFFFFFFC5000000000000000080000000000000FFFFFFFFFFFFFFFF0000000017020000900500001B0200000000000001000000040000000100000000000000000000000000000000000000000000000100000000000000FFFFFFFF0200000038030000D6010000018000800000000000000000000000000000010000003202000000000000EAFFFFFF010000001C02000000000000404100460200000009554C494E4B706C7573000000003803000001000000FFFFFFFFFFFFFFFF0F53797374656D20416E616C797A657200000000D601000001000000FFFFFFFFFFFFFFFFFFFFFFFF0000000001000000000000000000000001000000FFFFFFFFC80200001B020000CC020000BF02000000000000020000000400000000000000000000000000000000000000000000000000000001000000FFFFFFFF3803000001000000FFFFFFFF38030000000000000080000000000000FFFFFFFFFFFFFFFF00000000530300008007000057030000000000000100000004000000010000000000000000000000FFFFFFFF02000000D2010000CF01000001800080000000000000000000006D03000080070000FD030000000000005703000080070000E70300000000000040820046020000000E536F757263652042726F7773657200000000D201000001000000FFFFFFFFFFFFFFFF1346696E6420416C6C205265666572656E63657300000000CF01000001000000FFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000000000000000000001000000FFFFFFFFD201000001000000FFFFFFFFD2010000000000000000000000000000 - - - 59392 - File - - 2438 - 00200000010000002800FFFF01001100434D4643546F6F6C426172427574746F6E00E100000000000000000000000000000000000000000000000100000001000000018001E100000000000001000000000000000000000000000000000100000001000000018003E1000000000000020000000000000000000000000000000001000000010000000180CD7F0000000000000300000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018023E100000000040004000000000000000000000000000000000100000001000000018022E100000000040005000000000000000000000000000000000100000001000000018025E10000000000000600000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001802BE10000000004000700000000000000000000000000000000010000000100000001802CE10000000004000800000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001807A8A0000000004000900000000000000000000000000000000010000000100000001807B8A0000000004000A00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180D3B00000000000000B000000000000000000000000000000000100000001000000018015B10000000004000C0000000000000000000000000000000001000000010000000180F4B00000000004000D000000000000000000000000000000000100000001000000018036B10000000004000E00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180FF88000000000400460000000000000000000000000000000001000000010000000180FE880000000004004500000000000000000000000000000000010000000100000001800B810000000004001300000000000000000000000000000000010000000100000001800C810000000004001400000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180F0880000020000000F000000000000000000000000000000000100000001000000FFFF0100120043555646696E64436F6D626F427574746F6EE803000000000000000000000000000000000000000000000001000000010000009600000002002050000000000944657374726F796564960000000000000014000944657374726F79656406507265656D7006746872656164136F735274785468726561645265616479507574106F73527478546872656164426C6F636B15457672527478546872656164556E626C6F636B656413457672527478546872656164426C6F636B6564116F735274785468726561645377697463681545767252747854687265616444657374726F796564146F7352747854687265616457616974456E746572146F7352747854687265616444656C61795469636B0D7468726561642D3E7374617465126F73527478546872656164426C6F636B6564126F7352747854687265616457616974696E67204576745274784B65726E656C496E666F5265747269657665645F44657461696C194576745274784B65726E656C496E666F52657472696576656408546872656164437206236966646566136F735F69646C655F7468726561645F617474720E6F73546872656164417474725F740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018024E10000000000001100000000000000000000000000000000010000000100000001800A810000000000001200000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018022800000020000001500000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180C488000000000000160000000000000000000000000000000001000000010000000180C988000000000400180000000000000000000000000000000001000000010000000180C788000000000000190000000000000000000000000000000001000000010000000180C8880000000000001700000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000FFFF01001500434D4643546F6F6C4261724D656E75427574746F6E4C010000020001001A0000000F2650726F6A6563742057696E646F77000000000000000000000000010000000100000000000000000000000100000008002880DD880000000000001A0000000750726F6A656374000000000000000000000000010000000100000000000000000000000100000000002880DC8B0000000000003A00000005426F6F6B73000000000000000000000000010000000100000000000000000000000100000000002880E18B0000000000003B0000000946756E6374696F6E73000000000000000000000000010000000100000000000000000000000100000000002880E28B000000000000400000000954656D706C6174657300000000000000000000000001000000010000000000000000000000010000000000288018890000000000003D0000000E536F757263652042726F777365720000000000000000000000000100000001000000000000000000000001000000000028800000000000000400FFFFFFFF00000000000000000001000000000000000100000000000000000000000100000000002880D988000000000000390000000C4275696C64204F7574707574000000000000000000000000010000000100000000000000000000000100000000002880E38B000000000000410000000B46696E64204F75747075740000000000000000000000000100000001000000000000000000000001000000000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180FB7F0000000000001B000000000000000000000000000000000100000001000000000000000446696C65AC030000 - - - 1423 - 2800FFFF01001100434D4643546F6F6C426172427574746F6E00E1000000000000FFFFFFFF000100000000000000010000000000000001000000018001E1000000000000FFFFFFFF000100000000000000010000000000000001000000018003E1000000000000FFFFFFFF0001000000000000000100000000000000010000000180CD7F000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF000000000000000000010000000000000001000000018023E1000000000000FFFFFFFF000100000000000000010000000000000001000000018022E1000000000000FFFFFFFF000100000000000000010000000000000001000000018025E1000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001802BE1000000000000FFFFFFFF00010000000000000001000000000000000100000001802CE1000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001807A8A000000000000FFFFFFFF00010000000000000001000000000000000100000001807B8A000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF0000000000000000000100000000000000010000000180D3B0000000000000FFFFFFFF000100000000000000010000000000000001000000018015B1000000000000FFFFFFFF0001000000000000000100000000000000010000000180F4B0000000000000FFFFFFFF000100000000000000010000000000000001000000018036B1000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF0000000000000000000100000000000000010000000180FF88000000000000FFFFFFFF0001000000000000000100000000000000010000000180FE88000000000000FFFFFFFF00010000000000000001000000000000000100000001800B81000000000000FFFFFFFF00010000000000000001000000000000000100000001800C81000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF0000000000000000000100000000000000010000000180F088000000000000FFFFFFFF0001000000000000000100000000000000010000000180EE7F000000000000FFFFFFFF000100000000000000010000000000000001000000018024E1000000000000FFFFFFFF00010000000000000001000000000000000100000001800A81000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001802280000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF0000000000000000000100000000000000010000000180C488000000000000FFFFFFFF0001000000000000000100000000000000010000000180C988000000000000FFFFFFFF0001000000000000000100000000000000010000000180C788000000000000FFFFFFFF0001000000000000000100000000000000010000000180C888000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF0000000000000000000100000000000000010000000180DD88000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF0000000000000000000100000000000000010000000180FB7F000000000000FFFFFFFF000100000000000000010000000000000001000000 - - - 1423 - 2800FFFF01001100434D4643546F6F6C426172427574746F6E00E100000000000000000000000000000000000000000000000100000001000000018001E100000000000001000000000000000000000000000000000100000001000000018003E1000000000000020000000000000000000000000000000001000000010000000180CD7F0000000000000300000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018023E100000000000004000000000000000000000000000000000100000001000000018022E100000000000005000000000000000000000000000000000100000001000000018025E10000000000000600000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001802BE10000000000000700000000000000000000000000000000010000000100000001802CE10000000000000800000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001807A8A0000000000000900000000000000000000000000000000010000000100000001807B8A0000000000000A00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180D3B00000000000000B000000000000000000000000000000000100000001000000018015B10000000000000C0000000000000000000000000000000001000000010000000180F4B00000000000000D000000000000000000000000000000000100000001000000018036B10000000000000E00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180FF880000000000000F0000000000000000000000000000000001000000010000000180FE880000000000001000000000000000000000000000000000010000000100000001800B810000000000001100000000000000000000000000000000010000000100000001800C810000000000001200000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180F088000000000000130000000000000000000000000000000001000000010000000180EE7F00000000000014000000000000000000000000000000000100000001000000018024E10000000000001500000000000000000000000000000000010000000100000001800A810000000000001600000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018022800000000000001700000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180C488000000000000180000000000000000000000000000000001000000010000000180C988000000000000190000000000000000000000000000000001000000010000000180C7880000000000001A0000000000000000000000000000000001000000010000000180C8880000000000001B00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180DD880000000000001C00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180FB7F0000000000001D000000000000000000000000000000000100000001000000 - - - - 59399 - Build - - 1000 - 00200000010000001000FFFF01001100434D4643546F6F6C426172427574746F6ECF7F0000000004001C0000000000000000000000000000000001000000010000000180D07F0000000000001D000000000000000000000000000000000100000001000000018030800000000000001E000000000000000000000000000000000100000001000000FFFF01001500434D4643546F6F6C4261724D656E75427574746F6EC7040000000000006A0000000C4261746368204275696C2664000000000000000000000000010000000100000000000000000000000100000004000580C7040000000000006A0000000C4261746368204275696C266400000000000000000000000001000000010000000000000000000000010000000000058046070000000000006B0000000D42617463682052656275696C640000000000000000000000000100000001000000000000000000000001000000000005804707000000000000FFFFFFFF0B426174636820436C65616E0100000000000000000000000100000001000000000000000000000001000000000005809E8A0000000000001F0000000F4261746326682053657475702E2E2E000000000000000000000000010000000100000000000000000000000100000000000180D17F0000000004002000000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001804C8A0000000004002100000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000FFFF01001900434D4643546F6F6C426172436F6D626F426F78427574746F6EBA0000000000000000000000000000000000000000000000000100000001000000960000000300205000000000144656502053696D756C6174696F6E204D6F64656C96000000000000000100144656502053696D756C6174696F6E204D6F64656C000000000180EB880000000000002200000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180C07F000000000000230000000000000000000000000000000001000000010000000180B08A000000000000240000000000000000000000000000000001000000010000000180A8010000000000004E00000000000000000000000000000000010000000100000001807202000000000000530000000000000000000000000000000001000000010000000180BE010000000000005000000000000000000000000000000000010000000100000000000000054275696C642F010000 - - - 583 - 1000FFFF01001100434D4643546F6F6C426172427574746F6ECF7F000000000000FFFFFFFF0001000000000000000100000000000000010000000180D07F000000000000FFFFFFFF00010000000000000001000000000000000100000001803080000000000000FFFFFFFF00010000000000000001000000000000000100000001809E8A000000000000FFFFFFFF0001000000000000000100000000000000010000000180D17F000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001804C8A000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001806680000000000000FFFFFFFF0001000000000000000100000000000000010000000180EB88000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF0000000000000000000100000000000000010000000180C07F000000000000FFFFFFFF0001000000000000000100000000000000010000000180B08A000000000000FFFFFFFF0001000000000000000100000000000000010000000180A801000000000000FFFFFFFF00010000000000000001000000000000000100000001807202000000000000FFFFFFFF0001000000000000000100000000000000010000000180BE01000000000000FFFFFFFF000100000000000000010000000000000001000000 - - - 583 - 1000FFFF01001100434D4643546F6F6C426172427574746F6ECF7F000000000000000000000000000000000000000000000001000000010000000180D07F00000000000001000000000000000000000000000000000100000001000000018030800000000000000200000000000000000000000000000000010000000100000001809E8A000000000000030000000000000000000000000000000001000000010000000180D17F0000000000000400000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001804C8A0000000000000500000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001806680000000000000060000000000000000000000000000000001000000010000000180EB880000000000000700000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180C07F000000000000080000000000000000000000000000000001000000010000000180B08A000000000000090000000000000000000000000000000001000000010000000180A8010000000000000A000000000000000000000000000000000100000001000000018072020000000000000B0000000000000000000000000000000001000000010000000180BE010000000000000C000000000000000000000000000000000100000001000000 - - - - 59400 - Debug - - 2373 - 00200000000000001900FFFF01001100434D4643546F6F6C426172427574746F6ECC880000000000002500000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018017800000000000002600000000000000000000000000000000010000000100000001801D800000000000002700000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001801A800000000000002800000000000000000000000000000000010000000100000001801B80000000000000290000000000000000000000000000000001000000010000000180E57F0000000000002A00000000000000000000000000000000010000000100000001801C800000000000002B00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018000890000000000002C00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180E48B0000000000002D0000000000000000000000000000000001000000010000000180F07F0000000000002E0000000000000000000000000000000001000000010000000180E8880000000000003700000000000000000000000000000000010000000100000001803B010000000000002F0000000000000000000000000000000001000000010000000180BB8A00000000000030000000000000000000000000000000000100000001000000FFFF01001500434D4643546F6F6C4261724D656E75427574746F6E0E01000000000000310000000D57617463682057696E646F7773000000000000000000000000010000000100000000000000000000000100000003001380D88B00000000000031000000085761746368202631000000000000000000000000010000000100000000000000000000000100000000001380D98B00000000000031000000085761746368202632000000000000000000000000010000000100000000000000000000000100000000001380CE01000000000000FFFFFFFF0C576174636820416E63686F720000000000000000010000000000000001000000000000000000000001000000000013800F01000000000000320000000E4D656D6F72792057696E646F7773000000000000000000000000010000000100000000000000000000000100000004001380D28B00000000000032000000094D656D6F7279202631000000000000000000000000010000000100000000000000000000000100000000001380D38B00000000000032000000094D656D6F7279202632000000000000000000000000010000000100000000000000000000000100000000001380D48B00000000000032000000094D656D6F7279202633000000000000000000000000010000000100000000000000000000000100000000001380D58B00000000000032000000094D656D6F72792026340000000000000000000000000100000001000000000000000000000001000000000013801001000000000000330000000E53657269616C2057696E646F77730000000000000000000000000100000001000000000000000000000001000000040013809307000000000000330000000855415254202326310000000000000000000000000100000001000000000000000000000001000000000013809407000000000000330000000855415254202326320000000000000000000000000100000001000000000000000000000001000000000013809507000000000000330000000855415254202326330000000000000000000000000100000001000000000000000000000001000000000013809607000000000000330000001626446562756720287072696E746629205669657765720000000000000000000000000100000001000000000000000000000001000000000013803C010000000000003400000010416E616C797369732057696E646F7773000000000000000000000000010000000100000000000000000000000100000004001380658A000000000000340000000F264C6F67696320416E616C797A6572000000000000000000000000010000000100000000000000000000000100000000001380DC7F0000000000003E0000001526506572666F726D616E636520416E616C797A6572000000000000000000000000010000000100000000000000000000000100000000001380E788000000000000380000000E26436F646520436F766572616765000000000000000000000000010000000100000000000000000000000100000000001380CD01000000000000FFFFFFFF0F416E616C7973697320416E63686F7200000000000000000100000000000000010000000000000000000000010000000000138053010000000000003F0000000D54726163652057696E646F77730000000000000000000000000100000001000000000000000000000001000000010013805401000000000000FFFFFFFF115472616365204D656E7520416E63686F720000000000000000010000000000000001000000000000000000000001000000000013802901000000000000350000001553797374656D205669657765722057696E646F77730000000000000000000000000100000001000000000000000000000001000000010013804B01000000000000FFFFFFFF1453797374656D2056696577657220416E63686F720000000000000000010000000000000001000000000000000000000001000000000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000013800189000000000000360000000F26546F6F6C626F782057696E646F7700000000000000000000000001000000010000000000000000000000010000000300138044C5000000000000FFFFFFFF0E5570646174652057696E646F77730000000000000000010000000000000001000000000000000000000001000000000013800000000000000400FFFFFFFF000000000000000000010000000000000001000000000000000000000001000000000013805B01000000000000FFFFFFFF12546F6F6C626F78204D656E75416E63686F72000000000000000001000000000000000100000000000000000000000100000000000000000005446562756764020000 - - - 898 - 1900FFFF01001100434D4643546F6F6C426172427574746F6ECC88000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001801780000000000000FFFFFFFF00010000000000000001000000000000000100000001801D80000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001801A80000000000000FFFFFFFF00010000000000000001000000000000000100000001801B80000000000000FFFFFFFF0001000000000000000100000000000000010000000180E57F000000000000FFFFFFFF00010000000000000001000000000000000100000001801C80000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001800089000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF0000000000000000000100000000000000010000000180E48B000000000000FFFFFFFF0001000000000000000100000000000000010000000180F07F000000000000FFFFFFFF0001000000000000000100000000000000010000000180E888000000000000FFFFFFFF00010000000000000001000000000000000100000001803B01000000000000FFFFFFFF0001000000000000000100000000000000010000000180BB8A000000000000FFFFFFFF0001000000000000000100000000000000010000000180D88B000000000000FFFFFFFF0001000000000000000100000000000000010000000180D28B000000000000FFFFFFFF00010000000000000001000000000000000100000001809307000000000000FFFFFFFF0001000000000000000100000000000000010000000180658A000000000000FFFFFFFF0001000000000000000100000000000000010000000180C18A000000000000FFFFFFFF0001000000000000000100000000000000010000000180EE8B000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001800189000000000000FFFFFFFF000100000000000000010000000000000001000000 - - - 898 - 1900FFFF01001100434D4643546F6F6C426172427574746F6ECC880000000000000000000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018017800000000000000100000000000000000000000000000000010000000100000001801D800000000000000200000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001801A800000000000000300000000000000000000000000000000010000000100000001801B80000000000000040000000000000000000000000000000001000000010000000180E57F0000000000000500000000000000000000000000000000010000000100000001801C800000000000000600000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018000890000000000000700000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180E48B000000000000080000000000000000000000000000000001000000010000000180F07F000000000000090000000000000000000000000000000001000000010000000180E8880000000000000A00000000000000000000000000000000010000000100000001803B010000000000000B0000000000000000000000000000000001000000010000000180BB8A0000000000000C0000000000000000000000000000000001000000010000000180D88B0000000000000D0000000000000000000000000000000001000000010000000180D28B0000000000000E000000000000000000000000000000000100000001000000018093070000000000000F0000000000000000000000000000000001000000010000000180658A000000000000100000000000000000000000000000000001000000010000000180C18A000000000000110000000000000000000000000000000001000000010000000180EE8B0000000000001200000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180018900000000000013000000000000000000000000000000000100000001000000 - - - - 0 - 1920 - 1080 - - - - - - 1 - 0 - - 100 - 0 - - <1>.\Abstract.txt - 0 - 1 - 1 - 0 - - 0 - - - - -
diff --git a/ports/cortex_m55/ac6/example_build/ThreadX_Library.uvoptx b/ports/cortex_m55/ac6/example_build/ThreadX_Library.uvoptx deleted file mode 100644 index 8300b5907..000000000 --- a/ports/cortex_m55/ac6/example_build/ThreadX_Library.uvoptx +++ /dev/null @@ -1,2576 +0,0 @@ - - - - 1.0 - -
### uVision Project, (C) Keil Software
- - - *.c - *.s*; *.src; *.a* - *.obj; *.o - *.lib - *.txt; *.h; *.inc; *.md - *.plm - *.cpp - 0 - - - - 0 - 0 - - - - ThreadX_Library_Project - 0x4 - ARM-ADS - - 12000000 - - 1 - 1 - 0 - 1 - 0 - - - 1 - 65535 - 0 - 0 - 0 - - - 79 - 66 - 8 - .\ - - - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - - - 0 - 0 - 1 - - 7 - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 1 - 1 - 0 - 0 - 1 - 0 - 0 - 13 - - - - - - - - - - - BIN\UL2V8M.DLL - - - - 0 - UL2V8M - UL2V8M(-S0 -C0 -P0 -FC1000 -FD30000000 - - - - - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - - - - - - - - - - - - - Source Group - 1 - 0 - 0 - 0 - - 1 - 1 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_allocate.c - tx_block_allocate.c - 0 - 0 - - - 1 - 2 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_cleanup.c - tx_block_pool_cleanup.c - 0 - 0 - - - 1 - 3 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_create.c - tx_block_pool_create.c - 0 - 0 - - - 1 - 4 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_delete.c - tx_block_pool_delete.c - 0 - 0 - - - 1 - 5 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_info_get.c - tx_block_pool_info_get.c - 0 - 0 - - - 1 - 6 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_initialize.c - tx_block_pool_initialize.c - 0 - 0 - - - 1 - 7 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_performance_info_get.c - tx_block_pool_performance_info_get.c - 0 - 0 - - - 1 - 8 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_performance_system_info_get.c - tx_block_pool_performance_system_info_get.c - 0 - 0 - - - 1 - 9 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_prioritize.c - tx_block_pool_prioritize.c - 0 - 0 - - - 1 - 10 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_release.c - tx_block_release.c - 0 - 0 - - - 1 - 11 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_allocate.c - tx_byte_allocate.c - 0 - 0 - - - 1 - 12 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_cleanup.c - tx_byte_pool_cleanup.c - 0 - 0 - - - 1 - 13 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_create.c - tx_byte_pool_create.c - 0 - 0 - - - 1 - 14 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_delete.c - tx_byte_pool_delete.c - 0 - 0 - - - 1 - 15 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_info_get.c - tx_byte_pool_info_get.c - 0 - 0 - - - 1 - 16 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_initialize.c - tx_byte_pool_initialize.c - 0 - 0 - - - 1 - 17 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_performance_info_get.c - tx_byte_pool_performance_info_get.c - 0 - 0 - - - 1 - 18 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_performance_system_info_get.c - tx_byte_pool_performance_system_info_get.c - 0 - 0 - - - 1 - 19 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_prioritize.c - tx_byte_pool_prioritize.c - 0 - 0 - - - 1 - 20 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_search.c - tx_byte_pool_search.c - 0 - 0 - - - 1 - 21 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_release.c - tx_byte_release.c - 0 - 0 - - - 1 - 22 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_cleanup.c - tx_event_flags_cleanup.c - 0 - 0 - - - 1 - 23 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_create.c - tx_event_flags_create.c - 0 - 0 - - - 1 - 24 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_delete.c - tx_event_flags_delete.c - 0 - 0 - - - 1 - 25 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_get.c - tx_event_flags_get.c - 0 - 0 - - - 1 - 26 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_info_get.c - tx_event_flags_info_get.c - 0 - 0 - - - 1 - 27 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_initialize.c - tx_event_flags_initialize.c - 0 - 0 - - - 1 - 28 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_performance_info_get.c - tx_event_flags_performance_info_get.c - 0 - 0 - - - 1 - 29 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_performance_system_info_get.c - tx_event_flags_performance_system_info_get.c - 0 - 0 - - - 1 - 30 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_set.c - tx_event_flags_set.c - 0 - 0 - - - 1 - 31 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_set_notify.c - tx_event_flags_set_notify.c - 0 - 0 - - - 1 - 32 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_initialize_high_level.c - tx_initialize_high_level.c - 0 - 0 - - - 1 - 33 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_initialize_kernel_enter.c - tx_initialize_kernel_enter.c - 0 - 0 - - - 1 - 34 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_initialize_kernel_setup.c - tx_initialize_kernel_setup.c - 0 - 0 - - - 1 - 35 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_cleanup.c - tx_mutex_cleanup.c - 0 - 0 - - - 1 - 36 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_create.c - tx_mutex_create.c - 0 - 0 - - - 1 - 37 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_delete.c - tx_mutex_delete.c - 0 - 0 - - - 1 - 38 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_get.c - tx_mutex_get.c - 0 - 0 - - - 1 - 39 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_info_get.c - tx_mutex_info_get.c - 0 - 0 - - - 1 - 40 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_initialize.c - tx_mutex_initialize.c - 0 - 0 - - - 1 - 41 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_performance_info_get.c - tx_mutex_performance_info_get.c - 0 - 0 - - - 1 - 42 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_performance_system_info_get.c - tx_mutex_performance_system_info_get.c - 0 - 0 - - - 1 - 43 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_prioritize.c - tx_mutex_prioritize.c - 0 - 0 - - - 1 - 44 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_priority_change.c - tx_mutex_priority_change.c - 0 - 0 - - - 1 - 45 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_put.c - tx_mutex_put.c - 0 - 0 - - - 1 - 46 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_cleanup.c - tx_queue_cleanup.c - 0 - 0 - - - 1 - 47 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_create.c - tx_queue_create.c - 0 - 0 - - - 1 - 48 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_delete.c - tx_queue_delete.c - 0 - 0 - - - 1 - 49 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_flush.c - tx_queue_flush.c - 0 - 0 - - - 1 - 50 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_front_send.c - tx_queue_front_send.c - 0 - 0 - - - 1 - 51 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_info_get.c - tx_queue_info_get.c - 0 - 0 - - - 1 - 52 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_initialize.c - tx_queue_initialize.c - 0 - 0 - - - 1 - 53 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_performance_info_get.c - tx_queue_performance_info_get.c - 0 - 0 - - - 1 - 54 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_performance_system_info_get.c - tx_queue_performance_system_info_get.c - 0 - 0 - - - 1 - 55 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_prioritize.c - tx_queue_prioritize.c - 0 - 0 - - - 1 - 56 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_receive.c - tx_queue_receive.c - 0 - 0 - - - 1 - 57 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_send.c - tx_queue_send.c - 0 - 0 - - - 1 - 58 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_send_notify.c - tx_queue_send_notify.c - 0 - 0 - - - 1 - 59 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_ceiling_put.c - tx_semaphore_ceiling_put.c - 0 - 0 - - - 1 - 60 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_cleanup.c - tx_semaphore_cleanup.c - 0 - 0 - - - 1 - 61 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_create.c - tx_semaphore_create.c - 0 - 0 - - - 1 - 62 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_delete.c - tx_semaphore_delete.c - 0 - 0 - - - 1 - 63 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_get.c - tx_semaphore_get.c - 0 - 0 - - - 1 - 64 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_info_get.c - tx_semaphore_info_get.c - 0 - 0 - - - 1 - 65 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_initialize.c - tx_semaphore_initialize.c - 0 - 0 - - - 1 - 66 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_performance_info_get.c - tx_semaphore_performance_info_get.c - 0 - 0 - - - 1 - 67 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_performance_system_info_get.c - tx_semaphore_performance_system_info_get.c - 0 - 0 - - - 1 - 68 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_prioritize.c - tx_semaphore_prioritize.c - 0 - 0 - - - 1 - 69 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_put.c - tx_semaphore_put.c - 0 - 0 - - - 1 - 70 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_put_notify.c - tx_semaphore_put_notify.c - 0 - 0 - - - 1 - 71 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_create.c - tx_thread_create.c - 0 - 0 - - - 1 - 72 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_delete.c - tx_thread_delete.c - 0 - 0 - - - 1 - 73 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_entry_exit_notify.c - tx_thread_entry_exit_notify.c - 0 - 0 - - - 1 - 74 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_identify.c - tx_thread_identify.c - 0 - 0 - - - 1 - 75 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_info_get.c - tx_thread_info_get.c - 0 - 0 - - - 1 - 76 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_initialize.c - tx_thread_initialize.c - 0 - 0 - - - 1 - 77 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_performance_info_get.c - tx_thread_performance_info_get.c - 0 - 0 - - - 1 - 78 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_performance_system_info_get.c - tx_thread_performance_system_info_get.c - 0 - 0 - - - 1 - 79 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_preemption_change.c - tx_thread_preemption_change.c - 0 - 0 - - - 1 - 80 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_priority_change.c - tx_thread_priority_change.c - 0 - 0 - - - 1 - 81 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_relinquish.c - tx_thread_relinquish.c - 0 - 0 - - - 1 - 82 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_reset.c - tx_thread_reset.c - 0 - 0 - - - 1 - 83 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_resume.c - tx_thread_resume.c - 0 - 0 - - - 1 - 84 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_shell_entry.c - tx_thread_shell_entry.c - 0 - 0 - - - 1 - 85 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_sleep.c - tx_thread_sleep.c - 0 - 0 - - - 1 - 86 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_stack_analyze.c - tx_thread_stack_analyze.c - 0 - 0 - - - 1 - 87 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_suspend.c - tx_thread_suspend.c - 0 - 0 - - - 1 - 88 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_system_preempt_check.c - tx_thread_system_preempt_check.c - 0 - 0 - - - 1 - 89 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_system_resume.c - tx_thread_system_resume.c - 0 - 0 - - - 1 - 90 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_system_suspend.c - tx_thread_system_suspend.c - 0 - 0 - - - 1 - 91 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_terminate.c - tx_thread_terminate.c - 0 - 0 - - - 1 - 92 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_time_slice.c - tx_thread_time_slice.c - 0 - 0 - - - 1 - 93 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_time_slice_change.c - tx_thread_time_slice_change.c - 0 - 0 - - - 1 - 94 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_timeout.c - tx_thread_timeout.c - 0 - 0 - - - 1 - 95 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_wait_abort.c - tx_thread_wait_abort.c - 0 - 0 - - - 1 - 96 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_time_get.c - tx_time_get.c - 0 - 0 - - - 1 - 97 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_time_set.c - tx_time_set.c - 0 - 0 - - - 1 - 98 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_activate.c - tx_timer_activate.c - 0 - 0 - - - 1 - 99 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_change.c - tx_timer_change.c - 0 - 0 - - - 1 - 100 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_create.c - tx_timer_create.c - 0 - 0 - - - 1 - 101 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_deactivate.c - tx_timer_deactivate.c - 0 - 0 - - - 1 - 102 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_delete.c - tx_timer_delete.c - 0 - 0 - - - 1 - 103 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_expiration_process.c - tx_timer_expiration_process.c - 0 - 0 - - - 1 - 104 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_info_get.c - tx_timer_info_get.c - 0 - 0 - - - 1 - 105 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_initialize.c - tx_timer_initialize.c - 0 - 0 - - - 1 - 106 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_performance_info_get.c - tx_timer_performance_info_get.c - 0 - 0 - - - 1 - 107 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_performance_system_info_get.c - tx_timer_performance_system_info_get.c - 0 - 0 - - - 1 - 108 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_system_activate.c - tx_timer_system_activate.c - 0 - 0 - - - 1 - 109 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_system_deactivate.c - tx_timer_system_deactivate.c - 0 - 0 - - - 1 - 110 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_thread_entry.c - tx_timer_thread_entry.c - 0 - 0 - - - 1 - 111 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_disable.c - tx_trace_disable.c - 0 - 0 - - - 1 - 112 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_enable.c - tx_trace_enable.c - 0 - 0 - - - 1 - 113 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_initialize.c - tx_trace_initialize.c - 0 - 0 - - - 1 - 114 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_interrupt_control.c - tx_trace_interrupt_control.c - 0 - 0 - - - 1 - 115 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_isr_enter_insert.c - tx_trace_isr_enter_insert.c - 0 - 0 - - - 1 - 116 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_isr_exit_insert.c - tx_trace_isr_exit_insert.c - 0 - 0 - - - 1 - 117 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_object_register.c - tx_trace_object_register.c - 0 - 0 - - - 1 - 118 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_object_unregister.c - tx_trace_object_unregister.c - 0 - 0 - - - 1 - 119 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_user_event_insert.c - tx_trace_user_event_insert.c - 0 - 0 - - - 1 - 120 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_allocate.c - txe_block_allocate.c - 0 - 0 - - - 1 - 121 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_pool_create.c - txe_block_pool_create.c - 0 - 0 - - - 1 - 122 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_pool_delete.c - txe_block_pool_delete.c - 0 - 0 - - - 1 - 123 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_pool_info_get.c - txe_block_pool_info_get.c - 0 - 0 - - - 1 - 124 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_pool_prioritize.c - txe_block_pool_prioritize.c - 0 - 0 - - - 1 - 125 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_release.c - txe_block_release.c - 0 - 0 - - - 1 - 126 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_allocate.c - txe_byte_allocate.c - 0 - 0 - - - 1 - 127 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_pool_create.c - txe_byte_pool_create.c - 0 - 0 - - - 1 - 128 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_pool_delete.c - txe_byte_pool_delete.c - 0 - 0 - - - 1 - 129 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_pool_info_get.c - txe_byte_pool_info_get.c - 0 - 0 - - - 1 - 130 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_pool_prioritize.c - txe_byte_pool_prioritize.c - 0 - 0 - - - 1 - 131 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_release.c - txe_byte_release.c - 0 - 0 - - - 1 - 132 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_create.c - txe_event_flags_create.c - 0 - 0 - - - 1 - 133 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_delete.c - txe_event_flags_delete.c - 0 - 0 - - - 1 - 134 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_get.c - txe_event_flags_get.c - 0 - 0 - - - 1 - 135 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_info_get.c - txe_event_flags_info_get.c - 0 - 0 - - - 1 - 136 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_set.c - txe_event_flags_set.c - 0 - 0 - - - 1 - 137 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_set_notify.c - txe_event_flags_set_notify.c - 0 - 0 - - - 1 - 138 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_create.c - txe_mutex_create.c - 0 - 0 - - - 1 - 139 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_delete.c - txe_mutex_delete.c - 0 - 0 - - - 1 - 140 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_get.c - txe_mutex_get.c - 0 - 0 - - - 1 - 141 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_info_get.c - txe_mutex_info_get.c - 0 - 0 - - - 1 - 142 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_prioritize.c - txe_mutex_prioritize.c - 0 - 0 - - - 1 - 143 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_put.c - txe_mutex_put.c - 0 - 0 - - - 1 - 144 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_create.c - txe_queue_create.c - 0 - 0 - - - 1 - 145 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_delete.c - txe_queue_delete.c - 0 - 0 - - - 1 - 146 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_flush.c - txe_queue_flush.c - 0 - 0 - - - 1 - 147 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_front_send.c - txe_queue_front_send.c - 0 - 0 - - - 1 - 148 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_info_get.c - txe_queue_info_get.c - 0 - 0 - - - 1 - 149 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_prioritize.c - txe_queue_prioritize.c - 0 - 0 - - - 1 - 150 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_receive.c - txe_queue_receive.c - 0 - 0 - - - 1 - 151 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_send.c - txe_queue_send.c - 0 - 0 - - - 1 - 152 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_send_notify.c - txe_queue_send_notify.c - 0 - 0 - - - 1 - 153 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_ceiling_put.c - txe_semaphore_ceiling_put.c - 0 - 0 - - - 1 - 154 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_create.c - txe_semaphore_create.c - 0 - 0 - - - 1 - 155 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_delete.c - txe_semaphore_delete.c - 0 - 0 - - - 1 - 156 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_get.c - txe_semaphore_get.c - 0 - 0 - - - 1 - 157 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_info_get.c - txe_semaphore_info_get.c - 0 - 0 - - - 1 - 158 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_prioritize.c - txe_semaphore_prioritize.c - 0 - 0 - - - 1 - 159 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_put.c - txe_semaphore_put.c - 0 - 0 - - - 1 - 160 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_put_notify.c - txe_semaphore_put_notify.c - 0 - 0 - - - 1 - 161 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_create.c - txe_thread_create.c - 0 - 0 - - - 1 - 162 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_delete.c - txe_thread_delete.c - 0 - 0 - - - 1 - 163 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_entry_exit_notify.c - txe_thread_entry_exit_notify.c - 0 - 0 - - - 1 - 164 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_info_get.c - txe_thread_info_get.c - 0 - 0 - - - 1 - 165 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_preemption_change.c - txe_thread_preemption_change.c - 0 - 0 - - - 1 - 166 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_priority_change.c - txe_thread_priority_change.c - 0 - 0 - - - 1 - 167 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_relinquish.c - txe_thread_relinquish.c - 0 - 0 - - - 1 - 168 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_reset.c - txe_thread_reset.c - 0 - 0 - - - 1 - 169 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_resume.c - txe_thread_resume.c - 0 - 0 - - - 1 - 170 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_suspend.c - txe_thread_suspend.c - 0 - 0 - - - 1 - 171 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_terminate.c - txe_thread_terminate.c - 0 - 0 - - - 1 - 172 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_time_slice_change.c - txe_thread_time_slice_change.c - 0 - 0 - - - 1 - 173 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_wait_abort.c - txe_thread_wait_abort.c - 0 - 0 - - - 1 - 174 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_activate.c - txe_timer_activate.c - 0 - 0 - - - 1 - 175 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_change.c - txe_timer_change.c - 0 - 0 - - - 1 - 176 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_create.c - txe_timer_create.c - 0 - 0 - - - 1 - 177 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_deactivate.c - txe_timer_deactivate.c - 0 - 0 - - - 1 - 178 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_delete.c - txe_timer_delete.c - 0 - 0 - - - 1 - 179 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_info_get.c - txe_timer_info_get.c - 0 - 0 - - - 1 - 180 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_buffer_full_notify.c - tx_trace_buffer_full_notify.c - 0 - 0 - - - 1 - 181 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_event_filter.c - tx_trace_event_filter.c - 0 - 0 - - - 1 - 182 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_event_unfilter.c - tx_trace_event_unfilter.c - 0 - 0 - - - 1 - 183 - 1 - 0 - 0 - 0 - ..\src\txe_thread_secure_stack_allocate.c - txe_thread_secure_stack_allocate.c - 0 - 0 - - - 1 - 184 - 1 - 0 - 0 - 0 - ..\src\txe_thread_secure_stack_free.c - txe_thread_secure_stack_free.c - 0 - 0 - - - 1 - 185 - 2 - 0 - 0 - 0 - ..\src\tx_thread_context_restore.S - tx_thread_context_restore.S - 0 - 0 - - - 1 - 186 - 2 - 0 - 0 - 0 - ..\src\tx_thread_context_save.S - tx_thread_context_save.S - 0 - 0 - - - 1 - 187 - 2 - 0 - 0 - 0 - ..\src\tx_thread_interrupt_control.S - tx_thread_interrupt_control.S - 0 - 0 - - - 1 - 188 - 2 - 0 - 0 - 0 - ..\src\tx_thread_interrupt_disable.S - tx_thread_interrupt_disable.S - 0 - 0 - - - 1 - 189 - 2 - 0 - 0 - 0 - ..\src\tx_thread_interrupt_restore.S - tx_thread_interrupt_restore.S - 0 - 0 - - - 1 - 190 - 2 - 0 - 0 - 0 - ..\src\tx_thread_schedule.S - tx_thread_schedule.S - 0 - 0 - - - 1 - 191 - 2 - 0 - 0 - 0 - ..\src\tx_thread_secure_stack_allocate.S - tx_thread_secure_stack_allocate.S - 0 - 0 - - - 1 - 192 - 2 - 0 - 0 - 0 - ..\src\tx_thread_secure_stack_free.S - tx_thread_secure_stack_free.S - 0 - 0 - - - 1 - 193 - 2 - 0 - 0 - 0 - ..\src\tx_thread_stack_build.S - tx_thread_stack_build.S - 0 - 0 - - - 1 - 194 - 2 - 0 - 0 - 0 - ..\src\tx_thread_system_return.S - tx_thread_system_return.S - 0 - 0 - - - 1 - 195 - 2 - 0 - 0 - 0 - ..\src\tx_timer_interrupt.S - tx_timer_interrupt.S - 0 - 0 - - - 1 - 196 - 2 - 0 - 0 - 0 - .\tx_initialize_low_level.S - tx_initialize_low_level.S - 0 - 0 - - - 1 - 197 - 2 - 0 - 0 - 0 - ..\src\tx_thread_secure_stack_initialize.S - tx_thread_secure_stack_initialize.S - 0 - 0 - - - 1 - 198 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_stack_error_handler.c - tx_thread_stack_error_handler.c - 0 - 0 - - - 1 - 199 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_stack_error_notify.c - tx_thread_stack_error_notify.c - 0 - 0 - - - - - ::CMSIS - 0 - 0 - 0 - 1 - - -
diff --git a/ports/cortex_m55/ac6/example_build/demo_secure_zone/demo_secure_zone.uvoptx b/ports/cortex_m55/ac6/example_build/demo_secure_zone/demo_secure_zone.uvoptx deleted file mode 100644 index 92bdbefe4..000000000 --- a/ports/cortex_m55/ac6/example_build/demo_secure_zone/demo_secure_zone.uvoptx +++ /dev/null @@ -1,366 +0,0 @@ - - - - 1.0 - -
### uVision Project, (C) Keil Software
- - - *.c - *.s*; *.src; *.a* - *.obj; *.o - *.lib - *.txt; *.h; *.inc; *.md - *.plm - *.cpp - 0 - - - - 0 - 0 - - - - FVP Simulation Model - 0x4 - ARM-ADS - - 12000000 - - 1 - 1 - 0 - 1 - 0 - - - 1 - 65535 - 0 - 0 - 0 - - - 79 - 66 - 8 - .\Listings\ - - - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - - - 1 - 0 - 1 - - 7 - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - 1 - 1 - 1 - 0 - 1 - 1 - 1 - 1 - 0 - 0 - 1 - 0 - 0 - 15 - - - - - - - - - - ..\Debug.ini - BIN\DbgFMv8M.DLL - - - - 0 - UL2V8M - UL2V8M(-S0 -C0 -P0 -FC1000 -FD01000000 - - - 0 - DbgFMv8M - -I -S"System Generator:cpu_core" -L"cpu0" -O4102 -C0 -MC"$K\ARM\VHT\VHT_MPS3_Corstone_SSE-300.exe" -MF"..\CS300_config.txt" -PF -MA - - - 0 - DLGTARM - (6010=-1,-1,-1,-1,0)(6018=-1,-1,-1,-1,0)(6019=-1,-1,-1,-1,0)(6008=-1,-1,-1,-1,0)(6009=-1,-1,-1,-1,0)(6014=4619,189,4877,920,0)(6015=3743,140,4001,762,0)(6003=-1,-1,-1,-1,0)(6000=4424,206,4877,538,0)(6020=-1,-1,-1,-1,0) - - - 0 - ARMDBGFLAGS - - - - 0 - DLGUARM - (105=-1,-1,-1,-1,0)(106=-1,-1,-1,-1,0)(107=-1,-1,-1,-1,0) - - - - - 0 - 0 - 48 - 1 -
268439734
- 0 - 0 - 0 - 0 - 0 - 1 - <1>.\main_s.c - - \\secure_app\main_s.c\48 -
-
- - - 0 - 1 - thread_0_counter - - - 1 - 1 - thread_1_counter - - - 2 - 1 - thread_2_counter - - - 3 - 1 - thread_3_counter - - - 4 - 1 - thread_4_counter - - - 5 - 1 - thread_5_counter - - - 6 - 1 - thread_6_counter - - - 7 - 1 - thread_7_counter - - - - - 1 - 2 - 0x01000400 - 0 - - - - 0 - - - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - - - - - - - - - - 1 - 1 - 0 - 2 - 10000000 - -
-
- - - Secure Code - 1 - 0 - 0 - 0 - - 1 - 1 - 1 - 0 - 0 - 0 - .\main_s.c - main_s.c - 0 - 0 - - - 1 - 2 - 1 - 0 - 0 - 0 - ..\..\src\tx_thread_secure_stack.c - tx_thread_secure_stack.c - 0 - 0 - - - 1 - 3 - 2 - 0 - 0 - 0 - ..\..\src\tx_thread_interrupt_disable.S - tx_thread_interrupt_disable.S - 0 - 0 - - - 1 - 4 - 2 - 0 - 0 - 0 - ..\..\src\tx_thread_interrupt_restore.S - tx_thread_interrupt_restore.S - 0 - 0 - - - - - Interface - 1 - 0 - 0 - 0 - - 2 - 5 - 1 - 0 - 0 - 0 - .\interface.c - interface.c - 0 - 0 - - - - - ::CMSIS - 0 - 0 - 0 - 1 - - - - ::Device - 0 - 0 - 0 - 1 - - - - ::Native Driver - 0 - 0 - 0 - 1 - - -
diff --git a/ports/cortex_m55/ac6/example_build/demo_threadx_non-secure_zone/ThreadX_Demo.uvopt b/ports/cortex_m55/ac6/example_build/demo_threadx_non-secure_zone/ThreadX_Demo.uvopt deleted file mode 100644 index 7ec4b36b6..000000000 --- a/ports/cortex_m55/ac6/example_build/demo_threadx_non-secure_zone/ThreadX_Demo.uvopt +++ /dev/null @@ -1,305 +0,0 @@ - - - - 1.0 - -
### uVision Project, (C) Keil Software
- - - *.c - *.s*; *.src; *.a* - *.obj; *.o - *.lib - *.txt; *.h; *.inc - *.plm - *.cpp - 0 - - - - 0 - 0 - - - - ThreadX_Demo - 0x4 - ARM-ADS - - 12000000 - - 1 - 1 - 1 - 0 - 0 - - - 1 - 65535 - 0 - 0 - 0 - - - 79 - 66 - 8 - .\ - - - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - - - 1 - 0 - 1 - - 255 - - 1 - 0 - 1 - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 1 - 0 - 1 - 0 - 1 - 1 - 0 - 0 - 1 - 0 - 0 - -1 - - - - - - - - - - - - - - - 0 - ARMRTXEVENTFLAGS - -L70 -Z18 -C0 -M0 -T1 - - - 0 - DLGDARM - (1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0) - - - 0 - DLGUARM - (105=-1,-1,-1,-1,0)(106=-1,-1,-1,-1,0)(107=-1,-1,-1,-1,0) - - - 0 - DLGTARM - (1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0)(110=-1,-1,-1,-1,0)(100=-1,-1,-1,-1,0)(101=-1,-1,-1,-1,0)(102=-1,-1,-1,-1,0)(103=-1,-1,-1,-1,0)(104=-1,-1,-1,-1,0)(105=-1,-1,-1,-1,0)(106=-1,-1,-1,-1,0)(107=-1,-1,-1,-1,0)(161=-1,-1,-1,-1,0)(162=-1,-1,-1,-1,0)(163=-1,-1,-1,-1,0)(164=-1,-1,-1,-1,0)(150=-1,-1,-1,-1,0)(151=-1,-1,-1,-1,0)(152=-1,-1,-1,-1,0)(1011=-1,-1,-1,-1,0)(1012=-1,-1,-1,-1,0)(1013=-1,-1,-1,-1,0)(171=-1,-1,-1,-1,0)(172=-1,-1,-1,-1,0)(173=-1,-1,-1,-1,0)(1014=-1,-1,-1,-1,0)(1016=-1,-1,-1,-1,0)(136=-1,-1,-1,-1,0) - - - 0 - ARMDBGFLAGS - -T5F - - - 0 - UL2CM3 - -UV0289BJE -O14 -S0 -C0 -N00("ARM CoreSight JTAG-DP") -D00(3BA00477) -L00(4) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO7 -FD20000000 -FC800 -FN1 -FF0LM3S_16 -FS00 -FL04000 - - - - - - 0 - 1 - thread_0_counter - - - 1 - 1 - thread_1_counter - - - 2 - 1 - thread_2_counter - - - 3 - 1 - thread_3_counter - - - 4 - 1 - thread_4_counter - - - 5 - 1 - thread_5_counter - - - 6 - 1 - _tx_thread_current_ptr - - - - 0 - - - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - - - - - - - - - - - - - Source Group - 1 - 0 - 0 - 0 - - 1 - 1 - 2 - 0 - 0 - 0 - .\tx_initialize_low_level.s - tx_initialize_low_level.s - 0 - 0 - - - 1 - 2 - 1 - 1 - 0 - 0 - .\demo_threadx.c - demo_threadx.c - 0 - 0 - - 44 - 0 - 1 - - -1 - -1 - - - -1 - -1 - - - 56 - 12 - 1633 - 671 - - - - - - - Library_Group - 1 - 0 - 0 - 0 - - 2 - 3 - 4 - 0 - 0 - 0 - .\ThreadX_Library.lib - ThreadX_Library.lib - 0 - 0 - - - -
diff --git a/ports/cortex_m55/ac6/example_build/demo_threadx_non-secure_zone/demo_threadx_non-secure_zone.uvoptx b/ports/cortex_m55/ac6/example_build/demo_threadx_non-secure_zone/demo_threadx_non-secure_zone.uvoptx deleted file mode 100644 index dc8990d28..000000000 --- a/ports/cortex_m55/ac6/example_build/demo_threadx_non-secure_zone/demo_threadx_non-secure_zone.uvoptx +++ /dev/null @@ -1,342 +0,0 @@ - - - - 1.0 - -
### uVision Project, (C) Keil Software
- - - *.c - *.s*; *.src; *.a* - *.obj - *.lib - *.txt; *.h; *.inc; *.md - *.plm - *.cpp - 0 - - - - 0 - 0 - - - - FVP Simulation Model - 0x4 - ARM-ADS - - 12000000 - - 1 - 1 - 0 - 1 - 0 - - - 1 - 65535 - 0 - 0 - 0 - - - 79 - 66 - 8 - .\Listings\ - - - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - - - 1 - 0 - 1 - - 7 - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - 1 - 1 - 1 - 0 - 1 - 1 - 1 - 1 - 0 - 0 - 1 - 0 - 0 - 15 - - - - - - - - - - ..\Debug.ini - BIN\DbgFMv8M.DLL - - - - 0 - UL2V8M - UL2V8M(-S0 -C0 -P0 -FC1000 -FD01000000 - - - 0 - DbgFMv8M - -I -S -L"cpu0" -O4102 -C0 -MC"$K\ARM\VHT\VHT_MPS3_Corstone_SSE-300.exe" -MF"..\CS300_config.txt" -PF -MA - - - 0 - PWSTATINFO - 200,50,700 - - - 0 - DLGTARM - (6010=-1,-1,-1,-1,0)(6018=-1,-1,-1,-1,0)(6019=-1,-1,-1,-1,0)(6008=-1,-1,-1,-1,0)(6009=-1,-1,-1,-1,0)(6014=-1,-1,-1,-1,0)(6015=-1,-1,-1,-1,0)(6003=-1,-1,-1,-1,0)(6000=-1,-1,-1,-1,0)(6020=-1,-1,-1,-1,0) - - - 0 - ARMDBGFLAGS - - - - 0 - DLGUARM - (105=-1,-1,-1,-1,0)(106=-1,-1,-1,-1,0)(107=-1,-1,-1,-1,0) - - - - - - 0 - 1 - thread_0_counter - - - 1 - 1 - thread_1_counter - - - 2 - 1 - thread_2_counter - - - 3 - 1 - thread_3_counter - - - 4 - 1 - thread_4_counter - - - 5 - 1 - thread_5_counter - - - 6 - 1 - thread_6_counter - - - 7 - 1 - thread_7_counter - - - - - 1 - 2 - 0x00040400 - 0 - - - - 0 - - - 0 - 1 - 1 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - - - - - - - - - - 1 - 1 - 0 - 2 - 10000000 - - - - - - Non-secure Code - 1 - 0 - 0 - 0 - - 1 - 1 - 1 - 0 - 0 - 0 - .\demo_threadx.c - demo_threadx.c - 0 - 0 - - - 1 - 2 - 4 - 0 - 0 - 0 - ..\ThreadX_Library.lib - ThreadX_Library.lib - 0 - 0 - - - - - CMSE Library - 1 - 0 - 0 - 0 - - 2 - 3 - 5 - 0 - 0 - 0 - ..\demo_secure_zone\interface.h - interface.h - 0 - 0 - - - 2 - 4 - 3 - 0 - 0 - 0 - ..\demo_secure_zone\Objects\demo_secure_zone_CMSE_Lib.o - demo_secure_zone_CMSE_Lib.o - 0 - 0 - - - - - ::CMSIS - 0 - 0 - 0 - 1 - - - - ::Device - 0 - 0 - 0 - 1 - - - - ::Native Driver - 0 - 0 - 0 - 1 - - -
diff --git a/ports_module/cortex_m23/ac6/example_build/ThreadX_Library.uvoptx b/ports_module/cortex_m23/ac6/example_build/ThreadX_Library.uvoptx deleted file mode 100644 index 2964aed90..000000000 --- a/ports_module/cortex_m23/ac6/example_build/ThreadX_Library.uvoptx +++ /dev/null @@ -1,2972 +0,0 @@ - - - - 1.0 - -
### uVision Project, (C) Keil Software
- - - *.c - *.s*; *.src; *.a* - *.obj; *.o - *.lib - *.txt; *.h; *.inc - *.plm - *.cpp - 0 - - - - 0 - 0 - - - - ThreadX_Library_Project - 0x4 - ARM-ADS - - 12000000 - - 1 - 1 - 0 - 1 - 0 - - - 1 - 65535 - 0 - 0 - 0 - - - 79 - 66 - 8 - .\ - - - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - - - 1 - 0 - 1 - - 7 - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 1 - 1 - 0 - 0 - 1 - 0 - 0 - 13 - - - - - - - - - - - BIN\UL2V8M.DLL - - - - 0 - UL2V8M - UL2V8M(-S0 -C0 -P0 -FC1000 -FD20000000 - - - - - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - - - - - - - - - - - - - Source Group - 0 - 0 - 0 - 0 - - 1 - 1 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_allocate.c - tx_block_allocate.c - 0 - 0 - - - 1 - 2 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_cleanup.c - tx_block_pool_cleanup.c - 0 - 0 - - - 1 - 3 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_create.c - tx_block_pool_create.c - 0 - 0 - - - 1 - 4 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_delete.c - tx_block_pool_delete.c - 0 - 0 - - - 1 - 5 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_info_get.c - tx_block_pool_info_get.c - 0 - 0 - - - 1 - 6 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_initialize.c - tx_block_pool_initialize.c - 0 - 0 - - - 1 - 7 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_performance_info_get.c - tx_block_pool_performance_info_get.c - 0 - 0 - - - 1 - 8 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_performance_system_info_get.c - tx_block_pool_performance_system_info_get.c - 0 - 0 - - - 1 - 9 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_prioritize.c - tx_block_pool_prioritize.c - 0 - 0 - - - 1 - 10 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_release.c - tx_block_release.c - 0 - 0 - - - 1 - 11 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_allocate.c - tx_byte_allocate.c - 0 - 0 - - - 1 - 12 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_cleanup.c - tx_byte_pool_cleanup.c - 0 - 0 - - - 1 - 13 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_create.c - tx_byte_pool_create.c - 0 - 0 - - - 1 - 14 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_delete.c - tx_byte_pool_delete.c - 0 - 0 - - - 1 - 15 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_info_get.c - tx_byte_pool_info_get.c - 0 - 0 - - - 1 - 16 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_initialize.c - tx_byte_pool_initialize.c - 0 - 0 - - - 1 - 17 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_performance_info_get.c - tx_byte_pool_performance_info_get.c - 0 - 0 - - - 1 - 18 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_performance_system_info_get.c - tx_byte_pool_performance_system_info_get.c - 0 - 0 - - - 1 - 19 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_prioritize.c - tx_byte_pool_prioritize.c - 0 - 0 - - - 1 - 20 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_search.c - tx_byte_pool_search.c - 0 - 0 - - - 1 - 21 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_release.c - tx_byte_release.c - 0 - 0 - - - 1 - 22 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_cleanup.c - tx_event_flags_cleanup.c - 0 - 0 - - - 1 - 23 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_create.c - tx_event_flags_create.c - 0 - 0 - - - 1 - 24 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_delete.c - tx_event_flags_delete.c - 0 - 0 - - - 1 - 25 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_get.c - tx_event_flags_get.c - 0 - 0 - - - 1 - 26 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_info_get.c - tx_event_flags_info_get.c - 0 - 0 - - - 1 - 27 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_initialize.c - tx_event_flags_initialize.c - 0 - 0 - - - 1 - 28 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_performance_info_get.c - tx_event_flags_performance_info_get.c - 0 - 0 - - - 1 - 29 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_performance_system_info_get.c - tx_event_flags_performance_system_info_get.c - 0 - 0 - - - 1 - 30 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_set.c - tx_event_flags_set.c - 0 - 0 - - - 1 - 31 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_set_notify.c - tx_event_flags_set_notify.c - 0 - 0 - - - 1 - 32 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_initialize_high_level.c - tx_initialize_high_level.c - 0 - 0 - - - 1 - 33 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_initialize_kernel_enter.c - tx_initialize_kernel_enter.c - 0 - 0 - - - 1 - 34 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_initialize_kernel_setup.c - tx_initialize_kernel_setup.c - 0 - 0 - - - 1 - 35 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_cleanup.c - tx_mutex_cleanup.c - 0 - 0 - - - 1 - 36 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_create.c - tx_mutex_create.c - 0 - 0 - - - 1 - 37 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_delete.c - tx_mutex_delete.c - 0 - 0 - - - 1 - 38 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_get.c - tx_mutex_get.c - 0 - 0 - - - 1 - 39 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_info_get.c - tx_mutex_info_get.c - 0 - 0 - - - 1 - 40 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_initialize.c - tx_mutex_initialize.c - 0 - 0 - - - 1 - 41 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_performance_info_get.c - tx_mutex_performance_info_get.c - 0 - 0 - - - 1 - 42 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_performance_system_info_get.c - tx_mutex_performance_system_info_get.c - 0 - 0 - - - 1 - 43 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_prioritize.c - tx_mutex_prioritize.c - 0 - 0 - - - 1 - 44 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_priority_change.c - tx_mutex_priority_change.c - 0 - 0 - - - 1 - 45 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_put.c - tx_mutex_put.c - 0 - 0 - - - 1 - 46 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_cleanup.c - tx_queue_cleanup.c - 0 - 0 - - - 1 - 47 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_create.c - tx_queue_create.c - 0 - 0 - - - 1 - 48 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_delete.c - tx_queue_delete.c - 0 - 0 - - - 1 - 49 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_flush.c - tx_queue_flush.c - 0 - 0 - - - 1 - 50 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_front_send.c - tx_queue_front_send.c - 0 - 0 - - - 1 - 51 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_info_get.c - tx_queue_info_get.c - 0 - 0 - - - 1 - 52 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_initialize.c - tx_queue_initialize.c - 0 - 0 - - - 1 - 53 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_performance_info_get.c - tx_queue_performance_info_get.c - 0 - 0 - - - 1 - 54 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_performance_system_info_get.c - tx_queue_performance_system_info_get.c - 0 - 0 - - - 1 - 55 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_prioritize.c - tx_queue_prioritize.c - 0 - 0 - - - 1 - 56 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_receive.c - tx_queue_receive.c - 0 - 0 - - - 1 - 57 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_send.c - tx_queue_send.c - 0 - 0 - - - 1 - 58 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_send_notify.c - tx_queue_send_notify.c - 0 - 0 - - - 1 - 59 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_ceiling_put.c - tx_semaphore_ceiling_put.c - 0 - 0 - - - 1 - 60 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_cleanup.c - tx_semaphore_cleanup.c - 0 - 0 - - - 1 - 61 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_create.c - tx_semaphore_create.c - 0 - 0 - - - 1 - 62 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_delete.c - tx_semaphore_delete.c - 0 - 0 - - - 1 - 63 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_get.c - tx_semaphore_get.c - 0 - 0 - - - 1 - 64 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_info_get.c - tx_semaphore_info_get.c - 0 - 0 - - - 1 - 65 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_initialize.c - tx_semaphore_initialize.c - 0 - 0 - - - 1 - 66 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_performance_info_get.c - tx_semaphore_performance_info_get.c - 0 - 0 - - - 1 - 67 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_performance_system_info_get.c - tx_semaphore_performance_system_info_get.c - 0 - 0 - - - 1 - 68 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_prioritize.c - tx_semaphore_prioritize.c - 0 - 0 - - - 1 - 69 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_put.c - tx_semaphore_put.c - 0 - 0 - - - 1 - 70 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_put_notify.c - tx_semaphore_put_notify.c - 0 - 0 - - - 1 - 71 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_create.c - tx_thread_create.c - 0 - 0 - - - 1 - 72 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_delete.c - tx_thread_delete.c - 0 - 0 - - - 1 - 73 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_entry_exit_notify.c - tx_thread_entry_exit_notify.c - 0 - 0 - - - 1 - 74 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_identify.c - tx_thread_identify.c - 0 - 0 - - - 1 - 75 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_info_get.c - tx_thread_info_get.c - 0 - 0 - - - 1 - 76 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_initialize.c - tx_thread_initialize.c - 0 - 0 - - - 1 - 77 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_performance_info_get.c - tx_thread_performance_info_get.c - 0 - 0 - - - 1 - 78 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_performance_system_info_get.c - tx_thread_performance_system_info_get.c - 0 - 0 - - - 1 - 79 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_preemption_change.c - tx_thread_preemption_change.c - 0 - 0 - - - 1 - 80 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_priority_change.c - tx_thread_priority_change.c - 0 - 0 - - - 1 - 81 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_relinquish.c - tx_thread_relinquish.c - 0 - 0 - - - 1 - 82 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_reset.c - tx_thread_reset.c - 0 - 0 - - - 1 - 83 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_resume.c - tx_thread_resume.c - 0 - 0 - - - 1 - 84 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_shell_entry.c - tx_thread_shell_entry.c - 0 - 0 - - - 1 - 85 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_sleep.c - tx_thread_sleep.c - 0 - 0 - - - 1 - 86 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_stack_analyze.c - tx_thread_stack_analyze.c - 0 - 0 - - - 1 - 87 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_suspend.c - tx_thread_suspend.c - 0 - 0 - - - 1 - 88 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_system_preempt_check.c - tx_thread_system_preempt_check.c - 0 - 0 - - - 1 - 89 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_system_resume.c - tx_thread_system_resume.c - 0 - 0 - - - 1 - 90 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_system_suspend.c - tx_thread_system_suspend.c - 0 - 0 - - - 1 - 91 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_terminate.c - tx_thread_terminate.c - 0 - 0 - - - 1 - 92 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_time_slice.c - tx_thread_time_slice.c - 0 - 0 - - - 1 - 93 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_time_slice_change.c - tx_thread_time_slice_change.c - 0 - 0 - - - 1 - 94 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_timeout.c - tx_thread_timeout.c - 0 - 0 - - - 1 - 95 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_wait_abort.c - tx_thread_wait_abort.c - 0 - 0 - - - 1 - 96 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_time_get.c - tx_time_get.c - 0 - 0 - - - 1 - 97 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_time_set.c - tx_time_set.c - 0 - 0 - - - 1 - 98 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_activate.c - tx_timer_activate.c - 0 - 0 - - - 1 - 99 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_change.c - tx_timer_change.c - 0 - 0 - - - 1 - 100 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_create.c - tx_timer_create.c - 0 - 0 - - - 1 - 101 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_deactivate.c - tx_timer_deactivate.c - 0 - 0 - - - 1 - 102 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_delete.c - tx_timer_delete.c - 0 - 0 - - - 1 - 103 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_expiration_process.c - tx_timer_expiration_process.c - 0 - 0 - - - 1 - 104 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_info_get.c - tx_timer_info_get.c - 0 - 0 - - - 1 - 105 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_initialize.c - tx_timer_initialize.c - 0 - 0 - - - 1 - 106 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_performance_info_get.c - tx_timer_performance_info_get.c - 0 - 0 - - - 1 - 107 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_performance_system_info_get.c - tx_timer_performance_system_info_get.c - 0 - 0 - - - 1 - 108 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_system_activate.c - tx_timer_system_activate.c - 0 - 0 - - - 1 - 109 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_system_deactivate.c - tx_timer_system_deactivate.c - 0 - 0 - - - 1 - 110 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_thread_entry.c - tx_timer_thread_entry.c - 0 - 0 - - - 1 - 111 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_disable.c - tx_trace_disable.c - 0 - 0 - - - 1 - 112 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_enable.c - tx_trace_enable.c - 0 - 0 - - - 1 - 113 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_initialize.c - tx_trace_initialize.c - 0 - 0 - - - 1 - 114 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_interrupt_control.c - tx_trace_interrupt_control.c - 0 - 0 - - - 1 - 115 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_isr_enter_insert.c - tx_trace_isr_enter_insert.c - 0 - 0 - - - 1 - 116 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_isr_exit_insert.c - tx_trace_isr_exit_insert.c - 0 - 0 - - - 1 - 117 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_object_register.c - tx_trace_object_register.c - 0 - 0 - - - 1 - 118 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_object_unregister.c - tx_trace_object_unregister.c - 0 - 0 - - - 1 - 119 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_user_event_insert.c - tx_trace_user_event_insert.c - 0 - 0 - - - 1 - 120 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_allocate.c - txe_block_allocate.c - 0 - 0 - - - 1 - 121 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_pool_create.c - txe_block_pool_create.c - 0 - 0 - - - 1 - 122 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_pool_delete.c - txe_block_pool_delete.c - 0 - 0 - - - 1 - 123 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_pool_info_get.c - txe_block_pool_info_get.c - 0 - 0 - - - 1 - 124 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_pool_prioritize.c - txe_block_pool_prioritize.c - 0 - 0 - - - 1 - 125 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_release.c - txe_block_release.c - 0 - 0 - - - 1 - 126 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_allocate.c - txe_byte_allocate.c - 0 - 0 - - - 1 - 127 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_pool_create.c - txe_byte_pool_create.c - 0 - 0 - - - 1 - 128 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_pool_delete.c - txe_byte_pool_delete.c - 0 - 0 - - - 1 - 129 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_pool_info_get.c - txe_byte_pool_info_get.c - 0 - 0 - - - 1 - 130 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_pool_prioritize.c - txe_byte_pool_prioritize.c - 0 - 0 - - - 1 - 131 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_release.c - txe_byte_release.c - 0 - 0 - - - 1 - 132 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_create.c - txe_event_flags_create.c - 0 - 0 - - - 1 - 133 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_delete.c - txe_event_flags_delete.c - 0 - 0 - - - 1 - 134 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_get.c - txe_event_flags_get.c - 0 - 0 - - - 1 - 135 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_info_get.c - txe_event_flags_info_get.c - 0 - 0 - - - 1 - 136 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_set.c - txe_event_flags_set.c - 0 - 0 - - - 1 - 137 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_set_notify.c - txe_event_flags_set_notify.c - 0 - 0 - - - 1 - 138 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_create.c - txe_mutex_create.c - 0 - 0 - - - 1 - 139 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_delete.c - txe_mutex_delete.c - 0 - 0 - - - 1 - 140 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_get.c - txe_mutex_get.c - 0 - 0 - - - 1 - 141 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_info_get.c - txe_mutex_info_get.c - 0 - 0 - - - 1 - 142 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_prioritize.c - txe_mutex_prioritize.c - 0 - 0 - - - 1 - 143 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_put.c - txe_mutex_put.c - 0 - 0 - - - 1 - 144 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_create.c - txe_queue_create.c - 0 - 0 - - - 1 - 145 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_delete.c - txe_queue_delete.c - 0 - 0 - - - 1 - 146 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_flush.c - txe_queue_flush.c - 0 - 0 - - - 1 - 147 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_front_send.c - txe_queue_front_send.c - 0 - 0 - - - 1 - 148 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_info_get.c - txe_queue_info_get.c - 0 - 0 - - - 1 - 149 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_prioritize.c - txe_queue_prioritize.c - 0 - 0 - - - 1 - 150 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_receive.c - txe_queue_receive.c - 0 - 0 - - - 1 - 151 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_send.c - txe_queue_send.c - 0 - 0 - - - 1 - 152 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_send_notify.c - txe_queue_send_notify.c - 0 - 0 - - - 1 - 153 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_ceiling_put.c - txe_semaphore_ceiling_put.c - 0 - 0 - - - 1 - 154 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_create.c - txe_semaphore_create.c - 0 - 0 - - - 1 - 155 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_delete.c - txe_semaphore_delete.c - 0 - 0 - - - 1 - 156 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_get.c - txe_semaphore_get.c - 0 - 0 - - - 1 - 157 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_info_get.c - txe_semaphore_info_get.c - 0 - 0 - - - 1 - 158 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_prioritize.c - txe_semaphore_prioritize.c - 0 - 0 - - - 1 - 159 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_put.c - txe_semaphore_put.c - 0 - 0 - - - 1 - 160 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_put_notify.c - txe_semaphore_put_notify.c - 0 - 0 - - - 1 - 161 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_create.c - txe_thread_create.c - 0 - 0 - - - 1 - 162 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_delete.c - txe_thread_delete.c - 0 - 0 - - - 1 - 163 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_entry_exit_notify.c - txe_thread_entry_exit_notify.c - 0 - 0 - - - 1 - 164 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_info_get.c - txe_thread_info_get.c - 0 - 0 - - - 1 - 165 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_preemption_change.c - txe_thread_preemption_change.c - 0 - 0 - - - 1 - 166 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_priority_change.c - txe_thread_priority_change.c - 0 - 0 - - - 1 - 167 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_relinquish.c - txe_thread_relinquish.c - 0 - 0 - - - 1 - 168 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_reset.c - txe_thread_reset.c - 0 - 0 - - - 1 - 169 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_resume.c - txe_thread_resume.c - 0 - 0 - - - 1 - 170 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_suspend.c - txe_thread_suspend.c - 0 - 0 - - - 1 - 171 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_terminate.c - txe_thread_terminate.c - 0 - 0 - - - 1 - 172 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_time_slice_change.c - txe_thread_time_slice_change.c - 0 - 0 - - - 1 - 173 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_wait_abort.c - txe_thread_wait_abort.c - 0 - 0 - - - 1 - 174 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_activate.c - txe_timer_activate.c - 0 - 0 - - - 1 - 175 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_change.c - txe_timer_change.c - 0 - 0 - - - 1 - 176 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_create.c - txe_timer_create.c - 0 - 0 - - - 1 - 177 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_deactivate.c - txe_timer_deactivate.c - 0 - 0 - - - 1 - 178 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_delete.c - txe_timer_delete.c - 0 - 0 - - - 1 - 179 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_info_get.c - txe_timer_info_get.c - 0 - 0 - - - 1 - 180 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_buffer_full_notify.c - tx_trace_buffer_full_notify.c - 0 - 0 - - - 1 - 181 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_event_filter.c - tx_trace_event_filter.c - 0 - 0 - - - 1 - 182 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_event_unfilter.c - tx_trace_event_unfilter.c - 0 - 0 - - - 1 - 183 - 1 - 0 - 0 - 0 - ..\module_manager\src\txe_thread_secure_stack_allocate.c - txe_thread_secure_stack_allocate.c - 0 - 0 - - - 1 - 184 - 1 - 0 - 0 - 0 - ..\module_manager\src\txe_thread_secure_stack_free.c - txe_thread_secure_stack_free.c - 0 - 0 - - - 1 - 185 - 2 - 0 - 0 - 0 - ..\module_manager\src\tx_thread_context_restore.S - tx_thread_context_restore.S - 0 - 0 - - - 1 - 188 - 2 - 0 - 0 - 0 - ..\module_manager\src\tx_thread_context_save.S - tx_thread_context_save.S - 0 - 0 - - - 1 - 189 - 2 - 0 - 0 - 0 - ..\module_manager\src\tx_thread_interrupt_control.S - tx_thread_interrupt_control.S - 0 - 0 - - - 1 - 190 - 2 - 0 - 0 - 0 - ..\module_manager\src\tx_thread_interrupt_disable.S - tx_thread_interrupt_disable.S - 0 - 0 - - - 1 - 191 - 2 - 0 - 0 - 0 - ..\module_manager\src\tx_thread_interrupt_restore.S - tx_thread_interrupt_restore.S - 0 - 0 - - - 1 - 192 - 2 - 0 - 0 - 0 - ..\module_manager\src\tx_thread_schedule.S - tx_thread_schedule.S - 0 - 0 - - - 1 - 193 - 2 - 0 - 0 - 0 - ..\module_manager\src\tx_thread_secure_stack_allocate.S - tx_thread_secure_stack_allocate.S - 0 - 0 - - - 1 - 194 - 2 - 0 - 0 - 0 - ..\module_manager\src\tx_thread_secure_stack_free.S - tx_thread_secure_stack_free.S - 0 - 0 - - - 1 - 195 - 2 - 0 - 0 - 0 - ..\module_manager\src\tx_thread_stack_build.S - tx_thread_stack_build.S - 0 - 0 - - - 1 - 196 - 2 - 0 - 0 - 0 - ..\module_manager\src\tx_thread_system_return.S - tx_thread_system_return.S - 0 - 0 - - - 1 - 197 - 2 - 0 - 0 - 0 - ..\module_manager\src\tx_timer_interrupt.S - tx_timer_interrupt.S - 0 - 0 - - - 1 - 198 - 2 - 0 - 0 - 0 - .\tx_initialize_low_level.S - tx_initialize_low_level.S - 0 - 0 - - - 1 - 199 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_application_request.c - txm_module_manager_application_request.c - 0 - 0 - - - 1 - 200 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_callback_request.c - txm_module_manager_callback_request.c - 0 - 0 - - - 1 - 201 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_event_flags_notify_trampoline.c - txm_module_manager_event_flags_notify_trampoline.c - 0 - 0 - - - 1 - 202 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_file_load.c - txm_module_manager_file_load.c - 0 - 0 - - - 1 - 203 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_in_place_load.c - txm_module_manager_in_place_load.c - 0 - 0 - - - 1 - 204 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_initialize.c - txm_module_manager_initialize.c - 0 - 0 - - - 1 - 205 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_internal_load.c - txm_module_manager_internal_load.c - 0 - 0 - - - 1 - 206 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_kernel_dispatch.c - txm_module_manager_kernel_dispatch.c - 0 - 0 - - - 1 - 207 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_maximum_module_priority_set.c - txm_module_manager_maximum_module_priority_set.c - 0 - 0 - - - 1 - 208 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_memory_load.c - txm_module_manager_memory_load.c - 0 - 0 - - - 1 - 209 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_object_allocate.c - txm_module_manager_object_allocate.c - 0 - 0 - - - 1 - 210 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_object_deallocate.c - txm_module_manager_object_deallocate.c - 0 - 0 - - - 1 - 211 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_object_pointer_get.c - txm_module_manager_object_pointer_get.c - 0 - 0 - - - 1 - 212 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_object_pointer_get_extended.c - txm_module_manager_object_pointer_get_extended.c - 0 - 0 - - - 1 - 213 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_object_pool_create.c - txm_module_manager_object_pool_create.c - 0 - 0 - - - 1 - 214 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_properties_get.c - txm_module_manager_properties_get.c - 0 - 0 - - - 1 - 215 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_queue_notify_trampoline.c - txm_module_manager_queue_notify_trampoline.c - 0 - 0 - - - 1 - 216 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_semaphore_notify_trampoline.c - txm_module_manager_semaphore_notify_trampoline.c - 0 - 0 - - - 1 - 217 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_start.c - txm_module_manager_start.c - 0 - 0 - - - 1 - 218 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_stop.c - txm_module_manager_stop.c - 0 - 0 - - - 1 - 219 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_thread_create.c - txm_module_manager_thread_create.c - 0 - 0 - - - 1 - 220 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_thread_notify_trampoline.c - txm_module_manager_thread_notify_trampoline.c - 0 - 0 - - - 1 - 221 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_thread_reset.c - txm_module_manager_thread_reset.c - 0 - 0 - - - 1 - 222 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_timer_notify_trampoline.c - txm_module_manager_timer_notify_trampoline.c - 0 - 0 - - - 1 - 223 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_unload.c - txm_module_manager_unload.c - 0 - 0 - - - 1 - 224 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_util.c - txm_module_manager_util.c - 0 - 0 - - - 1 - 225 - 1 - 0 - 0 - 0 - ..\module_manager\src\txm_module_manager_alignment_adjust.c - txm_module_manager_alignment_adjust.c - 0 - 0 - - - 1 - 226 - 1 - 0 - 0 - 0 - ..\module_manager\src\txm_module_manager_external_memory_enable.c - txm_module_manager_external_memory_enable.c - 0 - 0 - - - 1 - 227 - 1 - 0 - 0 - 0 - ..\module_manager\src\txm_module_manager_memory_fault_handler.c - txm_module_manager_memory_fault_handler.c - 0 - 0 - - - 1 - 228 - 1 - 0 - 0 - 0 - ..\module_manager\src\txm_module_manager_memory_fault_notify.c - txm_module_manager_memory_fault_notify.c - 0 - 0 - - - 1 - 229 - 1 - 0 - 0 - 0 - ..\module_manager\src\txm_module_manager_mm_register_setup.c - txm_module_manager_mm_register_setup.c - 0 - 0 - - - 1 - 230 - 2 - 0 - 0 - 0 - ..\module_manager\src\txm_module_manager_thread_stack_build.S - txm_module_manager_thread_stack_build.S - 0 - 0 - - - 1 - 231 - 1 - 0 - 0 - 0 - ..\module_manager\src\txm_module_manager_port_dispatch.c - txm_module_manager_port_dispatch.c - 0 - 0 - - - 1 - 232 - 2 - 0 - 0 - 0 - ..\module_manager\src\tx_thread_secure_stack_initialize.S - tx_thread_secure_stack_initialize.S - 0 - 0 - - - 1 - 231 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_stack_error_handler.c - tx_thread_stack_error_handler.c - 0 - 0 - - - 1 - 232 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_stack_error_notify.c - tx_thread_stack_error_notify.c - 0 - 0 - - - - - ::CMSIS - 0 - 0 - 0 - 1 - - -
diff --git a/ports_module/cortex_m23/ac6/example_build/demo_secure_zone/demo_secure_zone.uvoptx b/ports_module/cortex_m23/ac6/example_build/demo_secure_zone/demo_secure_zone.uvoptx deleted file mode 100644 index fb2925dea..000000000 --- a/ports_module/cortex_m23/ac6/example_build/demo_secure_zone/demo_secure_zone.uvoptx +++ /dev/null @@ -1,467 +0,0 @@ - - - - 1.0 - -
### uVision Project, (C) Keil Software
- - - *.c - *.s*; *.src; *.a* - *.obj; *.o - *.lib - *.txt; *.h; *.inc - *.plm - *.cpp - 0 - - - - 0 - 0 - - - - FVP Simulation Model - 0x4 - ARM-ADS - - 12000000 - - 1 - 1 - 0 - 1 - 0 - - - 1 - 65535 - 0 - 0 - 0 - - - 79 - 66 - 8 - .\Listings\ - - - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - - - 1 - 0 - 1 - - 7 - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 1 - 1 - 0 - 0 - 1 - 0 - 0 - 15 - - - - - - - - - - ..\Debug.ini - BIN\DbgFMv8M.DLL - - - - 0 - UL2V8M - UL2V8M(-S0 -C0 -P0 -FC1000 -FD20000000 - - - 0 - DbgFMv8M - -I -S -L"cpu0" -O4102 -C0 -MC".\FVP\MPS2_Cortex-M\FVP_MPS2_Cortex-M23_MDK.exe" -MF"..\ARMCM23_TZ_config.txt" -PF -MA - - - 0 - DLGTARM - (6010=851,404,1328,1000,0)(6018=-1,-1,-1,-1,0)(6019=105,137,294,473,0)(6008=1511,0,1805,185,0)(6009=137,177,431,362,0)(6014=1310,310,1568,1041,0)(6015=1547,312,1805,934,0)(6003=1122,384,1704,920,0)(6000=758,242,1211,574,0) - - - 0 - ARMDBGFLAGS - - - - 0 - DLGUARM - (105=-1,-1,-1,-1,0)(106=1039,107,1805,421,0)(107=-1,-1,-1,-1,0) - - - - - 0 - 0 - 120 - 1 -
263362
- 0 - 0 - 0 - 0 - 0 - 1 - <2>.\sample_threadx_module_manager.c - - \\demo_threadx_non_secure_zone\sample_threadx_module_manager.c\120 -
- - 1 - 0 - 244 - 1 -
2101172
- 0 - 0 - 0 - 0 - 0 - 1 - <4>.\sample_threadx_module.c - - \\sample_threadx_module\sample_threadx_module.c\244 -
- - 2 - 0 - 87 - 1 -
1046
- 0 - 0 - 0 - 0 - 0 - 1 - <1>RTE\Device\ARMCM23_TZ\system_ARMCM23.c - - \\demo_secure_zone\RTE/Device/ARMCM23_TZ/system_ARMCM23.c\87 -
- - 3 - 0 - 0 - 1 -
2097478
- 0 - 0 - 0 - 0 - 0 - 1 - - - 0x00200146 -
- - 4 - 0 - 274 - 1 -
270338
- 0 - 0 - 0 - 0 - 0 - 1 - <3>..\..\..\..\common\src\tx_timer_initialize.c - - \\demo_threadx_non_secure_zone\../../../../common/src/tx_timer_initialize.c\274 -
- - 5 - 0 - 0 - 1 -
270592
- 0 - 0 - 0 - 0 - 0 - 1 - - - 0x00042100 -
- - 6 - 0 - 304 - 1 -
2101344
- 0 - 0 - 0 - 0 - 0 - 1 - <4>.\sample_threadx_module.c - - \\sample_threadx_module\sample_threadx_module.c\304 -
- - 7 - 0 - 304 - 1 -
2101392
- 0 - 0 - 0 - 0 - 0 - 1 - <4>.\sample_threadx_module.c - - \\sample_threadx_module\sample_threadx_module.c\304 -
-
- - - 0 - 1 - thread_0_counter - - - 1 - 1 - thread_1_counter - - - 2 - 1 - thread_2_counter - - - 3 - 1 - thread_3_counter - - - 4 - 1 - thread_4_counter - - - 5 - 1 - thread_5_counter - - - 6 - 1 - thread_6_counter - - - 7 - 1 - thread_7_counter - - - 8 - 1 - _tx_thread_current_ptr - - - 9 - 1 - _tx_thread_execute_ptr - - - 10 - 1 - my_module - - - 11 - 1 - _tx_timer_system_clock - - - - - 1 - 2 - 0x20040000 - 0 - - - - - 2 - 2 - 0xE000ED28 - 0 - - - - 0 - - - 0 - 1 - 1 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - - - - - - - - -
-
- - - Secure Code - 1 - 0 - 0 - 0 - - 1 - 1 - 1 - 0 - 0 - 0 - .\main_s.c - main_s.c - 0 - 0 - - - 1 - 2 - 1 - 0 - 0 - 0 - ..\..\module_manager\src\tx_thread_secure_stack.c - tx_thread_secure_stack.c - 0 - 0 - - - - - Interface - 0 - 0 - 0 - 0 - - 2 - 3 - 1 - 0 - 0 - 0 - .\interface.c - interface.c - 0 - 0 - - - - - ::CMSIS - 0 - 0 - 0 - 1 - - - - ::Device - 1 - 0 - 0 - 1 - - -
diff --git a/ports_module/cortex_m23/ac6/example_build/demo_threadx_non-secure_zone/ThreadX_Demo.uvopt b/ports_module/cortex_m23/ac6/example_build/demo_threadx_non-secure_zone/ThreadX_Demo.uvopt deleted file mode 100644 index 7ec4b36b6..000000000 --- a/ports_module/cortex_m23/ac6/example_build/demo_threadx_non-secure_zone/ThreadX_Demo.uvopt +++ /dev/null @@ -1,305 +0,0 @@ - - - - 1.0 - -
### uVision Project, (C) Keil Software
- - - *.c - *.s*; *.src; *.a* - *.obj; *.o - *.lib - *.txt; *.h; *.inc - *.plm - *.cpp - 0 - - - - 0 - 0 - - - - ThreadX_Demo - 0x4 - ARM-ADS - - 12000000 - - 1 - 1 - 1 - 0 - 0 - - - 1 - 65535 - 0 - 0 - 0 - - - 79 - 66 - 8 - .\ - - - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - - - 1 - 0 - 1 - - 255 - - 1 - 0 - 1 - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 1 - 0 - 1 - 0 - 1 - 1 - 0 - 0 - 1 - 0 - 0 - -1 - - - - - - - - - - - - - - - 0 - ARMRTXEVENTFLAGS - -L70 -Z18 -C0 -M0 -T1 - - - 0 - DLGDARM - (1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0) - - - 0 - DLGUARM - (105=-1,-1,-1,-1,0)(106=-1,-1,-1,-1,0)(107=-1,-1,-1,-1,0) - - - 0 - DLGTARM - (1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0)(110=-1,-1,-1,-1,0)(100=-1,-1,-1,-1,0)(101=-1,-1,-1,-1,0)(102=-1,-1,-1,-1,0)(103=-1,-1,-1,-1,0)(104=-1,-1,-1,-1,0)(105=-1,-1,-1,-1,0)(106=-1,-1,-1,-1,0)(107=-1,-1,-1,-1,0)(161=-1,-1,-1,-1,0)(162=-1,-1,-1,-1,0)(163=-1,-1,-1,-1,0)(164=-1,-1,-1,-1,0)(150=-1,-1,-1,-1,0)(151=-1,-1,-1,-1,0)(152=-1,-1,-1,-1,0)(1011=-1,-1,-1,-1,0)(1012=-1,-1,-1,-1,0)(1013=-1,-1,-1,-1,0)(171=-1,-1,-1,-1,0)(172=-1,-1,-1,-1,0)(173=-1,-1,-1,-1,0)(1014=-1,-1,-1,-1,0)(1016=-1,-1,-1,-1,0)(136=-1,-1,-1,-1,0) - - - 0 - ARMDBGFLAGS - -T5F - - - 0 - UL2CM3 - -UV0289BJE -O14 -S0 -C0 -N00("ARM CoreSight JTAG-DP") -D00(3BA00477) -L00(4) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO7 -FD20000000 -FC800 -FN1 -FF0LM3S_16 -FS00 -FL04000 - - - - - - 0 - 1 - thread_0_counter - - - 1 - 1 - thread_1_counter - - - 2 - 1 - thread_2_counter - - - 3 - 1 - thread_3_counter - - - 4 - 1 - thread_4_counter - - - 5 - 1 - thread_5_counter - - - 6 - 1 - _tx_thread_current_ptr - - - - 0 - - - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - - - - - - - - - - - - - Source Group - 1 - 0 - 0 - 0 - - 1 - 1 - 2 - 0 - 0 - 0 - .\tx_initialize_low_level.s - tx_initialize_low_level.s - 0 - 0 - - - 1 - 2 - 1 - 1 - 0 - 0 - .\demo_threadx.c - demo_threadx.c - 0 - 0 - - 44 - 0 - 1 - - -1 - -1 - - - -1 - -1 - - - 56 - 12 - 1633 - 671 - - - - - - - Library_Group - 1 - 0 - 0 - 0 - - 2 - 3 - 4 - 0 - 0 - 0 - .\ThreadX_Library.lib - ThreadX_Library.lib - 0 - 0 - - - -
diff --git a/ports_module/cortex_m23/ac6/example_build/demo_threadx_non-secure_zone/demo_threadx_non-secure_zone.uvoptx b/ports_module/cortex_m23/ac6/example_build/demo_threadx_non-secure_zone/demo_threadx_non-secure_zone.uvoptx deleted file mode 100644 index 63fd727fd..000000000 --- a/ports_module/cortex_m23/ac6/example_build/demo_threadx_non-secure_zone/demo_threadx_non-secure_zone.uvoptx +++ /dev/null @@ -1,335 +0,0 @@ - - - - 1.0 - -
### uVision Project, (C) Keil Software
- - - *.c - *.s*; *.src; *.a* - *.obj; *.o - *.lib - *.txt; *.h; *.inc - *.plm - *.cpp - 0 - - - - 0 - 0 - - - - FVP Simulation Model - 0x4 - ARM-ADS - - 12000000 - - 1 - 1 - 0 - 1 - 0 - - - 1 - 65535 - 0 - 0 - 0 - - - 79 - 66 - 8 - .\Listings\ - - - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - - - 1 - 0 - 1 - - 7 - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 1 - 1 - 0 - 0 - 1 - 0 - 0 - 15 - - - - - - - - - - ..\Debug.ini - BIN\DbgFMv8M.DLL - - - - 0 - UL2V8M - UL2V8M(-S0 -C0 -P0 -FC1000 -FD20000000 - - - 0 - DbgFMv8M - -I -S -L"cpu0" -O4102 -C0 -MC".\FVP\MPS2_Cortex-M\FVP_MPS2_Cortex-M33_MDK.exe" -MF"..\ARMCM33_DSP_FP_TZ_config.txt" -PF -MA - - - 0 - PWSTATINFO - 200,50,700 - - - 0 - DLGTARM - (6010=1243,118,1720,714,0)(6018=1284,352,1473,701,0)(6019=1328,34,1517,370,0)(6008=-1,-1,-1,-1,0)(6009=969,18,1263,203,0)(6014=1111,129,1369,860,0)(6015=872,146,1130,768,0)(6003=-1,-1,-1,-1,0)(6000=-1,-1,-1,-1,0) - - - 0 - ARMDBGFLAGS - - - - 0 - DLGUARM - (105=-1,-1,-1,-1,0)(106=511,345,1277,660,0)(107=-1,-1,-1,-1,0) - - - - - - 0 - 1 - thread_0_counter - - - 1 - 1 - thread_1_counter - - - 2 - 1 - thread_2_counter - - - 3 - 1 - thread_3_counter - - - 4 - 1 - thread_4_counter - - - 5 - 1 - thread_5_counter - - - 6 - 1 - thread_6_counter - - - 7 - 1 - thread_7_counter - - - - - 1 - 2 - 0x20200a10 - 0 - - - - - 2 - 2 - 0xE000ED28 - 0 - - - - 0 - - - 0 - 1 - 1 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - - - - - - - - - - - - - Non-secure Code - 1 - 0 - 0 - 0 - - 1 - 1 - 4 - 0 - 0 - 0 - ..\ThreadX_Library.lib - ThreadX_Library.lib - 0 - 0 - - - 1 - 2 - 1 - 0 - 0 - 0 - .\sample_threadx_module_manager.c - sample_threadx_module_manager.c - 0 - 0 - - - - - CMSE Library - 0 - 0 - 0 - 0 - - 2 - 3 - 5 - 0 - 0 - 0 - ..\demo_secure_zone\interface.h - interface.h - 0 - 0 - - - 2 - 4 - 3 - 0 - 0 - 0 - ..\demo_secure_zone\Objects\demo_secure_zone_CMSE_Lib.o - demo_secure_zone_CMSE_Lib.o - 0 - 0 - - - - - ::CMSIS - 1 - 0 - 0 - 1 - - - - ::Device - 0 - 0 - 0 - 1 - - -
diff --git a/ports_module/cortex_m23/ac6/example_build/sample_threadx_module/sample_threadx_module.uvoptx b/ports_module/cortex_m23/ac6/example_build/sample_threadx_module/sample_threadx_module.uvoptx deleted file mode 100644 index 43fa32724..000000000 --- a/ports_module/cortex_m23/ac6/example_build/sample_threadx_module/sample_threadx_module.uvoptx +++ /dev/null @@ -1,236 +0,0 @@ - - - - 1.0 - -
### uVision Project, (C) Keil Software
- - - *.c - *.s*; *.src; *.a* - *.obj; *.o - *.lib - *.txt; *.h; *.inc - *.plm - *.cpp - 0 - - - - 0 - 0 - - - - FVP Simulation Model - 0x4 - ARM-ADS - - 12000000 - - 1 - 1 - 0 - 1 - 0 - - - 1 - 65535 - 0 - 0 - 0 - - - 79 - 66 - 8 - .\Listings\ - - - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - - - 1 - 0 - 1 - - 7 - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 1 - 1 - 0 - 0 - 1 - 0 - 0 - 15 - - - - - - - - - - - BIN\DbgFMv8M.DLL - - - - 0 - UL2V8M - UL2V8M(-S0 -C0 -P0 -FC1000 -FD20000000 - - - - - 0 - - - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - - - - - - - - - - - - - Module Code - 0 - 0 - 0 - 0 - - 1 - 1 - 1 - 0 - 0 - 0 - .\sample_threadx_module.c - sample_threadx_module.c - 0 - 0 - - - 1 - 2 - 2 - 0 - 0 - 0 - .\txm_module_preamble.S - txm_module_preamble.S - 0 - 0 - - - 1 - 3 - 4 - 0 - 0 - 0 - ..\txm\Objects\txm.lib - txm.lib - 0 - 0 - - - 1 - 4 - 3 - 0 - 0 - 0 - ..\demo_secure_zone\Objects\demo_secure_zone_CMSE_Lib.o - demo_secure_zone_CMSE_Lib.o - 0 - 0 - - - - - ::CMSIS - 0 - 0 - 0 - 1 - - -
diff --git a/ports_module/cortex_m23/ac6/example_build/txm/txm.uvoptx b/ports_module/cortex_m23/ac6/example_build/txm/txm.uvoptx deleted file mode 100644 index 8e8c53b5e..000000000 --- a/ports_module/cortex_m23/ac6/example_build/txm/txm.uvoptx +++ /dev/null @@ -1,1412 +0,0 @@ - - - - 1.0 - -
### uVision Project, (C) Keil Software
- - - *.c - *.s*; *.src; *.a* - *.obj; *.o - *.lib - *.txt; *.h; *.inc - *.plm - *.cpp - 0 - - - - 0 - 0 - - - - ThreadX Module Library - 0x4 - ARM-ADS - - 12000000 - - 1 - 1 - 0 - 1 - 0 - - - 1 - 65535 - 0 - 0 - 0 - - - 79 - 66 - 8 - .\Listings\ - - - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - - - 1 - 0 - 1 - - 7 - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 1 - 1 - 0 - 0 - 1 - 0 - 0 - 13 - - - - - - - - - - - BIN\UL2V8M.DLL - - - - 0 - UL2V8M - UL2V8M(-S0 -C0 -P0 -FC1000 -FD20000000 - - - - - 0 - - - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - - - - - - - - - - - - - Source Group - 0 - 0 - 0 - 0 - - 1 - 1 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_block_allocate.c - txm_block_allocate.c - 0 - 0 - - - 1 - 2 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_block_pool_create.c - txm_block_pool_create.c - 0 - 0 - - - 1 - 3 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_block_pool_delete.c - txm_block_pool_delete.c - 0 - 0 - - - 1 - 4 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_block_pool_info_get.c - txm_block_pool_info_get.c - 0 - 0 - - - 1 - 5 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_block_pool_performance_info_get.c - txm_block_pool_performance_info_get.c - 0 - 0 - - - 1 - 6 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_block_pool_performance_system_info_get.c - txm_block_pool_performance_system_info_get.c - 0 - 0 - - - 1 - 7 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_block_pool_prioritize.c - txm_block_pool_prioritize.c - 0 - 0 - - - 1 - 8 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_block_release.c - txm_block_release.c - 0 - 0 - - - 1 - 9 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_byte_allocate.c - txm_byte_allocate.c - 0 - 0 - - - 1 - 10 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_byte_pool_create.c - txm_byte_pool_create.c - 0 - 0 - - - 1 - 11 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_byte_pool_delete.c - txm_byte_pool_delete.c - 0 - 0 - - - 1 - 12 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_byte_pool_info_get.c - txm_byte_pool_info_get.c - 0 - 0 - - - 1 - 13 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_byte_pool_performance_info_get.c - txm_byte_pool_performance_info_get.c - 0 - 0 - - - 1 - 14 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_byte_pool_performance_system_info_get.c - txm_byte_pool_performance_system_info_get.c - 0 - 0 - - - 1 - 15 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_byte_pool_prioritize.c - txm_byte_pool_prioritize.c - 0 - 0 - - - 1 - 16 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_byte_release.c - txm_byte_release.c - 0 - 0 - - - 1 - 17 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_event_flags_create.c - txm_event_flags_create.c - 0 - 0 - - - 1 - 18 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_event_flags_delete.c - txm_event_flags_delete.c - 0 - 0 - - - 1 - 19 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_event_flags_get.c - txm_event_flags_get.c - 0 - 0 - - - 1 - 20 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_event_flags_info_get.c - txm_event_flags_info_get.c - 0 - 0 - - - 1 - 21 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_event_flags_performance_info_get.c - txm_event_flags_performance_info_get.c - 0 - 0 - - - 1 - 22 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_event_flags_performance_system_info_get.c - txm_event_flags_performance_system_info_get.c - 0 - 0 - - - 1 - 23 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_event_flags_set.c - txm_event_flags_set.c - 0 - 0 - - - 1 - 24 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_event_flags_set_notify.c - txm_event_flags_set_notify.c - 0 - 0 - - - 1 - 25 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_module_application_request.c - txm_module_application_request.c - 0 - 0 - - - 1 - 26 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_module_callback_request_thread_entry.c - txm_module_callback_request_thread_entry.c - 0 - 0 - - - 1 - 27 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_module_object_allocate.c - txm_module_object_allocate.c - 0 - 0 - - - 1 - 28 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_module_object_deallocate.c - txm_module_object_deallocate.c - 0 - 0 - - - 1 - 29 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_module_object_pointer_get.c - txm_module_object_pointer_get.c - 0 - 0 - - - 1 - 30 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_module_object_pointer_get_extended.c - txm_module_object_pointer_get_extended.c - 0 - 0 - - - 1 - 31 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_module_thread_system_suspend.c - txm_module_thread_system_suspend.c - 0 - 0 - - - 1 - 32 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_mutex_create.c - txm_mutex_create.c - 0 - 0 - - - 1 - 33 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_mutex_delete.c - txm_mutex_delete.c - 0 - 0 - - - 1 - 34 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_mutex_get.c - txm_mutex_get.c - 0 - 0 - - - 1 - 35 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_mutex_info_get.c - txm_mutex_info_get.c - 0 - 0 - - - 1 - 36 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_mutex_performance_info_get.c - txm_mutex_performance_info_get.c - 0 - 0 - - - 1 - 37 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_mutex_performance_system_info_get.c - txm_mutex_performance_system_info_get.c - 0 - 0 - - - 1 - 38 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_mutex_prioritize.c - txm_mutex_prioritize.c - 0 - 0 - - - 1 - 39 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_mutex_put.c - txm_mutex_put.c - 0 - 0 - - - 1 - 40 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_queue_create.c - txm_queue_create.c - 0 - 0 - - - 1 - 41 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_queue_delete.c - txm_queue_delete.c - 0 - 0 - - - 1 - 42 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_queue_flush.c - txm_queue_flush.c - 0 - 0 - - - 1 - 43 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_queue_front_send.c - txm_queue_front_send.c - 0 - 0 - - - 1 - 44 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_queue_info_get.c - txm_queue_info_get.c - 0 - 0 - - - 1 - 45 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_queue_performance_info_get.c - txm_queue_performance_info_get.c - 0 - 0 - - - 1 - 46 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_queue_performance_system_info_get.c - txm_queue_performance_system_info_get.c - 0 - 0 - - - 1 - 47 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_queue_prioritize.c - txm_queue_prioritize.c - 0 - 0 - - - 1 - 48 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_queue_receive.c - txm_queue_receive.c - 0 - 0 - - - 1 - 49 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_queue_send.c - txm_queue_send.c - 0 - 0 - - - 1 - 50 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_queue_send_notify.c - txm_queue_send_notify.c - 0 - 0 - - - 1 - 51 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_semaphore_ceiling_put.c - txm_semaphore_ceiling_put.c - 0 - 0 - - - 1 - 52 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_semaphore_create.c - txm_semaphore_create.c - 0 - 0 - - - 1 - 53 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_semaphore_delete.c - txm_semaphore_delete.c - 0 - 0 - - - 1 - 54 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_semaphore_get.c - txm_semaphore_get.c - 0 - 0 - - - 1 - 55 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_semaphore_info_get.c - txm_semaphore_info_get.c - 0 - 0 - - - 1 - 56 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_semaphore_performance_info_get.c - txm_semaphore_performance_info_get.c - 0 - 0 - - - 1 - 57 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_semaphore_performance_system_info_get.c - txm_semaphore_performance_system_info_get.c - 0 - 0 - - - 1 - 58 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_semaphore_prioritize.c - txm_semaphore_prioritize.c - 0 - 0 - - - 1 - 59 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_semaphore_put.c - txm_semaphore_put.c - 0 - 0 - - - 1 - 60 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_semaphore_put_notify.c - txm_semaphore_put_notify.c - 0 - 0 - - - 1 - 61 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_thread_create.c - txm_thread_create.c - 0 - 0 - - - 1 - 62 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_thread_delete.c - txm_thread_delete.c - 0 - 0 - - - 1 - 63 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_thread_entry_exit_notify.c - txm_thread_entry_exit_notify.c - 0 - 0 - - - 1 - 64 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_thread_identify.c - txm_thread_identify.c - 0 - 0 - - - 1 - 65 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_thread_info_get.c - txm_thread_info_get.c - 0 - 0 - - - 1 - 66 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_thread_interrupt_control.c - txm_thread_interrupt_control.c - 0 - 0 - - - 1 - 67 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_thread_performance_info_get.c - txm_thread_performance_info_get.c - 0 - 0 - - - 1 - 68 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_thread_performance_system_info_get.c - txm_thread_performance_system_info_get.c - 0 - 0 - - - 1 - 69 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_thread_preemption_change.c - txm_thread_preemption_change.c - 0 - 0 - - - 1 - 70 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_thread_priority_change.c - txm_thread_priority_change.c - 0 - 0 - - - 1 - 71 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_thread_relinquish.c - txm_thread_relinquish.c - 0 - 0 - - - 1 - 72 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_thread_reset.c - txm_thread_reset.c - 0 - 0 - - - 1 - 73 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_thread_resume.c - txm_thread_resume.c - 0 - 0 - - - 1 - 74 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_thread_sleep.c - txm_thread_sleep.c - 0 - 0 - - - 1 - 75 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_thread_stack_error_notify.c - txm_thread_stack_error_notify.c - 0 - 0 - - - 1 - 76 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_thread_suspend.c - txm_thread_suspend.c - 0 - 0 - - - 1 - 77 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_thread_terminate.c - txm_thread_terminate.c - 0 - 0 - - - 1 - 78 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_thread_time_slice_change.c - txm_thread_time_slice_change.c - 0 - 0 - - - 1 - 79 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_thread_wait_abort.c - txm_thread_wait_abort.c - 0 - 0 - - - 1 - 80 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_time_get.c - txm_time_get.c - 0 - 0 - - - 1 - 81 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_time_set.c - txm_time_set.c - 0 - 0 - - - 1 - 82 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_timer_activate.c - txm_timer_activate.c - 0 - 0 - - - 1 - 83 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_timer_change.c - txm_timer_change.c - 0 - 0 - - - 1 - 84 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_timer_create.c - txm_timer_create.c - 0 - 0 - - - 1 - 85 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_timer_deactivate.c - txm_timer_deactivate.c - 0 - 0 - - - 1 - 86 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_timer_delete.c - txm_timer_delete.c - 0 - 0 - - - 1 - 87 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_timer_info_get.c - txm_timer_info_get.c - 0 - 0 - - - 1 - 88 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_timer_performance_info_get.c - txm_timer_performance_info_get.c - 0 - 0 - - - 1 - 89 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_timer_performance_system_info_get.c - txm_timer_performance_system_info_get.c - 0 - 0 - - - 1 - 90 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_trace_buffer_full_notify.c - txm_trace_buffer_full_notify.c - 0 - 0 - - - 1 - 91 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_trace_disable.c - txm_trace_disable.c - 0 - 0 - - - 1 - 92 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_trace_enable.c - txm_trace_enable.c - 0 - 0 - - - 1 - 93 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_trace_event_filter.c - txm_trace_event_filter.c - 0 - 0 - - - 1 - 94 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_trace_event_unfilter.c - txm_trace_event_unfilter.c - 0 - 0 - - - 1 - 95 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_trace_interrupt_control.c - txm_trace_interrupt_control.c - 0 - 0 - - - 1 - 96 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_trace_isr_enter_insert.c - txm_trace_isr_enter_insert.c - 0 - 0 - - - 1 - 97 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_trace_isr_exit_insert.c - txm_trace_isr_exit_insert.c - 0 - 0 - - - 1 - 98 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_trace_user_event_insert.c - txm_trace_user_event_insert.c - 0 - 0 - - - 1 - 99 - 2 - 0 - 0 - 0 - ..\..\module_lib\src\txm_module_initialize.S - txm_module_initialize.S - 0 - 0 - - - 1 - 100 - 1 - 0 - 0 - 0 - ..\..\module_lib\src\txm_module_thread_shell_entry.c - txm_module_thread_shell_entry.c - 0 - 0 - - - 1 - 101 - 1 - 0 - 0 - 0 - ..\..\module_lib\src\txm_thread_secure_stack_allocate.c - txm_thread_secure_stack_allocate.c - 0 - 0 - - - 1 - 102 - 1 - 0 - 0 - 0 - ..\..\module_lib\src\txm_thread_secure_stack_free.c - txm_thread_secure_stack_free.c - 0 - 0 - - - - - ::CMSIS - 0 - 0 - 0 - 1 - - -
diff --git a/ports_module/cortex_m33/ac6/example_build/RTOS.uvmpw.uvgui b/ports_module/cortex_m33/ac6/example_build/RTOS.uvmpw.uvgui deleted file mode 100644 index 5c23c31fc..000000000 --- a/ports_module/cortex_m33/ac6/example_build/RTOS.uvmpw.uvgui +++ /dev/null @@ -1,1777 +0,0 @@ - - - - -6.1 - -
### uVision Project, (C) Keil Software
- - - - - 44 - 2 - 3 - - -1 - -1 - - - -1 - -1 - - - 0 - 0 - 1024 - 728 - - - - 0 - - 297 - 0100000004000000010000000100000001000000010000000000000002000000000000000100000001000000000000002800000028000000010000000100000000000000010000005F433A5C4B65696C5C41524D5C5041434B5C41524D5C434D5349535C352E322E305C434D5349535C52544F53325C5254585C4578616D706C65735C54727573745A6F6E6556384D5C52544F535C434D33335F735C41627374726163742E747874000000000C41627374726163742E74787400000000C5D4F200FFFFFFFF0100000010000000C5D4F200FFDC7800BECEA100F0A0A100BCA8E1009CC1B600F7B88600D9ADC200A5C2D700B3A6BE00EAD6A300F6FA7D00B5E99D005FC3CF00C1838300CACAD500010000000000000002000000380100006500000080070000FD030000 - - - - 0 - Build - - -1 - -1 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - F40000004F00000090050000F0000000 - - - 16 - F4000000650000009005000006010000 - - - - 1005 - 1005 - 1 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 030000006600000031010000CE030000 - - - 16 - 2100000037000000110100001A010000 - - - - 109 - 109 - 1 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 030000006600000031010000CE030000 - - - 16 - 21000000370000003D010000BD020000 - - - - 1465 - 1465 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000760200008D050000FB020000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 1466 - 1466 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000760200008D050000FB020000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 1467 - 1467 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000760200008D050000FB020000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 1468 - 1468 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000760200008D050000FB020000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 1506 - 1506 - 0 - 0 - 0 - 0 - 32767 - 0 - 16384 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 1913 - 1913 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - F7000000660000008D050000D7000000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 1935 - 1935 - 0 - 0 - 0 - 0 - 32767 - 0 - 32768 - 0 - - 16 - 03000000760200008D050000FB020000 - - - 16 - 2100000037000000110100001A010000 - - - - 1936 - 1936 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000760200008D050000FB020000 - - - 16 - 2100000037000000110100001A010000 - - - - 1937 - 1937 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000760200008D050000FB020000 - - - 16 - 2100000037000000110100001A010000 - - - - 1939 - 1939 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000760200008D050000FB020000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 1940 - 1940 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000760200008D050000FB020000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 1941 - 1941 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000760200008D050000FB020000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 1942 - 1942 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000760200008D050000FB020000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 195 - 195 - 1 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 030000006600000031010000CE030000 - - - 16 - 21000000370000003D010000BD020000 - - - - 196 - 196 - 1 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 030000006600000031010000CE030000 - - - 16 - 21000000370000003D010000BD020000 - - - - 197 - 197 - 0 - 0 - 0 - 0 - 32767 - 0 - 32768 - 0 - - 16 - 03000000390300007D070000CE030000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 198 - 198 - 0 - 0 - 0 - 0 - 32767 - 0 - 32768 - 0 - - 16 - 000000005F0200009005000014030000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 199 - 199 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000390300007D070000CE030000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 203 - 203 - 0 - 0 - 0 - 0 - 32767 - 0 - 8192 - 0 - - 16 - F7000000660000008D050000D7000000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 204 - 204 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - F7000000660000008D050000D7000000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 221 - 221 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 00000000000000000000000000000000 - - - 16 - 0A0000000A0000006E0000006E000000 - - - - 2506 - 2506 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 2507 - 2507 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000760200008D050000FB020000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 343 - 343 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - F7000000660000008D050000D7000000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 346 - 346 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - F7000000660000008D050000D7000000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 35824 - 35824 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - F7000000660000008D050000D7000000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 35885 - 35885 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35886 - 35886 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35887 - 35887 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35888 - 35888 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35889 - 35889 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35890 - 35890 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35891 - 35891 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35892 - 35892 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35893 - 35893 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35894 - 35894 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35895 - 35895 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35896 - 35896 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35897 - 35897 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35898 - 35898 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35899 - 35899 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35900 - 35900 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35901 - 35901 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35902 - 35902 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35903 - 35903 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35904 - 35904 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 35905 - 35905 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 38003 - 38003 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 030000006600000031010000CE030000 - - - 16 - 21000000370000003D010000BD020000 - - - - 38007 - 38007 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000390300007D070000CE030000 - - - 16 - 2100000037000000E9020000D8000000 - - - - 436 - 436 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000390300007D070000CE030000 - - - 16 - 21000000370000003D010000BD020000 - - - - 437 - 437 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000760200008D050000FB020000 - - - 16 - 2100000037000000110100001A010000 - - - - 440 - 440 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000760200008D050000FB020000 - - - 16 - 2100000037000000110100001A010000 - - - - 463 - 463 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 030000006E0300007D070000CE030000 - - - 16 - 21000000370000003D01000079020000 - - - - 466 - 466 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 030000006E0300007D070000CE030000 - - - 16 - 21000000370000003D01000079020000 - - - - 470 - 470 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000010000000300000003020000 - - - 16 - 2100000037000000E9020000C7000000 - - - - 50000 - 50000 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50001 - 50001 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50002 - 50002 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50003 - 50003 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50004 - 50004 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50005 - 50005 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50006 - 50006 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50007 - 50007 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50008 - 50008 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50009 - 50009 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50010 - 50010 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50011 - 50011 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50012 - 50012 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50013 - 50013 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50014 - 50014 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50015 - 50015 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50016 - 50016 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50017 - 50017 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50018 - 50018 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 50019 - 50019 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - A3040000660000008D05000056020000 - - - 16 - 2100000037000000110100001A010000 - - - - 59392 - 59392 - 1 - 0 - 0 - 0 - 940 - 0 - 8192 - 0 - - 16 - 0000000000000000B70300001C000000 - - - 16 - 0A0000000A0000006E0000006E000000 - - - - 59393 - 0 - 1 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 00000000E703000080070000FA030000 - - - 16 - 0A0000000A0000006E0000006E000000 - - - - 59399 - 59399 - 1 - 0 - 0 - 0 - 303 - 0 - 8192 - 1 - - 16 - 000000001C000000E701000038000000 - - - 16 - 0A0000000A0000006E0000006E000000 - - - - 59400 - 59400 - 0 - 0 - 0 - 0 - 612 - 0 - 8192 - 2 - - 16 - 00000000380000006F02000054000000 - - - 16 - 0A0000000A0000006E0000006E000000 - - - - 824 - 824 - 0 - 0 - 0 - 0 - 32767 - 0 - 4096 - 0 - - 16 - 03000000010000000300000003020000 - - - 16 - 21000000370000001101000002010000 - - - - 3692 - 000000000F000000000000000020000000000000FFFFFFFFFFFFFFFFF4000000F000000090050000F4000000000000000100000004000000010000000000000000000000FFFFFFFF06000000CB00000057010000CC000000F08B00005A01000079070000FFFF02000B004354616262656450616E650020000000000000F4000000650000009005000006010000F40000004F00000090050000F00000000000000040280046060000000B446973617373656D626C7900000000CB00000001000000FFFFFFFFFFFFFFFF14506572666F726D616E636520416E616C797A6572000000005701000001000000FFFFFFFFFFFFFFFF14506572666F726D616E636520416E616C797A657200000000CC00000001000000FFFFFFFFFFFFFFFF0E4C6F67696320416E616C797A657200000000F08B000001000000FFFFFFFFFFFFFFFF0D436F646520436F766572616765000000005A01000001000000FFFFFFFFFFFFFFFF11496E737472756374696F6E205472616365000000007907000001000000FFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000000000000000000001000000FFFFFFFFCB00000001000000FFFFFFFFCB000000000000000040000000000000FFFFFFFFFFFFFFFF9C0400004F000000A00400006F020000000000000200000004000000010000000000000000000000FFFFFFFF2B000000E2050000CA0900002D8C00002E8C00002F8C0000308C0000318C0000328C0000338C0000348C0000358C0000368C0000378C0000388C0000398C00003A8C00003B8C00003C8C00003D8C00003E8C00003F8C0000408C0000418C000050C3000051C3000052C3000053C3000054C3000055C3000056C3000057C3000058C3000059C300005AC300005BC300005CC300005DC300005EC300005FC3000060C3000061C3000062C3000063C3000001800040000000000000A0040000650000009005000085020000A00400004F000000900500006F02000000000000404100462B0000000753796D626F6C7300000000E205000001000000FFFFFFFFFFFFFFFF0A5472616365204461746100000000CA09000001000000FFFFFFFFFFFFFFFF00000000002D8C000001000000FFFFFFFFFFFFFFFF00000000002E8C000001000000FFFFFFFFFFFFFFFF00000000002F8C000001000000FFFFFFFFFFFFFFFF0000000000308C000001000000FFFFFFFFFFFFFFFF0000000000318C000001000000FFFFFFFFFFFFFFFF0000000000328C000001000000FFFFFFFFFFFFFFFF0000000000338C000001000000FFFFFFFFFFFFFFFF0000000000348C000001000000FFFFFFFFFFFFFFFF0000000000358C000001000000FFFFFFFFFFFFFFFF0000000000368C000001000000FFFFFFFFFFFFFFFF0000000000378C000001000000FFFFFFFFFFFFFFFF0000000000388C000001000000FFFFFFFFFFFFFFFF0000000000398C000001000000FFFFFFFFFFFFFFFF00000000003A8C000001000000FFFFFFFFFFFFFFFF00000000003B8C000001000000FFFFFFFFFFFFFFFF00000000003C8C000001000000FFFFFFFFFFFFFFFF00000000003D8C000001000000FFFFFFFFFFFFFFFF00000000003E8C000001000000FFFFFFFFFFFFFFFF00000000003F8C000001000000FFFFFFFFFFFFFFFF0000000000408C000001000000FFFFFFFFFFFFFFFF0000000000418C000001000000FFFFFFFFFFFFFFFF000000000050C3000001000000FFFFFFFFFFFFFFFF000000000051C3000001000000FFFFFFFFFFFFFFFF000000000052C3000001000000FFFFFFFFFFFFFFFF000000000053C3000001000000FFFFFFFFFFFFFFFF000000000054C3000001000000FFFFFFFFFFFFFFFF000000000055C3000001000000FFFFFFFFFFFFFFFF000000000056C3000001000000FFFFFFFFFFFFFFFF000000000057C3000001000000FFFFFFFFFFFFFFFF000000000058C3000001000000FFFFFFFFFFFFFFFF000000000059C3000001000000FFFFFFFFFFFFFFFF00000000005AC3000001000000FFFFFFFFFFFFFFFF00000000005BC3000001000000FFFFFFFFFFFFFFFF00000000005CC3000001000000FFFFFFFFFFFFFFFF00000000005DC3000001000000FFFFFFFFFFFFFFFF00000000005EC3000001000000FFFFFFFFFFFFFFFF00000000005FC3000001000000FFFFFFFFFFFFFFFF000000000060C3000001000000FFFFFFFFFFFFFFFF000000000061C3000001000000FFFFFFFFFFFFFFFF000000000062C3000001000000FFFFFFFFFFFFFFFF000000000063C3000001000000FFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000000000000000000001000000FFFFFFFFE205000001000000FFFFFFFFE2050000000000000010000001000000FFFFFFFFFFFFFFFF340100004F00000038010000E703000001000000020000100400000001000000A7FEFFFF1C060000FFFFFFFF05000000ED0300006D000000C3000000C40000007394000001800010000001000000000000006500000034010000FD030000000000004F00000034010000E70300000000000040410056050000000750726F6A65637401000000ED03000001000000FFFFFFFFFFFFFFFF05426F6F6B73010000006D00000001000000FFFFFFFFFFFFFFFF0946756E6374696F6E7301000000C300000001000000FFFFFFFFFFFFFFFF0954656D706C6174657301000000C400000001000000FFFFFFFFFFFFFFFF09526567697374657273000000007394000001000000FFFFFFFFFFFFFFFF00000000000000000000000000000000000000000000000001000000FFFFFFFFED03000001000000FFFFFFFFED030000000000000080000000000000FFFFFFFFFFFFFFFF000000005B020000900500005F02000000000000010000000400000001000000000000000000000000000000000000000000000001000000C6000000FFFFFFFF0E0000008F070000930700009407000095070000960700009007000091070000B5010000B8010000B9050000BA050000BB050000BC050000CB090000018000800000000000000000000075020000900500002A030000000000005F020000900500001403000000000000404100460E0000001343616C6C20537461636B202B204C6F63616C73000000008F07000001000000FFFFFFFFFFFFFFFF0755415254202331000000009307000001000000FFFFFFFFFFFFFFFF0755415254202332000000009407000001000000FFFFFFFFFFFFFFFF0755415254202333000000009507000001000000FFFFFFFFFFFFFFFF15446562756720287072696E74662920566965776572000000009607000001000000FFFFFFFFFFFFFFFF0757617463682031000000009007000001000000FFFFFFFFFFFFFFFF0757617463682032000000009107000001000000FFFFFFFFFFFFFFFF10547261636520457863657074696F6E7300000000B501000001000000FFFFFFFFFFFFFFFF0E4576656E7420436F756E7465727300000000B801000001000000FFFFFFFFFFFFFFFF084D656D6F7279203100000000B905000001000000FFFFFFFFFFFFFFFF084D656D6F7279203200000000BA05000001000000FFFFFFFFFFFFFFFF084D656D6F7279203300000000BB05000001000000FFFFFFFFFFFFFFFF084D656D6F7279203400000000BC05000001000000FFFFFFFFFFFFFFFF105472616365204E617669676174696F6E00000000CB09000001000000FFFFFFFFFFFFFFFFFFFFFFFF0000000001000000000000000000000001000000FFFFFFFFC80200005F020000CC0200001403000000000000020000000400000000000000000000000000000000000000000000000000000002000000C6000000FFFFFFFF8F07000001000000FFFFFFFF8F07000001000000C6000000000000000080000000000000FFFFFFFFFFFFFFFF000000001E03000080070000220300000000000001000000040000000100000067FDFFFFF4000000FFFFFFFF04000000C5000000C7000000B40100007794000001800080000000000000000000003803000080070000FD030000000000002203000080070000E70300000000000040820046040000000C4275696C64204F757470757400000000C500000001000000FFFFFFFFFFFFFFFF0D46696E6420496E2046696C657300000000C700000001000000FFFFFFFFFFFFFFFF0A4572726F72204C69737400000000B401000001000000FFFFFFFFFFFFFFFF0742726F77736572000000007794000001000000FFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000000000000000000001000000FFFFFFFFC500000001000000FFFFFFFFC5000000000000000080000000000000FFFFFFFFFFFFFFFF0000000017020000900500001B0200000000000001000000040000000100000000000000000000000000000000000000000000000100000000000000FFFFFFFF0200000038030000D6010000018000800000000000000000000000000000010000003202000000000000EAFFFFFF010000001C02000000000000404100460200000009554C494E4B706C7573000000003803000001000000FFFFFFFFFFFFFFFF0F53797374656D20416E616C797A657200000000D601000001000000FFFFFFFFFFFFFFFFFFFFFFFF0000000001000000000000000000000001000000FFFFFFFFC80200001B020000CC020000BF02000000000000020000000400000000000000000000000000000000000000000000000000000001000000FFFFFFFF3803000001000000FFFFFFFF38030000000000000080000000000000FFFFFFFFFFFFFFFF00000000530300008007000057030000000000000100000004000000010000000000000000000000FFFFFFFF02000000D2010000CF01000001800080000000000000000000006D03000080070000FD030000000000005703000080070000E70300000000000040820046020000000E536F757263652042726F7773657200000000D201000001000000FFFFFFFFFFFFFFFF1346696E6420416C6C205265666572656E63657300000000CF01000001000000FFFFFFFFFFFFFFFFFFFFFFFF000000000000000000000000000000000000000001000000FFFFFFFFD201000001000000FFFFFFFFD2010000000000000000000000000000 - - - 59392 - File - - 2438 - 00200000010000002800FFFF01001100434D4643546F6F6C426172427574746F6E00E100000000000000000000000000000000000000000000000100000001000000018001E100000000000001000000000000000000000000000000000100000001000000018003E1000000000000020000000000000000000000000000000001000000010000000180CD7F0000000000000300000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018023E100000000040004000000000000000000000000000000000100000001000000018022E100000000040005000000000000000000000000000000000100000001000000018025E10000000000000600000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001802BE10000000004000700000000000000000000000000000000010000000100000001802CE10000000004000800000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001807A8A0000000004000900000000000000000000000000000000010000000100000001807B8A0000000004000A00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180D3B00000000000000B000000000000000000000000000000000100000001000000018015B10000000004000C0000000000000000000000000000000001000000010000000180F4B00000000004000D000000000000000000000000000000000100000001000000018036B10000000004000E00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180FF88000000000400460000000000000000000000000000000001000000010000000180FE880000000004004500000000000000000000000000000000010000000100000001800B810000000004001300000000000000000000000000000000010000000100000001800C810000000004001400000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180F0880000020000000F000000000000000000000000000000000100000001000000FFFF0100120043555646696E64436F6D626F427574746F6EE803000000000000000000000000000000000000000000000001000000010000009600000002002050000000000944657374726F796564960000000000000014000944657374726F79656406507265656D7006746872656164136F735274785468726561645265616479507574106F73527478546872656164426C6F636B15457672527478546872656164556E626C6F636B656413457672527478546872656164426C6F636B6564116F735274785468726561645377697463681545767252747854687265616444657374726F796564146F7352747854687265616457616974456E746572146F7352747854687265616444656C61795469636B0D7468726561642D3E7374617465126F73527478546872656164426C6F636B6564126F7352747854687265616457616974696E67204576745274784B65726E656C496E666F5265747269657665645F44657461696C194576745274784B65726E656C496E666F52657472696576656408546872656164437206236966646566136F735F69646C655F7468726561645F617474720E6F73546872656164417474725F740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000018024E10000000000001100000000000000000000000000000000010000000100000001800A810000000000001200000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018022800000020000001500000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180C488000000000000160000000000000000000000000000000001000000010000000180C988000000000400180000000000000000000000000000000001000000010000000180C788000000000000190000000000000000000000000000000001000000010000000180C8880000000000001700000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000FFFF01001500434D4643546F6F6C4261724D656E75427574746F6E4C010000020001001A0000000F2650726F6A6563742057696E646F77000000000000000000000000010000000100000000000000000000000100000008002880DD880000000000001A0000000750726F6A656374000000000000000000000000010000000100000000000000000000000100000000002880DC8B0000000000003A00000005426F6F6B73000000000000000000000000010000000100000000000000000000000100000000002880E18B0000000000003B0000000946756E6374696F6E73000000000000000000000000010000000100000000000000000000000100000000002880E28B000000000000400000000954656D706C6174657300000000000000000000000001000000010000000000000000000000010000000000288018890000000000003D0000000E536F757263652042726F777365720000000000000000000000000100000001000000000000000000000001000000000028800000000000000400FFFFFFFF00000000000000000001000000000000000100000000000000000000000100000000002880D988000000000000390000000C4275696C64204F7574707574000000000000000000000000010000000100000000000000000000000100000000002880E38B000000000000410000000B46696E64204F75747075740000000000000000000000000100000001000000000000000000000001000000000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180FB7F0000000000001B000000000000000000000000000000000100000001000000000000000446696C65AC030000 - - - 1423 - 2800FFFF01001100434D4643546F6F6C426172427574746F6E00E1000000000000FFFFFFFF000100000000000000010000000000000001000000018001E1000000000000FFFFFFFF000100000000000000010000000000000001000000018003E1000000000000FFFFFFFF0001000000000000000100000000000000010000000180CD7F000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF000000000000000000010000000000000001000000018023E1000000000000FFFFFFFF000100000000000000010000000000000001000000018022E1000000000000FFFFFFFF000100000000000000010000000000000001000000018025E1000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001802BE1000000000000FFFFFFFF00010000000000000001000000000000000100000001802CE1000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001807A8A000000000000FFFFFFFF00010000000000000001000000000000000100000001807B8A000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF0000000000000000000100000000000000010000000180D3B0000000000000FFFFFFFF000100000000000000010000000000000001000000018015B1000000000000FFFFFFFF0001000000000000000100000000000000010000000180F4B0000000000000FFFFFFFF000100000000000000010000000000000001000000018036B1000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF0000000000000000000100000000000000010000000180FF88000000000000FFFFFFFF0001000000000000000100000000000000010000000180FE88000000000000FFFFFFFF00010000000000000001000000000000000100000001800B81000000000000FFFFFFFF00010000000000000001000000000000000100000001800C81000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF0000000000000000000100000000000000010000000180F088000000000000FFFFFFFF0001000000000000000100000000000000010000000180EE7F000000000000FFFFFFFF000100000000000000010000000000000001000000018024E1000000000000FFFFFFFF00010000000000000001000000000000000100000001800A81000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001802280000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF0000000000000000000100000000000000010000000180C488000000000000FFFFFFFF0001000000000000000100000000000000010000000180C988000000000000FFFFFFFF0001000000000000000100000000000000010000000180C788000000000000FFFFFFFF0001000000000000000100000000000000010000000180C888000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF0000000000000000000100000000000000010000000180DD88000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF0000000000000000000100000000000000010000000180FB7F000000000000FFFFFFFF000100000000000000010000000000000001000000 - - - 1423 - 2800FFFF01001100434D4643546F6F6C426172427574746F6E00E100000000000000000000000000000000000000000000000100000001000000018001E100000000000001000000000000000000000000000000000100000001000000018003E1000000000000020000000000000000000000000000000001000000010000000180CD7F0000000000000300000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018023E100000000000004000000000000000000000000000000000100000001000000018022E100000000000005000000000000000000000000000000000100000001000000018025E10000000000000600000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001802BE10000000000000700000000000000000000000000000000010000000100000001802CE10000000000000800000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001807A8A0000000000000900000000000000000000000000000000010000000100000001807B8A0000000000000A00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180D3B00000000000000B000000000000000000000000000000000100000001000000018015B10000000000000C0000000000000000000000000000000001000000010000000180F4B00000000000000D000000000000000000000000000000000100000001000000018036B10000000000000E00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180FF880000000000000F0000000000000000000000000000000001000000010000000180FE880000000000001000000000000000000000000000000000010000000100000001800B810000000000001100000000000000000000000000000000010000000100000001800C810000000000001200000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180F088000000000000130000000000000000000000000000000001000000010000000180EE7F00000000000014000000000000000000000000000000000100000001000000018024E10000000000001500000000000000000000000000000000010000000100000001800A810000000000001600000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018022800000000000001700000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180C488000000000000180000000000000000000000000000000001000000010000000180C988000000000000190000000000000000000000000000000001000000010000000180C7880000000000001A0000000000000000000000000000000001000000010000000180C8880000000000001B00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180DD880000000000001C00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180FB7F0000000000001D000000000000000000000000000000000100000001000000 - - - - 59399 - Build - - 1000 - 00200000010000001000FFFF01001100434D4643546F6F6C426172427574746F6ECF7F0000000004001C0000000000000000000000000000000001000000010000000180D07F0000000000001D000000000000000000000000000000000100000001000000018030800000000000001E000000000000000000000000000000000100000001000000FFFF01001500434D4643546F6F6C4261724D656E75427574746F6EC7040000000000006A0000000C4261746368204275696C2664000000000000000000000000010000000100000000000000000000000100000004000580C7040000000000006A0000000C4261746368204275696C266400000000000000000000000001000000010000000000000000000000010000000000058046070000000000006B0000000D42617463682052656275696C640000000000000000000000000100000001000000000000000000000001000000000005804707000000000000FFFFFFFF0B426174636820436C65616E0100000000000000000000000100000001000000000000000000000001000000000005809E8A0000000000001F0000000F4261746326682053657475702E2E2E000000000000000000000000010000000100000000000000000000000100000000000180D17F0000000004002000000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001804C8A0000000004002100000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000FFFF01001900434D4643546F6F6C426172436F6D626F426F78427574746F6EBA0000000000000000000000000000000000000000000000000100000001000000960000000300205000000000144656502053696D756C6174696F6E204D6F64656C96000000000000000100144656502053696D756C6174696F6E204D6F64656C000000000180EB880000000000002200000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180C07F000000000000230000000000000000000000000000000001000000010000000180B08A000000000000240000000000000000000000000000000001000000010000000180A8010000000000004E00000000000000000000000000000000010000000100000001807202000000000000530000000000000000000000000000000001000000010000000180BE010000000000005000000000000000000000000000000000010000000100000000000000054275696C642F010000 - - - 583 - 1000FFFF01001100434D4643546F6F6C426172427574746F6ECF7F000000000000FFFFFFFF0001000000000000000100000000000000010000000180D07F000000000000FFFFFFFF00010000000000000001000000000000000100000001803080000000000000FFFFFFFF00010000000000000001000000000000000100000001809E8A000000000000FFFFFFFF0001000000000000000100000000000000010000000180D17F000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001804C8A000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001806680000000000000FFFFFFFF0001000000000000000100000000000000010000000180EB88000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF0000000000000000000100000000000000010000000180C07F000000000000FFFFFFFF0001000000000000000100000000000000010000000180B08A000000000000FFFFFFFF0001000000000000000100000000000000010000000180A801000000000000FFFFFFFF00010000000000000001000000000000000100000001807202000000000000FFFFFFFF0001000000000000000100000000000000010000000180BE01000000000000FFFFFFFF000100000000000000010000000000000001000000 - - - 583 - 1000FFFF01001100434D4643546F6F6C426172427574746F6ECF7F000000000000000000000000000000000000000000000001000000010000000180D07F00000000000001000000000000000000000000000000000100000001000000018030800000000000000200000000000000000000000000000000010000000100000001809E8A000000000000030000000000000000000000000000000001000000010000000180D17F0000000000000400000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001804C8A0000000000000500000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001806680000000000000060000000000000000000000000000000001000000010000000180EB880000000000000700000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180C07F000000000000080000000000000000000000000000000001000000010000000180B08A000000000000090000000000000000000000000000000001000000010000000180A8010000000000000A000000000000000000000000000000000100000001000000018072020000000000000B0000000000000000000000000000000001000000010000000180BE010000000000000C000000000000000000000000000000000100000001000000 - - - - 59400 - Debug - - 2373 - 00200000000000001900FFFF01001100434D4643546F6F6C426172427574746F6ECC880000000000002500000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018017800000000000002600000000000000000000000000000000010000000100000001801D800000000000002700000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001801A800000000000002800000000000000000000000000000000010000000100000001801B80000000000000290000000000000000000000000000000001000000010000000180E57F0000000000002A00000000000000000000000000000000010000000100000001801C800000000000002B00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018000890000000000002C00000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180E48B0000000000002D0000000000000000000000000000000001000000010000000180F07F0000000000002E0000000000000000000000000000000001000000010000000180E8880000000000003700000000000000000000000000000000010000000100000001803B010000000000002F0000000000000000000000000000000001000000010000000180BB8A00000000000030000000000000000000000000000000000100000001000000FFFF01001500434D4643546F6F6C4261724D656E75427574746F6E0E01000000000000310000000D57617463682057696E646F7773000000000000000000000000010000000100000000000000000000000100000003001380D88B00000000000031000000085761746368202631000000000000000000000000010000000100000000000000000000000100000000001380D98B00000000000031000000085761746368202632000000000000000000000000010000000100000000000000000000000100000000001380CE01000000000000FFFFFFFF0C576174636820416E63686F720000000000000000010000000000000001000000000000000000000001000000000013800F01000000000000320000000E4D656D6F72792057696E646F7773000000000000000000000000010000000100000000000000000000000100000004001380D28B00000000000032000000094D656D6F7279202631000000000000000000000000010000000100000000000000000000000100000000001380D38B00000000000032000000094D656D6F7279202632000000000000000000000000010000000100000000000000000000000100000000001380D48B00000000000032000000094D656D6F7279202633000000000000000000000000010000000100000000000000000000000100000000001380D58B00000000000032000000094D656D6F72792026340000000000000000000000000100000001000000000000000000000001000000000013801001000000000000330000000E53657269616C2057696E646F77730000000000000000000000000100000001000000000000000000000001000000040013809307000000000000330000000855415254202326310000000000000000000000000100000001000000000000000000000001000000000013809407000000000000330000000855415254202326320000000000000000000000000100000001000000000000000000000001000000000013809507000000000000330000000855415254202326330000000000000000000000000100000001000000000000000000000001000000000013809607000000000000330000001626446562756720287072696E746629205669657765720000000000000000000000000100000001000000000000000000000001000000000013803C010000000000003400000010416E616C797369732057696E646F7773000000000000000000000000010000000100000000000000000000000100000004001380658A000000000000340000000F264C6F67696320416E616C797A6572000000000000000000000000010000000100000000000000000000000100000000001380DC7F0000000000003E0000001526506572666F726D616E636520416E616C797A6572000000000000000000000000010000000100000000000000000000000100000000001380E788000000000000380000000E26436F646520436F766572616765000000000000000000000000010000000100000000000000000000000100000000001380CD01000000000000FFFFFFFF0F416E616C7973697320416E63686F7200000000000000000100000000000000010000000000000000000000010000000000138053010000000000003F0000000D54726163652057696E646F77730000000000000000000000000100000001000000000000000000000001000000010013805401000000000000FFFFFFFF115472616365204D656E7520416E63686F720000000000000000010000000000000001000000000000000000000001000000000013802901000000000000350000001553797374656D205669657765722057696E646F77730000000000000000000000000100000001000000000000000000000001000000010013804B01000000000000FFFFFFFF1453797374656D2056696577657220416E63686F720000000000000000010000000000000001000000000000000000000001000000000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000013800189000000000000360000000F26546F6F6C626F782057696E646F7700000000000000000000000001000000010000000000000000000000010000000300138044C5000000000000FFFFFFFF0E5570646174652057696E646F77730000000000000000010000000000000001000000000000000000000001000000000013800000000000000400FFFFFFFF000000000000000000010000000000000001000000000000000000000001000000000013805B01000000000000FFFFFFFF12546F6F6C626F78204D656E75416E63686F72000000000000000001000000000000000100000000000000000000000100000000000000000005446562756764020000 - - - 898 - 1900FFFF01001100434D4643546F6F6C426172427574746F6ECC88000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001801780000000000000FFFFFFFF00010000000000000001000000000000000100000001801D80000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001801A80000000000000FFFFFFFF00010000000000000001000000000000000100000001801B80000000000000FFFFFFFF0001000000000000000100000000000000010000000180E57F000000000000FFFFFFFF00010000000000000001000000000000000100000001801C80000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001800089000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF0000000000000000000100000000000000010000000180E48B000000000000FFFFFFFF0001000000000000000100000000000000010000000180F07F000000000000FFFFFFFF0001000000000000000100000000000000010000000180E888000000000000FFFFFFFF00010000000000000001000000000000000100000001803B01000000000000FFFFFFFF0001000000000000000100000000000000010000000180BB8A000000000000FFFFFFFF0001000000000000000100000000000000010000000180D88B000000000000FFFFFFFF0001000000000000000100000000000000010000000180D28B000000000000FFFFFFFF00010000000000000001000000000000000100000001809307000000000000FFFFFFFF0001000000000000000100000000000000010000000180658A000000000000FFFFFFFF0001000000000000000100000000000000010000000180C18A000000000000FFFFFFFF0001000000000000000100000000000000010000000180EE8B000000000000FFFFFFFF00010000000000000001000000000000000100000001800000000000000000FFFFFFFF00000000000000000001000000000000000100000001800189000000000000FFFFFFFF000100000000000000010000000000000001000000 - - - 898 - 1900FFFF01001100434D4643546F6F6C426172427574746F6ECC880000000000000000000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018017800000000000000100000000000000000000000000000000010000000100000001801D800000000000000200000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF00000000000000000000000000010000000100000001801A800000000000000300000000000000000000000000000000010000000100000001801B80000000000000040000000000000000000000000000000001000000010000000180E57F0000000000000500000000000000000000000000000000010000000100000001801C800000000000000600000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF000000000000000000000000000100000001000000018000890000000000000700000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180E48B000000000000080000000000000000000000000000000001000000010000000180F07F000000000000090000000000000000000000000000000001000000010000000180E8880000000000000A00000000000000000000000000000000010000000100000001803B010000000000000B0000000000000000000000000000000001000000010000000180BB8A0000000000000C0000000000000000000000000000000001000000010000000180D88B0000000000000D0000000000000000000000000000000001000000010000000180D28B0000000000000E000000000000000000000000000000000100000001000000018093070000000000000F0000000000000000000000000000000001000000010000000180658A000000000000100000000000000000000000000000000001000000010000000180C18A000000000000110000000000000000000000000000000001000000010000000180EE8B0000000000001200000000000000000000000000000000010000000100000001800000000001000000FFFFFFFF0000000000000000000000000001000000010000000180018900000000000013000000000000000000000000000000000100000001000000 - - - - 0 - 1920 - 1080 - - - - - - 1 - 0 - - 100 - 0 - - <1>.\Abstract.txt - 0 - 1 - 1 - 0 - - 0 - - - - -
diff --git a/ports_module/cortex_m33/ac6/example_build/ThreadX_Library.uvoptx b/ports_module/cortex_m33/ac6/example_build/ThreadX_Library.uvoptx deleted file mode 100644 index 015946e6c..000000000 --- a/ports_module/cortex_m33/ac6/example_build/ThreadX_Library.uvoptx +++ /dev/null @@ -1,2972 +0,0 @@ - - - - 1.0 - -
### uVision Project, (C) Keil Software
- - - *.c - *.s*; *.src; *.a* - *.obj; *.o - *.lib - *.txt; *.h; *.inc - *.plm - *.cpp - 0 - - - - 0 - 0 - - - - ThreadX_Library_Project - 0x4 - ARM-ADS - - 12000000 - - 1 - 1 - 0 - 1 - 0 - - - 1 - 65535 - 0 - 0 - 0 - - - 79 - 66 - 8 - .\ - - - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - - - 0 - 0 - 1 - - 7 - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 1 - 1 - 0 - 0 - 1 - 0 - 0 - 13 - - - - - - - - - - - BIN\UL2V8M.DLL - - - - 0 - UL2V8M - UL2V8M(-S0 -C0 -P0 -FD20000000 -FC1000) - - - - - 0 - - - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - - - - - - - - - - - - - Source Group - 0 - 0 - 0 - 0 - - 1 - 1 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_allocate.c - tx_block_allocate.c - 0 - 0 - - - 1 - 2 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_cleanup.c - tx_block_pool_cleanup.c - 0 - 0 - - - 1 - 3 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_create.c - tx_block_pool_create.c - 0 - 0 - - - 1 - 4 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_delete.c - tx_block_pool_delete.c - 0 - 0 - - - 1 - 5 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_info_get.c - tx_block_pool_info_get.c - 0 - 0 - - - 1 - 6 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_initialize.c - tx_block_pool_initialize.c - 0 - 0 - - - 1 - 7 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_performance_info_get.c - tx_block_pool_performance_info_get.c - 0 - 0 - - - 1 - 8 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_performance_system_info_get.c - tx_block_pool_performance_system_info_get.c - 0 - 0 - - - 1 - 9 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_pool_prioritize.c - tx_block_pool_prioritize.c - 0 - 0 - - - 1 - 10 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_block_release.c - tx_block_release.c - 0 - 0 - - - 1 - 11 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_allocate.c - tx_byte_allocate.c - 0 - 0 - - - 1 - 12 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_cleanup.c - tx_byte_pool_cleanup.c - 0 - 0 - - - 1 - 13 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_create.c - tx_byte_pool_create.c - 0 - 0 - - - 1 - 14 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_delete.c - tx_byte_pool_delete.c - 0 - 0 - - - 1 - 15 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_info_get.c - tx_byte_pool_info_get.c - 0 - 0 - - - 1 - 16 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_initialize.c - tx_byte_pool_initialize.c - 0 - 0 - - - 1 - 17 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_performance_info_get.c - tx_byte_pool_performance_info_get.c - 0 - 0 - - - 1 - 18 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_performance_system_info_get.c - tx_byte_pool_performance_system_info_get.c - 0 - 0 - - - 1 - 19 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_prioritize.c - tx_byte_pool_prioritize.c - 0 - 0 - - - 1 - 20 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_pool_search.c - tx_byte_pool_search.c - 0 - 0 - - - 1 - 21 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_byte_release.c - tx_byte_release.c - 0 - 0 - - - 1 - 22 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_cleanup.c - tx_event_flags_cleanup.c - 0 - 0 - - - 1 - 23 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_create.c - tx_event_flags_create.c - 0 - 0 - - - 1 - 24 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_delete.c - tx_event_flags_delete.c - 0 - 0 - - - 1 - 25 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_get.c - tx_event_flags_get.c - 0 - 0 - - - 1 - 26 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_info_get.c - tx_event_flags_info_get.c - 0 - 0 - - - 1 - 27 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_initialize.c - tx_event_flags_initialize.c - 0 - 0 - - - 1 - 28 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_performance_info_get.c - tx_event_flags_performance_info_get.c - 0 - 0 - - - 1 - 29 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_performance_system_info_get.c - tx_event_flags_performance_system_info_get.c - 0 - 0 - - - 1 - 30 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_set.c - tx_event_flags_set.c - 0 - 0 - - - 1 - 31 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_event_flags_set_notify.c - tx_event_flags_set_notify.c - 0 - 0 - - - 1 - 32 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_initialize_high_level.c - tx_initialize_high_level.c - 0 - 0 - - - 1 - 33 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_initialize_kernel_enter.c - tx_initialize_kernel_enter.c - 0 - 0 - - - 1 - 34 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_initialize_kernel_setup.c - tx_initialize_kernel_setup.c - 0 - 0 - - - 1 - 35 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_cleanup.c - tx_mutex_cleanup.c - 0 - 0 - - - 1 - 36 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_create.c - tx_mutex_create.c - 0 - 0 - - - 1 - 37 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_delete.c - tx_mutex_delete.c - 0 - 0 - - - 1 - 38 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_get.c - tx_mutex_get.c - 0 - 0 - - - 1 - 39 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_info_get.c - tx_mutex_info_get.c - 0 - 0 - - - 1 - 40 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_initialize.c - tx_mutex_initialize.c - 0 - 0 - - - 1 - 41 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_performance_info_get.c - tx_mutex_performance_info_get.c - 0 - 0 - - - 1 - 42 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_performance_system_info_get.c - tx_mutex_performance_system_info_get.c - 0 - 0 - - - 1 - 43 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_prioritize.c - tx_mutex_prioritize.c - 0 - 0 - - - 1 - 44 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_priority_change.c - tx_mutex_priority_change.c - 0 - 0 - - - 1 - 45 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_mutex_put.c - tx_mutex_put.c - 0 - 0 - - - 1 - 46 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_cleanup.c - tx_queue_cleanup.c - 0 - 0 - - - 1 - 47 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_create.c - tx_queue_create.c - 0 - 0 - - - 1 - 48 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_delete.c - tx_queue_delete.c - 0 - 0 - - - 1 - 49 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_flush.c - tx_queue_flush.c - 0 - 0 - - - 1 - 50 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_front_send.c - tx_queue_front_send.c - 0 - 0 - - - 1 - 51 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_info_get.c - tx_queue_info_get.c - 0 - 0 - - - 1 - 52 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_initialize.c - tx_queue_initialize.c - 0 - 0 - - - 1 - 53 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_performance_info_get.c - tx_queue_performance_info_get.c - 0 - 0 - - - 1 - 54 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_performance_system_info_get.c - tx_queue_performance_system_info_get.c - 0 - 0 - - - 1 - 55 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_prioritize.c - tx_queue_prioritize.c - 0 - 0 - - - 1 - 56 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_receive.c - tx_queue_receive.c - 0 - 0 - - - 1 - 57 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_send.c - tx_queue_send.c - 0 - 0 - - - 1 - 58 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_queue_send_notify.c - tx_queue_send_notify.c - 0 - 0 - - - 1 - 59 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_ceiling_put.c - tx_semaphore_ceiling_put.c - 0 - 0 - - - 1 - 60 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_cleanup.c - tx_semaphore_cleanup.c - 0 - 0 - - - 1 - 61 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_create.c - tx_semaphore_create.c - 0 - 0 - - - 1 - 62 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_delete.c - tx_semaphore_delete.c - 0 - 0 - - - 1 - 63 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_get.c - tx_semaphore_get.c - 0 - 0 - - - 1 - 64 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_info_get.c - tx_semaphore_info_get.c - 0 - 0 - - - 1 - 65 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_initialize.c - tx_semaphore_initialize.c - 0 - 0 - - - 1 - 66 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_performance_info_get.c - tx_semaphore_performance_info_get.c - 0 - 0 - - - 1 - 67 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_performance_system_info_get.c - tx_semaphore_performance_system_info_get.c - 0 - 0 - - - 1 - 68 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_prioritize.c - tx_semaphore_prioritize.c - 0 - 0 - - - 1 - 69 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_put.c - tx_semaphore_put.c - 0 - 0 - - - 1 - 70 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_semaphore_put_notify.c - tx_semaphore_put_notify.c - 0 - 0 - - - 1 - 71 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_create.c - tx_thread_create.c - 0 - 0 - - - 1 - 72 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_delete.c - tx_thread_delete.c - 0 - 0 - - - 1 - 73 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_entry_exit_notify.c - tx_thread_entry_exit_notify.c - 0 - 0 - - - 1 - 74 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_identify.c - tx_thread_identify.c - 0 - 0 - - - 1 - 75 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_info_get.c - tx_thread_info_get.c - 0 - 0 - - - 1 - 76 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_initialize.c - tx_thread_initialize.c - 0 - 0 - - - 1 - 77 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_performance_info_get.c - tx_thread_performance_info_get.c - 0 - 0 - - - 1 - 78 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_performance_system_info_get.c - tx_thread_performance_system_info_get.c - 0 - 0 - - - 1 - 79 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_preemption_change.c - tx_thread_preemption_change.c - 0 - 0 - - - 1 - 80 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_priority_change.c - tx_thread_priority_change.c - 0 - 0 - - - 1 - 81 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_relinquish.c - tx_thread_relinquish.c - 0 - 0 - - - 1 - 82 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_reset.c - tx_thread_reset.c - 0 - 0 - - - 1 - 83 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_resume.c - tx_thread_resume.c - 0 - 0 - - - 1 - 84 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_shell_entry.c - tx_thread_shell_entry.c - 0 - 0 - - - 1 - 85 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_sleep.c - tx_thread_sleep.c - 0 - 0 - - - 1 - 86 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_stack_analyze.c - tx_thread_stack_analyze.c - 0 - 0 - - - 1 - 87 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_suspend.c - tx_thread_suspend.c - 0 - 0 - - - 1 - 88 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_system_preempt_check.c - tx_thread_system_preempt_check.c - 0 - 0 - - - 1 - 89 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_system_resume.c - tx_thread_system_resume.c - 0 - 0 - - - 1 - 90 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_system_suspend.c - tx_thread_system_suspend.c - 0 - 0 - - - 1 - 91 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_terminate.c - tx_thread_terminate.c - 0 - 0 - - - 1 - 92 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_time_slice.c - tx_thread_time_slice.c - 0 - 0 - - - 1 - 93 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_time_slice_change.c - tx_thread_time_slice_change.c - 0 - 0 - - - 1 - 94 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_timeout.c - tx_thread_timeout.c - 0 - 0 - - - 1 - 95 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_wait_abort.c - tx_thread_wait_abort.c - 0 - 0 - - - 1 - 96 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_time_get.c - tx_time_get.c - 0 - 0 - - - 1 - 97 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_time_set.c - tx_time_set.c - 0 - 0 - - - 1 - 98 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_activate.c - tx_timer_activate.c - 0 - 0 - - - 1 - 99 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_change.c - tx_timer_change.c - 0 - 0 - - - 1 - 100 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_create.c - tx_timer_create.c - 0 - 0 - - - 1 - 101 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_deactivate.c - tx_timer_deactivate.c - 0 - 0 - - - 1 - 102 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_delete.c - tx_timer_delete.c - 0 - 0 - - - 1 - 103 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_expiration_process.c - tx_timer_expiration_process.c - 0 - 0 - - - 1 - 104 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_info_get.c - tx_timer_info_get.c - 0 - 0 - - - 1 - 105 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_initialize.c - tx_timer_initialize.c - 0 - 0 - - - 1 - 106 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_performance_info_get.c - tx_timer_performance_info_get.c - 0 - 0 - - - 1 - 107 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_performance_system_info_get.c - tx_timer_performance_system_info_get.c - 0 - 0 - - - 1 - 108 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_system_activate.c - tx_timer_system_activate.c - 0 - 0 - - - 1 - 109 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_system_deactivate.c - tx_timer_system_deactivate.c - 0 - 0 - - - 1 - 110 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_timer_thread_entry.c - tx_timer_thread_entry.c - 0 - 0 - - - 1 - 111 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_disable.c - tx_trace_disable.c - 0 - 0 - - - 1 - 112 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_enable.c - tx_trace_enable.c - 0 - 0 - - - 1 - 113 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_initialize.c - tx_trace_initialize.c - 0 - 0 - - - 1 - 114 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_interrupt_control.c - tx_trace_interrupt_control.c - 0 - 0 - - - 1 - 115 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_isr_enter_insert.c - tx_trace_isr_enter_insert.c - 0 - 0 - - - 1 - 116 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_isr_exit_insert.c - tx_trace_isr_exit_insert.c - 0 - 0 - - - 1 - 117 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_object_register.c - tx_trace_object_register.c - 0 - 0 - - - 1 - 118 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_object_unregister.c - tx_trace_object_unregister.c - 0 - 0 - - - 1 - 119 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_user_event_insert.c - tx_trace_user_event_insert.c - 0 - 0 - - - 1 - 120 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_allocate.c - txe_block_allocate.c - 0 - 0 - - - 1 - 121 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_pool_create.c - txe_block_pool_create.c - 0 - 0 - - - 1 - 122 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_pool_delete.c - txe_block_pool_delete.c - 0 - 0 - - - 1 - 123 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_pool_info_get.c - txe_block_pool_info_get.c - 0 - 0 - - - 1 - 124 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_pool_prioritize.c - txe_block_pool_prioritize.c - 0 - 0 - - - 1 - 125 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_block_release.c - txe_block_release.c - 0 - 0 - - - 1 - 126 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_allocate.c - txe_byte_allocate.c - 0 - 0 - - - 1 - 127 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_pool_create.c - txe_byte_pool_create.c - 0 - 0 - - - 1 - 128 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_pool_delete.c - txe_byte_pool_delete.c - 0 - 0 - - - 1 - 129 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_pool_info_get.c - txe_byte_pool_info_get.c - 0 - 0 - - - 1 - 130 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_pool_prioritize.c - txe_byte_pool_prioritize.c - 0 - 0 - - - 1 - 131 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_byte_release.c - txe_byte_release.c - 0 - 0 - - - 1 - 132 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_create.c - txe_event_flags_create.c - 0 - 0 - - - 1 - 133 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_delete.c - txe_event_flags_delete.c - 0 - 0 - - - 1 - 134 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_get.c - txe_event_flags_get.c - 0 - 0 - - - 1 - 135 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_info_get.c - txe_event_flags_info_get.c - 0 - 0 - - - 1 - 136 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_set.c - txe_event_flags_set.c - 0 - 0 - - - 1 - 137 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_event_flags_set_notify.c - txe_event_flags_set_notify.c - 0 - 0 - - - 1 - 138 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_create.c - txe_mutex_create.c - 0 - 0 - - - 1 - 139 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_delete.c - txe_mutex_delete.c - 0 - 0 - - - 1 - 140 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_get.c - txe_mutex_get.c - 0 - 0 - - - 1 - 141 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_info_get.c - txe_mutex_info_get.c - 0 - 0 - - - 1 - 142 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_prioritize.c - txe_mutex_prioritize.c - 0 - 0 - - - 1 - 143 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_mutex_put.c - txe_mutex_put.c - 0 - 0 - - - 1 - 144 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_create.c - txe_queue_create.c - 0 - 0 - - - 1 - 145 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_delete.c - txe_queue_delete.c - 0 - 0 - - - 1 - 146 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_flush.c - txe_queue_flush.c - 0 - 0 - - - 1 - 147 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_front_send.c - txe_queue_front_send.c - 0 - 0 - - - 1 - 148 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_info_get.c - txe_queue_info_get.c - 0 - 0 - - - 1 - 149 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_prioritize.c - txe_queue_prioritize.c - 0 - 0 - - - 1 - 150 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_receive.c - txe_queue_receive.c - 0 - 0 - - - 1 - 151 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_send.c - txe_queue_send.c - 0 - 0 - - - 1 - 152 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_queue_send_notify.c - txe_queue_send_notify.c - 0 - 0 - - - 1 - 153 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_ceiling_put.c - txe_semaphore_ceiling_put.c - 0 - 0 - - - 1 - 154 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_create.c - txe_semaphore_create.c - 0 - 0 - - - 1 - 155 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_delete.c - txe_semaphore_delete.c - 0 - 0 - - - 1 - 156 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_get.c - txe_semaphore_get.c - 0 - 0 - - - 1 - 157 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_info_get.c - txe_semaphore_info_get.c - 0 - 0 - - - 1 - 158 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_prioritize.c - txe_semaphore_prioritize.c - 0 - 0 - - - 1 - 159 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_put.c - txe_semaphore_put.c - 0 - 0 - - - 1 - 160 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_semaphore_put_notify.c - txe_semaphore_put_notify.c - 0 - 0 - - - 1 - 161 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_create.c - txe_thread_create.c - 0 - 0 - - - 1 - 162 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_delete.c - txe_thread_delete.c - 0 - 0 - - - 1 - 163 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_entry_exit_notify.c - txe_thread_entry_exit_notify.c - 0 - 0 - - - 1 - 164 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_info_get.c - txe_thread_info_get.c - 0 - 0 - - - 1 - 165 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_preemption_change.c - txe_thread_preemption_change.c - 0 - 0 - - - 1 - 166 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_priority_change.c - txe_thread_priority_change.c - 0 - 0 - - - 1 - 167 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_relinquish.c - txe_thread_relinquish.c - 0 - 0 - - - 1 - 168 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_reset.c - txe_thread_reset.c - 0 - 0 - - - 1 - 169 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_resume.c - txe_thread_resume.c - 0 - 0 - - - 1 - 170 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_suspend.c - txe_thread_suspend.c - 0 - 0 - - - 1 - 171 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_terminate.c - txe_thread_terminate.c - 0 - 0 - - - 1 - 172 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_time_slice_change.c - txe_thread_time_slice_change.c - 0 - 0 - - - 1 - 173 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_thread_wait_abort.c - txe_thread_wait_abort.c - 0 - 0 - - - 1 - 174 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_activate.c - txe_timer_activate.c - 0 - 0 - - - 1 - 175 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_change.c - txe_timer_change.c - 0 - 0 - - - 1 - 176 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_create.c - txe_timer_create.c - 0 - 0 - - - 1 - 177 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_deactivate.c - txe_timer_deactivate.c - 0 - 0 - - - 1 - 178 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_delete.c - txe_timer_delete.c - 0 - 0 - - - 1 - 179 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\txe_timer_info_get.c - txe_timer_info_get.c - 0 - 0 - - - 1 - 180 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_buffer_full_notify.c - tx_trace_buffer_full_notify.c - 0 - 0 - - - 1 - 181 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_event_filter.c - tx_trace_event_filter.c - 0 - 0 - - - 1 - 182 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_trace_event_unfilter.c - tx_trace_event_unfilter.c - 0 - 0 - - - 1 - 183 - 1 - 0 - 0 - 0 - ..\module_manager\src\txe_thread_secure_stack_allocate.c - txe_thread_secure_stack_allocate.c - 0 - 0 - - - 1 - 184 - 1 - 0 - 0 - 0 - ..\module_manager\src\txe_thread_secure_stack_free.c - txe_thread_secure_stack_free.c - 0 - 0 - - - 1 - 185 - 2 - 0 - 0 - 0 - ..\module_manager\src\tx_thread_context_restore.S - tx_thread_context_restore.S - 0 - 0 - - - 1 - 188 - 2 - 0 - 0 - 0 - ..\module_manager\src\tx_thread_context_save.S - tx_thread_context_save.S - 0 - 0 - - - 1 - 189 - 2 - 0 - 0 - 0 - ..\module_manager\src\tx_thread_interrupt_control.S - tx_thread_interrupt_control.S - 0 - 0 - - - 1 - 190 - 2 - 0 - 0 - 0 - ..\module_manager\src\tx_thread_interrupt_disable.S - tx_thread_interrupt_disable.S - 0 - 0 - - - 1 - 191 - 2 - 0 - 0 - 0 - ..\module_manager\src\tx_thread_interrupt_restore.S - tx_thread_interrupt_restore.S - 0 - 0 - - - 1 - 192 - 2 - 0 - 0 - 0 - ..\module_manager\src\tx_thread_schedule.S - tx_thread_schedule.S - 0 - 0 - - - 1 - 193 - 2 - 0 - 0 - 0 - ..\module_manager\src\tx_thread_secure_stack_allocate.S - tx_thread_secure_stack_allocate.S - 0 - 0 - - - 1 - 194 - 2 - 0 - 0 - 0 - ..\module_manager\src\tx_thread_secure_stack_free.S - tx_thread_secure_stack_free.S - 0 - 0 - - - 1 - 195 - 2 - 0 - 0 - 0 - ..\module_manager\src\tx_thread_stack_build.S - tx_thread_stack_build.S - 0 - 0 - - - 1 - 196 - 2 - 0 - 0 - 0 - ..\module_manager\src\tx_thread_system_return.S - tx_thread_system_return.S - 0 - 0 - - - 1 - 197 - 2 - 0 - 0 - 0 - ..\module_manager\src\tx_timer_interrupt.S - tx_timer_interrupt.S - 0 - 0 - - - 1 - 198 - 2 - 0 - 0 - 0 - .\tx_initialize_low_level.S - tx_initialize_low_level.S - 0 - 0 - - - 1 - 199 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_application_request.c - txm_module_manager_application_request.c - 0 - 0 - - - 1 - 200 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_callback_request.c - txm_module_manager_callback_request.c - 0 - 0 - - - 1 - 201 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_event_flags_notify_trampoline.c - txm_module_manager_event_flags_notify_trampoline.c - 0 - 0 - - - 1 - 202 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_file_load.c - txm_module_manager_file_load.c - 0 - 0 - - - 1 - 203 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_in_place_load.c - txm_module_manager_in_place_load.c - 0 - 0 - - - 1 - 204 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_initialize.c - txm_module_manager_initialize.c - 0 - 0 - - - 1 - 205 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_internal_load.c - txm_module_manager_internal_load.c - 0 - 0 - - - 1 - 206 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_kernel_dispatch.c - txm_module_manager_kernel_dispatch.c - 0 - 0 - - - 1 - 207 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_maximum_module_priority_set.c - txm_module_manager_maximum_module_priority_set.c - 0 - 0 - - - 1 - 208 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_memory_load.c - txm_module_manager_memory_load.c - 0 - 0 - - - 1 - 209 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_object_allocate.c - txm_module_manager_object_allocate.c - 0 - 0 - - - 1 - 210 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_object_deallocate.c - txm_module_manager_object_deallocate.c - 0 - 0 - - - 1 - 211 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_object_pointer_get.c - txm_module_manager_object_pointer_get.c - 0 - 0 - - - 1 - 212 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_object_pointer_get_extended.c - txm_module_manager_object_pointer_get_extended.c - 0 - 0 - - - 1 - 213 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_object_pool_create.c - txm_module_manager_object_pool_create.c - 0 - 0 - - - 1 - 214 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_properties_get.c - txm_module_manager_properties_get.c - 0 - 0 - - - 1 - 215 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_queue_notify_trampoline.c - txm_module_manager_queue_notify_trampoline.c - 0 - 0 - - - 1 - 216 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_semaphore_notify_trampoline.c - txm_module_manager_semaphore_notify_trampoline.c - 0 - 0 - - - 1 - 217 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_start.c - txm_module_manager_start.c - 0 - 0 - - - 1 - 218 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_stop.c - txm_module_manager_stop.c - 0 - 0 - - - 1 - 219 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_thread_create.c - txm_module_manager_thread_create.c - 0 - 0 - - - 1 - 220 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_thread_notify_trampoline.c - txm_module_manager_thread_notify_trampoline.c - 0 - 0 - - - 1 - 221 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_thread_reset.c - txm_module_manager_thread_reset.c - 0 - 0 - - - 1 - 222 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_timer_notify_trampoline.c - txm_module_manager_timer_notify_trampoline.c - 0 - 0 - - - 1 - 223 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_unload.c - txm_module_manager_unload.c - 0 - 0 - - - 1 - 224 - 1 - 0 - 0 - 0 - ..\..\..\..\common_modules\module_manager\src\txm_module_manager_util.c - txm_module_manager_util.c - 0 - 0 - - - 1 - 225 - 1 - 0 - 0 - 0 - ..\module_manager\src\txm_module_manager_alignment_adjust.c - txm_module_manager_alignment_adjust.c - 0 - 0 - - - 1 - 226 - 1 - 0 - 0 - 0 - ..\module_manager\src\txm_module_manager_external_memory_enable.c - txm_module_manager_external_memory_enable.c - 0 - 0 - - - 1 - 227 - 1 - 0 - 0 - 0 - ..\module_manager\src\txm_module_manager_memory_fault_handler.c - txm_module_manager_memory_fault_handler.c - 0 - 0 - - - 1 - 228 - 1 - 0 - 0 - 0 - ..\module_manager\src\txm_module_manager_memory_fault_notify.c - txm_module_manager_memory_fault_notify.c - 0 - 0 - - - 1 - 229 - 1 - 0 - 0 - 0 - ..\module_manager\src\txm_module_manager_mm_register_setup.c - txm_module_manager_mm_register_setup.c - 0 - 0 - - - 1 - 230 - 2 - 0 - 0 - 0 - ..\module_manager\src\txm_module_manager_thread_stack_build.S - txm_module_manager_thread_stack_build.S - 0 - 0 - - - 1 - 231 - 1 - 0 - 0 - 0 - ..\module_manager\src\txm_module_manager_port_dispatch.c - txm_module_manager_port_dispatch.c - 0 - 0 - - - 1 - 232 - 2 - 0 - 0 - 0 - ..\module_manager\src\tx_thread_secure_stack_initialize.S - tx_thread_secure_stack_initialize.S - 0 - 0 - - - 1 - 231 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_stack_error_handler.c - tx_thread_stack_error_handler.c - 0 - 0 - - - 1 - 232 - 1 - 0 - 0 - 0 - ..\..\..\..\common\src\tx_thread_stack_error_notify.c - tx_thread_stack_error_notify.c - 0 - 0 - - - - - ::CMSIS - 0 - 0 - 0 - 1 - - -
diff --git a/ports_module/cortex_m33/ac6/example_build/demo_secure_zone/demo_secure_zone.uvoptx b/ports_module/cortex_m33/ac6/example_build/demo_secure_zone/demo_secure_zone.uvoptx deleted file mode 100644 index 8731d61f3..000000000 --- a/ports_module/cortex_m33/ac6/example_build/demo_secure_zone/demo_secure_zone.uvoptx +++ /dev/null @@ -1,440 +0,0 @@ - - - - 1.0 - -
### uVision Project, (C) Keil Software
- - - *.c - *.s*; *.src; *.a* - *.obj; *.o - *.lib - *.txt; *.h; *.inc - *.plm - *.cpp - 0 - - - - 0 - 0 - - - - FVP Simulation Model - 0x4 - ARM-ADS - - 12000000 - - 1 - 1 - 0 - 1 - 0 - - - 1 - 65535 - 0 - 0 - 0 - - - 79 - 66 - 8 - .\Listings\ - - - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - - - 1 - 0 - 1 - - 7 - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 1 - 1 - 0 - 0 - 1 - 0 - 0 - 15 - - - - - - - - - - ..\Debug.ini - BIN\DbgFMv8M.DLL - - - - 0 - DLGTARM - (6010=1895,-444,2372,152,1)(6018=-1,-1,-1,-1,0)(6019=105,137,294,473,0)(6008=1877,-377,2171,-192,0)(6009=-1,-1,-1,-1,0)(6014=1819,316,2077,1047,1)(6015=2064,312,2322,934,1)(6003=1812,210,2394,746,1)(6000=1831,294,2284,626,0) - - - 0 - ARMDBGFLAGS - - - - 0 - DLGUARM - (105=-1,-1,-1,-1,0)(106=2227,107,2993,421,0)(107=-1,-1,-1,-1,0) - - - 0 - DbgFMv8M - -I -S -L"cpu0" -O4102 -C0 -MC".\FVP\MPS2_Cortex-M\FVP_MPS2_Cortex-M33_MDK.exe" -MF"..\ARMCM33_DSP_FP_TZ_config.txt" -PF -MA - - - 0 - UL2V8M - UL2V8M(-S0 -C0 -P0 -FD20000000 -FC1000) - - - - - 0 - 0 - 137 - 1 -
2068
- 0 - 0 - 0 - 0 - 0 - 1 - <1>RTE\Device\ARMCM33_DSP_FP_TZ\startup_ARMCM33.c - - \\demo_secure_zone\RTE/Device/ARMCM33_DSP_FP_TZ/startup_ARMCM33.c\137 -
- - 1 - 0 - 113 - 1 -
1050838
- 0 - 0 - 0 - 0 - 0 - 1 - <2>.\sample_threadx_module_manager.c - - \\demo_threadx_non_secure_zone\sample_threadx_module_manager.c\113 -
- - 2 - 0 - 128 - 1 -
1050886
- 0 - 0 - 0 - 0 - 0 - 1 - <2>.\sample_threadx_module_manager.c - - \\demo_threadx_non_secure_zone\sample_threadx_module_manager.c\128 -
- - 3 - 0 - 0 - 1 -
1059030
- 0 - 0 - 0 - 0 - 0 - 1 - - - 0x001028D6 -
- - 4 - 0 - 81 - 1 -
1064656
- 0 - 0 - 0 - 0 - 0 - 1 - <3>..\module_manager\src\tx_thread_stack_error_handler.c - - \\demo_threadx_non_secure_zone\../module_manager/src/tx_thread_stack_error_handler.c\81 -
- - 5 - 0 - 244 - 1 -
2101430
- 0 - 0 - 0 - 0 - 0 - 1 - <4>.\sample_threadx_module.c - - \\sample_threadx_module\sample_threadx_module.c\244 -
-
- - - 0 - 1 - thread_0_counter - - - 1 - 1 - thread_1_counter - - - 2 - 1 - thread_2_counter - - - 3 - 1 - thread_3_counter - - - 4 - 1 - thread_4_counter - - - 5 - 1 - thread_5_counter - - - 6 - 1 - thread_6_counter - - - 7 - 1 - thread_7_counter - - - 8 - 1 - _tx_thread_current_ptr - - - 9 - 1 - _tx_thread_execute_ptr - - - 10 - 1 - my_module - - - 11 - 1 - _tx_timer_system_clock - - - 12 - 1 - (TX_THREAD*)0x202116B8 - - - - - 1 - 2 - 0x20211090 - 0 - - - - - 2 - 2 - 0xE000ED28 - 0 - - - - 0 - - - 0 - 1 - 1 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - - - - - - - - -
-
- - - Secure Code - 1 - 0 - 0 - 0 - - 1 - 1 - 1 - 0 - 0 - 0 - .\main_s.c - main_s.c - 0 - 0 - - - 1 - 2 - 1 - 0 - 0 - 0 - ..\..\module_manager\src\tx_thread_secure_stack.c - tx_thread_secure_stack.c - 0 - 0 - - - - - Interface - 1 - 0 - 0 - 0 - - 2 - 3 - 1 - 0 - 0 - 0 - .\interface.c - interface.c - 0 - 0 - - - - - ::CMSIS - 0 - 0 - 0 - 1 - - - - ::Device - 1 - 0 - 0 - 1 - - -
diff --git a/ports_module/cortex_m33/ac6/example_build/demo_threadx_non-secure_zone/ThreadX_Demo.uvopt b/ports_module/cortex_m33/ac6/example_build/demo_threadx_non-secure_zone/ThreadX_Demo.uvopt deleted file mode 100644 index 7ec4b36b6..000000000 --- a/ports_module/cortex_m33/ac6/example_build/demo_threadx_non-secure_zone/ThreadX_Demo.uvopt +++ /dev/null @@ -1,305 +0,0 @@ - - - - 1.0 - -
### uVision Project, (C) Keil Software
- - - *.c - *.s*; *.src; *.a* - *.obj; *.o - *.lib - *.txt; *.h; *.inc - *.plm - *.cpp - 0 - - - - 0 - 0 - - - - ThreadX_Demo - 0x4 - ARM-ADS - - 12000000 - - 1 - 1 - 1 - 0 - 0 - - - 1 - 65535 - 0 - 0 - 0 - - - 79 - 66 - 8 - .\ - - - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - - - 1 - 0 - 1 - - 255 - - 1 - 0 - 1 - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 1 - 0 - 1 - 0 - 1 - 1 - 0 - 0 - 1 - 0 - 0 - -1 - - - - - - - - - - - - - - - 0 - ARMRTXEVENTFLAGS - -L70 -Z18 -C0 -M0 -T1 - - - 0 - DLGDARM - (1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0) - - - 0 - DLGUARM - (105=-1,-1,-1,-1,0)(106=-1,-1,-1,-1,0)(107=-1,-1,-1,-1,0) - - - 0 - DLGTARM - (1010=-1,-1,-1,-1,0)(1007=-1,-1,-1,-1,0)(1008=-1,-1,-1,-1,0)(1009=-1,-1,-1,-1,0)(110=-1,-1,-1,-1,0)(100=-1,-1,-1,-1,0)(101=-1,-1,-1,-1,0)(102=-1,-1,-1,-1,0)(103=-1,-1,-1,-1,0)(104=-1,-1,-1,-1,0)(105=-1,-1,-1,-1,0)(106=-1,-1,-1,-1,0)(107=-1,-1,-1,-1,0)(161=-1,-1,-1,-1,0)(162=-1,-1,-1,-1,0)(163=-1,-1,-1,-1,0)(164=-1,-1,-1,-1,0)(150=-1,-1,-1,-1,0)(151=-1,-1,-1,-1,0)(152=-1,-1,-1,-1,0)(1011=-1,-1,-1,-1,0)(1012=-1,-1,-1,-1,0)(1013=-1,-1,-1,-1,0)(171=-1,-1,-1,-1,0)(172=-1,-1,-1,-1,0)(173=-1,-1,-1,-1,0)(1014=-1,-1,-1,-1,0)(1016=-1,-1,-1,-1,0)(136=-1,-1,-1,-1,0) - - - 0 - ARMDBGFLAGS - -T5F - - - 0 - UL2CM3 - -UV0289BJE -O14 -S0 -C0 -N00("ARM CoreSight JTAG-DP") -D00(3BA00477) -L00(4) -TO18 -TC10000000 -TP21 -TDS8007 -TDT0 -TDC1F -TIEFFFFFFFF -TIP8 -FO7 -FD20000000 -FC800 -FN1 -FF0LM3S_16 -FS00 -FL04000 - - - - - - 0 - 1 - thread_0_counter - - - 1 - 1 - thread_1_counter - - - 2 - 1 - thread_2_counter - - - 3 - 1 - thread_3_counter - - - 4 - 1 - thread_4_counter - - - 5 - 1 - thread_5_counter - - - 6 - 1 - _tx_thread_current_ptr - - - - 0 - - - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - - - - - - - - - - - - - Source Group - 1 - 0 - 0 - 0 - - 1 - 1 - 2 - 0 - 0 - 0 - .\tx_initialize_low_level.s - tx_initialize_low_level.s - 0 - 0 - - - 1 - 2 - 1 - 1 - 0 - 0 - .\demo_threadx.c - demo_threadx.c - 0 - 0 - - 44 - 0 - 1 - - -1 - -1 - - - -1 - -1 - - - 56 - 12 - 1633 - 671 - - - - - - - Library_Group - 1 - 0 - 0 - 0 - - 2 - 3 - 4 - 0 - 0 - 0 - .\ThreadX_Library.lib - ThreadX_Library.lib - 0 - 0 - - - -
diff --git a/ports_module/cortex_m33/ac6/example_build/demo_threadx_non-secure_zone/demo_threadx_non-secure_zone.uvoptx b/ports_module/cortex_m33/ac6/example_build/demo_threadx_non-secure_zone/demo_threadx_non-secure_zone.uvoptx deleted file mode 100644 index bc65c4e5e..000000000 --- a/ports_module/cortex_m33/ac6/example_build/demo_threadx_non-secure_zone/demo_threadx_non-secure_zone.uvoptx +++ /dev/null @@ -1,342 +0,0 @@ - - - - 1.0 - -
### uVision Project, (C) Keil Software
- - - *.c - *.s*; *.src; *.a* - *.obj; *.o - *.lib - *.txt; *.h; *.inc - *.plm - *.cpp - 0 - - - - 0 - 0 - - - - FVP Simulation Model - 0x4 - ARM-ADS - - 12000000 - - 1 - 1 - 0 - 1 - 0 - - - 1 - 65535 - 0 - 0 - 0 - - - 79 - 66 - 8 - .\Listings\ - - - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - - - 1 - 0 - 1 - - 7 - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 1 - 1 - 0 - 0 - 1 - 0 - 0 - 15 - - - - - - - - - - ..\Debug.ini - BIN\DbgFMv8M.DLL - - - - 0 - PWSTATINFO - 200,50,700 - - - 0 - DLGTARM - (6010=1243,118,1720,714,0)(6018=1284,352,1473,701,0)(6019=1328,34,1517,370,0)(6008=-1,-1,-1,-1,0)(6009=969,18,1263,203,0)(6014=1111,129,1369,860,0)(6015=872,146,1130,768,0)(6003=-1,-1,-1,-1,0)(6000=-1,-1,-1,-1,0) - - - 0 - ARMDBGFLAGS - - - - 0 - DLGUARM - (105=-1,-1,-1,-1,0)(106=511,345,1277,660,0)(107=-1,-1,-1,-1,0) - - - 0 - DbgFMv8M - -I -S -L"cpu0" -O4102 -C0 -MC".\FVP\MPS2_Cortex-M\FVP_MPS2_Cortex-M33_MDK.exe" -MF"..\ARMCM33_DSP_FP_TZ_config.txt" -PF -MA - - - 0 - UL2V8M - UL2V8M(-S0 -C0 -P0 -FC1000 -FD20000000 - - - - - - 0 - 1 - thread_0_counter - - - 1 - 1 - thread_1_counter - - - 2 - 1 - thread_2_counter - - - 3 - 1 - thread_3_counter - - - 4 - 1 - thread_4_counter - - - 5 - 1 - thread_5_counter - - - 6 - 1 - thread_6_counter - - - 7 - 1 - thread_7_counter - - - - - 1 - 2 - 0x20200a10 - 0 - - - - - 2 - 2 - 0xE000ED28 - 0 - - - - 0 - - - 0 - 1 - 1 - 0 - 0 - 0 - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - - - - - - - - - - 1 - 0 - 0 - 1 - 10000000 - - - - - - Non-secure Code - 1 - 0 - 0 - 0 - - 1 - 1 - 4 - 0 - 0 - 0 - ..\ThreadX_Library.lib - ThreadX_Library.lib - 0 - 0 - - - 1 - 2 - 1 - 0 - 0 - 0 - .\sample_threadx_module_manager.c - sample_threadx_module_manager.c - 0 - 0 - - - - - CMSE Library - 1 - 0 - 0 - 0 - - 2 - 3 - 5 - 0 - 0 - 0 - ..\demo_secure_zone\interface.h - interface.h - 0 - 0 - - - 2 - 4 - 3 - 0 - 0 - 0 - ..\demo_secure_zone\Objects\demo_secure_zone_CMSE_Lib.o - demo_secure_zone_CMSE_Lib.o - 0 - 0 - - - - - ::CMSIS - 1 - 0 - 0 - 1 - - - - ::Device - 1 - 0 - 0 - 1 - - -
diff --git a/ports_module/cortex_m33/ac6/example_build/sample_threadx_module/sample_threadx_module.uvoptx b/ports_module/cortex_m33/ac6/example_build/sample_threadx_module/sample_threadx_module.uvoptx deleted file mode 100644 index cef6b11f9..000000000 --- a/ports_module/cortex_m33/ac6/example_build/sample_threadx_module/sample_threadx_module.uvoptx +++ /dev/null @@ -1,236 +0,0 @@ - - - - 1.0 - -
### uVision Project, (C) Keil Software
- - - *.c - *.s*; *.src; *.a* - *.obj; *.o - *.lib - *.txt; *.h; *.inc - *.plm - *.cpp - 0 - - - - 0 - 0 - - - - FVP Simulation Model - 0x4 - ARM-ADS - - 12000000 - - 1 - 1 - 0 - 1 - 0 - - - 1 - 65535 - 0 - 0 - 0 - - - 79 - 66 - 8 - .\Listings\ - - - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - - - 1 - 0 - 1 - - 7 - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 1 - 1 - 0 - 0 - 1 - 0 - 0 - 13 - - - - - - - - - - - BIN\UL2V8M.DLL - - - - 0 - UL2V8M - UL2V8M(-S0 -C0 -P0 -FD20000000 -FC1000) - - - - - 0 - - - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - - - - - - - - - - - - - Module Code - 0 - 0 - 0 - 0 - - 1 - 1 - 1 - 0 - 0 - 0 - .\sample_threadx_module.c - sample_threadx_module.c - 0 - 0 - - - 1 - 2 - 2 - 0 - 0 - 0 - .\txm_module_preamble.S - txm_module_preamble.S - 0 - 0 - - - 1 - 3 - 4 - 0 - 0 - 0 - ..\txm\Objects\txm.lib - txm.lib - 0 - 0 - - - 1 - 4 - 3 - 0 - 0 - 0 - ..\demo_secure_zone\Objects\demo_secure_zone_CMSE_Lib.o - demo_secure_zone_CMSE_Lib.o - 0 - 0 - - - - - ::CMSIS - 0 - 0 - 0 - 1 - - -
diff --git a/ports_module/cortex_m33/ac6/example_build/txm/txm.uvoptx b/ports_module/cortex_m33/ac6/example_build/txm/txm.uvoptx deleted file mode 100644 index dab51218b..000000000 --- a/ports_module/cortex_m33/ac6/example_build/txm/txm.uvoptx +++ /dev/null @@ -1,1412 +0,0 @@ - - - - 1.0 - -
### uVision Project, (C) Keil Software
- - - *.c - *.s*; *.src; *.a* - *.obj; *.o - *.lib - *.txt; *.h; *.inc - *.plm - *.cpp - 0 - - - - 0 - 0 - - - - ThreadX Module Library - 0x4 - ARM-ADS - - 12000000 - - 1 - 1 - 0 - 1 - 0 - - - 1 - 65535 - 0 - 0 - 0 - - - 79 - 66 - 8 - .\Listings\ - - - 1 - 1 - 1 - 0 - 1 - 1 - 0 - 1 - 0 - 0 - 0 - 0 - - - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 0 - - - 1 - 0 - 1 - - 7 - - 0 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 1 - 0 - 1 - 1 - 1 - 1 - 0 - 0 - 1 - 0 - 0 - 13 - - - - - - - - - - - BIN\UL2V8M.DLL - - - - 0 - UL2V8M - UL2V8M(-S0 -C0 -P0 -FD20000000 -FC1000) - - - - - 0 - - - 0 - 1 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - 0 - - - - 0 - 0 - 0 - - - - - - - - - - - - - Source Group - 0 - 0 - 0 - 0 - - 1 - 1 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_block_allocate.c - txm_block_allocate.c - 0 - 0 - - - 1 - 2 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_block_pool_create.c - txm_block_pool_create.c - 0 - 0 - - - 1 - 3 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_block_pool_delete.c - txm_block_pool_delete.c - 0 - 0 - - - 1 - 4 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_block_pool_info_get.c - txm_block_pool_info_get.c - 0 - 0 - - - 1 - 5 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_block_pool_performance_info_get.c - txm_block_pool_performance_info_get.c - 0 - 0 - - - 1 - 6 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_block_pool_performance_system_info_get.c - txm_block_pool_performance_system_info_get.c - 0 - 0 - - - 1 - 7 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_block_pool_prioritize.c - txm_block_pool_prioritize.c - 0 - 0 - - - 1 - 8 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_block_release.c - txm_block_release.c - 0 - 0 - - - 1 - 9 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_byte_allocate.c - txm_byte_allocate.c - 0 - 0 - - - 1 - 10 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_byte_pool_create.c - txm_byte_pool_create.c - 0 - 0 - - - 1 - 11 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_byte_pool_delete.c - txm_byte_pool_delete.c - 0 - 0 - - - 1 - 12 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_byte_pool_info_get.c - txm_byte_pool_info_get.c - 0 - 0 - - - 1 - 13 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_byte_pool_performance_info_get.c - txm_byte_pool_performance_info_get.c - 0 - 0 - - - 1 - 14 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_byte_pool_performance_system_info_get.c - txm_byte_pool_performance_system_info_get.c - 0 - 0 - - - 1 - 15 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_byte_pool_prioritize.c - txm_byte_pool_prioritize.c - 0 - 0 - - - 1 - 16 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_byte_release.c - txm_byte_release.c - 0 - 0 - - - 1 - 17 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_event_flags_create.c - txm_event_flags_create.c - 0 - 0 - - - 1 - 18 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_event_flags_delete.c - txm_event_flags_delete.c - 0 - 0 - - - 1 - 19 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_event_flags_get.c - txm_event_flags_get.c - 0 - 0 - - - 1 - 20 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_event_flags_info_get.c - txm_event_flags_info_get.c - 0 - 0 - - - 1 - 21 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_event_flags_performance_info_get.c - txm_event_flags_performance_info_get.c - 0 - 0 - - - 1 - 22 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_event_flags_performance_system_info_get.c - txm_event_flags_performance_system_info_get.c - 0 - 0 - - - 1 - 23 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_event_flags_set.c - txm_event_flags_set.c - 0 - 0 - - - 1 - 24 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_event_flags_set_notify.c - txm_event_flags_set_notify.c - 0 - 0 - - - 1 - 25 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_module_application_request.c - txm_module_application_request.c - 0 - 0 - - - 1 - 26 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_module_callback_request_thread_entry.c - txm_module_callback_request_thread_entry.c - 0 - 0 - - - 1 - 27 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_module_object_allocate.c - txm_module_object_allocate.c - 0 - 0 - - - 1 - 28 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_module_object_deallocate.c - txm_module_object_deallocate.c - 0 - 0 - - - 1 - 29 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_module_object_pointer_get.c - txm_module_object_pointer_get.c - 0 - 0 - - - 1 - 30 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_module_object_pointer_get_extended.c - txm_module_object_pointer_get_extended.c - 0 - 0 - - - 1 - 31 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_module_thread_system_suspend.c - txm_module_thread_system_suspend.c - 0 - 0 - - - 1 - 32 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_mutex_create.c - txm_mutex_create.c - 0 - 0 - - - 1 - 33 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_mutex_delete.c - txm_mutex_delete.c - 0 - 0 - - - 1 - 34 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_mutex_get.c - txm_mutex_get.c - 0 - 0 - - - 1 - 35 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_mutex_info_get.c - txm_mutex_info_get.c - 0 - 0 - - - 1 - 36 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_mutex_performance_info_get.c - txm_mutex_performance_info_get.c - 0 - 0 - - - 1 - 37 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_mutex_performance_system_info_get.c - txm_mutex_performance_system_info_get.c - 0 - 0 - - - 1 - 38 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_mutex_prioritize.c - txm_mutex_prioritize.c - 0 - 0 - - - 1 - 39 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_mutex_put.c - txm_mutex_put.c - 0 - 0 - - - 1 - 40 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_queue_create.c - txm_queue_create.c - 0 - 0 - - - 1 - 41 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_queue_delete.c - txm_queue_delete.c - 0 - 0 - - - 1 - 42 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_queue_flush.c - txm_queue_flush.c - 0 - 0 - - - 1 - 43 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_queue_front_send.c - txm_queue_front_send.c - 0 - 0 - - - 1 - 44 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_queue_info_get.c - txm_queue_info_get.c - 0 - 0 - - - 1 - 45 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_queue_performance_info_get.c - txm_queue_performance_info_get.c - 0 - 0 - - - 1 - 46 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_queue_performance_system_info_get.c - txm_queue_performance_system_info_get.c - 0 - 0 - - - 1 - 47 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_queue_prioritize.c - txm_queue_prioritize.c - 0 - 0 - - - 1 - 48 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_queue_receive.c - txm_queue_receive.c - 0 - 0 - - - 1 - 49 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_queue_send.c - txm_queue_send.c - 0 - 0 - - - 1 - 50 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_queue_send_notify.c - txm_queue_send_notify.c - 0 - 0 - - - 1 - 51 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_semaphore_ceiling_put.c - txm_semaphore_ceiling_put.c - 0 - 0 - - - 1 - 52 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_semaphore_create.c - txm_semaphore_create.c - 0 - 0 - - - 1 - 53 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_semaphore_delete.c - txm_semaphore_delete.c - 0 - 0 - - - 1 - 54 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_semaphore_get.c - txm_semaphore_get.c - 0 - 0 - - - 1 - 55 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_semaphore_info_get.c - txm_semaphore_info_get.c - 0 - 0 - - - 1 - 56 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_semaphore_performance_info_get.c - txm_semaphore_performance_info_get.c - 0 - 0 - - - 1 - 57 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_semaphore_performance_system_info_get.c - txm_semaphore_performance_system_info_get.c - 0 - 0 - - - 1 - 58 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_semaphore_prioritize.c - txm_semaphore_prioritize.c - 0 - 0 - - - 1 - 59 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_semaphore_put.c - txm_semaphore_put.c - 0 - 0 - - - 1 - 60 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_semaphore_put_notify.c - txm_semaphore_put_notify.c - 0 - 0 - - - 1 - 61 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_thread_create.c - txm_thread_create.c - 0 - 0 - - - 1 - 62 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_thread_delete.c - txm_thread_delete.c - 0 - 0 - - - 1 - 63 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_thread_entry_exit_notify.c - txm_thread_entry_exit_notify.c - 0 - 0 - - - 1 - 64 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_thread_identify.c - txm_thread_identify.c - 0 - 0 - - - 1 - 65 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_thread_info_get.c - txm_thread_info_get.c - 0 - 0 - - - 1 - 66 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_thread_interrupt_control.c - txm_thread_interrupt_control.c - 0 - 0 - - - 1 - 67 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_thread_performance_info_get.c - txm_thread_performance_info_get.c - 0 - 0 - - - 1 - 68 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_thread_performance_system_info_get.c - txm_thread_performance_system_info_get.c - 0 - 0 - - - 1 - 69 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_thread_preemption_change.c - txm_thread_preemption_change.c - 0 - 0 - - - 1 - 70 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_thread_priority_change.c - txm_thread_priority_change.c - 0 - 0 - - - 1 - 71 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_thread_relinquish.c - txm_thread_relinquish.c - 0 - 0 - - - 1 - 72 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_thread_reset.c - txm_thread_reset.c - 0 - 0 - - - 1 - 73 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_thread_resume.c - txm_thread_resume.c - 0 - 0 - - - 1 - 74 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_thread_sleep.c - txm_thread_sleep.c - 0 - 0 - - - 1 - 75 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_thread_stack_error_notify.c - txm_thread_stack_error_notify.c - 0 - 0 - - - 1 - 76 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_thread_suspend.c - txm_thread_suspend.c - 0 - 0 - - - 1 - 77 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_thread_terminate.c - txm_thread_terminate.c - 0 - 0 - - - 1 - 78 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_thread_time_slice_change.c - txm_thread_time_slice_change.c - 0 - 0 - - - 1 - 79 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_thread_wait_abort.c - txm_thread_wait_abort.c - 0 - 0 - - - 1 - 80 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_time_get.c - txm_time_get.c - 0 - 0 - - - 1 - 81 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_time_set.c - txm_time_set.c - 0 - 0 - - - 1 - 82 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_timer_activate.c - txm_timer_activate.c - 0 - 0 - - - 1 - 83 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_timer_change.c - txm_timer_change.c - 0 - 0 - - - 1 - 84 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_timer_create.c - txm_timer_create.c - 0 - 0 - - - 1 - 85 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_timer_deactivate.c - txm_timer_deactivate.c - 0 - 0 - - - 1 - 86 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_timer_delete.c - txm_timer_delete.c - 0 - 0 - - - 1 - 87 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_timer_info_get.c - txm_timer_info_get.c - 0 - 0 - - - 1 - 88 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_timer_performance_info_get.c - txm_timer_performance_info_get.c - 0 - 0 - - - 1 - 89 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_timer_performance_system_info_get.c - txm_timer_performance_system_info_get.c - 0 - 0 - - - 1 - 90 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_trace_buffer_full_notify.c - txm_trace_buffer_full_notify.c - 0 - 0 - - - 1 - 91 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_trace_disable.c - txm_trace_disable.c - 0 - 0 - - - 1 - 92 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_trace_enable.c - txm_trace_enable.c - 0 - 0 - - - 1 - 93 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_trace_event_filter.c - txm_trace_event_filter.c - 0 - 0 - - - 1 - 94 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_trace_event_unfilter.c - txm_trace_event_unfilter.c - 0 - 0 - - - 1 - 95 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_trace_interrupt_control.c - txm_trace_interrupt_control.c - 0 - 0 - - - 1 - 96 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_trace_isr_enter_insert.c - txm_trace_isr_enter_insert.c - 0 - 0 - - - 1 - 97 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_trace_isr_exit_insert.c - txm_trace_isr_exit_insert.c - 0 - 0 - - - 1 - 98 - 1 - 0 - 0 - 0 - ..\..\..\..\..\common_modules\module_lib\src\txm_trace_user_event_insert.c - txm_trace_user_event_insert.c - 0 - 0 - - - 1 - 99 - 2 - 0 - 0 - 0 - ..\..\module_lib\src\txm_module_initialize.S - txm_module_initialize.S - 0 - 0 - - - 1 - 100 - 1 - 0 - 0 - 0 - ..\..\module_lib\src\txm_module_thread_shell_entry.c - txm_module_thread_shell_entry.c - 0 - 0 - - - 1 - 101 - 1 - 0 - 0 - 0 - ..\..\module_lib\src\txm_thread_secure_stack_allocate.c - txm_thread_secure_stack_allocate.c - 0 - 0 - - - 1 - 102 - 1 - 0 - 0 - 0 - ..\..\module_lib\src\txm_thread_secure_stack_free.c - txm_thread_secure_stack_free.c - 0 - 0 - - - - - ::CMSIS - 0 - 0 - 0 - 1 - - -
diff --git a/scripts/check_clang.sh b/scripts/check_clang.sh index 446782df0..3c4faee33 100755 --- a/scripts/check_clang.sh +++ b/scripts/check_clang.sh @@ -189,8 +189,12 @@ CMAKE_EXAMPLE_CORES="cortex_r52" # explicitly rather than silently skipped, so the gaps stay visible. # # These fail with the GNU toolchain too, so they are not LLVM problems: -# arm9 arm11 need newlib multilib variants for those CPUs, which are -# cortex_r4 cortex_r5 not present in every GNU toolchain packaging. +# arm9 arm11 their linker scripts do not define _init and _fini. +# Those symbols come from crti.o and crtn.o, which +# -nostartfiles leaves out, so newlib's fini.c fails to +# link. Reproduced with arm-none-eabi-gcc 13.2.1. +# cortex_r4 cortex_r5 need newlib multilib variants for those CPUs, which are +# not present in every GNU toolchain packaging. EXAMPLES_EXPECTED_TO_FAIL="arm9 arm11 cortex_r4 cortex_r5" failures=0 From 358e7a9ea537dff49d970c8b684eef229f40bc53 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Sat, 15 Aug 2026 16:58:59 -0400 Subject: [PATCH 047/181] Stopped the remaining example scripts naming archives that were deleted (#620) #618 fixed the arm9 and arm11 shell scripts, but not their .bat counterparts, and did not look at cortex_r4 and cortex_r5 at all. An audit of every build script against the files actually present in its directory found the rest. The .bat scripts for arm9, arm11, cortex_r4 and cortex_r5 still linked libc.a, libgcc.a and, for arm11, libnosys.a from their own example_build directories, and the cortex_r4 and cortex_r5 shell scripts did too. Those archives went in 6.1.10 under "Removal of unneeded files", so on Windows all four examples failed exactly as the shell versions did before #618, and on Linux the two R-profile ones still did. Link through the compiler driver, as the other examples have since #594. This does not make the examples link, and the change stops there deliberately. All four now fail the same way, undefined reference to `_fini' because their linker scripts define the .init and .fini sections but not the _init and _fini symbols, which live in crti.o and crtn.o and are omitted by -nostartfiles. Reviving four very old cores is separate work. Correct the comment on EXAMPLES_EXPECTED_TO_FAIL again. It had cortex_r4 and cortex_r5 failing for want of newlib multilib variants; they do not. All four share the single cause above, and the multilib explanation was wrong for the R-profile pair just as it was for arm9 and arm11. Verified by running each shell script: cortex_r4 and cortex_r5 fail on _fini rather than on missing files, matching arm9 and arm11. The .bat changes mirror link lines proven that way in the same directories; they cannot be run here. Three scripts are left alone and reported instead, because a blind edit could not be verified: ports_module/cortex_m3 and cortex_m4 have Windows-only .bat scripts that also name sources which are absent or differ in case, and ports_smp/mips32_interaptiv_smp needs a MIPS toolchain. Assisted-by: Claude Code (Opus 5) --- .../example_build/build_threadx_sample.bat | 2 +- .../example_build/build_threadx_sample.bat | 2 +- .../example_build/build_threadx_sample.bat | 2 +- .../gnu/example_build/build_threadx_sample.sh | 2 +- .../example_build/build_threadx_sample.bat | 2 +- .../gnu/example_build/build_threadx_sample.sh | 2 +- scripts/check_clang.sh | 19 ++++++++++++------- 7 files changed, 18 insertions(+), 13 deletions(-) diff --git a/ports/arm11/gnu/example_build/build_threadx_sample.bat b/ports/arm11/gnu/example_build/build_threadx_sample.bat index e67e3c20b..1515eb277 100644 --- a/ports/arm11/gnu/example_build/build_threadx_sample.bat +++ b/ports/arm11/gnu/example_build/build_threadx_sample.bat @@ -2,5 +2,5 @@ arm-none-eabi-gcc -c -g -mcpu=arm1136j-s reset.S arm-none-eabi-gcc -c -g -mcpu=arm1136j-s crt0.S arm-none-eabi-gcc -c -g -mcpu=arm1136j-s tx_initialize_low_level.S arm-none-eabi-gcc -c -g -mcpu=arm1136j-s -I../../../../common/inc -I../inc sample_threadx.c -arm-none-eabi-ld -A arm1136j-s -T sample_threadx.ld reset.o crt0.o tx_initialize_low_level.o sample_threadx.o tx.a libc.a libnosys.a libgcc.a -o sample_threadx.out -M > sample_threadx.map +arm-none-eabi-gcc -g -nostartfiles -mcpu=arm1136j-s -T sample_threadx.ld --specs=nosys.specs -o sample_threadx.out -Wl,-Map=sample_threadx.map reset.o crt0.o tx_initialize_low_level.o sample_threadx.o tx.a diff --git a/ports/arm9/gnu/example_build/build_threadx_sample.bat b/ports/arm9/gnu/example_build/build_threadx_sample.bat index c35d2bc63..5c9347f4d 100644 --- a/ports/arm9/gnu/example_build/build_threadx_sample.bat +++ b/ports/arm9/gnu/example_build/build_threadx_sample.bat @@ -2,5 +2,5 @@ arm-none-eabi-gcc -c -g -mcpu=arm9 reset.S arm-none-eabi-gcc -c -g -mcpu=arm9 crt0.S arm-none-eabi-gcc -c -g -mcpu=arm9 tx_initialize_low_level.S arm-none-eabi-gcc -c -g -mcpu=arm9 -I../../../../common/inc -I../inc sample_threadx.c -arm-none-eabi-ld -A arm9 -T sample_threadx.ld reset.o crt0.o tx_initialize_low_level.o sample_threadx.o tx.a libc.a libgcc.a -o sample_threadx.out -M > sample_threadx.map +arm-none-eabi-gcc -g -nostartfiles -mcpu=arm9 -T sample_threadx.ld --specs=nosys.specs -o sample_threadx.out -Wl,-Map=sample_threadx.map reset.o crt0.o tx_initialize_low_level.o sample_threadx.o tx.a diff --git a/ports/cortex_r4/gnu/example_build/build_threadx_sample.bat b/ports/cortex_r4/gnu/example_build/build_threadx_sample.bat index 517b6d62d..72444e4bd 100644 --- a/ports/cortex_r4/gnu/example_build/build_threadx_sample.bat +++ b/ports/cortex_r4/gnu/example_build/build_threadx_sample.bat @@ -2,5 +2,5 @@ arm-none-eabi-gcc -c -g -mcpu=cortex-r4 reset.S arm-none-eabi-gcc -c -g -mcpu=cortex-r4 crt0.S arm-none-eabi-gcc -c -g -mcpu=cortex-r4 tx_initialize_low_level.S arm-none-eabi-gcc -c -g -mcpu=cortex-r4 -I../../../../common/inc -I../inc sample_threadx.c -arm-none-eabi-ld -A cortex-r4 -T sample_threadx.ld reset.o crt0.o tx_initialize_low_level.o sample_threadx.o tx.a libc.a libgcc.a -o sample_threadx.out -M > sample_threadx.map +arm-none-eabi-gcc -g -nostartfiles -mcpu=cortex-r4 -T sample_threadx.ld --specs=nosys.specs -o sample_threadx.out -Wl,-Map=sample_threadx.map reset.o crt0.o tx_initialize_low_level.o sample_threadx.o tx.a diff --git a/ports/cortex_r4/gnu/example_build/build_threadx_sample.sh b/ports/cortex_r4/gnu/example_build/build_threadx_sample.sh index 0d8dbcd5c..1f0e2709e 100755 --- a/ports/cortex_r4/gnu/example_build/build_threadx_sample.sh +++ b/ports/cortex_r4/gnu/example_build/build_threadx_sample.sh @@ -61,5 +61,5 @@ esac "${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-r4 crt0.S "${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-r4 tx_initialize_low_level.S "${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-r4 -I../../../../common/inc -I../inc sample_threadx.c -arm-none-eabi-ld -A cortex-r4 -T sample_threadx.ld reset.o crt0.o tx_initialize_low_level.o sample_threadx.o tx.a libc.a libgcc.a -o sample_threadx.out -M > sample_threadx.map +"${CC}" ${TARGET_FLAGS} -g -nostartfiles -mcpu=cortex-r4 -T sample_threadx.ld ${SYSCALL_LIB} -o sample_threadx.out -Wl,-Map=sample_threadx.map reset.o crt0.o tx_initialize_low_level.o sample_threadx.o tx.a diff --git a/ports/cortex_r5/gnu/example_build/build_threadx_sample.bat b/ports/cortex_r5/gnu/example_build/build_threadx_sample.bat index 2ded427d3..f2de17cd0 100644 --- a/ports/cortex_r5/gnu/example_build/build_threadx_sample.bat +++ b/ports/cortex_r5/gnu/example_build/build_threadx_sample.bat @@ -2,5 +2,5 @@ arm-none-eabi-gcc -c -g -mcpu=cortex-r5 reset.S arm-none-eabi-gcc -c -g -mcpu=cortex-r5 crt0.S arm-none-eabi-gcc -c -g -mcpu=cortex-r5 tx_initialize_low_level.S arm-none-eabi-gcc -c -g -mcpu=cortex-r5 -I../../../../common/inc -I../inc sample_threadx.c -arm-none-eabi-ld -A cortex-r5 -T sample_threadx.ld reset.o crt0.o tx_initialize_low_level.o sample_threadx.o tx.a libc.a libgcc.a -o sample_threadx.out -M > sample_threadx.map +arm-none-eabi-gcc -g -nostartfiles -mcpu=cortex-r5 -T sample_threadx.ld --specs=nosys.specs -o sample_threadx.out -Wl,-Map=sample_threadx.map reset.o crt0.o tx_initialize_low_level.o sample_threadx.o tx.a diff --git a/ports/cortex_r5/gnu/example_build/build_threadx_sample.sh b/ports/cortex_r5/gnu/example_build/build_threadx_sample.sh index e3e133d63..2b3e4d551 100755 --- a/ports/cortex_r5/gnu/example_build/build_threadx_sample.sh +++ b/ports/cortex_r5/gnu/example_build/build_threadx_sample.sh @@ -61,5 +61,5 @@ esac "${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-r5 crt0.S "${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-r5 tx_initialize_low_level.S "${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-r5 -I../../../../common/inc -I../inc sample_threadx.c -arm-none-eabi-ld -A cortex-r5 -T sample_threadx.ld reset.o crt0.o tx_initialize_low_level.o sample_threadx.o tx.a libc.a libgcc.a -o sample_threadx.out -M > sample_threadx.map +"${CC}" ${TARGET_FLAGS} -g -nostartfiles -mcpu=cortex-r5 -T sample_threadx.ld ${SYSCALL_LIB} -o sample_threadx.out -Wl,-Map=sample_threadx.map reset.o crt0.o tx_initialize_low_level.o sample_threadx.o tx.a diff --git a/scripts/check_clang.sh b/scripts/check_clang.sh index 3c4faee33..5f13c4914 100755 --- a/scripts/check_clang.sh +++ b/scripts/check_clang.sh @@ -188,13 +188,18 @@ CMAKE_EXAMPLE_CORES="cortex_r52" # their port directory, which covers both ports/ and ports_smp/. Listed # explicitly rather than silently skipped, so the gaps stay visible. # -# These fail with the GNU toolchain too, so they are not LLVM problems: -# arm9 arm11 their linker scripts do not define _init and _fini. -# Those symbols come from crti.o and crtn.o, which -# -nostartfiles leaves out, so newlib's fini.c fails to -# link. Reproduced with arm-none-eabi-gcc 13.2.1. -# cortex_r4 cortex_r5 need newlib multilib variants for those CPUs, which are -# not present in every GNU toolchain packaging. +# These fail with the GNU toolchain too, so they are not LLVM problems. All four +# fail the same way, for the same reason: +# +# their linker scripts define the .init and .fini sections but not the _init +# and _fini symbols. Those come from crti.o and crtn.o, which -nostartfiles +# leaves out, so newlib's fini.c cannot resolve them and the link ends with +# "undefined reference to `_fini'". Reproduced with arm-none-eabi-gcc 13.2.1. +# +# Until 6.1.10 the four linked libc.a and libgcc.a checked in beside them, which +# supplied those symbols. That sweep removed the archives without updating the +# link lines, so for years the examples failed earlier still, on the missing +# files themselves. Fixing the link lines exposed the _fini gap underneath. EXAMPLES_EXPECTED_TO_FAIL="arm9 arm11 cortex_r4 cortex_r5" failures=0 From 1296cf1740e592338ea5203190b8761eb4b80fbf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Sat, 15 Aug 2026 17:02:01 -0400 Subject: [PATCH 048/181] Corrected the S32Z280 data SRAM map against the Reference Manual and the part (#621) The RTU has 1 MB of data SRAM in three contiguous banks, and this port described it wrongly in both directions. DRAM0 0x31780000 256 KB full core speed DRAM1 0x317C0000 256 KB full core speed DRAM2 0x31800000 512 KB half core speed DRAM1 was not declared at all, so 256 KB of full-speed memory went unused and the linker's DATA region stopped at 256 KB. DRAM2 was declared as 2 MB when it is 512 KB, which mattered more: the MPU mapped 1.5 MB past the end of the bank, and that range aliases back onto its base. Anything placed above 0x31880000 would have shared storage with the bottom of the region silently -- no fault, two objects at one address. Nothing was placed there yet, so this was a trap rather than a live defect. Sources: S32Z2 Reference Manual Rev. 5, section 6.3.6 and Table 13, and the board. Writing distinct values to all three banks and reading them back shows 1 MB of independent storage, and the first word past DRAM2 returns the value written to its base, which is what fixes the size. Note that NXP's own debugger memory map, s32z2e2_memory_regions.py in S32 Design Studio, calls the last bank 2 MB. The Reference Manual and the silicon agree it is 512 KB. Also corrected the description of these banks throughout. They are all RTU-local; the earlier comments treated locality as the thing that distinguishes them, when the actual difference is clock speed. That is why the cache benchmark uses DRAM2 -- caching a bank that already runs at core speed shows nothing, which is a real effect the old wording explained with the wrong cause. Verified on the S32Z280-594EVB: builds clean, and the boot probes pass six of six with the MPU, GIC, interrupts, caches and both protection faults exercised. Assisted-by: Claude Code (Opus 5) --- .../gnu/example_build/s32z280_evb/bsp_boot.c | 21 +++++----- .../gnu/example_build/s32z280_evb/link.lds | 2 +- .../gnu/example_build/s32z280_evb/mpu.c | 29 ++++++++----- .../gnu/example_build/s32z280_evb/platform.h | 42 +++++++++++++------ 4 files changed, 60 insertions(+), 34 deletions(-) diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/bsp_boot.c b/ports/cortex_r52/gnu/example_build/s32z280_evb/bsp_boot.c index 0d555caad..96ee23d75 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/bsp_boot.c +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/bsp_boot.c @@ -176,13 +176,13 @@ static void enable_irq_at_el1(void) * * Two things have to be right for a cache to show a measurable effect, and the * first version of this test got both wrong. It used a 4 KB static buffer in - * the RTU-local fast-data bank and reported a 0.036% difference -- noise -- as a - * pass. Fast local SRAM is already close to core speed, so caching it can save - * almost nothing. + * DRAM0, a full-core-speed bank, and reported a 0.036% difference -- noise -- + * as a pass. A bank running at core speed leaves a cache almost nothing to + * save. DRAM2 runs at half core speed, which is why the buffer lives there. * * 1. The memory must be slower than the core. This uses the extended SRAM at - * S32Z_EXT_SRAM_BASE, which the Reference Manual describes as NOT - * RTU-local, unlike the fast-data bank. + * S32Z_DRAM2_BASE, the RTU data bank that runs at half the core + * frequency, so caching it has something to show. * * 2. The working set must fit in the cache and be revisited. It is sized * from CCSIDR at run time -- half the reported L1 data cache -- rather @@ -197,7 +197,7 @@ static unsigned long cache_bench_words; static void cache_workload(void) { - volatile unsigned int *buffer = (volatile unsigned int *) S32Z_EXT_SRAM_BASE; + volatile unsigned int *buffer = (volatile unsigned int *) S32Z_DRAM2_BASE; unsigned long pass; unsigned long i; @@ -656,7 +656,7 @@ void bsp_main(void) cache_bench_words = cache_dcache_bytes() / (2UL * sizeof(unsigned int)); report("bench wds", (unsigned int) cache_bench_words); - linflexd_puts("C1 timing over non-RTU-local SRAM, caches OFF\n"); + linflexd_puts("C1 timing over DRAM2, the half-speed bank, caches OFF\n"); { unsigned long long before; unsigned long long after; @@ -692,10 +692,9 @@ void bsp_main(void) A cache having little to offer here is plausible rather than broken. Both the code and the data this workload touches live in - RTU-local low-latency SRAM, which is close to core speed already; - there is no slow memory on this board to demonstrate against. DDR - would be the place to measure a real cache effect, and DDR is not - initialised. */ + full-speed RTU banks, which the core reaches at its own + clock; the only slower memory on this board is DRAM2 at + half speed, and DDR, which is not initialised. */ if (cache_enabled() == 1U) { diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/link.lds b/ports/cortex_r52/gnu/example_build/s32z280_evb/link.lds index 6200bb316..ac0583b3c 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/link.lds +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/link.lds @@ -44,7 +44,7 @@ __sys_stack_size__ = 0x0800; MEMORY { CODE (rx) : ORIGIN = 0x79900000, LENGTH = 0x00700000 /* 7 MB */ - DATA (rwx) : ORIGIN = 0x31780000, LENGTH = 0x00040000 /* 256 KB */ + DATA (rwx) : ORIGIN = 0x31780000, LENGTH = 0x00080000 /* 512 KB: DRAM0 + DRAM1, both full core speed */ } ENTRY(_start) diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/mpu.c b/ports/cortex_r52/gnu/example_build/s32z280_evb/mpu.c index 097b2dd0f..42fe0f772 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/mpu.c +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/mpu.c @@ -293,9 +293,13 @@ static void build_table(void) mpu_regions[0].mpu_region_name = "code RO X normal-wb"; /* Data, bss and every per-mode stack: writable, never executable. Sized - from the SRAM bank, not from __data_end__: the stacks are NOLOAD and sit + from the SRAM banks, not from __data_end__: the stacks are NOLOAD and sit above that symbol, so sizing from it would leave them unmapped and the - first push after enabling the MPU would abort. */ + first push after enabling the MPU would abort. + + This covers DRAM0 and DRAM1 together -- 512 KB, contiguous, both at full + core speed. DRAM1 went undeclared until the banks were read out of the + Reference Manual and confirmed on the board. */ mpu_regions[1].mpu_region_base = S32Z_DATA_SRAM_BASE; mpu_regions[1].mpu_region_limit = S32Z_DATA_SRAM_BASE @@ -338,19 +342,24 @@ static void build_table(void) mpu_regions[4].mpu_region_attr_index = MPU_ATTR_DEVICE; mpu_regions[4].mpu_region_name = "rtu RW NX device"; - /* Extended SRAM. Deliberately mapped so the cache benchmark has memory - that is NOT RTU-local to work against: the fast-data bank in region 1 is - close to core speed, so caching it shows nothing. Normal write-back and - never executable. */ + /* DRAM2. Deliberately mapped so the cache benchmark has slower memory to + work against: this bank runs at half the core frequency, where region 1's + banks run at full speed and caching them shows little. Normal write-back + and never executable. + + Sized 512 KB, which is the whole bank. An earlier revision mapped 2 MB + here; the upper 1.5 MB of that aliased back onto the bank, so anything + placed above 0x31880000 would have silently shared storage with the + bottom of the region -- no fault, just two objects on one address. */ - mpu_regions[5].mpu_region_base = S32Z_EXT_SRAM_BASE; - mpu_regions[5].mpu_region_limit = S32Z_EXT_SRAM_BASE - + S32Z_EXT_SRAM_SIZE - 1UL; + mpu_regions[5].mpu_region_base = S32Z_DRAM2_BASE; + mpu_regions[5].mpu_region_limit = S32Z_DRAM2_BASE + + S32Z_DRAM2_SIZE - 1UL; mpu_regions[5].mpu_region_ap = MPU_AP_RW_EL1; mpu_regions[5].mpu_region_execute_never = 1U; mpu_regions[5].mpu_region_shareability = MPU_SH_NON; mpu_regions[5].mpu_region_attr_index = MPU_ATTR_NORMAL_WB; - mpu_regions[5].mpu_region_name = "ext RW NX normal-wb"; + mpu_regions[5].mpu_region_name = "dram2 RW NX normal-wb"; /* One region per TCM bank. The TRM is explicit that an enabled TCM still needs an MPU region before it can be used, and that an enabled TCM always diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/platform.h b/ports/cortex_r52/gnu/example_build/s32z280_evb/platform.h index 984b4370b..37f2e9e4a 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/platform.h +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/platform.h @@ -108,18 +108,36 @@ #define S32Z_CODE_SRAM_DATA_ALIAS 0x32100000UL -/* RTU-local data SRAM. The Reference Manual notes that when an RTU */ -/* accesses its own blocks the traffic stays inside the RTU, so this is */ -/* the right home for stacks and .data. 256 KB. [verified writable] */ - -#define S32Z_DATA_SRAM_BASE 0x31780000UL -#define S32Z_DATA_SRAM_SIZE 0x00040000UL - -/* Larger but not RTU-local: 2 MB, for images that outgrow the above. */ -/* [verified writable] */ - -#define S32Z_EXT_SRAM_BASE 0x31800000UL -#define S32Z_EXT_SRAM_SIZE 0x00200000UL +/* RTU data SRAM. The RTU has 1 MB of it, in three contiguous banks that */ +/* are all RTU-local -- when an RTU accesses its own blocks the traffic */ +/* stays inside the RTU. The banks differ in speed, not in locality: */ +/* */ +/* DRAM0 0x31780000 256 KB full core speed */ +/* DRAM1 0x317C0000 256 KB full core speed */ +/* DRAM2 0x31800000 512 KB half core speed */ +/* */ +/* S32Z2 Reference Manual Rev. 5, section 6.3.6 and Table 13. Confirmed */ +/* on the board: writing distinct values to all three banks and reading */ +/* them back shows 1 MB of independent storage, and the first address */ +/* past DRAM2 aliases back onto its base, which is what fixes its size at */ +/* 512 KB rather than the 2 MB an earlier revision of this file claimed. */ +/* */ +/* Note that NXP's own debugger memory map, s32z2e2_memory_regions.py in */ +/* S32 Design Studio, describes this last bank as 2 MB. The Reference */ +/* Manual and the silicon agree it is 512 KB; the script is wrong here. */ + +#define S32Z_DRAM0_BASE 0x31780000UL +#define S32Z_DRAM0_SIZE 0x00040000UL +#define S32Z_DRAM1_BASE 0x317C0000UL +#define S32Z_DRAM1_SIZE 0x00040000UL +#define S32Z_DRAM2_BASE 0x31800000UL +#define S32Z_DRAM2_SIZE 0x00080000UL + +/* The full-speed pair, contiguous, and the right home for stacks and */ +/* .data. This is what link.lds calls DATA. */ + +#define S32Z_DATA_SRAM_BASE S32Z_DRAM0_BASE +#define S32Z_DATA_SRAM_SIZE (S32Z_DRAM0_SIZE + S32Z_DRAM1_SIZE) /* Console. The EVB user guide (UG10268) dedicates LIN9 to the */ /* daughtercard USB-UART, selected by jumper J248, so LINFlex_9 is the */ From 09c190a71d83b2ba993a1d2e3e2adbf2c710f3a8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Sat, 15 Aug 2026 17:28:33 -0400 Subject: [PATCH 049/181] Added a CMake target for the Linux sample program (#622) The CMake build produced libthreadx.a and nothing else, so trying ThreadX on Linux meant using the Makefile beside the port instead. Build the demo the Makefile builds, for the linux port and its SMP counterpart. The target is behind an option that defaults off, so an ordinary build is unchanged and still produces just the library. -DTHREADX_SAMPLE=ON adds it: cmake -S . -B build -DTHREADX_ARCH=linux -DTHREADX_TOOLCHAIN=gnu \ -DTHREADX_SAMPLE=ON cmake --build build --target sample_threadx The include path uses TX_COMMON_DIR rather than naming common or common_smp, since the top level already resolves which of the two applies. Verified by building and running both variants. Non-SMP prints **** ThreadX Linux Demonstration **** (c) 1996-2020 Microsoft Corporation and SMP prints the SMP banner, both with the demo's thread counters advancing. A default configure with no THREADX_SAMPLE has no sample_threadx target and still produces libthreadx.a, so nothing existing moves. Derived from the two example_build files in #404 by Yanfeng Liu, which had the same goal. That change also rewrote the top level's SMP selection, added common_smp/CMakeLists.txt and added ports_smp/linux/gnu/CMakeLists.txt; all three have since arrived on dev by other routes, so only the sample targets were still missing. The include path needed adjusting because the original depended on THREADX_SMP being a string suffix, which it no longer is. Assisted-by: Claude Code (Opus 5) --- ports/linux/gnu/CMakeLists.txt | 9 ++++++++- ports/linux/gnu/example_build/CMakeLists.txt | 17 +++++++++++++++++ ports_smp/linux/gnu/CMakeLists.txt | 7 +++++++ .../linux/gnu/example_build/CMakeLists.txt | 17 +++++++++++++++++ 4 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 ports/linux/gnu/example_build/CMakeLists.txt create mode 100644 ports_smp/linux/gnu/example_build/CMakeLists.txt diff --git a/ports/linux/gnu/CMakeLists.txt b/ports/linux/gnu/CMakeLists.txt index 4b5179402..073f4b7e2 100644 --- a/ports/linux/gnu/CMakeLists.txt +++ b/ports/linux/gnu/CMakeLists.txt @@ -19,4 +19,11 @@ target_include_directories(${PROJECT_NAME} ${CMAKE_CURRENT_LIST_DIR}/inc ) -target_compile_definitions(${PROJECT_NAME} PUBLIC "-D_GNU_SOURCE -DTX_LINUX_DEBUG_ENABLE") \ No newline at end of file +target_compile_definitions(${PROJECT_NAME} PUBLIC "-D_GNU_SOURCE -DTX_LINUX_DEBUG_ENABLE") + +# The demo program beside the port. Off by default so the ordinary build +# produces just the library; -DTHREADX_SAMPLE=ON adds the sample_threadx target. +option(THREADX_SAMPLE "Build the sample program for this port" OFF) +if(THREADX_SAMPLE) + add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/example_build) +endif() diff --git a/ports/linux/gnu/example_build/CMakeLists.txt b/ports/linux/gnu/example_build/CMakeLists.txt new file mode 100644 index 000000000..90d4078a9 --- /dev/null +++ b/ports/linux/gnu/example_build/CMakeLists.txt @@ -0,0 +1,17 @@ +# Build the sample_threadx program that ports/linux/gnu/Makefile builds, so the +# CMake build can produce a runnable demo rather than only the library. +# +# Guarded by THREADX_SAMPLE in the parent so the default build stays a pure +# library build. + +add_executable(sample_threadx) + +target_sources(sample_threadx PRIVATE ${CMAKE_CURRENT_LIST_DIR}/sample_threadx.c) + +target_include_directories(sample_threadx + PRIVATE + ${CMAKE_CURRENT_LIST_DIR}/../inc + ${CMAKE_CURRENT_LIST_DIR}/../../../../${TX_COMMON_DIR}/inc +) + +target_link_libraries(sample_threadx PRIVATE threadx) diff --git a/ports_smp/linux/gnu/CMakeLists.txt b/ports_smp/linux/gnu/CMakeLists.txt index 6ad4d25b1..67209ee7f 100644 --- a/ports_smp/linux/gnu/CMakeLists.txt +++ b/ports_smp/linux/gnu/CMakeLists.txt @@ -31,3 +31,10 @@ target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) + +# The demo program beside the port. Off by default so the ordinary build +# produces just the library; -DTHREADX_SAMPLE=ON adds the sample_threadx target. +option(THREADX_SAMPLE "Build the sample program for this port" OFF) +if(THREADX_SAMPLE) + add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/example_build) +endif() diff --git a/ports_smp/linux/gnu/example_build/CMakeLists.txt b/ports_smp/linux/gnu/example_build/CMakeLists.txt new file mode 100644 index 000000000..90d4078a9 --- /dev/null +++ b/ports_smp/linux/gnu/example_build/CMakeLists.txt @@ -0,0 +1,17 @@ +# Build the sample_threadx program that ports/linux/gnu/Makefile builds, so the +# CMake build can produce a runnable demo rather than only the library. +# +# Guarded by THREADX_SAMPLE in the parent so the default build stays a pure +# library build. + +add_executable(sample_threadx) + +target_sources(sample_threadx PRIVATE ${CMAKE_CURRENT_LIST_DIR}/sample_threadx.c) + +target_include_directories(sample_threadx + PRIVATE + ${CMAKE_CURRENT_LIST_DIR}/../inc + ${CMAKE_CURRENT_LIST_DIR}/../../../../${TX_COMMON_DIR}/inc +) + +target_link_libraries(sample_threadx PRIVATE threadx) From 090f8edc56e40b1c5dde16d1c7f36f1428274324 Mon Sep 17 00:00:00 2001 From: Armchina_JidongMei Date: Sun, 16 Aug 2026 20:29:46 +0800 Subject: [PATCH 050/181] Added Cortex-M52 (Armv8.1-M) port (#519) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ports: add Cortex-M52 (Armv8.1-M) port support Add ThreadX port for Cortex-M52, supporting three toolchains: - GNU (GCC) - AC6 (Arm Compiler 6) - IAR Cortex-M52 is an Armv8.1-M Mainline processor sharing the same architecture profile as Cortex-M55 and Cortex-M85. The port is functionally identical to the existing Cortex-M85 port. * ports: update cortex_m52 port copy script,using it update content -Add cortex_m52 in threadx/scriprts/copy_armv8m.sh -Using updated copy_armv8m.sh to generate new cortex_m52 port content * Regenerated the Cortex-M52 port against dev and wired it into the checks The port was generated from ports_arch/ARMv8-M as it stood on master, which has since moved on. Rebasing onto dev and running scripts/copy_armv8_m.sh again brings the twelve stale files into line, which is the point of generating them: the core picks up every ARMv8-M fix made since without anyone porting it by hand. Among what it picks up: "MOV r0, 0" becomes "MOV r0, #0" in the schedule and system-return paths, the non-canonical immediate form that GNU as tolerates and LLVM's assembler rejects; and gnu/src/tx_initialize_low_level.S goes away, since the shared source no longer has it. Two integration points exist only on dev, so the original change could not have included them. cmake/cortex_m52.cmake, so the port can be selected the documented way. Every other Cortex-M core has one. It uses the hard float ABI, as Cortex-M55 and Cortex-M85 do. An entry in scripts/check_clang.sh, likewise with -mfloat-abi=hard. That flag is not decoration: -mcpu=cortex-m52 implies Helium, and building it soft-float ends in "multilib configuration error: No library available for MVE with soft-float ABI" on every file, which reads as a broken port rather than a missing flag. Verified after regenerating: scripts/copy_armv8_m.sh is a no-op, so the tree matches its source; all 14 assembly sources and 188 C sources compile for cortex-m52 with Arm Toolchain for Embedded 22.1.0. Note for anyone building with GNU tools: arm-none-eabi-gcc 13.2.1 rejects -mcpu=cortex-m52 outright. Support arrives in GCC 14. --------- Co-authored-by: Frédéric Desbiens Assisted-by: Claude Code (Opus 5) --- cmake/cortex_m52.cmake | 40 + ports/cortex_m52/ac6/CMakeLists.txt | 21 + ports/cortex_m52/ac6/inc/tx_port.h | 631 ++++++++++++++ .../cortex_m52/ac6/inc/tx_secure_interface.h | 55 ++ ports/cortex_m52/ac6/readme_threadx.txt | 228 +++++ .../ac6/src/tx_initialize_low_level.S | 278 ++++++ ports/cortex_m52/ac6/src/tx_misra.S | 723 ++++++++++++++++ .../ac6/src/tx_thread_context_restore.S | 81 ++ .../ac6/src/tx_thread_context_save.S | 81 ++ .../ac6/src/tx_thread_interrupt_control.S | 79 ++ .../ac6/src/tx_thread_interrupt_disable.S | 80 ++ .../ac6/src/tx_thread_interrupt_restore.S | 77 ++ ports/cortex_m52/ac6/src/tx_thread_schedule.S | 383 +++++++++ .../ac6/src/tx_thread_secure_stack.c | 577 +++++++++++++ .../ac6/src/tx_thread_secure_stack_allocate.S | 82 ++ .../ac6/src/tx_thread_secure_stack_free.S | 80 ++ .../src/tx_thread_secure_stack_initialize.S | 76 ++ .../ac6/src/tx_thread_stack_build.S | 137 +++ .../ac6/src/tx_thread_system_return.S | 99 +++ ports/cortex_m52/ac6/src/tx_timer_interrupt.S | 240 ++++++ .../src/txe_thread_secure_stack_allocate.c | 113 +++ .../ac6/src/txe_thread_secure_stack_free.c | 114 +++ ports/cortex_m52/gnu/CMakeLists.txt | 24 + ports/cortex_m52/gnu/inc/tx_port.h | 631 ++++++++++++++ .../cortex_m52/gnu/inc/tx_secure_interface.h | 55 ++ ports/cortex_m52/gnu/readme_threadx.txt | 210 +++++ ports/cortex_m52/gnu/src/tx_misra.S | 723 ++++++++++++++++ .../gnu/src/tx_thread_context_restore.S | 81 ++ .../gnu/src/tx_thread_context_save.S | 81 ++ .../gnu/src/tx_thread_interrupt_control.S | 79 ++ .../gnu/src/tx_thread_interrupt_disable.S | 80 ++ .../gnu/src/tx_thread_interrupt_restore.S | 77 ++ ports/cortex_m52/gnu/src/tx_thread_schedule.S | 379 +++++++++ .../gnu/src/tx_thread_secure_stack.c | 581 +++++++++++++ .../gnu/src/tx_thread_secure_stack_allocate.S | 82 ++ .../gnu/src/tx_thread_secure_stack_free.S | 80 ++ .../src/tx_thread_secure_stack_initialize.S | 76 ++ .../gnu/src/tx_thread_stack_build.S | 137 +++ .../gnu/src/tx_thread_system_return.S | 99 +++ ports/cortex_m52/gnu/src/tx_timer_interrupt.S | 240 ++++++ .../src/txe_thread_secure_stack_allocate.c | 113 +++ .../gnu/src/txe_thread_secure_stack_free.c | 114 +++ ports/cortex_m52/iar/inc/tx_port.h | 631 ++++++++++++++ .../cortex_m52/iar/inc/tx_secure_interface.h | 55 ++ ports/cortex_m52/iar/readme_threadx.txt | 221 +++++ ports/cortex_m52/iar/src/tx_iar.c | 804 ++++++++++++++++++ .../iar/src/tx_initialize_low_level.s | 237 ++++++ ports/cortex_m52/iar/src/tx_misra.s | 767 +++++++++++++++++ .../iar/src/tx_thread_context_restore.s | 74 ++ .../iar/src/tx_thread_context_save.s | 74 ++ .../iar/src/tx_thread_interrupt_control.s | 75 ++ .../iar/src/tx_thread_interrupt_disable.s | 75 ++ .../iar/src/tx_thread_interrupt_restore.s | 72 ++ ports/cortex_m52/iar/src/tx_thread_schedule.s | 370 ++++++++ .../iar/src/tx_thread_secure_stack.c | 583 +++++++++++++ .../iar/src/tx_thread_secure_stack_allocate.s | 77 ++ .../iar/src/tx_thread_secure_stack_free.s | 75 ++ .../src/tx_thread_secure_stack_initialize.s | 71 ++ .../iar/src/tx_thread_stack_build.s | 132 +++ .../iar/src/tx_thread_system_return.s | 95 +++ ports/cortex_m52/iar/src/tx_timer_interrupt.s | 248 ++++++ .../src/txe_thread_secure_stack_allocate.c | 113 +++ .../iar/src/txe_thread_secure_stack_free.c | 114 +++ scripts/check_clang.sh | 1 + scripts/copy_armv8_m.sh | 4 +- 65 files changed, 13183 insertions(+), 2 deletions(-) create mode 100644 cmake/cortex_m52.cmake create mode 100644 ports/cortex_m52/ac6/CMakeLists.txt create mode 100644 ports/cortex_m52/ac6/inc/tx_port.h create mode 100644 ports/cortex_m52/ac6/inc/tx_secure_interface.h create mode 100644 ports/cortex_m52/ac6/readme_threadx.txt create mode 100644 ports/cortex_m52/ac6/src/tx_initialize_low_level.S create mode 100644 ports/cortex_m52/ac6/src/tx_misra.S create mode 100644 ports/cortex_m52/ac6/src/tx_thread_context_restore.S create mode 100644 ports/cortex_m52/ac6/src/tx_thread_context_save.S create mode 100644 ports/cortex_m52/ac6/src/tx_thread_interrupt_control.S create mode 100644 ports/cortex_m52/ac6/src/tx_thread_interrupt_disable.S create mode 100644 ports/cortex_m52/ac6/src/tx_thread_interrupt_restore.S create mode 100644 ports/cortex_m52/ac6/src/tx_thread_schedule.S create mode 100644 ports/cortex_m52/ac6/src/tx_thread_secure_stack.c create mode 100644 ports/cortex_m52/ac6/src/tx_thread_secure_stack_allocate.S create mode 100644 ports/cortex_m52/ac6/src/tx_thread_secure_stack_free.S create mode 100644 ports/cortex_m52/ac6/src/tx_thread_secure_stack_initialize.S create mode 100644 ports/cortex_m52/ac6/src/tx_thread_stack_build.S create mode 100644 ports/cortex_m52/ac6/src/tx_thread_system_return.S create mode 100644 ports/cortex_m52/ac6/src/tx_timer_interrupt.S create mode 100644 ports/cortex_m52/ac6/src/txe_thread_secure_stack_allocate.c create mode 100644 ports/cortex_m52/ac6/src/txe_thread_secure_stack_free.c create mode 100644 ports/cortex_m52/gnu/CMakeLists.txt create mode 100644 ports/cortex_m52/gnu/inc/tx_port.h create mode 100644 ports/cortex_m52/gnu/inc/tx_secure_interface.h create mode 100644 ports/cortex_m52/gnu/readme_threadx.txt create mode 100644 ports/cortex_m52/gnu/src/tx_misra.S create mode 100644 ports/cortex_m52/gnu/src/tx_thread_context_restore.S create mode 100644 ports/cortex_m52/gnu/src/tx_thread_context_save.S create mode 100644 ports/cortex_m52/gnu/src/tx_thread_interrupt_control.S create mode 100644 ports/cortex_m52/gnu/src/tx_thread_interrupt_disable.S create mode 100644 ports/cortex_m52/gnu/src/tx_thread_interrupt_restore.S create mode 100644 ports/cortex_m52/gnu/src/tx_thread_schedule.S create mode 100644 ports/cortex_m52/gnu/src/tx_thread_secure_stack.c create mode 100644 ports/cortex_m52/gnu/src/tx_thread_secure_stack_allocate.S create mode 100644 ports/cortex_m52/gnu/src/tx_thread_secure_stack_free.S create mode 100644 ports/cortex_m52/gnu/src/tx_thread_secure_stack_initialize.S create mode 100644 ports/cortex_m52/gnu/src/tx_thread_stack_build.S create mode 100644 ports/cortex_m52/gnu/src/tx_thread_system_return.S create mode 100644 ports/cortex_m52/gnu/src/tx_timer_interrupt.S create mode 100644 ports/cortex_m52/gnu/src/txe_thread_secure_stack_allocate.c create mode 100644 ports/cortex_m52/gnu/src/txe_thread_secure_stack_free.c create mode 100644 ports/cortex_m52/iar/inc/tx_port.h create mode 100644 ports/cortex_m52/iar/inc/tx_secure_interface.h create mode 100644 ports/cortex_m52/iar/readme_threadx.txt create mode 100644 ports/cortex_m52/iar/src/tx_iar.c create mode 100644 ports/cortex_m52/iar/src/tx_initialize_low_level.s create mode 100644 ports/cortex_m52/iar/src/tx_misra.s create mode 100644 ports/cortex_m52/iar/src/tx_thread_context_restore.s create mode 100644 ports/cortex_m52/iar/src/tx_thread_context_save.s create mode 100644 ports/cortex_m52/iar/src/tx_thread_interrupt_control.s create mode 100644 ports/cortex_m52/iar/src/tx_thread_interrupt_disable.s create mode 100644 ports/cortex_m52/iar/src/tx_thread_interrupt_restore.s create mode 100644 ports/cortex_m52/iar/src/tx_thread_schedule.s create mode 100644 ports/cortex_m52/iar/src/tx_thread_secure_stack.c create mode 100644 ports/cortex_m52/iar/src/tx_thread_secure_stack_allocate.s create mode 100644 ports/cortex_m52/iar/src/tx_thread_secure_stack_free.s create mode 100644 ports/cortex_m52/iar/src/tx_thread_secure_stack_initialize.s create mode 100644 ports/cortex_m52/iar/src/tx_thread_stack_build.s create mode 100644 ports/cortex_m52/iar/src/tx_thread_system_return.s create mode 100644 ports/cortex_m52/iar/src/tx_timer_interrupt.s create mode 100644 ports/cortex_m52/iar/src/txe_thread_secure_stack_allocate.c create mode 100644 ports/cortex_m52/iar/src/txe_thread_secure_stack_free.c diff --git a/cmake/cortex_m52.cmake b/cmake/cortex_m52.cmake new file mode 100644 index 000000000..be25f62dd --- /dev/null +++ b/cmake/cortex_m52.cmake @@ -0,0 +1,40 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# Toolchain file for Arm Cortex-M52 using GNU tools. +# +# The FPU and the MVE unit come with the core, so the hard float ABI +# is selected here rather than left to the caller. scripts/check_clang.sh +# builds this core the same way. + +# Name of the target +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR cortex-m52) + +set(THREADX_ARCH "cortex_m52") +set(THREADX_TOOLCHAIN "gnu") + +# The hard float ABI is not optional here: -mcpu=cortex-m52 implies Helium, and +# the soft-float variant has no matching library. +set(MCPU_FLAGS "-mthumb -mcpu=cortex-m52") +set(VFP_FLAGS "-mfloat-abi=hard") +set(SPEC_FLAGS "--specs=nosys.specs") + +include(${CMAKE_CURRENT_LIST_DIR}/arm-none-eabi.cmake) + +# Pin the reference cross toolchain, as cmake/cortex_r52.cmake does. This core +# needs it rather than merely preferring it: arm-none-eabi-gcc only learned +# -mcpu=cortex-m52 in GCC 14, so a distribution compiler on PATH is likely to +# reject the port outright. Override with -DARM_TOOLCHAIN_PATH= to build with a different compiler. The check leaves PATH +# alone when the pinned directory is absent. +if(NOT DEFINED ARM_TOOLCHAIN_PATH) + set(ARM_TOOLCHAIN_PATH + "$ENV{HOME}/toolchains/arm-gnu-toolchain-14.3.rel1-x86_64-arm-none-eabi/bin") +endif() +if(EXISTS "${ARM_TOOLCHAIN_PATH}/arm-none-eabi-gcc") + set(CMAKE_C_COMPILER "${ARM_TOOLCHAIN_PATH}/arm-none-eabi-gcc") + set(CMAKE_CXX_COMPILER "${ARM_TOOLCHAIN_PATH}/arm-none-eabi-g++") + set(CMAKE_ASM_COMPILER "${ARM_TOOLCHAIN_PATH}/arm-none-eabi-gcc") +endif() diff --git a/ports/cortex_m52/ac6/CMakeLists.txt b/ports/cortex_m52/ac6/CMakeLists.txt new file mode 100644 index 000000000..5ad3b8e75 --- /dev/null +++ b/ports/cortex_m52/ac6/CMakeLists.txt @@ -0,0 +1,21 @@ +target_sources(${PROJECT_NAME} PRIVATE + ${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_secure_stack_allocate.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_secure_stack_free.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_initialize_low_level.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_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_secure_stack.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_secure_stack_allocate.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_secure_stack_free.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S +) + +target_include_directories(${PROJECT_NAME} PUBLIC + inc +) diff --git a/ports/cortex_m52/ac6/inc/tx_port.h b/ports/cortex_m52/ac6/inc/tx_port.h new file mode 100644 index 000000000..18f28f0d9 --- /dev/null +++ b/ports/cortex_m52/ac6/inc/tx_port.h @@ -0,0 +1,631 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + +// Some portions generated by Gemini (Gemini 2.0 Flash). +// Some portions generated by Claude Code (Opus 5). + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Port Specific */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* PORT SPECIFIC C INFORMATION RELEASE */ +/* */ +/* tx_port.h Cortex-M52/AC6 */ +/* 6.2.1 */ +/* */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains data type definitions that make the ThreadX */ +/* real-time kernel function identically on a variety of different */ +/* processor architectures. For example, the size or number of bits */ +/* in an "int" data type vary between microprocessor architectures and */ +/* even C compilers for the same microprocessor. ThreadX does not */ +/* directly use native C data types. Instead, ThreadX creates its */ +/* own special types that can be mapped to actual data types by this */ +/* file to guarantee consistency in the interface and functionality. */ +/* */ +/* This file replaces the previous Cortex-M52 files. It unifies */ +/* the Cortex-M52 compilers into one common file. */ +/* */ +/**************************************************************************/ + +#ifndef TX_PORT_H +#define TX_PORT_H + +/* Determine if the optional ThreadX user define file should be used. */ +#ifdef TX_INCLUDE_USER_DEFINE_FILE + +/* Yes, include the user defines in tx_user.h. The defines in this file may + alternately be defined on the command line. */ + +#include "tx_user.h" +#endif /* TX_INCLUDE_USER_DEFINE_FILE */ + +/* Define compiler library include files. */ + +#include +#include + +#ifdef __ICCARM__ +#include /* IAR Intrinsics */ +#define __asm__ __asm /* Define to make all inline asm from each compiler look similar */ +#define _tx_control_get __get_CONTROL +#define _tx_control_set __set_CONTROL +#define _tx_ipsr_get __get_IPSR +#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT +#include +#endif /* TX_ENABLE_IAR_LIBRARY_SUPPORT */ +#endif /* __ICCARM__ */ + + +/* Define ThreadX basic types for this port. */ + +#define VOID void +typedef char CHAR; +typedef unsigned char UCHAR; +typedef int INT; +typedef unsigned int UINT; +typedef long LONG; +typedef unsigned long ULONG; +typedef unsigned long long ULONG64; +typedef short SHORT; +typedef unsigned short USHORT; +#define ULONG64_DEFINED + +/* Function prototypes for this port. */ +struct TX_THREAD_STRUCT; +UINT _txe_thread_secure_stack_allocate(struct TX_THREAD_STRUCT *thread_ptr, ULONG stack_size); +UINT _txe_thread_secure_stack_free(struct TX_THREAD_STRUCT *thread_ptr); +UINT _tx_thread_secure_stack_allocate(struct TX_THREAD_STRUCT *tx_thread, ULONG stack_size); +UINT _tx_thread_secure_stack_free(struct TX_THREAD_STRUCT *tx_thread); + +/* Define the system API mappings based on the error checking + selected by the user. Note: this section is only applicable to + application source code, hence the conditional that turns off this + stuff when the include file is processed by the ThreadX source. */ + +#ifndef TX_SOURCE_CODE + + +/* Determine if error checking is desired. If so, map API functions + to the appropriate error checking front-ends. Otherwise, map API + functions to the core functions that actually perform the work. + Note: error checking is enabled by default. */ + +#ifdef TX_DISABLE_ERROR_CHECKING + +/* Services without error checking. */ + +#define tx_thread_secure_stack_allocate _tx_thread_secure_stack_allocate +#define tx_thread_secure_stack_free _tx_thread_secure_stack_free + +#else + +/* Services with error checking. */ + +#define tx_thread_secure_stack_allocate _txe_thread_secure_stack_allocate +#define tx_thread_secure_stack_free _txe_thread_secure_stack_free + +#endif /* TX_DISABLE_ERROR_CHECKING */ +#endif /* TX_SOURCE_CODE */ + +/* This port has a usage fault handler in _tx_initialize_low_level for stack exceptions. */ +#define TX_PORT_THREAD_STACK_ERROR_HANDLING + +/* Define the priority levels for ThreadX. Legal values range + from 32 to 1024 and MUST be evenly divisible by 32. */ + +#ifndef TX_MAX_PRIORITIES +#define TX_MAX_PRIORITIES 32 +#endif + + +/* Define the minimum stack for a ThreadX thread on this processor. If the size supplied during + thread creation is less than this value, the thread create call will return an error. */ + +#ifndef TX_MINIMUM_STACK +#define TX_MINIMUM_STACK 200 /* Minimum stack size for this port */ +#endif + + +/* Define the system timer thread's default stack size and priority. These are only applicable + if TX_TIMER_PROCESS_IN_ISR is not defined. */ + +#ifndef TX_TIMER_THREAD_STACK_SIZE +#define TX_TIMER_THREAD_STACK_SIZE 1024 /* Default timer thread stack size */ +#endif + +#ifndef TX_TIMER_THREAD_PRIORITY +#define TX_TIMER_THREAD_PRIORITY 0 /* Default timer thread priority */ +#endif + +/* By default, ThreadX for Cortex-M uses the PRIMASK register to enable/disable interrupts. +If using BASEPRI is desired, define the following two symbols for both c and assembly files: +TX_PORT_USE_BASEPRI - This tells ThreadX to use BASEPRI instead of PRIMASK. +TX_PORT_BASEPRI = (priority_mask << (8 - number_priority_bits)) - this defines the maximum priority level to mask. +Any interrupt with a higher priority than priority_mask will not be masked, thus the interrupt will run. +*/ + +/* Define various constants for the ThreadX Cortex-M port. */ + +#define TX_INT_DISABLE 1 /* Disable interrupts */ +#define TX_INT_ENABLE 0 /* Enable interrupts */ + + +/* Define the clock source for trace event entry time stamp. The following two item are port specific. + For example, if the time source is at the address 0x0a800024 and is 16-bits in size, the clock + source constants would be: + +#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0x0a800024) +#define TX_TRACE_TIME_MASK 0x0000FFFFUL + +*/ + +#ifndef TX_MISRA_ENABLE +#ifndef TX_TRACE_TIME_SOURCE +#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0xE0001004) +#endif +#else +ULONG _tx_misra_time_stamp_get(VOID); +#define TX_TRACE_TIME_SOURCE _tx_misra_time_stamp_get() +#endif + +#ifndef TX_TRACE_TIME_MASK +#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL +#endif + + +/* Define the port specific options for the _tx_build_options variable. This variable indicates + how the ThreadX library was built. */ + +#define TX_PORT_SPECIFIC_BUILD_OPTIONS (0) + + +/* Define the in-line initialization constant so that modules with in-line + initialization capabilities can prevent their initialization from being + a function call. */ + +#ifdef TX_MISRA_ENABLE +#define TX_DISABLE_INLINE +#else +#define TX_INLINE_INITIALIZATION +#endif + + +/* Determine whether or not stack checking is enabled. By default, ThreadX stack checking is + disabled. When the following is defined, ThreadX thread stack checking is enabled. If stack + checking is enabled (TX_ENABLE_STACK_CHECKING is defined), the TX_DISABLE_STACK_FILLING + define is negated, thereby forcing the stack fill which is necessary for the stack checking + logic. */ + +#ifndef TX_MISRA_ENABLE +#ifdef TX_ENABLE_STACK_CHECKING +#undef TX_DISABLE_STACK_FILLING +#endif +#endif + + +/* Define the TX_THREAD control block extensions for this port. The main reason + for the multiple macros is so that backward compatibility can be maintained with + existing ThreadX kernel awareness modules. */ + +#define TX_THREAD_EXTENSION_0 +#define TX_THREAD_EXTENSION_1 + +#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT +/* IAR library support */ +#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE) +/* ThreadX in non-secure zone with calls to secure zone. */ +#define TX_THREAD_EXTENSION_2 VOID *tx_thread_secure_stack_context; \ + VOID *tx_thread_iar_tls_pointer; +#else +/* ThreadX in only one zone. */ +#define TX_THREAD_EXTENSION_2 VOID *tx_thread_iar_tls_pointer; +#endif + +#else +/* No IAR library support */ +#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE) +/* ThreadX in non-secure zone with calls to secure zone. */ +#define TX_THREAD_EXTENSION_2 VOID *tx_thread_secure_stack_context; +#else +/* ThreadX in only one zone. */ +#define TX_THREAD_EXTENSION_2 +#endif + +#endif /* TX_ENABLE_IAR_LIBRARY_SUPPORT */ + +#define TX_THREAD_EXTENSION_3 + + +/* Define the port extensions of the remaining ThreadX objects. */ + +#define TX_BLOCK_POOL_EXTENSION +#define TX_BYTE_POOL_EXTENSION +#define TX_EVENT_FLAGS_GROUP_EXTENSION +#define TX_MUTEX_EXTENSION +#define TX_QUEUE_EXTENSION +#define TX_SEMAPHORE_EXTENSION +#define TX_TIMER_EXTENSION + + +/* Define the user extension field of the thread control block. Nothing + additional is needed for this port so it is defined as white space. */ + +#ifndef TX_THREAD_USER_EXTENSION +#define TX_THREAD_USER_EXTENSION +#endif + + +/* Define the macros for processing extensions in tx_thread_create, tx_thread_delete, + tx_thread_shell_entry, and tx_thread_terminate. */ +#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT +void *_tx_iar_create_per_thread_tls_area(void); +void _tx_iar_destroy_per_thread_tls_area(void *tls_ptr); +void __iar_Initlocks(void); +#define TX_THREAD_CREATE_EXTENSION(thread_ptr) thread_ptr -> tx_thread_iar_tls_pointer = _tx_iar_create_per_thread_tls_area(); + +#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE) +#define TX_THREAD_DELETE_EXTENSION(thread_ptr) do {_tx_iar_destroy_per_thread_tls_area(thread_ptr -> tx_thread_iar_tls_pointer); \ + thread_ptr -> tx_thread_iar_tls_pointer = TX_NULL; } while(0); \ + if(thread_ptr -> tx_thread_secure_stack_context){_tx_thread_secure_stack_free(thread_ptr);} +#else +#define TX_THREAD_DELETE_EXTENSION(thread_ptr) do {_tx_iar_destroy_per_thread_tls_area(thread_ptr -> tx_thread_iar_tls_pointer); \ + thread_ptr -> tx_thread_iar_tls_pointer = TX_NULL; } while(0); +#endif +#define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION do {__iar_Initlocks();} while(0); + +#else /* No IAR library support. */ +#define TX_THREAD_CREATE_EXTENSION(thread_ptr) +#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE) +#define TX_THREAD_DELETE_EXTENSION(thread_ptr) if(thread_ptr -> tx_thread_secure_stack_context){_tx_thread_secure_stack_free(thread_ptr);} +#else +#define TX_THREAD_DELETE_EXTENSION(thread_ptr) +#endif +#endif /* TX_ENABLE_IAR_LIBRARY_SUPPORT */ + +#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE) +/* Define the size of the secure stack for the timer thread and use the extension to allocate the secure stack. */ +#define TX_TIMER_THREAD_SECURE_STACK_SIZE 256 +#define TX_TIMER_INITIALIZE_EXTENSION(status) _tx_thread_secure_stack_allocate(&_tx_timer_thread, TX_TIMER_THREAD_SECURE_STACK_SIZE); +#endif + + +#if defined(__ARMVFP__) || defined(__ARM_PCS_VFP) || defined(__ARM_FP) || defined(__TARGET_FPU_VFP) || defined(__VFP__) + +#ifdef TX_MISRA_ENABLE + +ULONG _tx_misra_control_get(void); +void _tx_misra_control_set(ULONG value); +ULONG _tx_misra_fpccr_get(void); +void _tx_misra_vfp_touch(void); + +#else /* TX_MISRA_ENABLE not defined */ + +#ifdef __GNUC__ /* GCC and ARM Compiler 6 */ + +__attribute__( ( always_inline ) ) static inline ULONG _tx_control_get(void) +{ +ULONG control_value; + + __asm__ volatile (" MRS %0,CONTROL ": "=r" (control_value) ); + return(control_value); +} + +__attribute__( ( always_inline ) ) static inline void _tx_control_set(ULONG control_value) +{ + __asm__ volatile (" MSR CONTROL,%0": : "r" (control_value): "memory" ); +} + +#endif /* __GNUC__ */ + +/* Touch VFP register in order to flush. Works for AC6/GCC/IAR compilers. */ +#define TX_VFP_TOUCH() __asm__ volatile ("VMOV.F32 s0, s0"); + +#endif /* TX_MISRA_ENABLE */ + +/* A completed thread falls into _thread_shell_entry and we can simply deactivate the FPU via CONTROL.FPCA + in order to ensure no lazy stacking will occur. */ + +#ifndef TX_MISRA_ENABLE + +#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) { \ + ULONG _tx_vfp_state; \ + _tx_vfp_state = _tx_control_get(); \ + _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \ + _tx_control_set(_tx_vfp_state); \ + } +#else + +#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) { \ + ULONG _tx_vfp_state; \ + _tx_vfp_state = _tx_misra_control_get(); \ + _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \ + _tx_misra_control_set(_tx_vfp_state); \ + } +#endif + +/* A thread can be terminated by another thread, so we first check if it's self-terminating and not in an ISR. + If so, deactivate the FPU via CONTROL.FPCA. Otherwise we are in an interrupt or another thread is terminating + this one, so if the FPCCR.LSPACT bit is set, we need to save the CONTROL.FPCA state, touch the FPU to flush + the lazy FPU save, then restore the CONTROL.FPCA state. */ + +#ifndef TX_MISRA_ENABLE + +#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) { \ + ULONG _tx_system_state; \ + _tx_system_state = TX_THREAD_GET_SYSTEM_STATE(); \ + if ((_tx_system_state == ((ULONG) 0)) && ((thread_ptr) == _tx_thread_current_ptr)) \ + { \ + ULONG _tx_vfp_state; \ + _tx_vfp_state = _tx_control_get(); \ + _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \ + _tx_control_set(_tx_vfp_state); \ + } \ + else \ + { \ + ULONG _tx_fpccr; \ + _tx_fpccr = *((volatile ULONG *) 0xE000EF34); \ + _tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \ + if (_tx_fpccr == ((ULONG) 0x01)) \ + { \ + ULONG _tx_vfp_state; \ + _tx_vfp_state = _tx_control_get(); \ + _tx_vfp_state = _tx_vfp_state & ((ULONG) 0x4); \ + TX_VFP_TOUCH(); \ + if (_tx_vfp_state == ((ULONG) 0)) \ + { \ + _tx_vfp_state = _tx_control_get(); \ + _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \ + _tx_control_set(_tx_vfp_state); \ + } \ + } \ + } \ + } +#else + +#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) { \ + ULONG _tx_system_state; \ + _tx_system_state = TX_THREAD_GET_SYSTEM_STATE(); \ + if ((_tx_system_state == ((ULONG) 0)) && ((thread_ptr) == _tx_thread_current_ptr)) \ + { \ + ULONG _tx_vfp_state; \ + _tx_vfp_state = _tx_misra_control_get(); \ + _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \ + _tx_misra_control_set(_tx_vfp_state); \ + } \ + else \ + { \ + ULONG _tx_fpccr; \ + _tx_fpccr = _tx_misra_fpccr_get(); \ + _tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \ + if (_tx_fpccr == ((ULONG) 0x01)) \ + { \ + ULONG _tx_vfp_state; \ + _tx_vfp_state = _tx_misra_control_get(); \ + _tx_vfp_state = _tx_vfp_state & ((ULONG) 0x4); \ + _tx_misra_vfp_touch(); \ + if (_tx_vfp_state == ((ULONG) 0)) \ + { \ + _tx_vfp_state = _tx_misra_control_get(); \ + _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \ + _tx_misra_control_set(_tx_vfp_state); \ + } \ + } \ + } \ + } +#endif + +#else /* No VFP in use */ + +#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) +#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) + +#endif /* defined(__ARMVFP__) || defined(__ARM_PCS_VFP) || defined(__ARM_FP) || defined(__TARGET_FPU_VFP) || defined(__VFP__) */ + + +/* Define the ThreadX object creation extensions for the remaining objects. */ + +#define TX_BLOCK_POOL_CREATE_EXTENSION(pool_ptr) +#define TX_BYTE_POOL_CREATE_EXTENSION(pool_ptr) +#define TX_EVENT_FLAGS_GROUP_CREATE_EXTENSION(group_ptr) +#define TX_MUTEX_CREATE_EXTENSION(mutex_ptr) +#define TX_QUEUE_CREATE_EXTENSION(queue_ptr) +#define TX_SEMAPHORE_CREATE_EXTENSION(semaphore_ptr) +#define TX_TIMER_CREATE_EXTENSION(timer_ptr) + + +/* Define the ThreadX object deletion extensions for the remaining objects. */ + +#define TX_BLOCK_POOL_DELETE_EXTENSION(pool_ptr) +#define TX_BYTE_POOL_DELETE_EXTENSION(pool_ptr) +#define TX_EVENT_FLAGS_GROUP_DELETE_EXTENSION(group_ptr) +#define TX_MUTEX_DELETE_EXTENSION(mutex_ptr) +#define TX_QUEUE_DELETE_EXTENSION(queue_ptr) +#define TX_SEMAPHORE_DELETE_EXTENSION(semaphore_ptr) +#define TX_TIMER_DELETE_EXTENSION(timer_ptr) + + +/* Define the get system state macro. */ + +#ifndef TX_THREAD_GET_SYSTEM_STATE +#ifndef TX_MISRA_ENABLE + +#if defined(__GNUC__) /* GCC and AC6 */ +__attribute__( ( always_inline ) ) static inline UINT _tx_ipsr_get(void) +{ +UINT ipsr_value; + __asm__ volatile (" MRS %0,IPSR ": "=r" (ipsr_value) ); + return(ipsr_value); +} +#endif /* GCC and AC6 IPSR_get function. */ + +#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | _tx_ipsr_get()) + +#else /* TX_MISRA_ENABLE is defined, use MISRA function. */ +ULONG _tx_misra_ipsr_get(VOID); +#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | _tx_misra_ipsr_get()) +#endif /* TX_MISRA_ENABLE */ +#endif /* TX_THREAD_GET_SYSTEM_STATE */ + + +/* Define the check for whether or not to call the _tx_thread_system_return function. A non-zero value + indicates that _tx_thread_system_return should not be called. This overrides the definition in tx_thread.h + for Cortex-M since so we don't waste time checking the _tx_thread_system_state variable that is always + zero after initialization for Cortex-M ports. */ + +#ifndef TX_THREAD_SYSTEM_RETURN_CHECK +#define TX_THREAD_SYSTEM_RETURN_CHECK(c) (c) = ((ULONG) _tx_thread_preempt_disable); +#endif + +#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE) +/* Initialize secure stacks for threads calling secure functions. */ +extern void _tx_thread_secure_stack_initialize(void); +#define TX_PORT_SPECIFIC_PRE_INITIALIZATION _tx_thread_secure_stack_initialize(); +#endif + +/* Define the macro to ensure _tx_thread_preempt_disable is set early in initialization in order to + prevent early scheduling on Cortex-M parts. */ + +#define TX_PORT_SPECIFIC_POST_INITIALIZATION _tx_thread_preempt_disable++; + + + + +#ifndef TX_DISABLE_INLINE + +/* Define the TX_LOWEST_SET_BIT_CALCULATE macro for each compiler. */ +#ifdef __ICCARM__ /* IAR Compiler */ +#define TX_LOWEST_SET_BIT_CALCULATE(m, b) (b) = (UINT) __CLZ(__RBIT((m))); +#elif defined(__GNUC__) /* GCC and AC6 Compiler */ +#define TX_LOWEST_SET_BIT_CALCULATE(m, b) __asm__ volatile (" RBIT %0,%1 ": "=r" (m) : "r" (m) ); \ + __asm__ volatile (" CLZ %0,%1 ": "=r" (b) : "r" (m) ); +#else +#error "Compiler not supported." +#endif + + + +/* Define the interrupt disable/restore macros. */ + +__attribute__( ( always_inline ) ) static inline UINT __get_interrupt_posture(void) +{ +UINT posture; +#ifdef TX_PORT_USE_BASEPRI + __asm__ volatile ("MRS %0, BASEPRI ": "=r" (posture)); +#else + __asm__ volatile ("MRS %0, PRIMASK ": "=r" (posture)); +#endif + return(posture); +} + +#ifdef TX_PORT_USE_BASEPRI +__attribute__( ( always_inline ) ) static inline void __set_basepri_value(UINT basepri_value) +{ + __asm__ volatile ("MSR BASEPRI,%0 ": : "r" (basepri_value) : "memory"); +} +#else +__attribute__( ( always_inline ) ) static inline void __enable_interrupts(void) +{ + __asm__ volatile ("CPSIE i": : : "memory"); +} +#endif + +__attribute__( ( always_inline ) ) static inline void __restore_interrupt(UINT int_posture) +{ +#ifdef TX_PORT_USE_BASEPRI + __set_basepri_value(int_posture); + __asm__ volatile ("" : : : "memory"); +#else + __asm__ volatile ("MSR PRIMASK,%0": : "r" (int_posture): "memory"); +#endif +} + +__attribute__( ( always_inline ) ) static inline UINT __disable_interrupts(void) +{ +UINT int_posture; + + int_posture = __get_interrupt_posture(); + +#ifdef TX_PORT_USE_BASEPRI + __set_basepri_value(TX_PORT_BASEPRI); +#else + __asm__ volatile ("CPSID i" : : : "memory"); +#endif + return(int_posture); +} + +__attribute__( ( always_inline ) ) static inline void _tx_thread_system_return_inline(void) +{ +UINT interrupt_save; + + /* Set PendSV to invoke ThreadX scheduler. */ + *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); + __asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory"); + if (_tx_ipsr_get() == 0) + { + interrupt_save = __get_interrupt_posture(); +#ifdef TX_PORT_USE_BASEPRI + __set_basepri_value(0); +#else + __enable_interrupts(); +#endif + __restore_interrupt(interrupt_save); + __asm__ volatile ("isb 0xF " : : : "memory"); + } +} + +#define TX_INTERRUPT_SAVE_AREA UINT interrupt_save; +#define TX_DISABLE interrupt_save = __disable_interrupts(); +#define TX_RESTORE __restore_interrupt(interrupt_save); + +/* Redefine _tx_thread_system_return for improved performance. */ +#define _tx_thread_system_return _tx_thread_system_return_inline + +#else /* TX_DISABLE_INLINE is defined */ + +UINT _tx_thread_interrupt_disable(VOID); +VOID _tx_thread_interrupt_restore(UINT previous_posture); + +#define TX_INTERRUPT_SAVE_AREA register UINT interrupt_save; + +#define TX_DISABLE interrupt_save = _tx_thread_interrupt_disable(); +#define TX_RESTORE _tx_thread_interrupt_restore(interrupt_save); +#endif /* TX_DISABLE_INLINE */ + +/* Define the version ID of ThreadX. This may be utilized by the application. */ + +#ifdef TX_THREAD_INIT +CHAR _tx_version_id[] = + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M52/AC6 Version 6.5.1.202602a *"; +#else +#ifdef TX_MISRA_ENABLE +extern CHAR _tx_version_id[100]; +#else +extern CHAR _tx_version_id[]; +#endif +#endif + +#endif diff --git a/ports/cortex_m52/ac6/inc/tx_secure_interface.h b/ports/cortex_m52/ac6/inc/tx_secure_interface.h new file mode 100644 index 000000000..5ac37fbf4 --- /dev/null +++ b/ports/cortex_m52/ac6/inc/tx_secure_interface.h @@ -0,0 +1,55 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* tx_secure_interface.h PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file defines the ThreadX secure thread stack components, */ +/* including data types and external references. */ +/* It is assumed that tx_api.h and tx_port.h have already been */ +/* included. */ +/* */ +/**************************************************************************/ + +#ifndef TX_SECURE_INTERFACE_H +#define TX_SECURE_INTERFACE_H + +/* Define internal secure thread stack function prototypes. */ + +extern UINT _tx_thread_secure_mode_stack_initialize(void); +extern UINT _tx_thread_secure_mode_stack_allocate(TX_THREAD *thread_ptr, ULONG stack_size); +extern UINT _tx_thread_secure_mode_stack_free(TX_THREAD *thread_ptr); +extern void _tx_thread_secure_stack_initialize(void); +extern void _tx_thread_secure_stack_context_save(TX_THREAD *thread_ptr); +extern void _tx_thread_secure_stack_context_restore(TX_THREAD *thread_ptr); + +#endif diff --git a/ports/cortex_m52/ac6/readme_threadx.txt b/ports/cortex_m52/ac6/readme_threadx.txt new file mode 100644 index 000000000..2149ab351 --- /dev/null +++ b/ports/cortex_m52/ac6/readme_threadx.txt @@ -0,0 +1,228 @@ + Microsoft's Azure RTOS ThreadX for Cortex-M52 + + Using the AC6 Tools in Keil uVision + +1. Import the ThreadX Projects + +In order to build the ThreadX library and the ThreadX demonstration, first open +the AzureRTOS.uvmpw workspace (located in the "example_build" directory) +into Keil. + + +2. Building the ThreadX run-time Library + +Building the ThreadX library is easy; simply set the ThreadX_Library project +as active, then then build the library. You should now observe the compilation +and assembly of the ThreadX library. This project build produces the ThreadX +library file ThreadX_Library.lib. +Files tx_thread_stack_error_handler.c and tx_thread_stack_error_notify.c +replace the common files of the same name. + +3. Demonstration System + +The ThreadX demonstration is designed to execute under the Keil debugger on the +FVP_MPS2_Cortex-M52_MDK simulator. + +Building the demonstration is easy; simply select the "Batch Build" button. +You should now observe the compilation and assembly of the ThreadX demonstration of +both the demo_secure_zone and demo_threadx_non-secure_zone projects. +Then click the Start/Stop Debug Session button to start the simulator and begin debugging. +You are now ready to execute the ThreadX demonstration. + + +4. System Initialization + +The entry point in ThreadX for the Cortex-M52 using AC6 tools uses the standard AC6 +Cortex-M52 reset sequence. From the reset vector the C runtime will be initialized. + +The ThreadX tx_initialize_low_level.s file is responsible for setting up +various system data structures, the vector area, and a periodic timer interrupt +source. + +In addition, _tx_initialize_low_level determines the first available +address for use by the application, which is supplied as the sole input +parameter to your application definition function, tx_application_define. + + +5. Register Usage and Stack Frames + +The following defines the saved context stack frames for context switches +that occur as a result of interrupt handling or from thread-level API calls. +All suspended threads have the same stack frame in the Cortex-M52 version of +ThreadX. The top of the suspended thread's stack is pointed to by +tx_thread_stack_ptr in the associated thread control block TX_THREAD. + +Non-FPU Stack Frame: + + Stack Offset Stack Contents + + 0x00 LR Interrupted LR (LR at time of PENDSV) + 0x04 r4 Software stacked GP registers + 0x08 r5 + 0x0C r6 + 0x10 r7 + 0x14 r8 + 0x18 r9 + 0x1C r10 + 0x20 r11 + 0x24 r0 Hardware stacked registers + 0x28 r1 + 0x2C r2 + 0x30 r3 + 0x34 r12 + 0x38 lr + 0x3C pc + 0x40 xPSR + +FPU Stack Frame (only interrupted thread with FPU enabled): + + Stack Offset Stack Contents + + 0x00 LR Interrupted LR (LR at time of PENDSV) + 0x04 s16 Software stacked FPU registers + 0x08 s17 + 0x0C s18 + 0x10 s19 + 0x14 s20 + 0x18 s21 + 0x1C s22 + 0x20 s23 + 0x24 s24 + 0x28 s25 + 0x2C s26 + 0x30 s27 + 0x34 s28 + 0x38 s29 + 0x3C s30 + 0x40 s31 + 0x44 r4 Software stacked registers + 0x48 r5 + 0x4C r6 + 0x50 r7 + 0x54 r8 + 0x58 r9 + 0x5C r10 + 0x60 r11 + 0x64 r0 Hardware stacked registers + 0x68 r1 + 0x6C r2 + 0x70 r3 + 0x74 r12 + 0x78 lr + 0x7C pc + 0x80 xPSR + 0x84 s0 Hardware stacked FPU registers + 0x88 s1 + 0x8C s2 + 0x90 s3 + 0x94 s4 + 0x98 s5 + 0x9C s6 + 0xA0 s7 + 0xA4 s8 + 0xA8 s9 + 0xAC s10 + 0xB0 s11 + 0xB4 s12 + 0xB8 s13 + 0xBC s14 + 0xC0 s15 + 0xC4 fpscr + + +6. Improving Performance + +To make ThreadX and the application(s) run faster, you can enable +all compiler optimizations. + +In addition, you can eliminate the ThreadX basic API error checking by +compiling your application code with the symbol TX_DISABLE_ERROR_CHECKING +defined. + + +7. Interrupt Handling + +ThreadX provides complete and high-performance interrupt handling for Cortex-M52 +targets. There are a certain set of requirements that are defined in the +following sub-sections: + + +7.1 Vector Area + +The Cortex-M52 vectors start at the label __Vectors or similar. The application may modify +the vector area according to its needs. There is code in tx_initialize_low_level() that will +configure the vector base register. + + +7.2 Managed Interrupts + +ISRs can be written completely in C (or assembly language) without any calls to +_tx_thread_context_save or _tx_thread_context_restore. These ISRs are allowed access to the +ThreadX API that is available to ISRs. + +ISRs written in C will take the form (where "your_C_isr" is an entry in the vector table): + +void your_C_isr(void) +{ + + /* ISR processing goes here, including any needed function calls. */ +} + +ISRs written in assembly language will take the form: + + + .global your_assembly_isr + .thumb_func +your_assembly_isr: +; VOID your_assembly_isr(VOID) +; { + PUSH {r0, lr} +; +; /* Do interrupt handler work here */ +; /* BL */ + + POP {r0, lr} + BX lr +; } + +Note: the Cortex-M52 requires exception handlers to be thumb labels, this implies bit 0 set. +To accomplish this, the declaration of the label has to be preceded by the assembler directive +.thumb_func to instruct the linker to create thumb labels. The label __tx_IntHandler needs to +be inserted in the correct location in the interrupt vector table. This table is typically +located in either your runtime startup file or in the tx_initialize_low_level.s file. + + +8. FPU Support + +ThreadX for Cortex-M52 supports automatic ("lazy") VFP support, which means that applications threads +can simply use the VFP and ThreadX automatically maintains the VFP registers as part of the thread +context. + + +9. Revision History + +For generic code revision information, please refer to the readme_threadx_generic.txt +file, which is included in your distribution. The following details the revision +information associated with this specific port of ThreadX: + +06-02-2021 Release 6.1.7 changes: + tx_port.h Remove unneeded include file + tx_thread_secure_stack_initialize.S New file + tx_thread_schedule.S Added secure stack initialize to SVC hander + tx_thread_secure_stack.c Fixed stack pointer save, initialize in handler mode + +04-02-2021 Release 6.1.6 changes: + tx_port.h Updated macro definition + tx_thread_schedule.s Added low power support + +03-02-2021 The following files were changed/added for version 6.1.5: + tx_port.h Added ULONG64_DEFINED + +09-30-2020 Initial ThreadX 6.1 version for Cortex-M52 using AC6 tools. + + +Copyright(c) 1996-2020 Microsoft Corporation + + +https://azure.com/rtos + diff --git a/ports/cortex_m52/ac6/src/tx_initialize_low_level.S b/ports/cortex_m52/ac6/src/tx_initialize_low_level.S new file mode 100644 index 000000000..0e1af6b5c --- /dev/null +++ b/ports/cortex_m52/ac6/src/tx_initialize_low_level.S @@ -0,0 +1,278 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Initialize */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + +SYSTEM_CLOCK = 6000000 +SYSTICK_CYCLES = ((SYSTEM_CLOCK / 100) -1) + +/* Setup the stack and heap areas. */ + +STACK_SIZE = 0x00000400 +HEAP_SIZE = 0x00000000 + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_initialize_low_level Cortex-M52/AC6 */ +/* 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 */ +/* */ +/**************************************************************************/ +// VOID _tx_initialize_low_level(VOID) +// { + .section .text + .balign 4 + .syntax unified + .eabi_attribute Tag_ABI_align_preserved, 1 + .global _tx_initialize_low_level + .thumb_func +.type _tx_initialize_low_level, function +_tx_initialize_low_level: + + /* Disable interrupts during ThreadX initialization. */ + CPSID i + + /* Set base of available memory to end of non-initialised RAM area. */ + LDR r0, =_tx_initialize_unused_memory // Build address of unused memory pointer + LDR r1, =Image$$ARM_LIB_STACK$$ZI$$Limit // Build first free address + ADD r1, r1, #4 // + STR r1, [r0] // Setup first unused memory pointer + + /* Setup Vector Table Offset Register. */ + MOV r0, #0xE000E000 // Build address of NVIC registers + LDR r1, =__Vectors // Pickup address of vector table + STR r1, [r0, #0xD08] // Set vector table address + + /* Enable the cycle count register. */ + LDR r0, =0xE0001000 // Build address of DWT register + LDR r1, [r0] // Pickup the current value + ORR r1, r1, #1 // Set the CYCCNTENA bit + STR r1, [r0] // Enable the cycle count register + + /* Set system stack pointer from vector value. */ + LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer + LDR r1, =__Vectors // Pickup address of vector table + LDR r1, [r1] // Pickup reset stack pointer + STR r1, [r0] // Save system stack pointer + + /* Configure SysTick. */ + MOV r0, #0xE000E000 // Build address of NVIC registers + MOV r1, #0 // Build value for SysTick reset + STR r1, [r0, #0x10] // Reset SysTick Control + STR r1, [r0, #0x18] // Reset SysTick Counter Value + LDR r1, =SYSTICK_CYCLES + STR r1, [r0, #0x14] // Setup SysTick Reload Value + MOV r1, #0x7 // Build SysTick Control Enable Value + STR r1, [r0, #0x10] // Setup SysTick Control + + /* Configure handler priorities. */ + LDR r1, =0x00000000 // Rsrv, UsgF, BusF, MemM + STR r1, [r0, #0xD18] // Setup System Handlers 4-7 Priority Registers + + LDR r1, =0xFF000000 // SVCl, Rsrv, Rsrv, Rsrv + STR r1, [r0, #0xD1C] // Setup System Handlers 8-11 Priority Registers + // Note: SVC must be lowest priority, which is 0xFF + + LDR r1, =0x40FF0000 // SysT, PnSV, Rsrv, DbgM + STR r1, [r0, #0xD20] // Setup System Handlers 12-15 Priority Registers + // Note: PnSV must be lowest priority, which is 0xFF + + /* Return to caller. */ + BX lr +// } + + +/* Define shells for each of the unused vectors. */ + .section .text + .balign 4 + .syntax unified + .eabi_attribute Tag_ABI_align_preserved, 1 + .global __tx_BadHandler + .thumb_func +.type __tx_BadHandler, function +__tx_BadHandler: + B __tx_BadHandler + + + .section .text + .balign 4 + .syntax unified + .eabi_attribute Tag_ABI_align_preserved, 1 + .global __tx_IntHandler + .thumb_func +.type __tx_IntHandler, function +__tx_IntHandler: +// VOID InterruptHandler (VOID) +// { + PUSH {r0,lr} // Save LR (and dummy r0 to maintain stack alignment) +#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)) + BL _tx_execution_isr_enter // Call the ISR enter function +#endif + /* Do interrupt handler work here */ + /* .... */ +#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)) + BL _tx_execution_isr_exit // Call the ISR exit function +#endif + POP {r0,lr} + BX LR +// } + + + .section .text + .balign 4 + .syntax unified + .eabi_attribute Tag_ABI_align_preserved, 1 + .global SysTick_Handler + .thumb_func +.type SysTick_Handler, function +SysTick_Handler: +// VOID TimerInterruptHandler (VOID) +// { + PUSH {r0,lr} // Save LR (and dummy r0 to maintain stack alignment) +#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)) + BL _tx_execution_isr_enter // Call the ISR enter function +#endif + BL _tx_timer_interrupt +#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)) + BL _tx_execution_isr_exit // Call the ISR exit function +#endif + POP {r0,lr} + BX LR +// } + + + .section .text + .balign 4 + .syntax unified + .eabi_attribute Tag_ABI_align_preserved, 1 + .global HardFault_Handler + .thumb_func +.type HardFault_Handler, function +HardFault_Handler: + B HardFault_Handler + + + .section .text + .balign 4 + .syntax unified + .eabi_attribute Tag_ABI_align_preserved, 1 + .global UsageFault_Handler + .thumb_func +.type UsageFault_Handler, function +UsageFault_Handler: + CPSID i // Disable interrupts + // Check for stack limit fault + LDR r0, =0xE000ED28 // CFSR address + LDR r1,[r0] // Pick up CFSR + TST r1, #0x00100000 // Check for Stack Overflow +_unhandled_usage_loop: + BEQ _unhandled_usage_loop // If not stack overflow then loop + + // Handle stack overflow + STR r1, [r0] // Clear CFSR flag(s) + +#ifdef __ARM_PCS_VFP + LDR r0, =0xE000EF34 // Cleanup FPU context: Load FPCCR address + LDR r1, [r0] // Load FPCCR + BIC r1, r1, #1 // Clear the lazy preservation active bit + STR r1, [r0] // Store the value +#endif + + LDR r0, =_tx_thread_current_ptr // Build current thread pointer address + LDR r0,[r0] // Pick up current thread pointer + PUSH {r0,lr} // Save LR (and r0 to maintain stack alignment) + BL _tx_thread_stack_error_handler // Call ThreadX/user handler + POP {r0,lr} // Restore LR and dummy reg + +#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)) + // Call the thread exit function to indicate the thread is no longer executing. + PUSH {r0, lr} // Save LR (and r0 just for alignment) + BL _tx_execution_thread_exit // Call the thread exit function + POP {r0, lr} // Recover LR +#endif + + MOV r1, #0 // Build NULL value + LDR r0, =_tx_thread_current_ptr // Pickup address of current thread pointer + STR r1, [r0] // Clear current thread pointer + + // Return from UsageFault_Handler exception + LDR r0, =0xE000ED04 // Load ICSR + LDR r1, =0x10000000 // Set PENDSVSET bit + STR r1, [r0] // Store ICSR + DSB // Wait for memory access to complete + CPSIE i // Enable interrupts + BX lr // Return from exception + + + + .section .text + .balign 4 + .syntax unified + .eabi_attribute Tag_ABI_align_preserved, 1 + .global __tx_NMIHandler + .thumb_func +.type __tx_NMIHandler, function +__tx_NMIHandler: + B __tx_NMIHandler + + + .section .text + .balign 4 + .syntax unified + .eabi_attribute Tag_ABI_align_preserved, 1 + .global __tx_DBGHandler + .thumb_func +.type __tx_DBGHandler, function +__tx_DBGHandler: + B __tx_DBGHandler + + .end diff --git a/ports/cortex_m52/ac6/src/tx_misra.S b/ports/cortex_m52/ac6/src/tx_misra.S new file mode 100644 index 000000000..10548671a --- /dev/null +++ b/ports/cortex_m52/ac6/src/tx_misra.S @@ -0,0 +1,723 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** ThreadX MISRA Compliance */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + + #define SHT_PROGBITS 0x1 + + .global __aeabi_memset + .global _tx_thread_current_ptr + .global _tx_thread_interrupt_disable + .global _tx_thread_interrupt_restore + .global _tx_thread_stack_analyze + .global _tx_thread_stack_error_handler + .global _tx_thread_system_state +#ifdef TX_ENABLE_EVENT_TRACE + .global _tx_trace_buffer_current_ptr + .global _tx_trace_buffer_end_ptr + .global _tx_trace_buffer_start_ptr + .global _tx_trace_event_enable_bits + .global _tx_trace_full_notify_function + .global _tx_trace_header_ptr +#endif + + .global _tx_misra_always_true + .global _tx_misra_block_pool_to_uchar_pointer_convert + .global _tx_misra_byte_pool_to_uchar_pointer_convert + .global _tx_misra_char_to_uchar_pointer_convert + .global _tx_misra_const_char_to_char_pointer_convert +#ifdef TX_ENABLE_EVENT_TRACE + .global _tx_misra_entry_to_uchar_pointer_convert +#endif + .global _tx_misra_indirect_void_to_uchar_pointer_convert + .global _tx_misra_memset + .global _tx_misra_message_copy +#ifdef TX_ENABLE_EVENT_TRACE + .global _tx_misra_object_to_uchar_pointer_convert +#endif + .global _tx_misra_pointer_to_ulong_convert + .global _tx_misra_status_get + .global _tx_misra_thread_stack_check +#ifdef TX_ENABLE_EVENT_TRACE + .global _tx_misra_time_stamp_get +#endif + .global _tx_misra_timer_indirect_to_void_pointer_convert + .global _tx_misra_timer_pointer_add + .global _tx_misra_timer_pointer_dif +#ifdef TX_ENABLE_EVENT_TRACE + .global _tx_misra_trace_event_insert +#endif + .global _tx_misra_uchar_pointer_add + .global _tx_misra_uchar_pointer_dif + .global _tx_misra_uchar_pointer_sub + .global _tx_misra_uchar_to_align_type_pointer_convert + .global _tx_misra_uchar_to_block_pool_pointer_convert +#ifdef TX_ENABLE_EVENT_TRACE + .global _tx_misra_uchar_to_entry_pointer_convert + .global _tx_misra_uchar_to_header_pointer_convert +#endif + .global _tx_misra_uchar_to_indirect_byte_pool_pointer_convert + .global _tx_misra_uchar_to_indirect_uchar_pointer_convert +#ifdef TX_ENABLE_EVENT_TRACE + .global _tx_misra_uchar_to_object_pointer_convert +#endif + .global _tx_misra_uchar_to_void_pointer_convert + .global _tx_misra_ulong_pointer_add + .global _tx_misra_ulong_pointer_dif + .global _tx_misra_ulong_pointer_sub + .global _tx_misra_ulong_to_pointer_convert + .global _tx_misra_ulong_to_thread_pointer_convert + .global _tx_misra_user_timer_pointer_get + .global _tx_misra_void_to_block_pool_pointer_convert + .global _tx_misra_void_to_byte_pool_pointer_convert + .global _tx_misra_void_to_event_flags_pointer_convert + .global _tx_misra_void_to_indirect_uchar_pointer_convert + .global _tx_misra_void_to_mutex_pointer_convert + .global _tx_misra_void_to_queue_pointer_convert + .global _tx_misra_void_to_semaphore_pointer_convert + .global _tx_misra_void_to_thread_pointer_convert + .global _tx_misra_void_to_uchar_pointer_convert + .global _tx_misra_void_to_ulong_pointer_convert + .global _tx_misra_ipsr_get + .global _tx_misra_control_get + .global _tx_misra_control_set +#ifdef __ARM_FP + .global _tx_misra_fpccr_get + .global _tx_misra_vfp_touch +#endif + + .global _tx_misra_event_flags_group_not_used + .global _tx_misra_event_flags_set_notify_not_used + .global _tx_misra_queue_not_used + .global _tx_misra_queue_send_notify_not_used + .global _tx_misra_semaphore_not_used + .global _tx_misra_semaphore_put_notify_not_used + .global _tx_misra_thread_entry_exit_notify_not_used + .global _tx_misra_thread_not_used + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** VOID _tx_misra_memset(VOID *ptr, UINT value, UINT size); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .text + .align 4 + .syntax unified + .thumb_func +_tx_misra_memset: + PUSH {R4,LR} + MOVS R4,R0 + MOVS R0,R2 + MOVS R2,R1 + MOVS R1,R0 + MOVS R0,R4 + BL __aeabi_memset + POP {R4,PC} // return + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** UCHAR *_tx_misra_uchar_pointer_add(UCHAR *ptr, ULONG amount); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .text + .thumb_func +_tx_misra_uchar_pointer_add: + ADD R0,R0,R1 + BX LR // return + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** UCHAR *_tx_misra_uchar_pointer_sub(UCHAR *ptr, ULONG amount); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .text + .thumb_func +_tx_misra_uchar_pointer_sub: + RSBS R1,R1,#+0 + ADD R0,R0,R1 + BX LR // return + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ULONG _tx_misra_uchar_pointer_dif(UCHAR *ptr1, UCHAR *ptr2); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .text + .thumb_func +_tx_misra_uchar_pointer_dif: + SUBS R0,R0,R1 + BX LR // return + + +/************************************************************************************************************************************/ +/************************************************************************************************************************************/ +/** */ +/** This single function serves all of the below prototypes. */ +/** */ +/** ULONG _tx_misra_pointer_to_ulong_convert(VOID *ptr); */ +/** VOID *_tx_misra_ulong_to_pointer_convert(ULONG input); */ +/** UCHAR **_tx_misra_indirect_void_to_uchar_pointer_convert(VOID **return_ptr); */ +/** UCHAR **_tx_misra_uchar_to_indirect_uchar_pointer_convert(UCHAR *pointer); */ +/** UCHAR *_tx_misra_block_pool_to_uchar_pointer_convert(TX_BLOCK_POOL *pool); */ +/** TX_BLOCK_POOL *_tx_misra_void_to_block_pool_pointer_convert(VOID *pointer); */ +/** UCHAR *_tx_misra_void_to_uchar_pointer_convert(VOID *pointer); */ +/** TX_BLOCK_POOL *_tx_misra_uchar_to_block_pool_pointer_convert(UCHAR *pointer); */ +/** UCHAR **_tx_misra_void_to_indirect_uchar_pointer_convert(VOID *pointer); */ +/** TX_BYTE_POOL *_tx_misra_void_to_byte_pool_pointer_convert(VOID *pointer); */ +/** UCHAR *_tx_misra_byte_pool_to_uchar_pointer_convert(TX_BYTE_POOL *pool); */ +/** ALIGN_TYPE *_tx_misra_uchar_to_align_type_pointer_convert(UCHAR *pointer); */ +/** TX_BYTE_POOL **_tx_misra_uchar_to_indirect_byte_pool_pointer_convert(UCHAR *pointer); */ +/** TX_EVENT_FLAGS_GROUP *_tx_misra_void_to_event_flags_pointer_convert(VOID *pointer); */ +/** ULONG *_tx_misra_void_to_ulong_pointer_convert(VOID *pointer); */ +/** TX_MUTEX *_tx_misra_void_to_mutex_pointer_convert(VOID *pointer); */ +/** TX_QUEUE *_tx_misra_void_to_queue_pointer_convert(VOID *pointer); */ +/** TX_SEMAPHORE *_tx_misra_void_to_semaphore_pointer_convert(VOID *pointer); */ +/** VOID *_tx_misra_uchar_to_void_pointer_convert(UCHAR *pointer); */ +/** TX_THREAD *_tx_misra_ulong_to_thread_pointer_convert(ULONG value); */ +/** VOID *_tx_misra_timer_indirect_to_void_pointer_convert(TX_TIMER_INTERNAL **pointer); */ +/** CHAR *_tx_misra_const_char_to_char_pointer_convert(const char *pointer); */ +/** TX_THREAD *_tx_misra_void_to_thread_pointer_convert(void *pointer); */ +/** UCHAR *_tx_misra_object_to_uchar_pointer_convert(TX_TRACE_OBJECT_ENTRY *pointer); */ +/** TX_TRACE_OBJECT_ENTRY *_tx_misra_uchar_to_object_pointer_convert(UCHAR *pointer); */ +/** TX_TRACE_HEADER *_tx_misra_uchar_to_header_pointer_convert(UCHAR *pointer); */ +/** TX_TRACE_BUFFER_ENTRY *_tx_misra_uchar_to_entry_pointer_convert(UCHAR *pointer); */ +/** UCHAR *_tx_misra_entry_to_uchar_pointer_convert(TX_TRACE_BUFFER_ENTRY *pointer); */ +/** UCHAR *_tx_misra_char_to_uchar_pointer_convert(CHAR *pointer); */ +/** VOID _tx_misra_event_flags_group_not_used(TX_EVENT_FLAGS_GROUP *group_ptr); */ +/** VOID _tx_misra_event_flags_set_notify_not_used(VOID (*events_set_notify)(TX_EVENT_FLAGS_GROUP *notify_group_ptr)); */ +/** VOID _tx_misra_queue_not_used(TX_QUEUE *queue_ptr); */ +/** VOID _tx_misra_queue_send_notify_not_used(VOID (*queue_send_notify)(TX_QUEUE *notify_queue_ptr)); */ +/** VOID _tx_misra_semaphore_not_used(TX_SEMAPHORE *semaphore_ptr); */ +/** VOID _tx_misra_semaphore_put_notify_not_used(VOID (*semaphore_put_notify)(TX_SEMAPHORE *notify_semaphore_ptr)); */ +/** VOID _tx_misra_thread_not_used(TX_THREAD *thread_ptr); */ +/** VOID _tx_misra_thread_entry_exit_notify_not_used(VOID (*thread_entry_exit_notify)(TX_THREAD *notify_thread_ptr, UINT id)); */ +/** */ +/************************************************************************************************************************************/ +/************************************************************************************************************************************/ + .text + .thumb_func +_tx_misra_pointer_to_ulong_convert: +_tx_misra_ulong_to_pointer_convert: +_tx_misra_indirect_void_to_uchar_pointer_convert: +_tx_misra_uchar_to_indirect_uchar_pointer_convert: +_tx_misra_block_pool_to_uchar_pointer_convert: +_tx_misra_void_to_block_pool_pointer_convert: +_tx_misra_void_to_uchar_pointer_convert: +_tx_misra_uchar_to_block_pool_pointer_convert: +_tx_misra_void_to_indirect_uchar_pointer_convert: +_tx_misra_void_to_byte_pool_pointer_convert: +_tx_misra_byte_pool_to_uchar_pointer_convert: +_tx_misra_uchar_to_align_type_pointer_convert: +_tx_misra_uchar_to_indirect_byte_pool_pointer_convert: +_tx_misra_void_to_event_flags_pointer_convert: +_tx_misra_void_to_ulong_pointer_convert: +_tx_misra_void_to_mutex_pointer_convert: +_tx_misra_void_to_queue_pointer_convert: +_tx_misra_void_to_semaphore_pointer_convert: +_tx_misra_uchar_to_void_pointer_convert: +_tx_misra_ulong_to_thread_pointer_convert: +_tx_misra_timer_indirect_to_void_pointer_convert: +_tx_misra_const_char_to_char_pointer_convert: +_tx_misra_void_to_thread_pointer_convert: +#ifdef TX_ENABLE_EVENT_TRACE +_tx_misra_object_to_uchar_pointer_convert: +_tx_misra_uchar_to_object_pointer_convert: +_tx_misra_uchar_to_header_pointer_convert: +_tx_misra_uchar_to_entry_pointer_convert: +_tx_misra_entry_to_uchar_pointer_convert: +#endif +_tx_misra_char_to_uchar_pointer_convert: +_tx_misra_event_flags_group_not_used: +_tx_misra_event_flags_set_notify_not_used: +_tx_misra_queue_not_used: +_tx_misra_queue_send_notify_not_used: +_tx_misra_semaphore_not_used: +_tx_misra_semaphore_put_notify_not_used: +_tx_misra_thread_entry_exit_notify_not_used: +_tx_misra_thread_not_used: + + BX LR // return + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ULONG *_tx_misra_ulong_pointer_add(ULONG *ptr, ULONG amount); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .text + .thumb_func +_tx_misra_ulong_pointer_add: + ADD R0,R0,R1, LSL #+2 + BX LR // return + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ULONG *_tx_misra_ulong_pointer_sub(ULONG *ptr, ULONG amount); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .text + .thumb_func +_tx_misra_ulong_pointer_sub: + MVNS R2,#+3 + MULS R1,R2,R1 + ADD R0,R0,R1 + BX LR // return + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ULONG _tx_misra_ulong_pointer_dif(ULONG *ptr1, ULONG *ptr2); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .text + .thumb_func +_tx_misra_ulong_pointer_dif: + SUBS R0,R0,R1 + ASRS R0,R0,#+2 + BX LR // return + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** VOID _tx_misra_message_copy(ULONG **source, ULONG **destination, */ +/** UINT size); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .text + .thumb_func +_tx_misra_message_copy: + PUSH {R4,R5} + LDR R3,[R0, #+0] + LDR R4,[R1, #+0] + LDR R5,[R3, #+0] + STR R5,[R4, #+0] + ADDS R4,R4,#+4 + ADDS R3,R3,#+4 + CMP R2,#+2 + BCC.N _tx_misra_message_copy_0 + SUBS R2,R2,#+1 + B.N _tx_misra_message_copy_1 +_tx_misra_message_copy_2: + LDR R5,[R3, #+0] + STR R5,[R4, #+0] + ADDS R4,R4,#+4 + ADDS R3,R3,#+4 + SUBS R2,R2,#+1 +_tx_misra_message_copy_1: + CMP R2,#+0 + BNE.N _tx_misra_message_copy_2 +_tx_misra_message_copy_0: + STR R3,[R0, #+0] + STR R4,[R1, #+0] + POP {R4,R5} + BX LR // return + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ULONG _tx_misra_timer_pointer_dif(TX_TIMER_INTERNAL **ptr1, */ +/** TX_TIMER_INTERNAL **ptr2); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .text + .thumb_func +_tx_misra_timer_pointer_dif: + SUBS R0,R0,R1 + ASRS R0,R0,#+2 + BX LR // return + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** TX_TIMER_INTERNAL **_tx_misra_timer_pointer_add(TX_TIMER_INTERNAL */ +/** **ptr1, ULONG size); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .text + .thumb_func +_tx_misra_timer_pointer_add: + ADD R0,R0,R1, LSL #+2 + BX LR // return + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** VOID _tx_misra_user_timer_pointer_get(TX_TIMER_INTERNAL */ +/** *internal_timer, TX_TIMER **user_timer); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .text + .thumb_func +_tx_misra_user_timer_pointer_get: + SUBS R0,#8 + STR R0,[R1, #+0] + BX LR // return + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** VOID _tx_misra_thread_stack_check(TX_THREAD *thread_ptr, */ +/** VOID **highest_stack); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .text + .thumb_func +_tx_misra_thread_stack_check: + PUSH {R3-R5,LR} + MOVS R4,R0 + MOVS R5,R1 + BL _tx_thread_interrupt_disable + CMP R4,#+0 + BEQ.N _tx_misra_thread_stack_check_0 + LDR R1,[R4, #+0] + LDR R2,=0x54485244 + CMP R1,R2 + BNE.N _tx_misra_thread_stack_check_0 + LDR R1,[R4, #+8] + LDR R2,[R5, #+0] + CMP R1,R2 + BCS.N _tx_misra_thread_stack_check_1 + LDR R1,[R4, #+8] + STR R1,[R5, #+0] +_tx_misra_thread_stack_check_1: + LDR R1,[R4, #+12] + LDR R1,[R1, #+0] + CMP R1,#-269488145 + BNE.N _tx_misra_thread_stack_check_2 + LDR R1,[R4, #+16] + LDR R1,[R1, #+1] + CMP R1,#-269488145 + BNE.N _tx_misra_thread_stack_check_2 + LDR R1,[R5, #+0] + LDR R2,[R4, #+12] + CMP R1,R2 + BCS.N _tx_misra_thread_stack_check_3 +_tx_misra_thread_stack_check_2: + BL _tx_thread_interrupt_restore + MOVS R0,R4 + BL _tx_thread_stack_error_handler + BL _tx_thread_interrupt_disable +_tx_misra_thread_stack_check_3: + LDR R1,[R5, #+0] + LDR R1,[R1, #-4] + CMP R1,#-269488145 + BEQ.N _tx_misra_thread_stack_check_0 + BL _tx_thread_interrupt_restore + MOVS R0,R4 + BL _tx_thread_stack_analyze + BL _tx_thread_interrupt_disable +_tx_misra_thread_stack_check_0: + BL _tx_thread_interrupt_restore + POP {R0,R4,R5,PC} // return + +#ifdef TX_ENABLE_EVENT_TRACE + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** VOID _tx_misra_trace_event_insert(ULONG event_id, */ +/** VOID *info_field_1, ULONG info_field_2, ULONG info_field_3, */ +/** ULONG info_field_4, ULONG filter, ULONG time_stamp); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .text + .thumb_func +_tx_misra_trace_event_insert: + PUSH {R3-R7,LR} + LDR.N R4,DataTable2_1 + LDR R4,[R4, #+0] + CMP R4,#+0 + BEQ.N _tx_misra_trace_event_insert_0 + LDR.N R5,DataTable2_2 + LDR R5,[R5, #+0] + LDR R6,[SP, #+28] + TST R5,R6 + BEQ.N _tx_misra_trace_event_insert_0 + LDR.N R5,DataTable2_3 + LDR R5,[R5, #+0] + LDR.N R6,DataTable2_4 + LDR R6,[R6, #+0] + CMP R5,#+0 + BNE.N _tx_misra_trace_event_insert_1 + LDR R5,[R6, #+44] + LDR R7,[R6, #+60] + LSLS R7,R7,#+16 + ORRS R7,R7,#0x80000000 + ORRS R5,R7,R5 + B.N _tx_misra_trace_event_insert_2 +_tx_misra_trace_event_insert_1: + CMP R5,#-252645136 + BCS.N _tx_misra_trace_event_insert_3 + MOVS R5,R6 + MOVS R6,#-1 + B.N _tx_misra_trace_event_insert_2 +_tx_misra_trace_event_insert_3: + MOVS R6,#-252645136 + MOVS R5,#+0 +_tx_misra_trace_event_insert_2: + STR R6,[R4, #+0] + STR R5,[R4, #+4] + STR R0,[R4, #+8] + LDR R0,[SP, #+32] + STR R0,[R4, #+12] + STR R1,[R4, #+16] + STR R2,[R4, #+20] + STR R3,[R4, #+24] + LDR R0,[SP, #+24] + STR R0,[R4, #+28] + ADDS R4,R4,#+32 + LDR.N R0,DataTable2_5 + LDR R0,[R0, #+0] + CMP R4,R0 + BCC.N _tx_misra_trace_event_insert_4 + LDR.N R0,DataTable2_6 + LDR R4,[R0, #+0] + LDR.N R0,DataTable2_1 + STR R4,[R0, #+0] + LDR.N R0,DataTable2_7 + LDR R0,[R0, #+0] + STR R4,[R0, #+32] + LDR.N R0,DataTable2_8 + LDR R0,[R0, #+0] + CMP R0,#+0 + BEQ.N _tx_misra_trace_event_insert_0 + LDR.N R0,DataTable2_7 + LDR R0,[R0, #+0] + LDR.N R1,DataTable2_8 + LDR R1,[R1, #+0] + BLX R1 + B.N _tx_misra_trace_event_insert_0 +_tx_misra_trace_event_insert_4: + LDR.N R0,DataTable2_1 + STR R4,[R0, #+0] + LDR.N R0,DataTable2_7 + LDR R0,[R0, #+0] + STR R4,[R0, #+32] +_tx_misra_trace_event_insert_0: + POP {R0,R4-R7,PC} // return + + + .data +DataTable2_1: + .word _tx_trace_buffer_current_ptr + + .data +DataTable2_2: + .word _tx_trace_event_enable_bits + + .data +DataTable2_5: + .word _tx_trace_buffer_end_ptr + + .data +DataTable2_6: + .word _tx_trace_buffer_start_ptr + + .data +DataTable2_7: + .word _tx_trace_header_ptr + + .data +DataTable2_8: + .word _tx_trace_full_notify_function + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ULONG _tx_misra_time_stamp_get(VOID); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .text + .thumb_func +_tx_misra_time_stamp_get: + MOVS R0,#+0 + BX LR // return + +#endif + + .data +DataTable2_3: + .word _tx_thread_system_state + + .data +DataTable2_4: + .word _tx_thread_current_ptr + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** UINT _tx_misra_always_true(void); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .text + .thumb_func +_tx_misra_always_true: + MOVS R0,#+1 + BX LR // return + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** UINT _tx_misra_status_get(UINT status); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .text + .thumb_func +_tx_misra_status_get: + MOVS R0,#+0 + BX LR // return + + +/***********************************************************************************************/ +/***********************************************************************************************/ +/** */ +/** ULONG _tx_misra_ipsr_get(void); */ +/** */ +/***********************************************************************************************/ +/***********************************************************************************************/ + + .text + .thumb_func +_tx_misra_ipsr_get: + MRS R0, IPSR + BX LR // return + + +/***********************************************************************************************/ +/***********************************************************************************************/ +/** */ +/** ULONG _tx_misra_control_get(void); */ +/** */ +/***********************************************************************************************/ +/***********************************************************************************************/ + + .text + .thumb_func +_tx_misra_control_get: + MRS R0, CONTROL + BX LR // return + + +/***********************************************************************************************/ +/***********************************************************************************************/ +/** */ +/** void _tx_misra_control_set(ULONG value); */ +/** */ +/***********************************************************************************************/ +/***********************************************************************************************/ + + .text + .thumb_func +_tx_misra_control_set: + MSR CONTROL, R0 + BX LR // return + + +#ifdef __ARM_FP + +/***********************************************************************************************/ +/***********************************************************************************************/ +/** */ +/** ULONG _tx_misra_fpccr_get(void); */ +/** */ +/***********************************************************************************************/ +/***********************************************************************************************/ + + .text + .thumb_func +_tx_misra_fpccr_get: + LDR r0, =0xE000EF34 // Build FPCCR address + LDR r0, [r0] // Load FPCCR value + BX LR // return + + +/***********************************************************************************************/ +/***********************************************************************************************/ +/** */ +/** void _tx_misra_vfp_touch(void); */ +/** */ +/***********************************************************************************************/ +/***********************************************************************************************/ + + .text + .thumb_func +_tx_misra_vfp_touch: + vmov.f32 s0, s0 + BX LR // return + +#endif + + + .data + .word 0 diff --git a/ports/cortex_m52/ac6/src/tx_thread_context_restore.S b/ports/cortex_m52/ac6/src/tx_thread_context_restore.S new file mode 100644 index 000000000..4e9461b76 --- /dev/null +++ b/ports/cortex_m52/ac6/src/tx_thread_context_restore.S @@ -0,0 +1,81 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + +#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)) + .global _tx_execution_isr_exit +#endif +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_context_restore Cortex-M52/AC6 */ +/* 6.2.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is not needed for Cortex-M. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* [_tx_execution_isr_exit] Execution profiling ISR exit */ +/* */ +/* CALLED BY */ +/* */ +/* ISRs Interrupt Service Routines */ +/* */ +/**************************************************************************/ +// VOID _tx_thread_context_restore(VOID) +// { + .section .text + .balign 4 + .syntax unified + .eabi_attribute Tag_ABI_align_preserved, 1 + .global _tx_thread_context_restore + .thumb_func +.type _tx_thread_context_restore, function +_tx_thread_context_restore: + +#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)) + /* Call the ISR exit function to indicate an ISR is complete. */ + PUSH {r0, lr} // Save return address + BL _tx_execution_isr_exit // Call the ISR exit function + POP {r0, lr} // Recover return address +#endif + + BX lr +// } + .end diff --git a/ports/cortex_m52/ac6/src/tx_thread_context_save.S b/ports/cortex_m52/ac6/src/tx_thread_context_save.S new file mode 100644 index 000000000..08197a824 --- /dev/null +++ b/ports/cortex_m52/ac6/src/tx_thread_context_save.S @@ -0,0 +1,81 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + +#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)) + .global _tx_execution_isr_enter +#endif +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_context_save Cortex-M52/AC6 */ +/* 6.2.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is not needed for Cortex-M. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* [_tx_execution_isr_enter] Execution profiling ISR enter */ +/* */ +/* CALLED BY */ +/* */ +/* ISRs */ +/* */ +/**************************************************************************/ +// VOID _tx_thread_context_save(VOID) +// { + .section .text + .balign 4 + .syntax unified + .eabi_attribute Tag_ABI_align_preserved, 1 + .global _tx_thread_context_save + .thumb_func +.type _tx_thread_context_save, function +_tx_thread_context_save: + +#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)) + /* Call the ISR enter function to indicate an ISR is starting. */ + PUSH {r0, lr} // Save return address + BL _tx_execution_isr_enter // Call the ISR enter function + POP {r0, lr} // Recover return address +#endif + + BX lr +// } + .end diff --git a/ports/cortex_m52/ac6/src/tx_thread_interrupt_control.S b/ports/cortex_m52/ac6/src/tx_thread_interrupt_control.S new file mode 100644 index 000000000..3c6cfeb7b --- /dev/null +++ b/ports/cortex_m52/ac6/src/tx_thread_interrupt_control.S @@ -0,0 +1,79 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_interrupt_control Cortex-M52/AC6 */ +/* 6.2.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is responsible for changing the interrupt lockout */ +/* posture of the system. */ +/* */ +/* INPUT */ +/* */ +/* new_posture New interrupt lockout posture */ +/* */ +/* OUTPUT */ +/* */ +/* old_posture Old interrupt lockout posture */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/**************************************************************************/ +// UINT _tx_thread_interrupt_control(UINT new_posture) +// { + .section .text + .balign 4 + .eabi_attribute Tag_ABI_align_preserved, 1 + .global _tx_thread_interrupt_control + .thumb_func +.type _tx_thread_interrupt_control, function +_tx_thread_interrupt_control: +#ifdef TX_PORT_USE_BASEPRI + MRS r1, BASEPRI // Pickup current interrupt posture + MSR BASEPRI, r0 // Apply the new interrupt posture + MOV r0, r1 // Transfer old to return register +#else + MRS r1, PRIMASK // Pickup current interrupt lockout + MSR PRIMASK, r0 // Apply the new interrupt lockout + MOV r0, r1 // Transfer old to return register +#endif + BX lr // Return to caller +// } + .end diff --git a/ports/cortex_m52/ac6/src/tx_thread_interrupt_disable.S b/ports/cortex_m52/ac6/src/tx_thread_interrupt_disable.S new file mode 100644 index 000000000..2054a06a1 --- /dev/null +++ b/ports/cortex_m52/ac6/src/tx_thread_interrupt_disable.S @@ -0,0 +1,80 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_interrupt_disable Cortex-M52/AC6 */ +/* 6.2.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is responsible for disabling interrupts and returning */ +/* the previous interrupt lockout posture. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* old_posture Old interrupt lockout posture */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/**************************************************************************/ +// UINT _tx_thread_interrupt_disable(VOID) +// { + .section .text + .balign 4 + .syntax unified + .eabi_attribute Tag_ABI_align_preserved, 1 + .global _tx_thread_interrupt_disable + .thumb_func +.type _tx_thread_interrupt_disable, function +_tx_thread_interrupt_disable: + /* Return current interrupt lockout posture. */ +#ifdef TX_PORT_USE_BASEPRI + MRS r0, BASEPRI + LDR r1, =TX_PORT_BASEPRI + MSR BASEPRI, r1 +#else + MRS r0, PRIMASK + CPSID i +#endif + BX lr +// } + .end diff --git a/ports/cortex_m52/ac6/src/tx_thread_interrupt_restore.S b/ports/cortex_m52/ac6/src/tx_thread_interrupt_restore.S new file mode 100644 index 000000000..3eecffd5b --- /dev/null +++ b/ports/cortex_m52/ac6/src/tx_thread_interrupt_restore.S @@ -0,0 +1,77 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_interrupt_restore Cortex-M52/AC6 */ +/* 6.2.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is responsible for restoring the previous */ +/* interrupt lockout posture. */ +/* */ +/* INPUT */ +/* */ +/* previous_posture Previous interrupt posture */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/**************************************************************************/ +// VOID _tx_thread_interrupt_restore(UINT previous_posture) +// { + .section .text + .balign 4 + .syntax unified + .eabi_attribute Tag_ABI_align_preserved, 1 + .global _tx_thread_interrupt_restore + .thumb_func +.type _tx_thread_interrupt_restore, function +_tx_thread_interrupt_restore: + /* Restore previous interrupt lockout posture. */ +#ifdef TX_PORT_USE_BASEPRI + MSR BASEPRI, r0 +#else + MSR PRIMASK, r0 +#endif + BX lr +// } + .end diff --git a/ports/cortex_m52/ac6/src/tx_thread_schedule.S b/ports/cortex_m52/ac6/src/tx_thread_schedule.S new file mode 100644 index 000000000..937d03d5f --- /dev/null +++ b/ports/cortex_m52/ac6/src/tx_thread_schedule.S @@ -0,0 +1,383 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ +// Some portions generated by Codex (GPT-5). + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + +#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)) + .global _tx_execution_thread_enter + .global _tx_execution_thread_exit +#endif +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_schedule Cortex-M52/AC6 */ +/* 6.2.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function waits for a thread control block pointer to appear in */ +/* the _tx_thread_execute_ptr variable. Once a thread pointer appears */ +/* in the variable, the corresponding thread is resumed. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_initialize_kernel_enter ThreadX entry function */ +/* _tx_thread_system_return Return to system from thread */ +/* */ +/**************************************************************************/ +// VOID _tx_thread_schedule(VOID) +// { + .section .text + .balign 4 + .syntax unified + .eabi_attribute Tag_ABI_align_preserved, 1 + .global _tx_thread_schedule + .thumb_func +.type _tx_thread_schedule, function +_tx_thread_schedule: + /* This function should only ever be called on Cortex-M + from the first schedule request. Subsequent scheduling occurs + from the PendSV handling routine below. */ + + /* Clear the preempt-disable flag to enable rescheduling after initialization on Cortex-M targets. */ + MOV r0, #0 // Build value for TX_FALSE + LDR r2, =_tx_thread_preempt_disable // Build address of preempt disable flag + STR r0, [r2, #0] // Clear preempt disable flag + +#ifdef __ARM_PCS_VFP + /* Clear CONTROL.FPCA bit so VFP registers aren't unnecessarily stacked. */ + MRS r0, CONTROL // Pickup current CONTROL register + BIC r0, r0, #4 // Clear the FPCA bit + MSR CONTROL, r0 // Setup new CONTROL register +#endif + + /* Enable interrupts */ + CPSIE i + + /* Enter the scheduler for the first time. */ + MOV r0, #0x10000000 // Load PENDSVSET bit + MOV r1, #0xE000E000 // Load NVIC base + STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR + DSB // Complete all memory accesses + ISB // Flush pipeline + + /* Wait here for the PendSV to take place. */ + +__tx_wait_here: + B __tx_wait_here // Wait for the PendSV to happen +// } + + /* Generic context switching PendSV handler. */ + + .section .text + .balign 4 + .syntax unified + .eabi_attribute Tag_ABI_align_preserved, 1 + .global PendSV_Handler + .thumb_func +.type PendSV_Handler, function + /* Get current thread value and new thread pointer. */ +PendSV_Handler: +__tx_ts_handler: + +#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)) + /* Call the thread exit function to indicate the thread is no longer executing. */ +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI + MSR BASEPRI, r1 +#else + CPSID i // Disable interrupts +#endif /* TX_PORT_USE_BASEPRI */ + PUSH {r0, lr} // Save LR (and r0 just for alignment) + BL _tx_execution_thread_exit // Call the thread exit function + POP {r0, lr} // Recover LR +#ifdef TX_PORT_USE_BASEPRI + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) + MSR BASEPRI, r0 +#else + CPSIE i // Enable interrupts +#endif /* TX_PORT_USE_BASEPRI */ +#endif /* EXECUTION PROFILE */ + + LDR r0, =_tx_thread_current_ptr // Build current thread pointer address + LDR r2, =_tx_thread_execute_ptr // Build execute thread pointer address + MOV r3, #0 // Build NULL value + LDR r1, [r0] // Pickup current thread pointer + + /* Determine if there is a current thread to finish preserving. */ + + CBZ r1, __tx_ts_new // If NULL, skip preservation + + /* Recover PSP and preserve current thread context. */ + + STR r3, [r0] // Set _tx_thread_current_ptr to NULL + MRS r12, PSP // Pickup PSP pointer (thread's stack pointer) + STMDB r12!, {r4-r11} // Save its remaining registers +#ifdef __ARM_PCS_VFP + TST LR, #0x10 // Determine if the VFP extended frame is present + BNE _skip_vfp_save + VSTMDB r12!,{s16-s31} // Yes, save additional VFP registers +_skip_vfp_save: +#endif + LDR r4, =_tx_timer_time_slice // Build address of time-slice variable + STMDB r12!, {LR} // Save LR on the stack + STR r12, [r1, #8] // Save the thread stack pointer + +#if (!defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE)) + // Save secure context + LDR r5, [r1,#0x90] // Load secure stack index + CBZ r5, _skip_secure_save // Skip save if there is no secure context + PUSH {r0,r1,r2,r3} // Save scratch registers + MOV r0, r1 // Move thread ptr to r0 + BL _tx_thread_secure_stack_context_save // Save secure stack + POP {r0,r1,r2,r3} // Restore secure registers +_skip_secure_save: +#endif + + /* Determine if time-slice is active. If it isn't, skip time handling processing. */ + + LDR r5, [r4] // Pickup current time-slice + CBZ r5, __tx_ts_new // If not active, skip processing + + /* Time-slice is active, save the current thread's time-slice and clear the global time-slice variable. */ + + STR r5, [r1, #24] // Save current time-slice + + /* Clear the global time-slice. */ + + STR r3, [r4] // Clear time-slice + + /* Executing thread is now completely preserved!!! */ + +__tx_ts_new: + + /* Now we are looking for a new thread to execute! */ + +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI + MSR BASEPRI, r1 +#else + CPSID i // Disable interrupts +#endif + LDR r1, [r2] // Is there another thread ready to execute? + CBZ r1, __tx_ts_wait // No, skip to the wait processing + + /* Yes, another thread is ready for else, make the current thread the new thread. */ + + STR r1, [r0] // Setup the current thread pointer to the new thread +#ifdef TX_PORT_USE_BASEPRI + MOV r4, #0 // Disable BASEPRI masking (enable interrupts) + MSR BASEPRI, r4 +#else + CPSIE i // Enable interrupts +#endif + + /* Increment the thread run count. */ + +__tx_ts_restore: + LDR r7, [r1, #4] // Pickup the current thread run count + LDR r4, =_tx_timer_time_slice // Build address of time-slice variable + LDR r5, [r1, #24] // Pickup thread's current time-slice + ADD r7, r7, #1 // Increment the thread run count + STR r7, [r1, #4] // Store the new run count + + /* Setup global time-slice with thread's current time-slice. */ + + STR r5, [r4] // Setup global time-slice + +#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)) + /* Call the thread entry function to indicate the thread is executing. */ + PUSH {r0, r1} // Save r0 and r1 + BL _tx_execution_thread_enter // Call the thread execution enter function + POP {r0, r1} // Recover r0 and r1 +#endif + +#if (!defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE)) + // Restore secure context + LDR r0, [r1,#0x90] // Load secure stack index + CBZ r0, _skip_secure_restore // Skip restore if there is no secure context + PUSH {r0,r1} // Save r1 (and dummy r0) + MOV r0, r1 // Move thread ptr to r0 + BL _tx_thread_secure_stack_context_restore // Restore secure stack + POP {r0,r1} // Restore r1 (and dummy r0) +_skip_secure_restore: +#endif + + /* Restore the thread context and PSP. */ + LDR r12, [r1, #12] // Get stack start + MSR PSPLIM, r12 // Set stack limit + LDR r12, [r1, #8] // Pickup thread's stack pointer + LDMIA r12!, {LR} // Pickup LR +#ifdef __ARM_PCS_VFP + TST LR, #0x10 // Determine if the VFP extended frame is present + BNE _skip_vfp_restore // If not, skip VFP restore + VLDMIA r12!, {s16-s31} // Yes, restore additional VFP registers +_skip_vfp_restore: +#endif + LDMIA r12!, {r4-r11} // Recover thread's registers + MSR PSP, r12 // Setup the thread's stack pointer + + BX lr // Return to thread! + + /* The following is the idle wait processing... in this case, no threads are ready for execution and the + system will simply be idle until an interrupt occurs that makes a thread ready. Note that interrupts + are disabled to allow use of WFI for waiting for a thread to arrive. */ + +__tx_ts_wait: +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI + MSR BASEPRI, r1 +#else + CPSID i // Disable interrupts +#endif + LDR r1, [r2] // Pickup the next thread to execute pointer + STR r1, [r0] // Store it in the current pointer + CBNZ r1, __tx_ts_ready // If non-NULL, a new thread is ready! + +#ifdef TX_LOW_POWER + PUSH {r0-r3} + BL tx_low_power_enter // Possibly enter low power mode + POP {r0-r3} +#endif + +#ifdef TX_ENABLE_WFI + DSB // Ensure no outstanding memory transactions + WFI // Wait for interrupt + ISB // Ensure pipeline is flushed +#endif + +#ifdef TX_LOW_POWER + PUSH {r0-r3} + BL tx_low_power_exit // Exit low power mode + POP {r0-r3} +#endif + +#ifdef TX_PORT_USE_BASEPRI + MOV r4, #0 // Disable BASEPRI masking (enable interrupts) + MSR BASEPRI, r4 +#else + CPSIE i // Enable interrupts +#endif + B __tx_ts_wait // Loop to continue waiting + + /* At this point, we have a new thread ready to go. Clear any newly pended PendSV - since we are + already in the handler! */ +__tx_ts_ready: + MOV r7, #0x08000000 // Build clear PendSV value + MOV r8, #0xE000E000 // Build base NVIC address + STR r7, [r8, #0xD04] // Clear any PendSV + + /* Re-enable interrupts and restore new thread. */ +#ifdef TX_PORT_USE_BASEPRI + MOV r4, #0 // Disable BASEPRI masking (enable interrupts) + MSR BASEPRI, r4 +#else + CPSIE i // Enable interrupts +#endif + B __tx_ts_restore // Restore the thread +// } + + +#if (!defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE)) + // SVC_Handler is not needed when ThreadX is running in single mode. + .section .text + .balign 4 + .syntax unified + .eabi_attribute Tag_ABI_align_preserved, 1 + .global SVC_Handler + .thumb_func +.type SVC_Handler, function +SVC_Handler: + TST lr, #0x04 // Determine return stack from EXC_RETURN bit 2 + ITE EQ + MRSEQ r0, MSP // Get MSP if return stack is MSP + MRSNE r0, PSP // Get PSP if return stack is PSP + + LDR r1, [r0,#24] // Load saved PC from stack + LDRB r1, [r1,#-2] // Load SVC number + + CMP r1, #1 // Is it a secure stack allocate request? + BEQ _tx_svc_secure_alloc // Yes, go there + + CMP r1, #2 // Is it a secure stack free request? + BEQ _tx_svc_secure_free // Yes, go there + + CMP r1, #3 // Is it a secure stack init request? + BEQ _tx_svc_secure_init // Yes, go there + + // Unknown SVC argument - just return + BX lr + +_tx_svc_secure_alloc: + PUSH {r0,lr} // Save SP and EXC_RETURN + LDM r0, {r0-r3} // Load function parameters from stack + BL _tx_thread_secure_mode_stack_allocate + POP {r12,lr} // Restore SP and EXC_RETURN + STR r0,[r12] // Store function return value + BX lr +_tx_svc_secure_free: + PUSH {r0,lr} // Save SP and EXC_RETURN + LDM r0, {r0-r3} // Load function parameters from stack + BL _tx_thread_secure_mode_stack_free + POP {r12,lr} // Restore SP and EXC_RETURN + STR r0,[r12] // Store function return value + BX lr +_tx_svc_secure_init: + PUSH {r0,lr} // Save SP and EXC_RETURN + BL _tx_thread_secure_mode_stack_initialize + POP {r12,lr} // Restore SP and EXC_RETURN + BX lr +#endif // End of ifndef TX_SINGLE_MODE_SECURE, TX_SINGLE_MODE_NON_SECURE + + + .section .text + .balign 4 + .syntax unified + .eabi_attribute Tag_ABI_align_preserved, 1 + .global _tx_vfp_access + .thumb_func +.type _tx_vfp_access, function +_tx_vfp_access: +#ifdef __ARM_PCS_VFP + VMOV.F32 s0, s0 // Simply access the VFP +#endif + BX lr // Return to caller +.end diff --git a/ports/cortex_m52/ac6/src/tx_thread_secure_stack.c b/ports/cortex_m52/ac6/src/tx_thread_secure_stack.c new file mode 100644 index 000000000..6b6ea15e3 --- /dev/null +++ b/ports/cortex_m52/ac6/src/tx_thread_secure_stack.c @@ -0,0 +1,577 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +#include "tx_api.h" + +/* If TX_SINGLE_MODE_SECURE or TX_SINGLE_MODE_NON_SECURE is defined, + no secure stack functionality is needed. */ +#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE) + +#define TX_SOURCE_CODE + +#include "cmsis_compiler.h" /* For intrinsic functions. */ +#include "tx_secure_interface.h" /* Interface for NS code. */ + +/* Minimum size of secure stack. */ +#ifndef TX_THREAD_SECURE_STACK_MINIMUM +#define TX_THREAD_SECURE_STACK_MINIMUM 256 +#endif +/* Maximum size of secure stack. */ +#ifndef TX_THREAD_SECURE_STACK_MAXIMUM +#define TX_THREAD_SECURE_STACK_MAXIMUM 1024 +#endif + +/* 8 bytes added to stack size to "seal" stack. */ +#define TX_THREAD_STACK_SEAL_SIZE 8 +#define TX_THREAD_STACK_SEAL_VALUE 0xFEF5EDA5 + +/* max number of Secure context */ +#ifndef TX_MAX_SECURE_CONTEXTS +#define TX_MAX_SECURE_CONTEXTS 32 +#endif +#define TX_INVALID_SECURE_CONTEXT_IDX (-1) + +/* Secure stack info struct to hold stack start, stack limit, + current stack pointer, and pointer to owning thread. + This will be allocated for each thread with a secure stack. */ +typedef struct TX_THREAD_SECURE_STACK_INFO_STRUCT +{ + VOID *tx_thread_secure_stack_ptr; /* Thread's secure stack current pointer */ + VOID *tx_thread_secure_stack_start; /* Thread's secure stack start address */ + VOID *tx_thread_secure_stack_limit; /* Thread's secure stack limit */ + TX_THREAD *tx_thread_ptr; /* Keep track of thread for error handling */ + INT tx_next_free_index; /* Next free index of free secure context */ +} TX_THREAD_SECURE_STACK_INFO; + +/* Static secure contexts */ +static TX_THREAD_SECURE_STACK_INFO tx_thread_secure_context[TX_MAX_SECURE_CONTEXTS]; +/* Head of free secure context */ +static INT tx_head_free_index = 0U; + + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_secure_mode_stack_initialize Cortex-M52/AC6 */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function initializes secure mode to use PSP stack. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* status */ +/* */ +/* CALLS */ +/* */ +/* __get_CONTROL Intrinsic to get CONTROL */ +/* __set_CONTROL Intrinsic to set CONTROL */ +/* __set_PSPLIM Intrinsic to set PSP limit */ +/* __set_PSP Intrinsic to set PSP */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_initialize_kernel_enter */ +/* */ +/**************************************************************************/ +__attribute__((cmse_nonsecure_entry)) +UINT _tx_thread_secure_mode_stack_initialize(void) +{ +UINT status; +INT index; + + /* Make sure function is called from interrupt (threads should not call). */ + if (__get_IPSR() == 0) + { + status = TX_CALLER_ERROR; + } + else + { + /* Set secure mode to use PSP. */ + __set_CONTROL(__get_CONTROL() | 2); + + /* Set process stack pointer and stack limit to 0 to throw exception when a thread + without a secure stack calls a secure function that tries to use secure stack. */ + __set_PSPLIM(0); + __set_PSP(0); + + for (index = 0; index < TX_MAX_SECURE_CONTEXTS; index++) + { + + /* Check last index and mark next free to invalid index */ + if(index == (TX_MAX_SECURE_CONTEXTS - 1)) + { + tx_thread_secure_context[index].tx_next_free_index = TX_INVALID_SECURE_CONTEXT_IDX; + } + else + { + tx_thread_secure_context[index].tx_next_free_index = index + 1; + } + } + + status = TX_SUCCESS; + } + return status; +} + + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_secure_mode_stack_allocate Cortex-M52/AC6 */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function allocates a thread's secure stack. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Thread control block pointer */ +/* stack_size Size of stack to allocates */ +/* */ +/* OUTPUT */ +/* */ +/* TX_THREAD_ERROR Invalid thread pointer */ +/* TX_SIZE_ERROR Invalid stack size */ +/* TX_CALLER_ERROR Invalid caller of function */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* __get_IPSR Intrinsic to get IPSR */ +/* malloc Compiler's malloc function */ +/* __set_PSPLIM Intrinsic to set PSP limit */ +/* __set_PSP Intrinsic to set PSP */ +/* __TZ_get_PSPLIM_NS Intrinsic to get NS PSP */ +/* */ +/* CALLED BY */ +/* */ +/* SVC Handler */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 09-30-2020 Scott Larson Initial Version 6.1 */ +/* 10-16-2020 Scott Larson Modified comment(s), */ +/* added stack sealing, */ +/* resulting in version 6.1.1 */ +/* 01-31-2022 Himanshu Gupta Modified comments(s), updated */ +/* secure stack allocation, */ +/* resulting in version 6.1.10 */ +/* */ +/**************************************************************************/ +__attribute__((cmse_nonsecure_entry)) +UINT _tx_thread_secure_mode_stack_allocate(TX_THREAD *thread_ptr, ULONG stack_size) +{ +TX_INTERRUPT_SAVE_AREA +UINT status; +TX_THREAD_SECURE_STACK_INFO *info_ptr; +UCHAR *stack_mem; +INT secure_context_index; + + status = TX_SUCCESS; + + /* Make sure function is called from interrupt (threads should not call). */ + if (__get_IPSR() == 0) + { + status = TX_CALLER_ERROR; + } + else if (stack_size < TX_THREAD_SECURE_STACK_MINIMUM || stack_size > TX_THREAD_SECURE_STACK_MAXIMUM) + { + status = TX_SIZE_ERROR; + } + + /* Check if thread already has secure stack allocated. */ + else if (thread_ptr -> tx_thread_secure_stack_context != 0) + { + status = TX_THREAD_ERROR; + } + + else + { + TX_DISABLE + + /* Allocate free index for secure stack info. */ + if(tx_head_free_index != TX_INVALID_SECURE_CONTEXT_IDX) + { + secure_context_index = tx_head_free_index; + tx_head_free_index = tx_thread_secure_context[tx_head_free_index].tx_next_free_index; + tx_thread_secure_context[secure_context_index].tx_next_free_index = TX_INVALID_SECURE_CONTEXT_IDX; + } + else + { + secure_context_index = TX_INVALID_SECURE_CONTEXT_IDX; + } + + TX_RESTORE + + if(secure_context_index != TX_INVALID_SECURE_CONTEXT_IDX) + { + info_ptr = &tx_thread_secure_context[secure_context_index]; + + /* If stack info allocated, allocate a stack & seal. */ + stack_mem = malloc(stack_size + TX_THREAD_STACK_SEAL_SIZE); + + if(stack_mem != TX_NULL) + { + /* Secure stack has been allocated, save in the stack info struct. */ + info_ptr -> tx_thread_secure_stack_limit = stack_mem; + info_ptr -> tx_thread_secure_stack_start = stack_mem + stack_size; + info_ptr -> tx_thread_secure_stack_ptr = info_ptr -> tx_thread_secure_stack_start; + info_ptr -> tx_thread_ptr = thread_ptr; + + /* Seal bottom of stack. */ + *(ULONG*)info_ptr -> tx_thread_secure_stack_start = TX_THREAD_STACK_SEAL_VALUE; + + /* Save secure context id (i.e non-zero base index) in thread. */ + thread_ptr -> tx_thread_secure_stack_context = (VOID *)(secure_context_index + 1); + + /* Check if this thread is running by looking at its stack start and PSPLIM_NS */ + if(((ULONG) thread_ptr -> tx_thread_stack_start & 0xFFFFFFF8) == __TZ_get_PSPLIM_NS()) + { + /* If this thread is running, set Secure PSP and PSPLIM. */ + __set_PSPLIM((ULONG)(info_ptr -> tx_thread_secure_stack_limit)); + __set_PSP((ULONG)(info_ptr -> tx_thread_secure_stack_ptr)); + } + } + + else + { + TX_DISABLE + + /* Stack not allocated, free the info struct. */ + tx_thread_secure_context[secure_context_index].tx_next_free_index = tx_head_free_index; + tx_head_free_index = secure_context_index; + TX_RESTORE + + status = TX_NO_MEMORY; + } + } + + else + { + status = TX_NO_MEMORY; + } + } + + return(status); +} + + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_secure_mode_stack_free Cortex-M52/AC6 */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function frees a thread's secure stack. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Thread control block pointer */ +/* */ +/* OUTPUT */ +/* */ +/* TX_THREAD_ERROR Invalid thread pointer */ +/* TX_CALLER_ERROR Invalid caller of function */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* __get_IPSR Intrinsic to get IPSR */ +/* free Compiler's free() function */ +/* */ +/* CALLED BY */ +/* */ +/* SVC Handler */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 09-30-2020 Scott Larson Initial Version 6.1 */ +/* 10-16-2020 Scott Larson Modified comment(s), */ +/* resulting in version 6.1.1 */ +/* 01-31-2022 Himanshu Gupta Modified comments(s), updated */ +/* secure stack allocation, */ +/* resulting in version 6.1.10 */ +/* */ +/**************************************************************************/ +__attribute__((cmse_nonsecure_entry)) +UINT _tx_thread_secure_mode_stack_free(TX_THREAD *thread_ptr) +{ +TX_INTERRUPT_SAVE_AREA +UINT status; +TX_THREAD_SECURE_STACK_INFO *info_ptr; +INT secure_context_index; + + status = TX_SUCCESS; + + /* Pickup stack info id from thread. */ + secure_context_index = (INT)thread_ptr -> tx_thread_secure_stack_context - 1; + + /* Make sure function is called from interrupt (threads should not call). */ + if (__get_IPSR() == 0) + { + status = TX_CALLER_ERROR; + } + + /* Check if secure context index is in valid range. */ + else if (secure_context_index < 0 || secure_context_index >= TX_MAX_SECURE_CONTEXTS) + { + status = TX_THREAD_ERROR; + } + else + { + + /* Pickup stack info from static array of secure contexts. */ + info_ptr = &tx_thread_secure_context[secure_context_index]; + + /* Check that this secure context is for this thread. */ + if (info_ptr -> tx_thread_ptr != thread_ptr) + { + status = TX_THREAD_ERROR; + } + + else + { + + /* Free secure stack. */ + free(info_ptr -> tx_thread_secure_stack_limit); + + TX_DISABLE + + /* Free info struct. */ + tx_thread_secure_context[secure_context_index].tx_next_free_index = tx_head_free_index; + tx_head_free_index = secure_context_index; + TX_RESTORE + + /* Clear secure context from thread. */ + thread_ptr -> tx_thread_secure_stack_context = 0; + } + } + + return(status); +} + + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_secure_stack_context_save Cortex-M52/AC6 */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function saves context of the secure stack. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Thread control block pointer */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* __get_IPSR Intrinsic to get IPSR */ +/* __get_PSP Intrinsic to get PSP */ +/* __set_PSPLIM Intrinsic to set PSP limit */ +/* __set_PSP Intrinsic to set PSP */ +/* */ +/* CALLED BY */ +/* */ +/* PendSV Handler */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 09-30-2020 Scott Larson Initial Version 6.1 */ +/* 10-16-2020 Scott Larson Modified comment(s), */ +/* resulting in version 6.1.1 */ +/* 06-02-2021 Scott Larson Fix stack pointer save, */ +/* resulting in version 6.1.7 */ +/* 01-31-2022 Himanshu Gupta Modified comments(s), updated */ +/* secure stack allocation, */ +/* resulting in version 6.1.10 */ +/* */ +/**************************************************************************/ +__attribute__((cmse_nonsecure_entry)) +void _tx_thread_secure_stack_context_save(TX_THREAD *thread_ptr) +{ +TX_THREAD_SECURE_STACK_INFO *info_ptr; +ULONG sp; +INT secure_context_index = (INT)thread_ptr -> tx_thread_secure_stack_context - 1; + + /* This function should be called from scheduler only. */ + if (__get_IPSR() == 0) + { + return; + } + + /* Check if secure context index is in valid range. */ + else if (secure_context_index < 0 || secure_context_index >= TX_MAX_SECURE_CONTEXTS) + { + return; + } + + /* Pickup the secure context pointer. */ + info_ptr = &tx_thread_secure_context[secure_context_index]; + + /* Check that this secure context is for this thread. */ + if (info_ptr -> tx_thread_ptr != thread_ptr) + { + return; + } + + /* Check that stack pointer is in range */ + sp = __get_PSP(); + if ((sp < (ULONG)info_ptr -> tx_thread_secure_stack_limit) || + (sp > (ULONG)info_ptr -> tx_thread_secure_stack_start)) + { + return; + } + + /* Save stack pointer. */ + info_ptr -> tx_thread_secure_stack_ptr = (VOID *) sp; + + /* Set process stack pointer and stack limit to 0 to throw exception when a thread + without a secure stack calls a secure function that tries to use secure stack. */ + __set_PSPLIM(0); + __set_PSP(0); + + return; +} + + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_secure_stack_context_restore Cortex-M52/AC6 */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function restores context of the secure stack. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Thread control block pointer */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* __get_IPSR Intrinsic to get IPSR */ +/* __set_PSPLIM Intrinsic to set PSP limit */ +/* __set_PSP Intrinsic to set PSP */ +/* */ +/* CALLED BY */ +/* */ +/* PendSV Handler */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 09-30-2020 Scott Larson Initial Version 6.1 */ +/* 10-16-2020 Scott Larson Modified comment(s), */ +/* resulting in version 6.1.1 */ +/* 01-31-2022 Himanshu Gupta Modified comments(s), updated */ +/* secure stack allocation, */ +/* resulting in version 6.1.10 */ +/* */ +/**************************************************************************/ +__attribute__((cmse_nonsecure_entry)) +void _tx_thread_secure_stack_context_restore(TX_THREAD *thread_ptr) +{ +TX_THREAD_SECURE_STACK_INFO *info_ptr; +INT secure_context_index = (INT)thread_ptr -> tx_thread_secure_stack_context - 1; + + /* This function should be called from scheduler only. */ + if (__get_IPSR() == 0) + { + return; + } + + /* Check if secure context index is in valid range. */ + else if (secure_context_index < 0 || secure_context_index >= TX_MAX_SECURE_CONTEXTS) + { + return; + } + + /* Pickup the secure context pointer. */ + info_ptr = &tx_thread_secure_context[secure_context_index]; + + /* Check that this secure context is for this thread. */ + if (info_ptr -> tx_thread_ptr != thread_ptr) + { + return; + } + + /* Set stack pointer and limit. */ + __set_PSPLIM((ULONG)info_ptr -> tx_thread_secure_stack_limit); + __set_PSP ((ULONG)info_ptr -> tx_thread_secure_stack_ptr); + + return; +} + +#endif diff --git a/ports/cortex_m52/ac6/src/tx_thread_secure_stack_allocate.S b/ports/cortex_m52/ac6/src/tx_thread_secure_stack_allocate.S new file mode 100644 index 000000000..6ae82c634 --- /dev/null +++ b/ports/cortex_m52/ac6/src/tx_thread_secure_stack_allocate.S @@ -0,0 +1,82 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_secure_stack_allocate Cortex-M52/AC6 */ +/* 6.2.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function enters the SVC handler to allocate a secure stack. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Thread control block pointer */ +/* stack_size Size of secure stack to */ +/* allocate */ +/* */ +/* OUTPUT */ +/* */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* SVC 1 */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/**************************************************************************/ +// UINT _tx_thread_secure_stack_allocate(TX_THREAD *thread_ptr, ULONG stack_size) +// { + .section .text + .balign 4 + .syntax unified + .eabi_attribute Tag_ABI_align_preserved, 1 + .global _tx_thread_secure_stack_allocate + .thumb_func +.type _tx_thread_secure_stack_allocate, function +_tx_thread_secure_stack_allocate: +#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE) + MRS r3, PRIMASK // Save interrupt mask + CPSIE i // Enable interrupts for SVC call + SVC 1 + CMP r3, #0 // If interrupts enabled, just return + BEQ _alloc_return_interrupt_enabled + CPSID i // Otherwise, disable interrupts +#else + MOV r0, #0xFF // Feature not enabled +#endif +_alloc_return_interrupt_enabled: + BX lr + .end diff --git a/ports/cortex_m52/ac6/src/tx_thread_secure_stack_free.S b/ports/cortex_m52/ac6/src/tx_thread_secure_stack_free.S new file mode 100644 index 000000000..6b403dfba --- /dev/null +++ b/ports/cortex_m52/ac6/src/tx_thread_secure_stack_free.S @@ -0,0 +1,80 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_secure_stack_free Cortex-M52/AC6 */ +/* 6.2.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function enters the SVC handler to free a secure stack. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Thread control block pointer */ +/* */ +/* OUTPUT */ +/* */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* SVC 2 */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/**************************************************************************/ +// UINT _tx_thread_secure_stack_free(TX_THREAD *thread_ptr) +// { + .section .text + .balign 4 + .syntax unified + .eabi_attribute Tag_ABI_align_preserved, 1 + .global _tx_thread_secure_stack_free + .thumb_func +.type _tx_thread_secure_stack_free, function +_tx_thread_secure_stack_free: +#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE) + MRS r3, PRIMASK // Save interrupt mask + CPSIE i // Enable interrupts for SVC call + SVC 2 + CMP r3, #0 // If interrupts enabled, just return + BEQ _free_return_interrupt_enabled + CPSID i // Otherwise, disable interrupts +#else + MOV r0, #0xFF // Feature not enabled +#endif +_free_return_interrupt_enabled: + BX lr + .end diff --git a/ports/cortex_m52/ac6/src/tx_thread_secure_stack_initialize.S b/ports/cortex_m52/ac6/src/tx_thread_secure_stack_initialize.S new file mode 100644 index 000000000..7414dcf9c --- /dev/null +++ b/ports/cortex_m52/ac6/src/tx_thread_secure_stack_initialize.S @@ -0,0 +1,76 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_secure_stack_initialize Cortex-M52/AC6 */ +/* 6.2.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function enters the SVC handler to initialize a secure stack. */ +/* */ +/* INPUT */ +/* */ +/* none */ +/* */ +/* OUTPUT */ +/* */ +/* none */ +/* */ +/* CALLS */ +/* */ +/* SVC 3 */ +/* */ +/* CALLED BY */ +/* */ +/* TX_PORT_SPECIFIC_PRE_INITIALIZATION */ +/* */ +/**************************************************************************/ +// VOID _tx_thread_secure_stack_initialize(VOID) +// { + .section .text + .balign 4 + .syntax unified + .eabi_attribute Tag_ABI_align_preserved, 1 + .global _tx_thread_secure_stack_initialize + .thumb_func +.type _tx_thread_secure_stack_initialize, function +_tx_thread_secure_stack_initialize: +#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE) + CPSIE i // Enable interrupts for SVC call + SVC 3 + CPSID i // Disable interrupts +#else + MOV r0, #0xFF // Feature not enabled +#endif + BX lr + .end diff --git a/ports/cortex_m52/ac6/src/tx_thread_stack_build.S b/ports/cortex_m52/ac6/src/tx_thread_stack_build.S new file mode 100644 index 000000000..75b6a4de1 --- /dev/null +++ b/ports/cortex_m52/ac6/src/tx_thread_stack_build.S @@ -0,0 +1,137 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_stack_build Cortex-M52/AC6 */ +/* 6.2.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function builds a stack frame on the supplied thread's stack. */ +/* The stack frame results in a fake interrupt return to the supplied */ +/* function pointer. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Pointer to thread control blk */ +/* function_ptr Pointer to return function */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_thread_create Create thread service */ +/* */ +/**************************************************************************/ +// VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID)) +// { + .section .text + .balign 4 + .syntax unified + .eabi_attribute Tag_ABI_align_preserved, 1 + .global _tx_thread_stack_build + .thumb_func +.type _tx_thread_stack_build, function +_tx_thread_stack_build: + /* Build a fake interrupt frame. The form of the fake interrupt stack + on the Cortex-M should look like the following after it is built: + + Stack Top: + LR Interrupted LR (LR at time of PENDSV) + r4 Initial value for r4 + r5 Initial value for r5 + r6 Initial value for r6 + r7 Initial value for r7 + r8 Initial value for r8 + r9 Initial value for r9 + r10 Initial value for r10 + r11 Initial value for r11 + r0 Initial value for r0 (Hardware stack starts here!!) + r1 Initial value for r1 + r2 Initial value for r2 + r3 Initial value for r3 + r12 Initial value for r12 + lr Initial value for lr + pc Initial value for pc + xPSR Initial value for xPSR + + Stack Bottom: (higher memory address) */ + + LDR r2, [r0, #16] // Pickup end of stack area + BIC r2, r2, #0x7 // Align frame for 8-byte alignment + SUB r2, r2, #68 // Subtract frame size +#ifdef TX_SINGLE_MODE_SECURE + LDR r3, =0xFFFFFFFD // Build initial LR value for secure mode +#else + LDR r3, =0xFFFFFFBC // Build initial LR value to return to non-secure PSP +#endif + STR r3, [r2, #0] // Save on the stack + + /* Actually build the stack frame. */ + + MOV r3, #0 // Build initial register value + STR r3, [r2, #4] // Store initial r4 + STR r3, [r2, #8] // Store initial r5 + STR r3, [r2, #12] // Store initial r6 + STR r3, [r2, #16] // Store initial r7 + STR r3, [r2, #20] // Store initial r8 + STR r3, [r2, #24] // Store initial r9 + STR r3, [r2, #28] // Store initial r10 + STR r3, [r2, #32] // Store initial r11 + + /* Hardware stack follows. */ + + STR r3, [r2, #36] // Store initial r0 + STR r3, [r2, #40] // Store initial r1 + STR r3, [r2, #44] // Store initial r2 + STR r3, [r2, #48] // Store initial r3 + STR r3, [r2, #52] // Store initial r12 + MOV r3, #0xFFFFFFFF // Poison EXC_RETURN value + STR r3, [r2, #56] // Store initial lr + STR r1, [r2, #60] // Store initial pc + MOV r3, #0x01000000 // Only T-bit need be set + STR r3, [r2, #64] // Store initial xPSR + + /* Setup stack pointer. */ + // thread_ptr -> tx_thread_stack_ptr = r2; + + STR r2, [r0, #8] // Save stack pointer in thread's + // control block + BX lr // Return to caller +// } + .end diff --git a/ports/cortex_m52/ac6/src/tx_thread_system_return.S b/ports/cortex_m52/ac6/src/tx_thread_system_return.S new file mode 100644 index 000000000..abc809648 --- /dev/null +++ b/ports/cortex_m52/ac6/src/tx_thread_system_return.S @@ -0,0 +1,99 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + +// Some portions generated by Gemini (Gemini 2.0 Flash). + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_system_return Cortex-M52/AC6 */ +/* 6.2.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is target processor specific. It is used to transfer */ +/* control from a thread back to the ThreadX system. Only a */ +/* minimal context is saved since the compiler assumes temp registers */ +/* are going to get slicked by a function call anyway. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_schedule Thread scheduling loop */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX components */ +/* */ +/**************************************************************************/ +// VOID _tx_thread_system_return(VOID) +// { + .section .text + .balign 4 + .syntax unified + .eabi_attribute Tag_ABI_align_preserved, 1 + .global _tx_thread_system_return + .thumb_func +.type _tx_thread_system_return, function +_tx_thread_system_return: + /* Return to real scheduler via PendSV. Note that this routine is often + replaced with in-line assembly in tx_port.h to improved performance. */ + + MOV r0, #0x10000000 // Load PENDSVSET bit + MOV r1, #0xE000E000 // Load NVIC base + STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR + DSB #0xF // Ensure memory access is complete + ISB #0xF // Flush pipeline + MRS r0, IPSR // Pickup IPSR + CMP r0, #0 // Is it a thread returning? + BNE _isr_context // If ISR, skip interrupt enable +#ifdef TX_PORT_USE_BASEPRI + MRS r1, BASEPRI // Thread context returning, pickup BASEPRI + MOV r0, #0 + MSR BASEPRI, r0 // Enable interrupts + MSR BASEPRI, r1 // Restore original interrupt posture + ISB #0xF // Flush pipeline +#else + MRS r1, PRIMASK // Thread context returning, pickup PRIMASK + CPSIE i // Enable interrupts + MSR PRIMASK, r1 // Restore original interrupt posture + ISB #0xF // Flush pipeline +#endif +_isr_context: + BX lr // Return to caller +// } + .end diff --git a/ports/cortex_m52/ac6/src/tx_timer_interrupt.S b/ports/cortex_m52/ac6/src/tx_timer_interrupt.S new file mode 100644 index 000000000..6a4677985 --- /dev/null +++ b/ports/cortex_m52/ac6/src/tx_timer_interrupt.S @@ -0,0 +1,240 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Timer */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_timer_interrupt Cortex-M52/AC6 */ +/* 6.2.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes the hardware timer interrupt. This */ +/* processing includes incrementing the system clock and checking for */ +/* time slice and/or timer expiration. If either is found, the */ +/* expiration functions are called. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _tx_timer_expiration_process Timer expiration processing */ +/* _tx_thread_time_slice Time slice interrupted thread */ +/* */ +/* CALLED BY */ +/* */ +/* interrupt vector */ +/* */ +/**************************************************************************/ +// VOID _tx_timer_interrupt(VOID) +// { + .section .text + .balign 4 + .syntax unified + .eabi_attribute Tag_ABI_align_preserved, 1 + .global _tx_timer_interrupt + .thumb_func +.type _tx_timer_interrupt, function +_tx_timer_interrupt: + + /* Upon entry to this routine, it is assumed that the compiler scratch registers are available + for use. */ + + /* Increment the system clock. */ + // _tx_timer_system_clock++; + + LDR r1, =_tx_timer_system_clock // Pickup address of system clock + LDR r0, [r1, #0] // Pickup system clock + ADD r0, r0, #1 // Increment system clock + STR r0, [r1, #0] // Store new system clock + + /* Test for time-slice expiration. */ + // if (_tx_timer_time_slice) + // { + + LDR r3, =_tx_timer_time_slice // Pickup address of time-slice + LDR r2, [r3, #0] // Pickup time-slice + CBZ r2, __tx_timer_no_time_slice // Is it non-active? + // Yes, skip time-slice processing + + /* Decrement the time_slice. */ + // _tx_timer_time_slice--; + + SUB r2, r2, #1 // Decrement the time-slice + STR r2, [r3, #0] // Store new time-slice value + + /* Check for expiration. */ + // if (__tx_timer_time_slice == 0) + + CBNZ r2, __tx_timer_no_time_slice // Has it expired? + // No, skip expiration processing + + /* Set the time-slice expired flag. */ + // _tx_timer_expired_time_slice = TX_TRUE; + + LDR r3, =_tx_timer_expired_time_slice // Pickup address of expired flag + MOV r0, #1 // Build expired value + STR r0, [r3, #0] // Set time-slice expiration flag + + // } + +__tx_timer_no_time_slice: + + /* Test for timer expiration. */ + // if (*_tx_timer_current_ptr) + // { + + LDR r1, =_tx_timer_current_ptr // Pickup current timer pointer address + LDR r0, [r1, #0] // Pickup current timer + LDR r2, [r0, #0] // Pickup timer list entry + CBZ r2, __tx_timer_no_timer // Is there anything in the list? + // No, just increment the timer + + /* Set expiration flag. */ + // _tx_timer_expired = TX_TRUE; + + LDR r3, =_tx_timer_expired // Pickup expiration flag address + MOV r2, #1 // Build expired value + STR r2, [r3, #0] // Set expired flag + B __tx_timer_done // Finished timer processing + + // } + // else + // { +__tx_timer_no_timer: + + /* No timer expired, increment the timer pointer. */ + // _tx_timer_current_ptr++; + + ADD r0, r0, #4 // Move to next timer + + /* Check for wrap-around. */ + // if (_tx_timer_current_ptr == _tx_timer_list_end) + + LDR r3, =_tx_timer_list_end // Pickup addr of timer list end + LDR r2, [r3, #0] // Pickup list end + CMP r0, r2 // Are we at list end? + BNE __tx_timer_skip_wrap // No, skip wrap-around logic + + /* Wrap to beginning of list. */ + // _tx_timer_current_ptr = _tx_timer_list_start; + + LDR r3, =_tx_timer_list_start // Pickup addr of timer list start + LDR r0, [r3, #0] // Set current pointer to list start + +__tx_timer_skip_wrap: + + STR r0, [r1, #0] // Store new current timer pointer + // } + +__tx_timer_done: + + /* See if anything has expired. */ + // if ((_tx_timer_expired_time_slice) || (_tx_timer_expired)) + // { + + LDR r3, =_tx_timer_expired_time_slice // Pickup addr of expired flag + LDR r2, [r3, #0] // Pickup time-slice expired flag + CBNZ r2, __tx_something_expired // Did a time-slice expire? + // If non-zero, time-slice expired + LDR r1, =_tx_timer_expired // Pickup addr of other expired flag + LDR r0, [r1, #0] // Pickup timer expired flag + CBZ r0, __tx_timer_nothing_expired // Did a timer expire? + // No, nothing expired + +__tx_something_expired: + + PUSH {r0, lr} // Save the lr register on the stack + // and save r0 just to keep 8-byte alignment + + /* Did a timer expire? */ + // if (_tx_timer_expired) + // { + + LDR r1, =_tx_timer_expired // Pickup addr of expired flag + LDR r0, [r1, #0] // Pickup timer expired flag + CBZ r0, __tx_timer_dont_activate // Check for timer expiration + // If not set, skip timer activation + + /* Process timer expiration. */ + // _tx_timer_expiration_process(); + + BL _tx_timer_expiration_process // Call the timer expiration handling routine + + // } +__tx_timer_dont_activate: + + /* Did time slice expire? */ + // if (_tx_timer_expired_time_slice) + // { + + LDR r3, =_tx_timer_expired_time_slice // Pickup addr of time-slice expired + LDR r2, [r3, #0] // Pickup the actual flag + CBZ r2, __tx_timer_not_ts_expiration // See if the flag is set + // No, skip time-slice processing + + /* Time slice interrupted thread. */ + // _tx_thread_time_slice(); + + BL _tx_thread_time_slice // Call time-slice processing + LDR r0, =_tx_thread_preempt_disable // Build address of preempt disable flag + LDR r1, [r0] // Is the preempt disable flag set? + CBNZ r1, __tx_timer_skip_time_slice // Yes, skip the PendSV logic + LDR r0, =_tx_thread_current_ptr // Build current thread pointer address + LDR r1, [r0] // Pickup the current thread pointer + LDR r2, =_tx_thread_execute_ptr // Build execute thread pointer address + LDR r3, [r2] // Pickup the execute thread pointer + LDR r0, =0xE000ED04 // Build address of control register + LDR r2, =0x10000000 // Build value for PendSV bit + CMP r1, r3 // Are they the same? + BEQ __tx_timer_skip_time_slice // If the same, there was no time-slice performed + STR r2, [r0] // Not the same, issue the PendSV for preemption +__tx_timer_skip_time_slice: + // } + +__tx_timer_not_ts_expiration: + + POP {r0, lr} // Recover lr register (r0 is just there for + // the 8-byte stack alignment + + // } + +__tx_timer_nothing_expired: + + DSB // Complete all memory access + BX lr // Return to caller +// } + .end diff --git a/ports/cortex_m52/ac6/src/txe_thread_secure_stack_allocate.c b/ports/cortex_m52/ac6/src/txe_thread_secure_stack_allocate.c new file mode 100644 index 000000000..a37436dd7 --- /dev/null +++ b/ports/cortex_m52/ac6/src/txe_thread_secure_stack_allocate.c @@ -0,0 +1,113 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_initialize.h" +#include "tx_thread.h" + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_secure_stack_allocate Cortex-M52 */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the secure stack allocate */ +/* function call. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Thread control block pointer */ +/* stack_size Size of secure stack to */ +/* allocate */ +/* */ +/* OUTPUT */ +/* */ +/* TX_THREAD_ERROR Invalid thread pointer */ +/* TX_CALLER_ERROR Invalid caller of function */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_secure_stack_allocate Actual stack alloc function */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/**************************************************************************/ +UINT _txe_thread_secure_stack_allocate(TX_THREAD *thread_ptr, ULONG stack_size) +{ +#if defined(TX_SINGLE_MODE_SECURE) || defined(TX_SINGLE_MODE_NON_SECURE) + return(TX_FEATURE_NOT_ENABLED); +#else +UINT status; + + /* Default status to success. */ + status = TX_SUCCESS; + + /* Check for an invalid thread pointer. */ + if (thread_ptr == TX_NULL) + { + /* Thread pointer is invalid, return appropriate error code. */ + status = TX_THREAD_ERROR; + } + + /* Now check for invalid thread ID. */ + else if (thread_ptr -> tx_thread_id != TX_THREAD_ID) + { + /* Thread pointer is invalid, return appropriate error code. */ + status = TX_THREAD_ERROR; + } + + /* Check for interrupt call. */ + if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0)) + { + /* Is call from an interrupt and not initialization? */ + if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS) + { + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } + } + + /* Determine if everything is okay. */ + if (status == TX_SUCCESS) + { + /* Call actual secure stack allocate function. */ + status = _tx_thread_secure_stack_allocate(thread_ptr, stack_size); + } + + /* Return completion status. */ + return(status); +#endif +} diff --git a/ports/cortex_m52/ac6/src/txe_thread_secure_stack_free.c b/ports/cortex_m52/ac6/src/txe_thread_secure_stack_free.c new file mode 100644 index 000000000..b7e4b7d5c --- /dev/null +++ b/ports/cortex_m52/ac6/src/txe_thread_secure_stack_free.c @@ -0,0 +1,114 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_initialize.h" +#include "tx_thread.h" + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_thread_secure_stack_free Cortex-M52 */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the secure stack free */ +/* function call. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Thread control block pointer */ +/* */ +/* OUTPUT */ +/* */ +/* TX_THREAD_ERROR Invalid thread pointer */ +/* TX_CALLER_ERROR Invalid caller of function */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_secure_stack_free Actual stack free function */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/**************************************************************************/ +UINT _txe_thread_secure_stack_free(TX_THREAD *thread_ptr) +{ +#if defined(TX_SINGLE_MODE_SECURE) || defined(TX_SINGLE_MODE_NON_SECURE) + return(TX_FEATURE_NOT_ENABLED); +#else +UINT status; + + /* Default status to success. */ + status = TX_SUCCESS; + + /* Check for an invalid thread pointer. */ + if (thread_ptr == TX_NULL) + { + + /* Thread pointer is invalid, return appropriate error code. */ + status = TX_THREAD_ERROR; + } + + /* Now check for invalid thread ID. */ + else if (thread_ptr -> tx_thread_id != TX_THREAD_ID) + { + + /* Thread pointer is invalid, return appropriate error code. */ + status = TX_THREAD_ERROR; + } + + /* Check for interrupt call. */ + if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0)) + { + /* Is call from an interrupt and not initialization? */ + if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS) + { + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } + } + + /* Determine if everything is okay. */ + if (status == TX_SUCCESS) + { + + /* Call actual secure stack allocate function. */ + status = _tx_thread_secure_stack_free(thread_ptr); + } + + /* Return completion status. */ + return(status); +#endif +} diff --git a/ports/cortex_m52/gnu/CMakeLists.txt b/ports/cortex_m52/gnu/CMakeLists.txt new file mode 100644 index 000000000..763a2696c --- /dev/null +++ b/ports/cortex_m52/gnu/CMakeLists.txt @@ -0,0 +1,24 @@ +target_sources(${PROJECT_NAME} + PRIVATE + # {{BEGIN_TARGET_SOURCES}} + ${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_secure_stack_allocate.c + ${CMAKE_CURRENT_LIST_DIR}/src/txe_thread_secure_stack_free.c + ${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_interrupt_control.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_disable.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_interrupt_restore.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_schedule.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_secure_stack.c + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_secure_stack_allocate.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_secure_stack_free.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_stack_build.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_thread_system_return.S + ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S + # {{END_TARGET_SOURCES}} +) + +target_include_directories(${PROJECT_NAME} + PUBLIC + ${CMAKE_CURRENT_LIST_DIR}/inc +) diff --git a/ports/cortex_m52/gnu/inc/tx_port.h b/ports/cortex_m52/gnu/inc/tx_port.h new file mode 100644 index 000000000..bdba07b2d --- /dev/null +++ b/ports/cortex_m52/gnu/inc/tx_port.h @@ -0,0 +1,631 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + +// Some portions generated by Gemini (Gemini 2.0 Flash). +// Some portions generated by Claude Code (Opus 5). + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Port Specific */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* PORT SPECIFIC C INFORMATION RELEASE */ +/* */ +/* tx_port.h Cortex-M52/GNU */ +/* 6.2.1 */ +/* */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains data type definitions that make the ThreadX */ +/* real-time kernel function identically on a variety of different */ +/* processor architectures. For example, the size or number of bits */ +/* in an "int" data type vary between microprocessor architectures and */ +/* even C compilers for the same microprocessor. ThreadX does not */ +/* directly use native C data types. Instead, ThreadX creates its */ +/* own special types that can be mapped to actual data types by this */ +/* file to guarantee consistency in the interface and functionality. */ +/* */ +/* This file replaces the previous Cortex-M52 files. It unifies */ +/* the Cortex-M52 compilers into one common file. */ +/* */ +/**************************************************************************/ + +#ifndef TX_PORT_H +#define TX_PORT_H + +/* Determine if the optional ThreadX user define file should be used. */ +#ifdef TX_INCLUDE_USER_DEFINE_FILE + +/* Yes, include the user defines in tx_user.h. The defines in this file may + alternately be defined on the command line. */ + +#include "tx_user.h" +#endif /* TX_INCLUDE_USER_DEFINE_FILE */ + +/* Define compiler library include files. */ + +#include +#include + +#ifdef __ICCARM__ +#include /* IAR Intrinsics */ +#define __asm__ __asm /* Define to make all inline asm from each compiler look similar */ +#define _tx_control_get __get_CONTROL +#define _tx_control_set __set_CONTROL +#define _tx_ipsr_get __get_IPSR +#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT +#include +#endif /* TX_ENABLE_IAR_LIBRARY_SUPPORT */ +#endif /* __ICCARM__ */ + + +/* Define ThreadX basic types for this port. */ + +#define VOID void +typedef char CHAR; +typedef unsigned char UCHAR; +typedef int INT; +typedef unsigned int UINT; +typedef long LONG; +typedef unsigned long ULONG; +typedef unsigned long long ULONG64; +typedef short SHORT; +typedef unsigned short USHORT; +#define ULONG64_DEFINED + +/* Function prototypes for this port. */ +struct TX_THREAD_STRUCT; +UINT _txe_thread_secure_stack_allocate(struct TX_THREAD_STRUCT *thread_ptr, ULONG stack_size); +UINT _txe_thread_secure_stack_free(struct TX_THREAD_STRUCT *thread_ptr); +UINT _tx_thread_secure_stack_allocate(struct TX_THREAD_STRUCT *tx_thread, ULONG stack_size); +UINT _tx_thread_secure_stack_free(struct TX_THREAD_STRUCT *tx_thread); + +/* Define the system API mappings based on the error checking + selected by the user. Note: this section is only applicable to + application source code, hence the conditional that turns off this + stuff when the include file is processed by the ThreadX source. */ + +#ifndef TX_SOURCE_CODE + + +/* Determine if error checking is desired. If so, map API functions + to the appropriate error checking front-ends. Otherwise, map API + functions to the core functions that actually perform the work. + Note: error checking is enabled by default. */ + +#ifdef TX_DISABLE_ERROR_CHECKING + +/* Services without error checking. */ + +#define tx_thread_secure_stack_allocate _tx_thread_secure_stack_allocate +#define tx_thread_secure_stack_free _tx_thread_secure_stack_free + +#else + +/* Services with error checking. */ + +#define tx_thread_secure_stack_allocate _txe_thread_secure_stack_allocate +#define tx_thread_secure_stack_free _txe_thread_secure_stack_free + +#endif /* TX_DISABLE_ERROR_CHECKING */ +#endif /* TX_SOURCE_CODE */ + +/* This port has a usage fault handler in _tx_initialize_low_level for stack exceptions. */ +#define TX_PORT_THREAD_STACK_ERROR_HANDLING + +/* Define the priority levels for ThreadX. Legal values range + from 32 to 1024 and MUST be evenly divisible by 32. */ + +#ifndef TX_MAX_PRIORITIES +#define TX_MAX_PRIORITIES 32 +#endif + + +/* Define the minimum stack for a ThreadX thread on this processor. If the size supplied during + thread creation is less than this value, the thread create call will return an error. */ + +#ifndef TX_MINIMUM_STACK +#define TX_MINIMUM_STACK 200 /* Minimum stack size for this port */ +#endif + + +/* Define the system timer thread's default stack size and priority. These are only applicable + if TX_TIMER_PROCESS_IN_ISR is not defined. */ + +#ifndef TX_TIMER_THREAD_STACK_SIZE +#define TX_TIMER_THREAD_STACK_SIZE 1024 /* Default timer thread stack size */ +#endif + +#ifndef TX_TIMER_THREAD_PRIORITY +#define TX_TIMER_THREAD_PRIORITY 0 /* Default timer thread priority */ +#endif + +/* By default, ThreadX for Cortex-M uses the PRIMASK register to enable/disable interrupts. +If using BASEPRI is desired, define the following two symbols for both c and assembly files: +TX_PORT_USE_BASEPRI - This tells ThreadX to use BASEPRI instead of PRIMASK. +TX_PORT_BASEPRI = (priority_mask << (8 - number_priority_bits)) - this defines the maximum priority level to mask. +Any interrupt with a higher priority than priority_mask will not be masked, thus the interrupt will run. +*/ + +/* Define various constants for the ThreadX Cortex-M port. */ + +#define TX_INT_DISABLE 1 /* Disable interrupts */ +#define TX_INT_ENABLE 0 /* Enable interrupts */ + + +/* Define the clock source for trace event entry time stamp. The following two item are port specific. + For example, if the time source is at the address 0x0a800024 and is 16-bits in size, the clock + source constants would be: + +#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0x0a800024) +#define TX_TRACE_TIME_MASK 0x0000FFFFUL + +*/ + +#ifndef TX_MISRA_ENABLE +#ifndef TX_TRACE_TIME_SOURCE +#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0xE0001004) +#endif +#else +ULONG _tx_misra_time_stamp_get(VOID); +#define TX_TRACE_TIME_SOURCE _tx_misra_time_stamp_get() +#endif + +#ifndef TX_TRACE_TIME_MASK +#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL +#endif + + +/* Define the port specific options for the _tx_build_options variable. This variable indicates + how the ThreadX library was built. */ + +#define TX_PORT_SPECIFIC_BUILD_OPTIONS (0) + + +/* Define the in-line initialization constant so that modules with in-line + initialization capabilities can prevent their initialization from being + a function call. */ + +#ifdef TX_MISRA_ENABLE +#define TX_DISABLE_INLINE +#else +#define TX_INLINE_INITIALIZATION +#endif + + +/* Determine whether or not stack checking is enabled. By default, ThreadX stack checking is + disabled. When the following is defined, ThreadX thread stack checking is enabled. If stack + checking is enabled (TX_ENABLE_STACK_CHECKING is defined), the TX_DISABLE_STACK_FILLING + define is negated, thereby forcing the stack fill which is necessary for the stack checking + logic. */ + +#ifndef TX_MISRA_ENABLE +#ifdef TX_ENABLE_STACK_CHECKING +#undef TX_DISABLE_STACK_FILLING +#endif +#endif + + +/* Define the TX_THREAD control block extensions for this port. The main reason + for the multiple macros is so that backward compatibility can be maintained with + existing ThreadX kernel awareness modules. */ + +#define TX_THREAD_EXTENSION_0 +#define TX_THREAD_EXTENSION_1 + +#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT +/* IAR library support */ +#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE) +/* ThreadX in non-secure zone with calls to secure zone. */ +#define TX_THREAD_EXTENSION_2 VOID *tx_thread_secure_stack_context; \ + VOID *tx_thread_iar_tls_pointer; +#else +/* ThreadX in only one zone. */ +#define TX_THREAD_EXTENSION_2 VOID *tx_thread_iar_tls_pointer; +#endif + +#else +/* No IAR library support */ +#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE) +/* ThreadX in non-secure zone with calls to secure zone. */ +#define TX_THREAD_EXTENSION_2 VOID *tx_thread_secure_stack_context; +#else +/* ThreadX in only one zone. */ +#define TX_THREAD_EXTENSION_2 +#endif + +#endif /* TX_ENABLE_IAR_LIBRARY_SUPPORT */ + +#define TX_THREAD_EXTENSION_3 + + +/* Define the port extensions of the remaining ThreadX objects. */ + +#define TX_BLOCK_POOL_EXTENSION +#define TX_BYTE_POOL_EXTENSION +#define TX_EVENT_FLAGS_GROUP_EXTENSION +#define TX_MUTEX_EXTENSION +#define TX_QUEUE_EXTENSION +#define TX_SEMAPHORE_EXTENSION +#define TX_TIMER_EXTENSION + + +/* Define the user extension field of the thread control block. Nothing + additional is needed for this port so it is defined as white space. */ + +#ifndef TX_THREAD_USER_EXTENSION +#define TX_THREAD_USER_EXTENSION +#endif + + +/* Define the macros for processing extensions in tx_thread_create, tx_thread_delete, + tx_thread_shell_entry, and tx_thread_terminate. */ +#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT +void *_tx_iar_create_per_thread_tls_area(void); +void _tx_iar_destroy_per_thread_tls_area(void *tls_ptr); +void __iar_Initlocks(void); +#define TX_THREAD_CREATE_EXTENSION(thread_ptr) thread_ptr -> tx_thread_iar_tls_pointer = _tx_iar_create_per_thread_tls_area(); + +#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE) +#define TX_THREAD_DELETE_EXTENSION(thread_ptr) do {_tx_iar_destroy_per_thread_tls_area(thread_ptr -> tx_thread_iar_tls_pointer); \ + thread_ptr -> tx_thread_iar_tls_pointer = TX_NULL; } while(0); \ + if(thread_ptr -> tx_thread_secure_stack_context){_tx_thread_secure_stack_free(thread_ptr);} +#else +#define TX_THREAD_DELETE_EXTENSION(thread_ptr) do {_tx_iar_destroy_per_thread_tls_area(thread_ptr -> tx_thread_iar_tls_pointer); \ + thread_ptr -> tx_thread_iar_tls_pointer = TX_NULL; } while(0); +#endif +#define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION do {__iar_Initlocks();} while(0); + +#else /* No IAR library support. */ +#define TX_THREAD_CREATE_EXTENSION(thread_ptr) +#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE) +#define TX_THREAD_DELETE_EXTENSION(thread_ptr) if(thread_ptr -> tx_thread_secure_stack_context){_tx_thread_secure_stack_free(thread_ptr);} +#else +#define TX_THREAD_DELETE_EXTENSION(thread_ptr) +#endif +#endif /* TX_ENABLE_IAR_LIBRARY_SUPPORT */ + +#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE) +/* Define the size of the secure stack for the timer thread and use the extension to allocate the secure stack. */ +#define TX_TIMER_THREAD_SECURE_STACK_SIZE 256 +#define TX_TIMER_INITIALIZE_EXTENSION(status) _tx_thread_secure_stack_allocate(&_tx_timer_thread, TX_TIMER_THREAD_SECURE_STACK_SIZE); +#endif + + +#if defined(__ARMVFP__) || defined(__ARM_PCS_VFP) || defined(__ARM_FP) || defined(__TARGET_FPU_VFP) || defined(__VFP__) + +#ifdef TX_MISRA_ENABLE + +ULONG _tx_misra_control_get(void); +void _tx_misra_control_set(ULONG value); +ULONG _tx_misra_fpccr_get(void); +void _tx_misra_vfp_touch(void); + +#else /* TX_MISRA_ENABLE not defined */ + +#ifdef __GNUC__ /* GCC and ARM Compiler 6 */ + +__attribute__( ( always_inline ) ) static inline ULONG _tx_control_get(void) +{ +ULONG control_value; + + __asm__ volatile (" MRS %0,CONTROL ": "=r" (control_value) ); + return(control_value); +} + +__attribute__( ( always_inline ) ) static inline void _tx_control_set(ULONG control_value) +{ + __asm__ volatile (" MSR CONTROL,%0": : "r" (control_value): "memory" ); +} + +#endif /* __GNUC__ */ + +/* Touch VFP register in order to flush. Works for AC6/GCC/IAR compilers. */ +#define TX_VFP_TOUCH() __asm__ volatile ("VMOV.F32 s0, s0"); + +#endif /* TX_MISRA_ENABLE */ + +/* A completed thread falls into _thread_shell_entry and we can simply deactivate the FPU via CONTROL.FPCA + in order to ensure no lazy stacking will occur. */ + +#ifndef TX_MISRA_ENABLE + +#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) { \ + ULONG _tx_vfp_state; \ + _tx_vfp_state = _tx_control_get(); \ + _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \ + _tx_control_set(_tx_vfp_state); \ + } +#else + +#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) { \ + ULONG _tx_vfp_state; \ + _tx_vfp_state = _tx_misra_control_get(); \ + _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \ + _tx_misra_control_set(_tx_vfp_state); \ + } +#endif + +/* A thread can be terminated by another thread, so we first check if it's self-terminating and not in an ISR. + If so, deactivate the FPU via CONTROL.FPCA. Otherwise we are in an interrupt or another thread is terminating + this one, so if the FPCCR.LSPACT bit is set, we need to save the CONTROL.FPCA state, touch the FPU to flush + the lazy FPU save, then restore the CONTROL.FPCA state. */ + +#ifndef TX_MISRA_ENABLE + +#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) { \ + ULONG _tx_system_state; \ + _tx_system_state = TX_THREAD_GET_SYSTEM_STATE(); \ + if ((_tx_system_state == ((ULONG) 0)) && ((thread_ptr) == _tx_thread_current_ptr)) \ + { \ + ULONG _tx_vfp_state; \ + _tx_vfp_state = _tx_control_get(); \ + _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \ + _tx_control_set(_tx_vfp_state); \ + } \ + else \ + { \ + ULONG _tx_fpccr; \ + _tx_fpccr = *((volatile ULONG *) 0xE000EF34); \ + _tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \ + if (_tx_fpccr == ((ULONG) 0x01)) \ + { \ + ULONG _tx_vfp_state; \ + _tx_vfp_state = _tx_control_get(); \ + _tx_vfp_state = _tx_vfp_state & ((ULONG) 0x4); \ + TX_VFP_TOUCH(); \ + if (_tx_vfp_state == ((ULONG) 0)) \ + { \ + _tx_vfp_state = _tx_control_get(); \ + _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \ + _tx_control_set(_tx_vfp_state); \ + } \ + } \ + } \ + } +#else + +#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) { \ + ULONG _tx_system_state; \ + _tx_system_state = TX_THREAD_GET_SYSTEM_STATE(); \ + if ((_tx_system_state == ((ULONG) 0)) && ((thread_ptr) == _tx_thread_current_ptr)) \ + { \ + ULONG _tx_vfp_state; \ + _tx_vfp_state = _tx_misra_control_get(); \ + _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \ + _tx_misra_control_set(_tx_vfp_state); \ + } \ + else \ + { \ + ULONG _tx_fpccr; \ + _tx_fpccr = _tx_misra_fpccr_get(); \ + _tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \ + if (_tx_fpccr == ((ULONG) 0x01)) \ + { \ + ULONG _tx_vfp_state; \ + _tx_vfp_state = _tx_misra_control_get(); \ + _tx_vfp_state = _tx_vfp_state & ((ULONG) 0x4); \ + _tx_misra_vfp_touch(); \ + if (_tx_vfp_state == ((ULONG) 0)) \ + { \ + _tx_vfp_state = _tx_misra_control_get(); \ + _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \ + _tx_misra_control_set(_tx_vfp_state); \ + } \ + } \ + } \ + } +#endif + +#else /* No VFP in use */ + +#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) +#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) + +#endif /* defined(__ARMVFP__) || defined(__ARM_PCS_VFP) || defined(__ARM_FP) || defined(__TARGET_FPU_VFP) || defined(__VFP__) */ + + +/* Define the ThreadX object creation extensions for the remaining objects. */ + +#define TX_BLOCK_POOL_CREATE_EXTENSION(pool_ptr) +#define TX_BYTE_POOL_CREATE_EXTENSION(pool_ptr) +#define TX_EVENT_FLAGS_GROUP_CREATE_EXTENSION(group_ptr) +#define TX_MUTEX_CREATE_EXTENSION(mutex_ptr) +#define TX_QUEUE_CREATE_EXTENSION(queue_ptr) +#define TX_SEMAPHORE_CREATE_EXTENSION(semaphore_ptr) +#define TX_TIMER_CREATE_EXTENSION(timer_ptr) + + +/* Define the ThreadX object deletion extensions for the remaining objects. */ + +#define TX_BLOCK_POOL_DELETE_EXTENSION(pool_ptr) +#define TX_BYTE_POOL_DELETE_EXTENSION(pool_ptr) +#define TX_EVENT_FLAGS_GROUP_DELETE_EXTENSION(group_ptr) +#define TX_MUTEX_DELETE_EXTENSION(mutex_ptr) +#define TX_QUEUE_DELETE_EXTENSION(queue_ptr) +#define TX_SEMAPHORE_DELETE_EXTENSION(semaphore_ptr) +#define TX_TIMER_DELETE_EXTENSION(timer_ptr) + + +/* Define the get system state macro. */ + +#ifndef TX_THREAD_GET_SYSTEM_STATE +#ifndef TX_MISRA_ENABLE + +#if defined(__GNUC__) /* GCC and AC6 */ +__attribute__( ( always_inline ) ) static inline UINT _tx_ipsr_get(void) +{ +UINT ipsr_value; + __asm__ volatile (" MRS %0,IPSR ": "=r" (ipsr_value) ); + return(ipsr_value); +} +#endif /* GCC and AC6 IPSR_get function. */ + +#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | _tx_ipsr_get()) + +#else /* TX_MISRA_ENABLE is defined, use MISRA function. */ +ULONG _tx_misra_ipsr_get(VOID); +#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | _tx_misra_ipsr_get()) +#endif /* TX_MISRA_ENABLE */ +#endif /* TX_THREAD_GET_SYSTEM_STATE */ + + +/* Define the check for whether or not to call the _tx_thread_system_return function. A non-zero value + indicates that _tx_thread_system_return should not be called. This overrides the definition in tx_thread.h + for Cortex-M since so we don't waste time checking the _tx_thread_system_state variable that is always + zero after initialization for Cortex-M ports. */ + +#ifndef TX_THREAD_SYSTEM_RETURN_CHECK +#define TX_THREAD_SYSTEM_RETURN_CHECK(c) (c) = ((ULONG) _tx_thread_preempt_disable); +#endif + +#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE) +/* Initialize secure stacks for threads calling secure functions. */ +extern void _tx_thread_secure_stack_initialize(void); +#define TX_PORT_SPECIFIC_PRE_INITIALIZATION _tx_thread_secure_stack_initialize(); +#endif + +/* Define the macro to ensure _tx_thread_preempt_disable is set early in initialization in order to + prevent early scheduling on Cortex-M parts. */ + +#define TX_PORT_SPECIFIC_POST_INITIALIZATION _tx_thread_preempt_disable++; + + + + +#ifndef TX_DISABLE_INLINE + +/* Define the TX_LOWEST_SET_BIT_CALCULATE macro for each compiler. */ +#ifdef __ICCARM__ /* IAR Compiler */ +#define TX_LOWEST_SET_BIT_CALCULATE(m, b) (b) = (UINT) __CLZ(__RBIT((m))); +#elif defined(__GNUC__) /* GCC and AC6 Compiler */ +#define TX_LOWEST_SET_BIT_CALCULATE(m, b) __asm__ volatile (" RBIT %0,%1 ": "=r" (m) : "r" (m) ); \ + __asm__ volatile (" CLZ %0,%1 ": "=r" (b) : "r" (m) ); +#else +#error "Compiler not supported." +#endif + + + +/* Define the interrupt disable/restore macros. */ + +__attribute__( ( always_inline ) ) static inline UINT __get_interrupt_posture(void) +{ +UINT posture; +#ifdef TX_PORT_USE_BASEPRI + __asm__ volatile ("MRS %0, BASEPRI ": "=r" (posture)); +#else + __asm__ volatile ("MRS %0, PRIMASK ": "=r" (posture)); +#endif + return(posture); +} + +#ifdef TX_PORT_USE_BASEPRI +__attribute__( ( always_inline ) ) static inline void __set_basepri_value(UINT basepri_value) +{ + __asm__ volatile ("MSR BASEPRI,%0 ": : "r" (basepri_value) : "memory"); +} +#else +__attribute__( ( always_inline ) ) static inline void __enable_interrupts(void) +{ + __asm__ volatile ("CPSIE i": : : "memory"); +} +#endif + +__attribute__( ( always_inline ) ) static inline void __restore_interrupt(UINT int_posture) +{ +#ifdef TX_PORT_USE_BASEPRI + __set_basepri_value(int_posture); + __asm__ volatile ("" : : : "memory"); +#else + __asm__ volatile ("MSR PRIMASK,%0": : "r" (int_posture): "memory"); +#endif +} + +__attribute__( ( always_inline ) ) static inline UINT __disable_interrupts(void) +{ +UINT int_posture; + + int_posture = __get_interrupt_posture(); + +#ifdef TX_PORT_USE_BASEPRI + __set_basepri_value(TX_PORT_BASEPRI); +#else + __asm__ volatile ("CPSID i" : : : "memory"); +#endif + return(int_posture); +} + +__attribute__( ( always_inline ) ) static inline void _tx_thread_system_return_inline(void) +{ +UINT interrupt_save; + + /* Set PendSV to invoke ThreadX scheduler. */ + *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); + __asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory"); + if (_tx_ipsr_get() == 0) + { + interrupt_save = __get_interrupt_posture(); +#ifdef TX_PORT_USE_BASEPRI + __set_basepri_value(0); +#else + __enable_interrupts(); +#endif + __restore_interrupt(interrupt_save); + __asm__ volatile ("isb 0xF " : : : "memory"); + } +} + +#define TX_INTERRUPT_SAVE_AREA UINT interrupt_save; +#define TX_DISABLE interrupt_save = __disable_interrupts(); +#define TX_RESTORE __restore_interrupt(interrupt_save); + +/* Redefine _tx_thread_system_return for improved performance. */ +#define _tx_thread_system_return _tx_thread_system_return_inline + +#else /* TX_DISABLE_INLINE is defined */ + +UINT _tx_thread_interrupt_disable(VOID); +VOID _tx_thread_interrupt_restore(UINT previous_posture); + +#define TX_INTERRUPT_SAVE_AREA register UINT interrupt_save; + +#define TX_DISABLE interrupt_save = _tx_thread_interrupt_disable(); +#define TX_RESTORE _tx_thread_interrupt_restore(interrupt_save); +#endif /* TX_DISABLE_INLINE */ + +/* Define the version ID of ThreadX. This may be utilized by the application. */ + +#ifdef TX_THREAD_INIT +CHAR _tx_version_id[] = + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M52/GNU Version 6.5.1.202602a *"; +#else +#ifdef TX_MISRA_ENABLE +extern CHAR _tx_version_id[100]; +#else +extern CHAR _tx_version_id[]; +#endif +#endif + +#endif diff --git a/ports/cortex_m52/gnu/inc/tx_secure_interface.h b/ports/cortex_m52/gnu/inc/tx_secure_interface.h new file mode 100644 index 000000000..5ac37fbf4 --- /dev/null +++ b/ports/cortex_m52/gnu/inc/tx_secure_interface.h @@ -0,0 +1,55 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* tx_secure_interface.h PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file defines the ThreadX secure thread stack components, */ +/* including data types and external references. */ +/* It is assumed that tx_api.h and tx_port.h have already been */ +/* included. */ +/* */ +/**************************************************************************/ + +#ifndef TX_SECURE_INTERFACE_H +#define TX_SECURE_INTERFACE_H + +/* Define internal secure thread stack function prototypes. */ + +extern UINT _tx_thread_secure_mode_stack_initialize(void); +extern UINT _tx_thread_secure_mode_stack_allocate(TX_THREAD *thread_ptr, ULONG stack_size); +extern UINT _tx_thread_secure_mode_stack_free(TX_THREAD *thread_ptr); +extern void _tx_thread_secure_stack_initialize(void); +extern void _tx_thread_secure_stack_context_save(TX_THREAD *thread_ptr); +extern void _tx_thread_secure_stack_context_restore(TX_THREAD *thread_ptr); + +#endif diff --git a/ports/cortex_m52/gnu/readme_threadx.txt b/ports/cortex_m52/gnu/readme_threadx.txt new file mode 100644 index 000000000..9278ed82c --- /dev/null +++ b/ports/cortex_m52/gnu/readme_threadx.txt @@ -0,0 +1,210 @@ + Microsoft's Azure RTOS ThreadX for Cortex-M52 + + Using the GNU Tools + +1. Building the ThreadX run-time Library + +Import all ThreadX common and port-specific source files into a GNU project. +Configure the project to build a library rather than an executable. This +results in the ThreadX run-time library file tx.a, which is needed by +the application. +Files tx_thread_stack_error_handler.c and tx_thread_stack_error_notify.c +replace the common files of the same name. + +2. Demonstration System + +No demonstration project is provided. + + +3. System Initialization + +The entry point in ThreadX for the Cortex-M52 using gnu tools uses the standard GNU +Cortex-M52 reset sequence. From the reset vector the C runtime will be initialized. + +The ThreadX tx_initialize_low_level.S file is responsible for setting up +various system data structures, the vector area, and a periodic timer interrupt +source. + +In addition, _tx_initialize_low_level determines the first available +address for use by the application, which is supplied as the sole input +parameter to your application definition function, tx_application_define. + + +4. Register Usage and Stack Frames + +The following defines the saved context stack frames for context switches +that occur as a result of interrupt handling or from thread-level API calls. +All suspended threads have the same stack frame in the Cortex-M52 version of +ThreadX. The top of the suspended thread's stack is pointed to by +tx_thread_stack_ptr in the associated thread control block TX_THREAD. + +Non-FPU Stack Frame: + + Stack Offset Stack Contents + + 0x00 LR Interrupted LR (LR at time of PENDSV) + 0x04 r4 Software stacked GP registers + 0x08 r5 + 0x0C r6 + 0x10 r7 + 0x14 r8 + 0x18 r9 + 0x1C r10 + 0x20 r11 + 0x24 r0 Hardware stacked registers + 0x28 r1 + 0x2C r2 + 0x30 r3 + 0x34 r12 + 0x38 lr + 0x3C pc + 0x40 xPSR + +FPU Stack Frame (only interrupted thread with FPU enabled): + + Stack Offset Stack Contents + + 0x00 LR Interrupted LR (LR at time of PENDSV) + 0x04 s16 Software stacked FPU registers + 0x08 s17 + 0x0C s18 + 0x10 s19 + 0x14 s20 + 0x18 s21 + 0x1C s22 + 0x20 s23 + 0x24 s24 + 0x28 s25 + 0x2C s26 + 0x30 s27 + 0x34 s28 + 0x38 s29 + 0x3C s30 + 0x40 s31 + 0x44 r4 Software stacked registers + 0x48 r5 + 0x4C r6 + 0x50 r7 + 0x54 r8 + 0x58 r9 + 0x5C r10 + 0x60 r11 + 0x64 r0 Hardware stacked registers + 0x68 r1 + 0x6C r2 + 0x70 r3 + 0x74 r12 + 0x78 lr + 0x7C pc + 0x80 xPSR + 0x84 s0 Hardware stacked FPU registers + 0x88 s1 + 0x8C s2 + 0x90 s3 + 0x94 s4 + 0x98 s5 + 0x9C s6 + 0xA0 s7 + 0xA4 s8 + 0xA8 s9 + 0xAC s10 + 0xB0 s11 + 0xB4 s12 + 0xB8 s13 + 0xBC s14 + 0xC0 s15 + 0xC4 fpscr + + +5. Improving Performance + +To make ThreadX and the application(s) run faster, you can enable +all compiler optimizations. + +In addition, you can eliminate the ThreadX basic API error checking by +compiling your application code with the symbol TX_DISABLE_ERROR_CHECKING +defined. + + +6. Interrupt Handling + +ThreadX provides complete and high-performance interrupt handling for Cortex-M52 +targets. There are a certain set of requirements that are defined in the +following sub-sections: + + +6.1 Vector Area + +The Cortex-M52 vectors start at the label __tx_vectors or similar. The application may modify +the vector area according to its needs. There is code in tx_initialize_low_level() that will +configure the vector base register. + + +6.2 Managed Interrupts + +ISRs can be written completely in C (or assembly language) without any calls to +_tx_thread_context_save or _tx_thread_context_restore. These ISRs are allowed access to the +ThreadX API that is available to ISRs. + +ISRs written in C will take the form (where "your_C_isr" is an entry in the vector table): + +void your_C_isr(void) +{ + + /* ISR processing goes here, including any needed function calls. */ +} + +ISRs written in assembly language will take the form: + + + .global your_assembly_isr + .thumb_func +your_assembly_isr: + PUSH {r0, lr} +; +; /* Do interrupt handler work here */ +; /* BL */ + + POP {r0, lr} + BX lr + +Note: the Cortex-M52 requires exception handlers to be thumb labels, this implies bit 0 set. +To accomplish this, the declaration of the label has to be preceded by the assembler directive +.thumb_func to instruct the linker to create thumb labels. The label __tx_IntHandler needs to +be inserted in the correct location in the interrupt vector table. This table is typically +located in either your runtime startup file or in the tx_initialize_low_level.S file. + + +7. FPU Support + +ThreadX for Cortex-M52 supports automatic ("lazy") VFP support, which means that applications threads +can simply use the VFP and ThreadX automatically maintains the VFP registers as part of the thread +context. + + +8. Revision History + +For generic code revision information, please refer to the readme_threadx_generic.txt +file, which is included in your distribution. The following details the revision +information associated with this specific port of ThreadX: + +06-02-2021 Release 6.1.7 changes: + tx_thread_secure_stack_initialize.S New file + tx_thread_schedule.S Added secure stack initialize to SVC hander + tx_thread_secure_stack.c Fixed stack pointer save, initialize in handler mode + +04-02-2021 Release 6.1.6 changes: + tx_port.h Updated macro definition + tx_thread_schedule.s Added low power support + +03-02-2021 The following files were changed/added for version 6.1.5: + tx_port.h Added ULONG64_DEFINED + +09-30-2020 Initial ThreadX 6.1 version for Cortex-M52 using GNU tools. + + +Copyright(c) 1996-2020 Microsoft Corporation + + +https://azure.com/rtos + diff --git a/ports/cortex_m52/gnu/src/tx_misra.S b/ports/cortex_m52/gnu/src/tx_misra.S new file mode 100644 index 000000000..10548671a --- /dev/null +++ b/ports/cortex_m52/gnu/src/tx_misra.S @@ -0,0 +1,723 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** ThreadX MISRA Compliance */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + + #define SHT_PROGBITS 0x1 + + .global __aeabi_memset + .global _tx_thread_current_ptr + .global _tx_thread_interrupt_disable + .global _tx_thread_interrupt_restore + .global _tx_thread_stack_analyze + .global _tx_thread_stack_error_handler + .global _tx_thread_system_state +#ifdef TX_ENABLE_EVENT_TRACE + .global _tx_trace_buffer_current_ptr + .global _tx_trace_buffer_end_ptr + .global _tx_trace_buffer_start_ptr + .global _tx_trace_event_enable_bits + .global _tx_trace_full_notify_function + .global _tx_trace_header_ptr +#endif + + .global _tx_misra_always_true + .global _tx_misra_block_pool_to_uchar_pointer_convert + .global _tx_misra_byte_pool_to_uchar_pointer_convert + .global _tx_misra_char_to_uchar_pointer_convert + .global _tx_misra_const_char_to_char_pointer_convert +#ifdef TX_ENABLE_EVENT_TRACE + .global _tx_misra_entry_to_uchar_pointer_convert +#endif + .global _tx_misra_indirect_void_to_uchar_pointer_convert + .global _tx_misra_memset + .global _tx_misra_message_copy +#ifdef TX_ENABLE_EVENT_TRACE + .global _tx_misra_object_to_uchar_pointer_convert +#endif + .global _tx_misra_pointer_to_ulong_convert + .global _tx_misra_status_get + .global _tx_misra_thread_stack_check +#ifdef TX_ENABLE_EVENT_TRACE + .global _tx_misra_time_stamp_get +#endif + .global _tx_misra_timer_indirect_to_void_pointer_convert + .global _tx_misra_timer_pointer_add + .global _tx_misra_timer_pointer_dif +#ifdef TX_ENABLE_EVENT_TRACE + .global _tx_misra_trace_event_insert +#endif + .global _tx_misra_uchar_pointer_add + .global _tx_misra_uchar_pointer_dif + .global _tx_misra_uchar_pointer_sub + .global _tx_misra_uchar_to_align_type_pointer_convert + .global _tx_misra_uchar_to_block_pool_pointer_convert +#ifdef TX_ENABLE_EVENT_TRACE + .global _tx_misra_uchar_to_entry_pointer_convert + .global _tx_misra_uchar_to_header_pointer_convert +#endif + .global _tx_misra_uchar_to_indirect_byte_pool_pointer_convert + .global _tx_misra_uchar_to_indirect_uchar_pointer_convert +#ifdef TX_ENABLE_EVENT_TRACE + .global _tx_misra_uchar_to_object_pointer_convert +#endif + .global _tx_misra_uchar_to_void_pointer_convert + .global _tx_misra_ulong_pointer_add + .global _tx_misra_ulong_pointer_dif + .global _tx_misra_ulong_pointer_sub + .global _tx_misra_ulong_to_pointer_convert + .global _tx_misra_ulong_to_thread_pointer_convert + .global _tx_misra_user_timer_pointer_get + .global _tx_misra_void_to_block_pool_pointer_convert + .global _tx_misra_void_to_byte_pool_pointer_convert + .global _tx_misra_void_to_event_flags_pointer_convert + .global _tx_misra_void_to_indirect_uchar_pointer_convert + .global _tx_misra_void_to_mutex_pointer_convert + .global _tx_misra_void_to_queue_pointer_convert + .global _tx_misra_void_to_semaphore_pointer_convert + .global _tx_misra_void_to_thread_pointer_convert + .global _tx_misra_void_to_uchar_pointer_convert + .global _tx_misra_void_to_ulong_pointer_convert + .global _tx_misra_ipsr_get + .global _tx_misra_control_get + .global _tx_misra_control_set +#ifdef __ARM_FP + .global _tx_misra_fpccr_get + .global _tx_misra_vfp_touch +#endif + + .global _tx_misra_event_flags_group_not_used + .global _tx_misra_event_flags_set_notify_not_used + .global _tx_misra_queue_not_used + .global _tx_misra_queue_send_notify_not_used + .global _tx_misra_semaphore_not_used + .global _tx_misra_semaphore_put_notify_not_used + .global _tx_misra_thread_entry_exit_notify_not_used + .global _tx_misra_thread_not_used + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** VOID _tx_misra_memset(VOID *ptr, UINT value, UINT size); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .text + .align 4 + .syntax unified + .thumb_func +_tx_misra_memset: + PUSH {R4,LR} + MOVS R4,R0 + MOVS R0,R2 + MOVS R2,R1 + MOVS R1,R0 + MOVS R0,R4 + BL __aeabi_memset + POP {R4,PC} // return + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** UCHAR *_tx_misra_uchar_pointer_add(UCHAR *ptr, ULONG amount); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .text + .thumb_func +_tx_misra_uchar_pointer_add: + ADD R0,R0,R1 + BX LR // return + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** UCHAR *_tx_misra_uchar_pointer_sub(UCHAR *ptr, ULONG amount); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .text + .thumb_func +_tx_misra_uchar_pointer_sub: + RSBS R1,R1,#+0 + ADD R0,R0,R1 + BX LR // return + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ULONG _tx_misra_uchar_pointer_dif(UCHAR *ptr1, UCHAR *ptr2); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .text + .thumb_func +_tx_misra_uchar_pointer_dif: + SUBS R0,R0,R1 + BX LR // return + + +/************************************************************************************************************************************/ +/************************************************************************************************************************************/ +/** */ +/** This single function serves all of the below prototypes. */ +/** */ +/** ULONG _tx_misra_pointer_to_ulong_convert(VOID *ptr); */ +/** VOID *_tx_misra_ulong_to_pointer_convert(ULONG input); */ +/** UCHAR **_tx_misra_indirect_void_to_uchar_pointer_convert(VOID **return_ptr); */ +/** UCHAR **_tx_misra_uchar_to_indirect_uchar_pointer_convert(UCHAR *pointer); */ +/** UCHAR *_tx_misra_block_pool_to_uchar_pointer_convert(TX_BLOCK_POOL *pool); */ +/** TX_BLOCK_POOL *_tx_misra_void_to_block_pool_pointer_convert(VOID *pointer); */ +/** UCHAR *_tx_misra_void_to_uchar_pointer_convert(VOID *pointer); */ +/** TX_BLOCK_POOL *_tx_misra_uchar_to_block_pool_pointer_convert(UCHAR *pointer); */ +/** UCHAR **_tx_misra_void_to_indirect_uchar_pointer_convert(VOID *pointer); */ +/** TX_BYTE_POOL *_tx_misra_void_to_byte_pool_pointer_convert(VOID *pointer); */ +/** UCHAR *_tx_misra_byte_pool_to_uchar_pointer_convert(TX_BYTE_POOL *pool); */ +/** ALIGN_TYPE *_tx_misra_uchar_to_align_type_pointer_convert(UCHAR *pointer); */ +/** TX_BYTE_POOL **_tx_misra_uchar_to_indirect_byte_pool_pointer_convert(UCHAR *pointer); */ +/** TX_EVENT_FLAGS_GROUP *_tx_misra_void_to_event_flags_pointer_convert(VOID *pointer); */ +/** ULONG *_tx_misra_void_to_ulong_pointer_convert(VOID *pointer); */ +/** TX_MUTEX *_tx_misra_void_to_mutex_pointer_convert(VOID *pointer); */ +/** TX_QUEUE *_tx_misra_void_to_queue_pointer_convert(VOID *pointer); */ +/** TX_SEMAPHORE *_tx_misra_void_to_semaphore_pointer_convert(VOID *pointer); */ +/** VOID *_tx_misra_uchar_to_void_pointer_convert(UCHAR *pointer); */ +/** TX_THREAD *_tx_misra_ulong_to_thread_pointer_convert(ULONG value); */ +/** VOID *_tx_misra_timer_indirect_to_void_pointer_convert(TX_TIMER_INTERNAL **pointer); */ +/** CHAR *_tx_misra_const_char_to_char_pointer_convert(const char *pointer); */ +/** TX_THREAD *_tx_misra_void_to_thread_pointer_convert(void *pointer); */ +/** UCHAR *_tx_misra_object_to_uchar_pointer_convert(TX_TRACE_OBJECT_ENTRY *pointer); */ +/** TX_TRACE_OBJECT_ENTRY *_tx_misra_uchar_to_object_pointer_convert(UCHAR *pointer); */ +/** TX_TRACE_HEADER *_tx_misra_uchar_to_header_pointer_convert(UCHAR *pointer); */ +/** TX_TRACE_BUFFER_ENTRY *_tx_misra_uchar_to_entry_pointer_convert(UCHAR *pointer); */ +/** UCHAR *_tx_misra_entry_to_uchar_pointer_convert(TX_TRACE_BUFFER_ENTRY *pointer); */ +/** UCHAR *_tx_misra_char_to_uchar_pointer_convert(CHAR *pointer); */ +/** VOID _tx_misra_event_flags_group_not_used(TX_EVENT_FLAGS_GROUP *group_ptr); */ +/** VOID _tx_misra_event_flags_set_notify_not_used(VOID (*events_set_notify)(TX_EVENT_FLAGS_GROUP *notify_group_ptr)); */ +/** VOID _tx_misra_queue_not_used(TX_QUEUE *queue_ptr); */ +/** VOID _tx_misra_queue_send_notify_not_used(VOID (*queue_send_notify)(TX_QUEUE *notify_queue_ptr)); */ +/** VOID _tx_misra_semaphore_not_used(TX_SEMAPHORE *semaphore_ptr); */ +/** VOID _tx_misra_semaphore_put_notify_not_used(VOID (*semaphore_put_notify)(TX_SEMAPHORE *notify_semaphore_ptr)); */ +/** VOID _tx_misra_thread_not_used(TX_THREAD *thread_ptr); */ +/** VOID _tx_misra_thread_entry_exit_notify_not_used(VOID (*thread_entry_exit_notify)(TX_THREAD *notify_thread_ptr, UINT id)); */ +/** */ +/************************************************************************************************************************************/ +/************************************************************************************************************************************/ + .text + .thumb_func +_tx_misra_pointer_to_ulong_convert: +_tx_misra_ulong_to_pointer_convert: +_tx_misra_indirect_void_to_uchar_pointer_convert: +_tx_misra_uchar_to_indirect_uchar_pointer_convert: +_tx_misra_block_pool_to_uchar_pointer_convert: +_tx_misra_void_to_block_pool_pointer_convert: +_tx_misra_void_to_uchar_pointer_convert: +_tx_misra_uchar_to_block_pool_pointer_convert: +_tx_misra_void_to_indirect_uchar_pointer_convert: +_tx_misra_void_to_byte_pool_pointer_convert: +_tx_misra_byte_pool_to_uchar_pointer_convert: +_tx_misra_uchar_to_align_type_pointer_convert: +_tx_misra_uchar_to_indirect_byte_pool_pointer_convert: +_tx_misra_void_to_event_flags_pointer_convert: +_tx_misra_void_to_ulong_pointer_convert: +_tx_misra_void_to_mutex_pointer_convert: +_tx_misra_void_to_queue_pointer_convert: +_tx_misra_void_to_semaphore_pointer_convert: +_tx_misra_uchar_to_void_pointer_convert: +_tx_misra_ulong_to_thread_pointer_convert: +_tx_misra_timer_indirect_to_void_pointer_convert: +_tx_misra_const_char_to_char_pointer_convert: +_tx_misra_void_to_thread_pointer_convert: +#ifdef TX_ENABLE_EVENT_TRACE +_tx_misra_object_to_uchar_pointer_convert: +_tx_misra_uchar_to_object_pointer_convert: +_tx_misra_uchar_to_header_pointer_convert: +_tx_misra_uchar_to_entry_pointer_convert: +_tx_misra_entry_to_uchar_pointer_convert: +#endif +_tx_misra_char_to_uchar_pointer_convert: +_tx_misra_event_flags_group_not_used: +_tx_misra_event_flags_set_notify_not_used: +_tx_misra_queue_not_used: +_tx_misra_queue_send_notify_not_used: +_tx_misra_semaphore_not_used: +_tx_misra_semaphore_put_notify_not_used: +_tx_misra_thread_entry_exit_notify_not_used: +_tx_misra_thread_not_used: + + BX LR // return + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ULONG *_tx_misra_ulong_pointer_add(ULONG *ptr, ULONG amount); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .text + .thumb_func +_tx_misra_ulong_pointer_add: + ADD R0,R0,R1, LSL #+2 + BX LR // return + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ULONG *_tx_misra_ulong_pointer_sub(ULONG *ptr, ULONG amount); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .text + .thumb_func +_tx_misra_ulong_pointer_sub: + MVNS R2,#+3 + MULS R1,R2,R1 + ADD R0,R0,R1 + BX LR // return + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ULONG _tx_misra_ulong_pointer_dif(ULONG *ptr1, ULONG *ptr2); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .text + .thumb_func +_tx_misra_ulong_pointer_dif: + SUBS R0,R0,R1 + ASRS R0,R0,#+2 + BX LR // return + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** VOID _tx_misra_message_copy(ULONG **source, ULONG **destination, */ +/** UINT size); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .text + .thumb_func +_tx_misra_message_copy: + PUSH {R4,R5} + LDR R3,[R0, #+0] + LDR R4,[R1, #+0] + LDR R5,[R3, #+0] + STR R5,[R4, #+0] + ADDS R4,R4,#+4 + ADDS R3,R3,#+4 + CMP R2,#+2 + BCC.N _tx_misra_message_copy_0 + SUBS R2,R2,#+1 + B.N _tx_misra_message_copy_1 +_tx_misra_message_copy_2: + LDR R5,[R3, #+0] + STR R5,[R4, #+0] + ADDS R4,R4,#+4 + ADDS R3,R3,#+4 + SUBS R2,R2,#+1 +_tx_misra_message_copy_1: + CMP R2,#+0 + BNE.N _tx_misra_message_copy_2 +_tx_misra_message_copy_0: + STR R3,[R0, #+0] + STR R4,[R1, #+0] + POP {R4,R5} + BX LR // return + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ULONG _tx_misra_timer_pointer_dif(TX_TIMER_INTERNAL **ptr1, */ +/** TX_TIMER_INTERNAL **ptr2); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .text + .thumb_func +_tx_misra_timer_pointer_dif: + SUBS R0,R0,R1 + ASRS R0,R0,#+2 + BX LR // return + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** TX_TIMER_INTERNAL **_tx_misra_timer_pointer_add(TX_TIMER_INTERNAL */ +/** **ptr1, ULONG size); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .text + .thumb_func +_tx_misra_timer_pointer_add: + ADD R0,R0,R1, LSL #+2 + BX LR // return + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** VOID _tx_misra_user_timer_pointer_get(TX_TIMER_INTERNAL */ +/** *internal_timer, TX_TIMER **user_timer); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .text + .thumb_func +_tx_misra_user_timer_pointer_get: + SUBS R0,#8 + STR R0,[R1, #+0] + BX LR // return + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** VOID _tx_misra_thread_stack_check(TX_THREAD *thread_ptr, */ +/** VOID **highest_stack); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .text + .thumb_func +_tx_misra_thread_stack_check: + PUSH {R3-R5,LR} + MOVS R4,R0 + MOVS R5,R1 + BL _tx_thread_interrupt_disable + CMP R4,#+0 + BEQ.N _tx_misra_thread_stack_check_0 + LDR R1,[R4, #+0] + LDR R2,=0x54485244 + CMP R1,R2 + BNE.N _tx_misra_thread_stack_check_0 + LDR R1,[R4, #+8] + LDR R2,[R5, #+0] + CMP R1,R2 + BCS.N _tx_misra_thread_stack_check_1 + LDR R1,[R4, #+8] + STR R1,[R5, #+0] +_tx_misra_thread_stack_check_1: + LDR R1,[R4, #+12] + LDR R1,[R1, #+0] + CMP R1,#-269488145 + BNE.N _tx_misra_thread_stack_check_2 + LDR R1,[R4, #+16] + LDR R1,[R1, #+1] + CMP R1,#-269488145 + BNE.N _tx_misra_thread_stack_check_2 + LDR R1,[R5, #+0] + LDR R2,[R4, #+12] + CMP R1,R2 + BCS.N _tx_misra_thread_stack_check_3 +_tx_misra_thread_stack_check_2: + BL _tx_thread_interrupt_restore + MOVS R0,R4 + BL _tx_thread_stack_error_handler + BL _tx_thread_interrupt_disable +_tx_misra_thread_stack_check_3: + LDR R1,[R5, #+0] + LDR R1,[R1, #-4] + CMP R1,#-269488145 + BEQ.N _tx_misra_thread_stack_check_0 + BL _tx_thread_interrupt_restore + MOVS R0,R4 + BL _tx_thread_stack_analyze + BL _tx_thread_interrupt_disable +_tx_misra_thread_stack_check_0: + BL _tx_thread_interrupt_restore + POP {R0,R4,R5,PC} // return + +#ifdef TX_ENABLE_EVENT_TRACE + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** VOID _tx_misra_trace_event_insert(ULONG event_id, */ +/** VOID *info_field_1, ULONG info_field_2, ULONG info_field_3, */ +/** ULONG info_field_4, ULONG filter, ULONG time_stamp); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .text + .thumb_func +_tx_misra_trace_event_insert: + PUSH {R3-R7,LR} + LDR.N R4,DataTable2_1 + LDR R4,[R4, #+0] + CMP R4,#+0 + BEQ.N _tx_misra_trace_event_insert_0 + LDR.N R5,DataTable2_2 + LDR R5,[R5, #+0] + LDR R6,[SP, #+28] + TST R5,R6 + BEQ.N _tx_misra_trace_event_insert_0 + LDR.N R5,DataTable2_3 + LDR R5,[R5, #+0] + LDR.N R6,DataTable2_4 + LDR R6,[R6, #+0] + CMP R5,#+0 + BNE.N _tx_misra_trace_event_insert_1 + LDR R5,[R6, #+44] + LDR R7,[R6, #+60] + LSLS R7,R7,#+16 + ORRS R7,R7,#0x80000000 + ORRS R5,R7,R5 + B.N _tx_misra_trace_event_insert_2 +_tx_misra_trace_event_insert_1: + CMP R5,#-252645136 + BCS.N _tx_misra_trace_event_insert_3 + MOVS R5,R6 + MOVS R6,#-1 + B.N _tx_misra_trace_event_insert_2 +_tx_misra_trace_event_insert_3: + MOVS R6,#-252645136 + MOVS R5,#+0 +_tx_misra_trace_event_insert_2: + STR R6,[R4, #+0] + STR R5,[R4, #+4] + STR R0,[R4, #+8] + LDR R0,[SP, #+32] + STR R0,[R4, #+12] + STR R1,[R4, #+16] + STR R2,[R4, #+20] + STR R3,[R4, #+24] + LDR R0,[SP, #+24] + STR R0,[R4, #+28] + ADDS R4,R4,#+32 + LDR.N R0,DataTable2_5 + LDR R0,[R0, #+0] + CMP R4,R0 + BCC.N _tx_misra_trace_event_insert_4 + LDR.N R0,DataTable2_6 + LDR R4,[R0, #+0] + LDR.N R0,DataTable2_1 + STR R4,[R0, #+0] + LDR.N R0,DataTable2_7 + LDR R0,[R0, #+0] + STR R4,[R0, #+32] + LDR.N R0,DataTable2_8 + LDR R0,[R0, #+0] + CMP R0,#+0 + BEQ.N _tx_misra_trace_event_insert_0 + LDR.N R0,DataTable2_7 + LDR R0,[R0, #+0] + LDR.N R1,DataTable2_8 + LDR R1,[R1, #+0] + BLX R1 + B.N _tx_misra_trace_event_insert_0 +_tx_misra_trace_event_insert_4: + LDR.N R0,DataTable2_1 + STR R4,[R0, #+0] + LDR.N R0,DataTable2_7 + LDR R0,[R0, #+0] + STR R4,[R0, #+32] +_tx_misra_trace_event_insert_0: + POP {R0,R4-R7,PC} // return + + + .data +DataTable2_1: + .word _tx_trace_buffer_current_ptr + + .data +DataTable2_2: + .word _tx_trace_event_enable_bits + + .data +DataTable2_5: + .word _tx_trace_buffer_end_ptr + + .data +DataTable2_6: + .word _tx_trace_buffer_start_ptr + + .data +DataTable2_7: + .word _tx_trace_header_ptr + + .data +DataTable2_8: + .word _tx_trace_full_notify_function + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ULONG _tx_misra_time_stamp_get(VOID); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .text + .thumb_func +_tx_misra_time_stamp_get: + MOVS R0,#+0 + BX LR // return + +#endif + + .data +DataTable2_3: + .word _tx_thread_system_state + + .data +DataTable2_4: + .word _tx_thread_current_ptr + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** UINT _tx_misra_always_true(void); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .text + .thumb_func +_tx_misra_always_true: + MOVS R0,#+1 + BX LR // return + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** UINT _tx_misra_status_get(UINT status); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + .text + .thumb_func +_tx_misra_status_get: + MOVS R0,#+0 + BX LR // return + + +/***********************************************************************************************/ +/***********************************************************************************************/ +/** */ +/** ULONG _tx_misra_ipsr_get(void); */ +/** */ +/***********************************************************************************************/ +/***********************************************************************************************/ + + .text + .thumb_func +_tx_misra_ipsr_get: + MRS R0, IPSR + BX LR // return + + +/***********************************************************************************************/ +/***********************************************************************************************/ +/** */ +/** ULONG _tx_misra_control_get(void); */ +/** */ +/***********************************************************************************************/ +/***********************************************************************************************/ + + .text + .thumb_func +_tx_misra_control_get: + MRS R0, CONTROL + BX LR // return + + +/***********************************************************************************************/ +/***********************************************************************************************/ +/** */ +/** void _tx_misra_control_set(ULONG value); */ +/** */ +/***********************************************************************************************/ +/***********************************************************************************************/ + + .text + .thumb_func +_tx_misra_control_set: + MSR CONTROL, R0 + BX LR // return + + +#ifdef __ARM_FP + +/***********************************************************************************************/ +/***********************************************************************************************/ +/** */ +/** ULONG _tx_misra_fpccr_get(void); */ +/** */ +/***********************************************************************************************/ +/***********************************************************************************************/ + + .text + .thumb_func +_tx_misra_fpccr_get: + LDR r0, =0xE000EF34 // Build FPCCR address + LDR r0, [r0] // Load FPCCR value + BX LR // return + + +/***********************************************************************************************/ +/***********************************************************************************************/ +/** */ +/** void _tx_misra_vfp_touch(void); */ +/** */ +/***********************************************************************************************/ +/***********************************************************************************************/ + + .text + .thumb_func +_tx_misra_vfp_touch: + vmov.f32 s0, s0 + BX LR // return + +#endif + + + .data + .word 0 diff --git a/ports/cortex_m52/gnu/src/tx_thread_context_restore.S b/ports/cortex_m52/gnu/src/tx_thread_context_restore.S new file mode 100644 index 000000000..ffcfed465 --- /dev/null +++ b/ports/cortex_m52/gnu/src/tx_thread_context_restore.S @@ -0,0 +1,81 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + +#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)) + .global _tx_execution_isr_exit +#endif +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_context_restore Cortex-M52/GNU */ +/* 6.2.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is not needed for Cortex-M. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* [_tx_execution_isr_exit] Execution profiling ISR exit */ +/* */ +/* CALLED BY */ +/* */ +/* ISRs Interrupt Service Routines */ +/* */ +/**************************************************************************/ +// VOID _tx_thread_context_restore(VOID) +// { + .section .text + .balign 4 + .syntax unified + .eabi_attribute Tag_ABI_align_preserved, 1 + .global _tx_thread_context_restore + .thumb_func +.type _tx_thread_context_restore, function +_tx_thread_context_restore: + +#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)) + /* Call the ISR exit function to indicate an ISR is complete. */ + PUSH {r0, lr} // Save return address + BL _tx_execution_isr_exit // Call the ISR exit function + POP {r0, lr} // Recover return address +#endif + + BX lr +// } + .end diff --git a/ports/cortex_m52/gnu/src/tx_thread_context_save.S b/ports/cortex_m52/gnu/src/tx_thread_context_save.S new file mode 100644 index 000000000..e1d44619d --- /dev/null +++ b/ports/cortex_m52/gnu/src/tx_thread_context_save.S @@ -0,0 +1,81 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + +#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)) + .global _tx_execution_isr_enter +#endif +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_context_save Cortex-M52/GNU */ +/* 6.2.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is not needed for Cortex-M. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* [_tx_execution_isr_enter] Execution profiling ISR enter */ +/* */ +/* CALLED BY */ +/* */ +/* ISRs */ +/* */ +/**************************************************************************/ +// VOID _tx_thread_context_save(VOID) +// { + .section .text + .balign 4 + .syntax unified + .eabi_attribute Tag_ABI_align_preserved, 1 + .global _tx_thread_context_save + .thumb_func +.type _tx_thread_context_save, function +_tx_thread_context_save: + +#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)) + /* Call the ISR enter function to indicate an ISR is starting. */ + PUSH {r0, lr} // Save return address + BL _tx_execution_isr_enter // Call the ISR enter function + POP {r0, lr} // Recover return address +#endif + + BX lr +// } + .end diff --git a/ports/cortex_m52/gnu/src/tx_thread_interrupt_control.S b/ports/cortex_m52/gnu/src/tx_thread_interrupt_control.S new file mode 100644 index 000000000..2f304ba45 --- /dev/null +++ b/ports/cortex_m52/gnu/src/tx_thread_interrupt_control.S @@ -0,0 +1,79 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_interrupt_control Cortex-M52/GNU */ +/* 6.2.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is responsible for changing the interrupt lockout */ +/* posture of the system. */ +/* */ +/* INPUT */ +/* */ +/* new_posture New interrupt lockout posture */ +/* */ +/* OUTPUT */ +/* */ +/* old_posture Old interrupt lockout posture */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/**************************************************************************/ +// UINT _tx_thread_interrupt_control(UINT new_posture) +// { + .section .text + .balign 4 + .eabi_attribute Tag_ABI_align_preserved, 1 + .global _tx_thread_interrupt_control + .thumb_func +.type _tx_thread_interrupt_control, function +_tx_thread_interrupt_control: +#ifdef TX_PORT_USE_BASEPRI + MRS r1, BASEPRI // Pickup current interrupt posture + MSR BASEPRI, r0 // Apply the new interrupt posture + MOV r0, r1 // Transfer old to return register +#else + MRS r1, PRIMASK // Pickup current interrupt lockout + MSR PRIMASK, r0 // Apply the new interrupt lockout + MOV r0, r1 // Transfer old to return register +#endif + BX lr // Return to caller +// } + .end diff --git a/ports/cortex_m52/gnu/src/tx_thread_interrupt_disable.S b/ports/cortex_m52/gnu/src/tx_thread_interrupt_disable.S new file mode 100644 index 000000000..be6e1e87d --- /dev/null +++ b/ports/cortex_m52/gnu/src/tx_thread_interrupt_disable.S @@ -0,0 +1,80 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_interrupt_disable Cortex-M52/GNU */ +/* 6.2.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is responsible for disabling interrupts and returning */ +/* the previous interrupt lockout posture. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* old_posture Old interrupt lockout posture */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/**************************************************************************/ +// UINT _tx_thread_interrupt_disable(VOID) +// { + .section .text + .balign 4 + .syntax unified + .eabi_attribute Tag_ABI_align_preserved, 1 + .global _tx_thread_interrupt_disable + .thumb_func +.type _tx_thread_interrupt_disable, function +_tx_thread_interrupt_disable: + /* Return current interrupt lockout posture. */ +#ifdef TX_PORT_USE_BASEPRI + MRS r0, BASEPRI + LDR r1, =TX_PORT_BASEPRI + MSR BASEPRI, r1 +#else + MRS r0, PRIMASK + CPSID i +#endif + BX lr +// } + .end diff --git a/ports/cortex_m52/gnu/src/tx_thread_interrupt_restore.S b/ports/cortex_m52/gnu/src/tx_thread_interrupt_restore.S new file mode 100644 index 000000000..994bc6209 --- /dev/null +++ b/ports/cortex_m52/gnu/src/tx_thread_interrupt_restore.S @@ -0,0 +1,77 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_interrupt_restore Cortex-M52/GNU */ +/* 6.2.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is responsible for restoring the previous */ +/* interrupt lockout posture. */ +/* */ +/* INPUT */ +/* */ +/* previous_posture Previous interrupt posture */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/**************************************************************************/ +// VOID _tx_thread_interrupt_restore(UINT previous_posture) +// { + .section .text + .balign 4 + .syntax unified + .eabi_attribute Tag_ABI_align_preserved, 1 + .global _tx_thread_interrupt_restore + .thumb_func +.type _tx_thread_interrupt_restore, function +_tx_thread_interrupt_restore: + /* Restore previous interrupt lockout posture. */ +#ifdef TX_PORT_USE_BASEPRI + MSR BASEPRI, r0 +#else + MSR PRIMASK, r0 +#endif + BX lr +// } + .end diff --git a/ports/cortex_m52/gnu/src/tx_thread_schedule.S b/ports/cortex_m52/gnu/src/tx_thread_schedule.S new file mode 100644 index 000000000..736f084b2 --- /dev/null +++ b/ports/cortex_m52/gnu/src/tx_thread_schedule.S @@ -0,0 +1,379 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ +// Some portions generated by Codex (GPT-5). + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_schedule Cortex-M52/GNU */ +/* 6.2.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function waits for a thread control block pointer to appear in */ +/* the _tx_thread_execute_ptr variable. Once a thread pointer appears */ +/* in the variable, the corresponding thread is resumed. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_initialize_kernel_enter ThreadX entry function */ +/* _tx_thread_system_return Return to system from thread */ +/* */ +/**************************************************************************/ +// VOID _tx_thread_schedule(VOID) +// { + .section .text + .balign 4 + .syntax unified + .eabi_attribute Tag_ABI_align_preserved, 1 + .global _tx_thread_schedule + .thumb_func +.type _tx_thread_schedule, function +_tx_thread_schedule: + /* This function should only ever be called on Cortex-M + from the first schedule request. Subsequent scheduling occurs + from the PendSV handling routine below. */ + + /* Clear the preempt-disable flag to enable rescheduling after initialization on Cortex-M targets. */ + MOV r0, #0 // Build value for TX_FALSE + LDR r2, =_tx_thread_preempt_disable // Build address of preempt disable flag + STR r0, [r2, #0] // Clear preempt disable flag + +#ifdef __ARM_FP + /* Clear CONTROL.FPCA bit so VFP registers aren't unnecessarily stacked. */ + MRS r0, CONTROL // Pickup current CONTROL register + BIC r0, r0, #4 // Clear the FPCA bit + MSR CONTROL, r0 // Setup new CONTROL register +#endif + + /* Enable interrupts */ + CPSIE i + + /* Enter the scheduler for the first time. */ + MOV r0, #0x10000000 // Load PENDSVSET bit + MOV r1, #0xE000E000 // Load NVIC base + STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR + DSB // Complete all memory accesses + ISB // Flush pipeline + + /* Wait here for the PendSV to take place. */ + +__tx_wait_here: + B __tx_wait_here // Wait for the PendSV to happen +// } + + /* Generic context switching PendSV handler. */ + + .section .text + .balign 4 + .syntax unified + .eabi_attribute Tag_ABI_align_preserved, 1 + .global PendSV_Handler + .thumb_func +.type PendSV_Handler, function + /* Get current thread value and new thread pointer. */ +PendSV_Handler: +__tx_ts_handler: + +#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)) + /* Call the thread exit function to indicate the thread is no longer executing. */ +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI + MSR BASEPRI, r1 +#else + CPSID i // Disable interrupts +#endif /* TX_PORT_USE_BASEPRI */ + PUSH {r0, lr} // Save LR (and r0 just for alignment) + BL _tx_execution_thread_exit // Call the thread exit function + POP {r0, lr} // Recover LR +#ifdef TX_PORT_USE_BASEPRI + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) + MSR BASEPRI, r0 +#else + CPSIE i // Enable interrupts +#endif /* TX_PORT_USE_BASEPRI */ +#endif /* EXECUTION PROFILE */ + + LDR r0, =_tx_thread_current_ptr // Build current thread pointer address + LDR r2, =_tx_thread_execute_ptr // Build execute thread pointer address + MOV r3, #0 // Build NULL value + LDR r1, [r0] // Pickup current thread pointer + + /* Determine if there is a current thread to finish preserving. */ + + CBZ r1, __tx_ts_new // If NULL, skip preservation + + /* Recover PSP and preserve current thread context. */ + + STR r3, [r0] // Set _tx_thread_current_ptr to NULL + MRS r12, PSP // Pickup PSP pointer (thread's stack pointer) + STMDB r12!, {r4-r11} // Save its remaining registers +#ifdef __ARM_FP + TST LR, #0x10 // Determine if the VFP extended frame is present + BNE _skip_vfp_save + VSTMDB r12!,{s16-s31} // Yes, save additional VFP registers +_skip_vfp_save: +#endif + LDR r4, =_tx_timer_time_slice // Build address of time-slice variable + STMDB r12!, {LR} // Save LR on the stack + STR r12, [r1, #8] // Save the thread stack pointer + +#if (!defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE)) + // Save secure context + LDR r5, [r1,#0x90] // Load secure stack index + CBZ r5, _skip_secure_save // Skip save if there is no secure context + PUSH {r0,r1,r2,r3} // Save scratch registers + MOV r0, r1 // Move thread ptr to r0 + BL _tx_thread_secure_stack_context_save // Save secure stack + POP {r0,r1,r2,r3} // Restore secure registers +_skip_secure_save: +#endif + + /* Determine if time-slice is active. If it isn't, skip time handling processing. */ + + LDR r5, [r4] // Pickup current time-slice + CBZ r5, __tx_ts_new // If not active, skip processing + + /* Time-slice is active, save the current thread's time-slice and clear the global time-slice variable. */ + + STR r5, [r1, #24] // Save current time-slice + + /* Clear the global time-slice. */ + + STR r3, [r4] // Clear time-slice + + /* Executing thread is now completely preserved!!! */ + +__tx_ts_new: + + /* Now we are looking for a new thread to execute! */ + +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI + MSR BASEPRI, r1 +#else + CPSID i // Disable interrupts +#endif + LDR r1, [r2] // Is there another thread ready to execute? + CBZ r1, __tx_ts_wait // No, skip to the wait processing + + /* Yes, another thread is ready for else, make the current thread the new thread. */ + + STR r1, [r0] // Setup the current thread pointer to the new thread +#ifdef TX_PORT_USE_BASEPRI + MOV r4, #0 // Disable BASEPRI masking (enable interrupts) + MSR BASEPRI, r4 +#else + CPSIE i // Enable interrupts +#endif + + /* Increment the thread run count. */ + +__tx_ts_restore: + LDR r7, [r1, #4] // Pickup the current thread run count + LDR r4, =_tx_timer_time_slice // Build address of time-slice variable + LDR r5, [r1, #24] // Pickup thread's current time-slice + ADD r7, r7, #1 // Increment the thread run count + STR r7, [r1, #4] // Store the new run count + + /* Setup global time-slice with thread's current time-slice. */ + + STR r5, [r4] // Setup global time-slice + +#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)) + /* Call the thread entry function to indicate the thread is executing. */ + PUSH {r0, r1} // Save r0 and r1 + BL _tx_execution_thread_enter // Call the thread execution enter function + POP {r0, r1} // Recover r0 and r1 +#endif + +#if (!defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE)) + // Restore secure context + LDR r0, [r1,#0x90] // Load secure stack index + CBZ r0, _skip_secure_restore // Skip restore if there is no secure context + PUSH {r0,r1} // Save r1 (and dummy r0) + MOV r0, r1 // Move thread ptr to r0 + BL _tx_thread_secure_stack_context_restore // Restore secure stack + POP {r0,r1} // Restore r1 (and dummy r0) +_skip_secure_restore: +#endif + + /* Restore the thread context and PSP. */ + LDR r12, [r1, #12] // Get stack start + MSR PSPLIM, r12 // Set stack limit + LDR r12, [r1, #8] // Pickup thread's stack pointer + LDMIA r12!, {LR} // Pickup LR +#ifdef __ARM_FP + TST LR, #0x10 // Determine if the VFP extended frame is present + BNE _skip_vfp_restore // If not, skip VFP restore + VLDMIA r12!, {s16-s31} // Yes, restore additional VFP registers +_skip_vfp_restore: +#endif + LDMIA r12!, {r4-r11} // Recover thread's registers + MSR PSP, r12 // Setup the thread's stack pointer + + BX lr // Return to thread! + + /* The following is the idle wait processing... in this case, no threads are ready for execution and the + system will simply be idle until an interrupt occurs that makes a thread ready. Note that interrupts + are disabled to allow use of WFI for waiting for a thread to arrive. */ + +__tx_ts_wait: +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI + MSR BASEPRI, r1 +#else + CPSID i // Disable interrupts +#endif + LDR r1, [r2] // Pickup the next thread to execute pointer + STR r1, [r0] // Store it in the current pointer + CBNZ r1, __tx_ts_ready // If non-NULL, a new thread is ready! + +#ifdef TX_LOW_POWER + PUSH {r0-r3} + BL tx_low_power_enter // Possibly enter low power mode + POP {r0-r3} +#endif + +#ifdef TX_ENABLE_WFI + DSB // Ensure no outstanding memory transactions + WFI // Wait for interrupt + ISB // Ensure pipeline is flushed +#endif + +#ifdef TX_LOW_POWER + PUSH {r0-r3} + BL tx_low_power_exit // Exit low power mode + POP {r0-r3} +#endif + +#ifdef TX_PORT_USE_BASEPRI + MOV r4, #0 // Disable BASEPRI masking (enable interrupts) + MSR BASEPRI, r4 +#else + CPSIE i // Enable interrupts +#endif + B __tx_ts_wait // Loop to continue waiting + + /* At this point, we have a new thread ready to go. Clear any newly pended PendSV - since we are + already in the handler! */ +__tx_ts_ready: + MOV r7, #0x08000000 // Build clear PendSV value + MOV r8, #0xE000E000 // Build base NVIC address + STR r7, [r8, #0xD04] // Clear any PendSV + + /* Re-enable interrupts and restore new thread. */ +#ifdef TX_PORT_USE_BASEPRI + MOV r4, #0 // Disable BASEPRI masking (enable interrupts) + MSR BASEPRI, r4 +#else + CPSIE i // Enable interrupts +#endif + B __tx_ts_restore // Restore the thread +// } + + +#if (!defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE)) + // SVC_Handler is not needed when ThreadX is running in single mode. + .section .text + .balign 4 + .syntax unified + .eabi_attribute Tag_ABI_align_preserved, 1 + .global SVC_Handler + .thumb_func +.type SVC_Handler, function +SVC_Handler: + TST lr, #0x04 // Determine return stack from EXC_RETURN bit 2 + ITE EQ + MRSEQ r0, MSP // Get MSP if return stack is MSP + MRSNE r0, PSP // Get PSP if return stack is PSP + + LDR r1, [r0,#24] // Load saved PC from stack + LDRB r1, [r1,#-2] // Load SVC number + + CMP r1, #1 // Is it a secure stack allocate request? + BEQ _tx_svc_secure_alloc // Yes, go there + + CMP r1, #2 // Is it a secure stack free request? + BEQ _tx_svc_secure_free // Yes, go there + + CMP r1, #3 // Is it a secure stack init request? + BEQ _tx_svc_secure_init // Yes, go there + + // Unknown SVC argument - just return + BX lr + +_tx_svc_secure_alloc: + PUSH {r0,lr} // Save SP and EXC_RETURN + LDM r0, {r0-r3} // Load function parameters from stack + BL _tx_thread_secure_mode_stack_allocate + POP {r12,lr} // Restore SP and EXC_RETURN + STR r0,[r12] // Store function return value + BX lr +_tx_svc_secure_free: + PUSH {r0,lr} // Save SP and EXC_RETURN + LDM r0, {r0-r3} // Load function parameters from stack + BL _tx_thread_secure_mode_stack_free + POP {r12,lr} // Restore SP and EXC_RETURN + STR r0,[r12] // Store function return value + BX lr +_tx_svc_secure_init: + PUSH {r0,lr} // Save SP and EXC_RETURN + BL _tx_thread_secure_mode_stack_initialize + POP {r12,lr} // Restore SP and EXC_RETURN + BX lr +#endif // End of ifndef TX_SINGLE_MODE_SECURE, TX_SINGLE_MODE_NON_SECURE + + + .section .text + .balign 4 + .syntax unified + .eabi_attribute Tag_ABI_align_preserved, 1 + .global _tx_vfp_access + .thumb_func +.type _tx_vfp_access, function +_tx_vfp_access: +#if TX_ENABLE_FPU_SUPPORT + VMOV.F32 s0, s0 // Simply access the VFP +#endif + BX lr // Return to caller +.end diff --git a/ports/cortex_m52/gnu/src/tx_thread_secure_stack.c b/ports/cortex_m52/gnu/src/tx_thread_secure_stack.c new file mode 100644 index 000000000..48a3381f7 --- /dev/null +++ b/ports/cortex_m52/gnu/src/tx_thread_secure_stack.c @@ -0,0 +1,581 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +#include "tx_api.h" + +/* If TX_SINGLE_MODE_SECURE or TX_SINGLE_MODE_NON_SECURE is defined, + no secure stack functionality is needed. */ +#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE) + +#define TX_SOURCE_CODE + +#include "tx_secure_interface.h" /* Interface for NS code. */ + +/* Minimum size of secure stack. */ +#ifndef TX_THREAD_SECURE_STACK_MINIMUM +#define TX_THREAD_SECURE_STACK_MINIMUM 256 +#endif +/* Maximum size of secure stack. */ +#ifndef TX_THREAD_SECURE_STACK_MAXIMUM +#define TX_THREAD_SECURE_STACK_MAXIMUM 1024 +#endif + +/* 8 bytes added to stack size to "seal" stack. */ +#define TX_THREAD_STACK_SEAL_SIZE 8 +#define TX_THREAD_STACK_SEAL_VALUE 0xFEF5EDA5 + +/* max number of Secure context */ +#ifndef TX_MAX_SECURE_CONTEXTS +#define TX_MAX_SECURE_CONTEXTS 32 +#endif +#define TX_INVALID_SECURE_CONTEXT_IDX (-1) + +/* Secure stack info struct to hold stack start, stack limit, + current stack pointer, and pointer to owning thread. + This will be allocated for each thread with a secure stack. */ +typedef struct TX_THREAD_SECURE_STACK_INFO_STRUCT +{ + VOID *tx_thread_secure_stack_ptr; /* Thread's secure stack current pointer */ + VOID *tx_thread_secure_stack_start; /* Thread's secure stack start address */ + VOID *tx_thread_secure_stack_limit; /* Thread's secure stack limit */ + TX_THREAD *tx_thread_ptr; /* Keep track of thread for error handling */ + INT tx_next_free_index; /* Next free index of free secure context */ +} TX_THREAD_SECURE_STACK_INFO; + +/* Static secure contexts */ +static TX_THREAD_SECURE_STACK_INFO tx_thread_secure_context[TX_MAX_SECURE_CONTEXTS]; +/* Head of free secure context */ +static INT tx_head_free_index = 0U; + + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_secure_mode_stack_initialize Cortex-M52/GNU */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function initializes secure mode to use PSP stack. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_initialize_kernel_enter */ +/* */ +/**************************************************************************/ +__attribute__((cmse_nonsecure_entry, optimize(0))) +UINT _tx_thread_secure_mode_stack_initialize(void) +{ +UINT status; +ULONG control; +ULONG ipsr; +INT index; + + /* Make sure function is called from interrupt (threads should not call). */ + asm volatile("MRS %0, IPSR" : "=r" (ipsr)); /* Get IPSR register. */ + if (ipsr == 0) + { + status = TX_CALLER_ERROR; + } + else + { + /* Set secure mode to use PSP. */ + asm volatile("MRS %0, CONTROL" : "=r" (control)); /* Get CONTROL register. */ + control |= 2; /* Use PSP. */ + asm volatile("MSR CONTROL, %0" :: "r" (control)); /* Set CONTROL register. */ + + /* Set process stack pointer and stack limit to 0 to throw exception when a thread + without a secure stack calls a secure function that tries to use secure stack. */ + asm volatile("MSR PSPLIM, %0" :: "r" (0)); + asm volatile("MSR PSP, %0" :: "r" (0)); + + for (index = 0; index < TX_MAX_SECURE_CONTEXTS; index++) + { + + /* Check last index and mark next free to invalid index */ + if(index == (TX_MAX_SECURE_CONTEXTS - 1)) + { + tx_thread_secure_context[index].tx_next_free_index = TX_INVALID_SECURE_CONTEXT_IDX; + } + else + { + tx_thread_secure_context[index].tx_next_free_index = index + 1; + } + } + + status = TX_SUCCESS; + } + return status; +} + + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_secure_mode_stack_allocate Cortex-M52/GNU */ +/* 6.1.11a */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function allocates a thread's secure stack. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Thread control block pointer */ +/* stack_size Size of stack to allocates */ +/* */ +/* OUTPUT */ +/* */ +/* TX_THREAD_ERROR Invalid thread pointer */ +/* TX_SIZE_ERROR Invalid stack size */ +/* TX_CALLER_ERROR Invalid caller of function */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* malloc Compiler's malloc function */ +/* */ +/* CALLED BY */ +/* */ +/* SVC Handler */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 09-30-2020 Scott Larson Initial Version 6.1 */ +/* 10-16-2020 Scott Larson Modified comment(s), */ +/* added stack sealing, */ +/* resulting in version 6.1.1 */ +/* 01-31-2022 Himanshu Gupta Modified comments(s), updated */ +/* secure stack allocation, */ +/* resulting in version 6.1.10 */ +/* 05-02-2022 Scott Larson Modified comment(s), added */ +/* TX_INTERRUPT_SAVE_AREA, */ +/* resulting in version 6.1.11a*/ +/* */ +/**************************************************************************/ +__attribute__((cmse_nonsecure_entry)) +UINT _tx_thread_secure_mode_stack_allocate(TX_THREAD *thread_ptr, ULONG stack_size) +{ +TX_INTERRUPT_SAVE_AREA +UINT status; +TX_THREAD_SECURE_STACK_INFO *info_ptr; +UCHAR *stack_mem; +ULONG ipsr; +ULONG psplim_ns; +INT secure_context_index; + + status = TX_SUCCESS; + + /* Make sure function is called from interrupt (threads should not call). */ + asm volatile("MRS %0, IPSR" : "=r" (ipsr)); /* Get IPSR register. */ + if (ipsr == 0) + { + status = TX_CALLER_ERROR; + } + else if (stack_size < TX_THREAD_SECURE_STACK_MINIMUM || stack_size > TX_THREAD_SECURE_STACK_MAXIMUM) + { + status = TX_SIZE_ERROR; + } + + /* Check if thread already has secure stack allocated. */ + else if (thread_ptr -> tx_thread_secure_stack_context != 0) + { + status = TX_THREAD_ERROR; + } + + else + { + TX_DISABLE + + /* Allocate free index for secure stack info. */ + if(tx_head_free_index != TX_INVALID_SECURE_CONTEXT_IDX) + { + secure_context_index = tx_head_free_index; + tx_head_free_index = tx_thread_secure_context[tx_head_free_index].tx_next_free_index; + tx_thread_secure_context[secure_context_index].tx_next_free_index = TX_INVALID_SECURE_CONTEXT_IDX; + } + else + { + secure_context_index = TX_INVALID_SECURE_CONTEXT_IDX; + } + + TX_RESTORE + + if(secure_context_index != TX_INVALID_SECURE_CONTEXT_IDX) + { + info_ptr = &tx_thread_secure_context[secure_context_index]; + + /* If stack info allocated, allocate a stack & seal. */ + stack_mem = malloc(stack_size + TX_THREAD_STACK_SEAL_SIZE); + + if(stack_mem != TX_NULL) + { + /* Secure stack has been allocated, save in the stack info struct. */ + info_ptr -> tx_thread_secure_stack_limit = stack_mem; + info_ptr -> tx_thread_secure_stack_start = stack_mem + stack_size; + info_ptr -> tx_thread_secure_stack_ptr = info_ptr -> tx_thread_secure_stack_start; + info_ptr -> tx_thread_ptr = thread_ptr; + + /* Seal bottom of stack. */ + *(ULONG*)info_ptr -> tx_thread_secure_stack_start = TX_THREAD_STACK_SEAL_VALUE; + + /* Save secure context id (i.e non-zero base index) in thread. */ + thread_ptr -> tx_thread_secure_stack_context = (VOID *)(secure_context_index + 1); + + /* Check if this thread is running by looking at its stack start and PSPLIM_NS */ + asm volatile("MRS %0, PSPLIM_NS" : "=r" (psplim_ns)); /* Get PSPLIM_NS register. */ + if(((ULONG) thread_ptr -> tx_thread_stack_start & 0xFFFFFFF8) == psplim_ns) + { + /* If this thread is running, set Secure PSP and PSPLIM. */ + asm volatile("MSR PSPLIM, %0" :: "r" ((ULONG)(info_ptr -> tx_thread_secure_stack_limit))); + asm volatile("MSR PSP, %0" :: "r" ((ULONG)(info_ptr -> tx_thread_secure_stack_ptr))); + } + } + + else + { + TX_DISABLE + + /* Stack not allocated, free the info struct. */ + tx_thread_secure_context[secure_context_index].tx_next_free_index = tx_head_free_index; + tx_head_free_index = secure_context_index; + TX_RESTORE + + status = TX_NO_MEMORY; + } + } + + else + { + status = TX_NO_MEMORY; + } + } + + return(status); +} + + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_secure_mode_stack_free Cortex-M52/GNU */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function frees a thread's secure stack. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Thread control block pointer */ +/* */ +/* OUTPUT */ +/* */ +/* TX_THREAD_ERROR Invalid thread pointer */ +/* TX_CALLER_ERROR Invalid caller of function */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* free Compiler's free() function */ +/* */ +/* CALLED BY */ +/* */ +/* SVC Handler */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 09-30-2020 Scott Larson Initial Version 6.1 */ +/* 10-16-2020 Scott Larson Modified comment(s), */ +/* resulting in version 6.1.1 */ +/* 01-31-2022 Himanshu Gupta Modified comments(s), updated */ +/* secure stack allocation, */ +/* resulting in version 6.1.10 */ +/* */ +/**************************************************************************/ +__attribute__((cmse_nonsecure_entry)) +UINT _tx_thread_secure_mode_stack_free(TX_THREAD *thread_ptr) +{ +TX_INTERRUPT_SAVE_AREA +UINT status; +TX_THREAD_SECURE_STACK_INFO *info_ptr; +ULONG ipsr; +INT secure_context_index; + + status = TX_SUCCESS; + + /* Pickup stack info id from thread. */ + secure_context_index = (INT)thread_ptr -> tx_thread_secure_stack_context - 1; + + /* Make sure function is called from interrupt (threads should not call). */ + asm volatile("MRS %0, IPSR" : "=r" (ipsr)); /* Get IPSR register. */ + if (ipsr == 0) + { + status = TX_CALLER_ERROR; + } + + /* Check if secure context index is in valid range. */ + else if (secure_context_index < 0 || secure_context_index >= TX_MAX_SECURE_CONTEXTS) + { + status = TX_THREAD_ERROR; + } + else + { + + /* Pickup stack info from static array of secure contexts. */ + info_ptr = &tx_thread_secure_context[secure_context_index]; + + /* Check that this secure context is for this thread. */ + if (info_ptr -> tx_thread_ptr != thread_ptr) + { + status = TX_THREAD_ERROR; + } + + else + { + + /* Free secure stack. */ + free(info_ptr -> tx_thread_secure_stack_limit); + + TX_DISABLE + + /* Free info struct. */ + tx_thread_secure_context[secure_context_index].tx_next_free_index = tx_head_free_index; + tx_head_free_index = secure_context_index; + TX_RESTORE + + /* Clear secure context from thread. */ + thread_ptr -> tx_thread_secure_stack_context = 0; + } + } + + return(status); +} + + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_secure_stack_context_save Cortex-M52/GNU */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function saves context of the secure stack. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Thread control block pointer */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* PendSV Handler */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 09-30-2020 Scott Larson Initial Version 6.1 */ +/* 10-16-2020 Scott Larson Modified comment(s), */ +/* resulting in version 6.1.1 */ +/* 06-02-2021 Scott Larson Fix stack pointer save, */ +/* resulting in version 6.1.7 */ +/* 01-31-2022 Himanshu Gupta Modified comments(s), updated */ +/* secure stack allocation, */ +/* resulting in version 6.1.10 */ +/* */ +/**************************************************************************/ +__attribute__((cmse_nonsecure_entry)) +void _tx_thread_secure_stack_context_save(TX_THREAD *thread_ptr) +{ +TX_THREAD_SECURE_STACK_INFO *info_ptr; +ULONG sp; +ULONG ipsr; +INT secure_context_index = (INT)thread_ptr -> tx_thread_secure_stack_context - 1; + + /* This function should be called from scheduler only. */ + asm volatile("MRS %0, IPSR" : "=r" (ipsr)); /* Get IPSR register. */ + if (ipsr == 0) + { + return; + } + + /* Check if secure context index is in valid range. */ + else if (secure_context_index < 0 || secure_context_index >= TX_MAX_SECURE_CONTEXTS) + { + return; + } + + /* Pickup the secure context pointer. */ + info_ptr = &tx_thread_secure_context[secure_context_index]; + + /* Check that this secure context is for this thread. */ + if (info_ptr -> tx_thread_ptr != thread_ptr) + { + return; + } + + /* Check that stack pointer is in range */ + asm volatile("MRS %0, PSP" : "=r" (sp)); /* Get PSP register. */ + if ((sp < (ULONG)info_ptr -> tx_thread_secure_stack_limit) || + (sp > (ULONG)info_ptr -> tx_thread_secure_stack_start)) + { + return; + } + + /* Save stack pointer. */ + info_ptr -> tx_thread_secure_stack_ptr = (VOID *) sp; + + /* Set process stack pointer and stack limit to 0 to throw exception when a thread + without a secure stack calls a secure function that tries to use secure stack. */ + asm volatile("MSR PSPLIM, %0" :: "r" (0)); + asm volatile("MSR PSP, %0" :: "r" (0)); + + return; +} + + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_secure_stack_context_restore Cortex-M52/GNU */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function restores context of the secure stack. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Thread control block pointer */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* PendSV Handler */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 09-30-2020 Scott Larson Initial Version 6.1 */ +/* 10-16-2020 Scott Larson Modified comment(s), */ +/* resulting in version 6.1.1 */ +/* 01-31-2022 Himanshu Gupta Modified comments(s), updated */ +/* secure stack allocation, */ +/* resulting in version 6.1.10 */ +/* */ +/**************************************************************************/ +__attribute__((cmse_nonsecure_entry)) +void _tx_thread_secure_stack_context_restore(TX_THREAD *thread_ptr) +{ +TX_THREAD_SECURE_STACK_INFO *info_ptr; +ULONG ipsr; +INT secure_context_index = (INT)thread_ptr -> tx_thread_secure_stack_context - 1; + + /* This function should be called from scheduler only. */ + asm volatile("MRS %0, IPSR" : "=r" (ipsr)); /* Get IPSR register. */ + if (ipsr == 0) + { + return; + } + + /* Check if secure context index is in valid range. */ + else if (secure_context_index < 0 || secure_context_index >= TX_MAX_SECURE_CONTEXTS) + { + return; + } + + /* Pickup the secure context pointer. */ + info_ptr = &tx_thread_secure_context[secure_context_index]; + + /* Check that this secure context is for this thread. */ + if (info_ptr -> tx_thread_ptr != thread_ptr) + { + return; + } + + /* Set stack pointer and limit. */ + asm volatile("MSR PSPLIM, %0" :: "r" ((ULONG)info_ptr -> tx_thread_secure_stack_limit)); + asm volatile("MSR PSP, %0" :: "r" ((ULONG)info_ptr -> tx_thread_secure_stack_ptr)); + + return; +} + +#endif diff --git a/ports/cortex_m52/gnu/src/tx_thread_secure_stack_allocate.S b/ports/cortex_m52/gnu/src/tx_thread_secure_stack_allocate.S new file mode 100644 index 000000000..e49e3986a --- /dev/null +++ b/ports/cortex_m52/gnu/src/tx_thread_secure_stack_allocate.S @@ -0,0 +1,82 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_secure_stack_allocate Cortex-M52/GNU */ +/* 6.2.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function enters the SVC handler to allocate a secure stack. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Thread control block pointer */ +/* stack_size Size of secure stack to */ +/* allocate */ +/* */ +/* OUTPUT */ +/* */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* SVC 1 */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/**************************************************************************/ +// UINT _tx_thread_secure_stack_allocate(TX_THREAD *thread_ptr, ULONG stack_size) +// { + .section .text + .balign 4 + .syntax unified + .eabi_attribute Tag_ABI_align_preserved, 1 + .global _tx_thread_secure_stack_allocate + .thumb_func +.type _tx_thread_secure_stack_allocate, function +_tx_thread_secure_stack_allocate: +#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE) + MRS r3, PRIMASK // Save interrupt mask + CPSIE i // Enable interrupts for SVC call + SVC 1 + CMP r3, #0 // If interrupts enabled, just return + BEQ _alloc_return_interrupt_enabled + CPSID i // Otherwise, disable interrupts +#else + MOV r0, #0xFF // Feature not enabled +#endif +_alloc_return_interrupt_enabled: + BX lr + .end diff --git a/ports/cortex_m52/gnu/src/tx_thread_secure_stack_free.S b/ports/cortex_m52/gnu/src/tx_thread_secure_stack_free.S new file mode 100644 index 000000000..35f9b5199 --- /dev/null +++ b/ports/cortex_m52/gnu/src/tx_thread_secure_stack_free.S @@ -0,0 +1,80 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_secure_stack_free Cortex-M52/GNU */ +/* 6.2.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function enters the SVC handler to free a secure stack. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Thread control block pointer */ +/* */ +/* OUTPUT */ +/* */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* SVC 2 */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/**************************************************************************/ +// UINT _tx_thread_secure_stack_free(TX_THREAD *thread_ptr) +// { + .section .text + .balign 4 + .syntax unified + .eabi_attribute Tag_ABI_align_preserved, 1 + .global _tx_thread_secure_stack_free + .thumb_func +.type _tx_thread_secure_stack_free, function +_tx_thread_secure_stack_free: +#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE) + MRS r3, PRIMASK // Save interrupt mask + CPSIE i // Enable interrupts for SVC call + SVC 2 + CMP r3, #0 // If interrupts enabled, just return + BEQ _free_return_interrupt_enabled + CPSID i // Otherwise, disable interrupts +#else + MOV r0, #0xFF // Feature not enabled +#endif +_free_return_interrupt_enabled: + BX lr + .end diff --git a/ports/cortex_m52/gnu/src/tx_thread_secure_stack_initialize.S b/ports/cortex_m52/gnu/src/tx_thread_secure_stack_initialize.S new file mode 100644 index 000000000..4dc61ea27 --- /dev/null +++ b/ports/cortex_m52/gnu/src/tx_thread_secure_stack_initialize.S @@ -0,0 +1,76 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_secure_stack_initialize Cortex-M52/GNU */ +/* 6.2.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function enters the SVC handler to initialize a secure stack. */ +/* */ +/* INPUT */ +/* */ +/* none */ +/* */ +/* OUTPUT */ +/* */ +/* none */ +/* */ +/* CALLS */ +/* */ +/* SVC 3 */ +/* */ +/* CALLED BY */ +/* */ +/* TX_PORT_SPECIFIC_PRE_INITIALIZATION */ +/* */ +/**************************************************************************/ +// VOID _tx_thread_secure_stack_initialize(VOID) +// { + .section .text + .balign 4 + .syntax unified + .eabi_attribute Tag_ABI_align_preserved, 1 + .global _tx_thread_secure_stack_initialize + .thumb_func +.type _tx_thread_secure_stack_initialize, function +_tx_thread_secure_stack_initialize: +#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE) + CPSIE i // Enable interrupts for SVC call + SVC 3 + CPSID i // Disable interrupts +#else + MOV r0, #0xFF // Feature not enabled +#endif + BX lr + .end diff --git a/ports/cortex_m52/gnu/src/tx_thread_stack_build.S b/ports/cortex_m52/gnu/src/tx_thread_stack_build.S new file mode 100644 index 000000000..a61b5b126 --- /dev/null +++ b/ports/cortex_m52/gnu/src/tx_thread_stack_build.S @@ -0,0 +1,137 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_stack_build Cortex-M52/GNU */ +/* 6.2.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function builds a stack frame on the supplied thread's stack. */ +/* The stack frame results in a fake interrupt return to the supplied */ +/* function pointer. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Pointer to thread control blk */ +/* function_ptr Pointer to return function */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_thread_create Create thread service */ +/* */ +/**************************************************************************/ +// VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID)) +// { + .section .text + .balign 4 + .syntax unified + .eabi_attribute Tag_ABI_align_preserved, 1 + .global _tx_thread_stack_build + .thumb_func +.type _tx_thread_stack_build, function +_tx_thread_stack_build: + /* Build a fake interrupt frame. The form of the fake interrupt stack + on the Cortex-M should look like the following after it is built: + + Stack Top: + LR Interrupted LR (LR at time of PENDSV) + r4 Initial value for r4 + r5 Initial value for r5 + r6 Initial value for r6 + r7 Initial value for r7 + r8 Initial value for r8 + r9 Initial value for r9 + r10 Initial value for r10 + r11 Initial value for r11 + r0 Initial value for r0 (Hardware stack starts here!!) + r1 Initial value for r1 + r2 Initial value for r2 + r3 Initial value for r3 + r12 Initial value for r12 + lr Initial value for lr + pc Initial value for pc + xPSR Initial value for xPSR + + Stack Bottom: (higher memory address) */ + + LDR r2, [r0, #16] // Pickup end of stack area + BIC r2, r2, #0x7 // Align frame for 8-byte alignment + SUB r2, r2, #68 // Subtract frame size +#ifdef TX_SINGLE_MODE_SECURE + LDR r3, =0xFFFFFFFD // Build initial LR value for secure mode +#else + LDR r3, =0xFFFFFFBC // Build initial LR value to return to non-secure PSP +#endif + STR r3, [r2, #0] // Save on the stack + + /* Actually build the stack frame. */ + + MOV r3, #0 // Build initial register value + STR r3, [r2, #4] // Store initial r4 + STR r3, [r2, #8] // Store initial r5 + STR r3, [r2, #12] // Store initial r6 + STR r3, [r2, #16] // Store initial r7 + STR r3, [r2, #20] // Store initial r8 + STR r3, [r2, #24] // Store initial r9 + STR r3, [r2, #28] // Store initial r10 + STR r3, [r2, #32] // Store initial r11 + + /* Hardware stack follows. */ + + STR r3, [r2, #36] // Store initial r0 + STR r3, [r2, #40] // Store initial r1 + STR r3, [r2, #44] // Store initial r2 + STR r3, [r2, #48] // Store initial r3 + STR r3, [r2, #52] // Store initial r12 + MOV r3, #0xFFFFFFFF // Poison EXC_RETURN value + STR r3, [r2, #56] // Store initial lr + STR r1, [r2, #60] // Store initial pc + MOV r3, #0x01000000 // Only T-bit need be set + STR r3, [r2, #64] // Store initial xPSR + + /* Setup stack pointer. */ + // thread_ptr -> tx_thread_stack_ptr = r2; + + STR r2, [r0, #8] // Save stack pointer in thread's + // control block + BX lr // Return to caller +// } + .end diff --git a/ports/cortex_m52/gnu/src/tx_thread_system_return.S b/ports/cortex_m52/gnu/src/tx_thread_system_return.S new file mode 100644 index 000000000..3051f9409 --- /dev/null +++ b/ports/cortex_m52/gnu/src/tx_thread_system_return.S @@ -0,0 +1,99 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + +// Some portions generated by Gemini (Gemini 2.0 Flash). + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_system_return Cortex-M52/GNU */ +/* 6.2.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is target processor specific. It is used to transfer */ +/* control from a thread back to the ThreadX system. Only a */ +/* minimal context is saved since the compiler assumes temp registers */ +/* are going to get slicked by a function call anyway. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_schedule Thread scheduling loop */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX components */ +/* */ +/**************************************************************************/ +// VOID _tx_thread_system_return(VOID) +// { + .section .text + .balign 4 + .syntax unified + .eabi_attribute Tag_ABI_align_preserved, 1 + .global _tx_thread_system_return + .thumb_func +.type _tx_thread_system_return, function +_tx_thread_system_return: + /* Return to real scheduler via PendSV. Note that this routine is often + replaced with in-line assembly in tx_port.h to improved performance. */ + + MOV r0, #0x10000000 // Load PENDSVSET bit + MOV r1, #0xE000E000 // Load NVIC base + STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR + DSB #0xF // Ensure memory access is complete + ISB #0xF // Flush pipeline + MRS r0, IPSR // Pickup IPSR + CMP r0, #0 // Is it a thread returning? + BNE _isr_context // If ISR, skip interrupt enable +#ifdef TX_PORT_USE_BASEPRI + MRS r1, BASEPRI // Thread context returning, pickup BASEPRI + MOV r0, #0 + MSR BASEPRI, r0 // Enable interrupts + MSR BASEPRI, r1 // Restore original interrupt posture + ISB #0xF // Flush pipeline +#else + MRS r1, PRIMASK // Thread context returning, pickup PRIMASK + CPSIE i // Enable interrupts + MSR PRIMASK, r1 // Restore original interrupt posture + ISB #0xF // Flush pipeline +#endif +_isr_context: + BX lr // Return to caller +// } + .end diff --git a/ports/cortex_m52/gnu/src/tx_timer_interrupt.S b/ports/cortex_m52/gnu/src/tx_timer_interrupt.S new file mode 100644 index 000000000..16af99fa8 --- /dev/null +++ b/ports/cortex_m52/gnu/src/tx_timer_interrupt.S @@ -0,0 +1,240 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Timer */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_timer_interrupt Cortex-M52/GNU */ +/* 6.2.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes the hardware timer interrupt. This */ +/* processing includes incrementing the system clock and checking for */ +/* time slice and/or timer expiration. If either is found, the */ +/* expiration functions are called. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _tx_timer_expiration_process Timer expiration processing */ +/* _tx_thread_time_slice Time slice interrupted thread */ +/* */ +/* CALLED BY */ +/* */ +/* interrupt vector */ +/* */ +/**************************************************************************/ +// VOID _tx_timer_interrupt(VOID) +// { + .section .text + .balign 4 + .syntax unified + .eabi_attribute Tag_ABI_align_preserved, 1 + .global _tx_timer_interrupt + .thumb_func +.type _tx_timer_interrupt, function +_tx_timer_interrupt: + + /* Upon entry to this routine, it is assumed that the compiler scratch registers are available + for use. */ + + /* Increment the system clock. */ + // _tx_timer_system_clock++; + + LDR r1, =_tx_timer_system_clock // Pickup address of system clock + LDR r0, [r1, #0] // Pickup system clock + ADD r0, r0, #1 // Increment system clock + STR r0, [r1, #0] // Store new system clock + + /* Test for time-slice expiration. */ + // if (_tx_timer_time_slice) + // { + + LDR r3, =_tx_timer_time_slice // Pickup address of time-slice + LDR r2, [r3, #0] // Pickup time-slice + CBZ r2, __tx_timer_no_time_slice // Is it non-active? + // Yes, skip time-slice processing + + /* Decrement the time_slice. */ + // _tx_timer_time_slice--; + + SUB r2, r2, #1 // Decrement the time-slice + STR r2, [r3, #0] // Store new time-slice value + + /* Check for expiration. */ + // if (__tx_timer_time_slice == 0) + + CBNZ r2, __tx_timer_no_time_slice // Has it expired? + // No, skip expiration processing + + /* Set the time-slice expired flag. */ + // _tx_timer_expired_time_slice = TX_TRUE; + + LDR r3, =_tx_timer_expired_time_slice // Pickup address of expired flag + MOV r0, #1 // Build expired value + STR r0, [r3, #0] // Set time-slice expiration flag + + // } + +__tx_timer_no_time_slice: + + /* Test for timer expiration. */ + // if (*_tx_timer_current_ptr) + // { + + LDR r1, =_tx_timer_current_ptr // Pickup current timer pointer address + LDR r0, [r1, #0] // Pickup current timer + LDR r2, [r0, #0] // Pickup timer list entry + CBZ r2, __tx_timer_no_timer // Is there anything in the list? + // No, just increment the timer + + /* Set expiration flag. */ + // _tx_timer_expired = TX_TRUE; + + LDR r3, =_tx_timer_expired // Pickup expiration flag address + MOV r2, #1 // Build expired value + STR r2, [r3, #0] // Set expired flag + B __tx_timer_done // Finished timer processing + + // } + // else + // { +__tx_timer_no_timer: + + /* No timer expired, increment the timer pointer. */ + // _tx_timer_current_ptr++; + + ADD r0, r0, #4 // Move to next timer + + /* Check for wrap-around. */ + // if (_tx_timer_current_ptr == _tx_timer_list_end) + + LDR r3, =_tx_timer_list_end // Pickup addr of timer list end + LDR r2, [r3, #0] // Pickup list end + CMP r0, r2 // Are we at list end? + BNE __tx_timer_skip_wrap // No, skip wrap-around logic + + /* Wrap to beginning of list. */ + // _tx_timer_current_ptr = _tx_timer_list_start; + + LDR r3, =_tx_timer_list_start // Pickup addr of timer list start + LDR r0, [r3, #0] // Set current pointer to list start + +__tx_timer_skip_wrap: + + STR r0, [r1, #0] // Store new current timer pointer + // } + +__tx_timer_done: + + /* See if anything has expired. */ + // if ((_tx_timer_expired_time_slice) || (_tx_timer_expired)) + // { + + LDR r3, =_tx_timer_expired_time_slice // Pickup addr of expired flag + LDR r2, [r3, #0] // Pickup time-slice expired flag + CBNZ r2, __tx_something_expired // Did a time-slice expire? + // If non-zero, time-slice expired + LDR r1, =_tx_timer_expired // Pickup addr of other expired flag + LDR r0, [r1, #0] // Pickup timer expired flag + CBZ r0, __tx_timer_nothing_expired // Did a timer expire? + // No, nothing expired + +__tx_something_expired: + + PUSH {r0, lr} // Save the lr register on the stack + // and save r0 just to keep 8-byte alignment + + /* Did a timer expire? */ + // if (_tx_timer_expired) + // { + + LDR r1, =_tx_timer_expired // Pickup addr of expired flag + LDR r0, [r1, #0] // Pickup timer expired flag + CBZ r0, __tx_timer_dont_activate // Check for timer expiration + // If not set, skip timer activation + + /* Process timer expiration. */ + // _tx_timer_expiration_process(); + + BL _tx_timer_expiration_process // Call the timer expiration handling routine + + // } +__tx_timer_dont_activate: + + /* Did time slice expire? */ + // if (_tx_timer_expired_time_slice) + // { + + LDR r3, =_tx_timer_expired_time_slice // Pickup addr of time-slice expired + LDR r2, [r3, #0] // Pickup the actual flag + CBZ r2, __tx_timer_not_ts_expiration // See if the flag is set + // No, skip time-slice processing + + /* Time slice interrupted thread. */ + // _tx_thread_time_slice(); + + BL _tx_thread_time_slice // Call time-slice processing + LDR r0, =_tx_thread_preempt_disable // Build address of preempt disable flag + LDR r1, [r0] // Is the preempt disable flag set? + CBNZ r1, __tx_timer_skip_time_slice // Yes, skip the PendSV logic + LDR r0, =_tx_thread_current_ptr // Build current thread pointer address + LDR r1, [r0] // Pickup the current thread pointer + LDR r2, =_tx_thread_execute_ptr // Build execute thread pointer address + LDR r3, [r2] // Pickup the execute thread pointer + LDR r0, =0xE000ED04 // Build address of control register + LDR r2, =0x10000000 // Build value for PendSV bit + CMP r1, r3 // Are they the same? + BEQ __tx_timer_skip_time_slice // If the same, there was no time-slice performed + STR r2, [r0] // Not the same, issue the PendSV for preemption +__tx_timer_skip_time_slice: + // } + +__tx_timer_not_ts_expiration: + + POP {r0, lr} // Recover lr register (r0 is just there for + // the 8-byte stack alignment + + // } + +__tx_timer_nothing_expired: + + DSB // Complete all memory access + BX lr // Return to caller +// } + .end diff --git a/ports/cortex_m52/gnu/src/txe_thread_secure_stack_allocate.c b/ports/cortex_m52/gnu/src/txe_thread_secure_stack_allocate.c new file mode 100644 index 000000000..a37436dd7 --- /dev/null +++ b/ports/cortex_m52/gnu/src/txe_thread_secure_stack_allocate.c @@ -0,0 +1,113 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_initialize.h" +#include "tx_thread.h" + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_secure_stack_allocate Cortex-M52 */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the secure stack allocate */ +/* function call. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Thread control block pointer */ +/* stack_size Size of secure stack to */ +/* allocate */ +/* */ +/* OUTPUT */ +/* */ +/* TX_THREAD_ERROR Invalid thread pointer */ +/* TX_CALLER_ERROR Invalid caller of function */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_secure_stack_allocate Actual stack alloc function */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/**************************************************************************/ +UINT _txe_thread_secure_stack_allocate(TX_THREAD *thread_ptr, ULONG stack_size) +{ +#if defined(TX_SINGLE_MODE_SECURE) || defined(TX_SINGLE_MODE_NON_SECURE) + return(TX_FEATURE_NOT_ENABLED); +#else +UINT status; + + /* Default status to success. */ + status = TX_SUCCESS; + + /* Check for an invalid thread pointer. */ + if (thread_ptr == TX_NULL) + { + /* Thread pointer is invalid, return appropriate error code. */ + status = TX_THREAD_ERROR; + } + + /* Now check for invalid thread ID. */ + else if (thread_ptr -> tx_thread_id != TX_THREAD_ID) + { + /* Thread pointer is invalid, return appropriate error code. */ + status = TX_THREAD_ERROR; + } + + /* Check for interrupt call. */ + if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0)) + { + /* Is call from an interrupt and not initialization? */ + if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS) + { + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } + } + + /* Determine if everything is okay. */ + if (status == TX_SUCCESS) + { + /* Call actual secure stack allocate function. */ + status = _tx_thread_secure_stack_allocate(thread_ptr, stack_size); + } + + /* Return completion status. */ + return(status); +#endif +} diff --git a/ports/cortex_m52/gnu/src/txe_thread_secure_stack_free.c b/ports/cortex_m52/gnu/src/txe_thread_secure_stack_free.c new file mode 100644 index 000000000..b7e4b7d5c --- /dev/null +++ b/ports/cortex_m52/gnu/src/txe_thread_secure_stack_free.c @@ -0,0 +1,114 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_initialize.h" +#include "tx_thread.h" + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_thread_secure_stack_free Cortex-M52 */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the secure stack free */ +/* function call. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Thread control block pointer */ +/* */ +/* OUTPUT */ +/* */ +/* TX_THREAD_ERROR Invalid thread pointer */ +/* TX_CALLER_ERROR Invalid caller of function */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_secure_stack_free Actual stack free function */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/**************************************************************************/ +UINT _txe_thread_secure_stack_free(TX_THREAD *thread_ptr) +{ +#if defined(TX_SINGLE_MODE_SECURE) || defined(TX_SINGLE_MODE_NON_SECURE) + return(TX_FEATURE_NOT_ENABLED); +#else +UINT status; + + /* Default status to success. */ + status = TX_SUCCESS; + + /* Check for an invalid thread pointer. */ + if (thread_ptr == TX_NULL) + { + + /* Thread pointer is invalid, return appropriate error code. */ + status = TX_THREAD_ERROR; + } + + /* Now check for invalid thread ID. */ + else if (thread_ptr -> tx_thread_id != TX_THREAD_ID) + { + + /* Thread pointer is invalid, return appropriate error code. */ + status = TX_THREAD_ERROR; + } + + /* Check for interrupt call. */ + if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0)) + { + /* Is call from an interrupt and not initialization? */ + if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS) + { + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } + } + + /* Determine if everything is okay. */ + if (status == TX_SUCCESS) + { + + /* Call actual secure stack allocate function. */ + status = _tx_thread_secure_stack_free(thread_ptr); + } + + /* Return completion status. */ + return(status); +#endif +} diff --git a/ports/cortex_m52/iar/inc/tx_port.h b/ports/cortex_m52/iar/inc/tx_port.h new file mode 100644 index 000000000..6a3b23a6e --- /dev/null +++ b/ports/cortex_m52/iar/inc/tx_port.h @@ -0,0 +1,631 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + +// Some portions generated by Gemini (Gemini 2.0 Flash). +// Some portions generated by Claude Code (Opus 5). + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Port Specific */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* PORT SPECIFIC C INFORMATION RELEASE */ +/* */ +/* tx_port.h Cortex-M52/IAR */ +/* 6.2.1 */ +/* */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains data type definitions that make the ThreadX */ +/* real-time kernel function identically on a variety of different */ +/* processor architectures. For example, the size or number of bits */ +/* in an "int" data type vary between microprocessor architectures and */ +/* even C compilers for the same microprocessor. ThreadX does not */ +/* directly use native C data types. Instead, ThreadX creates its */ +/* own special types that can be mapped to actual data types by this */ +/* file to guarantee consistency in the interface and functionality. */ +/* */ +/* This file replaces the previous Cortex-M52 files. It unifies */ +/* the Cortex-M52 compilers into one common file. */ +/* */ +/**************************************************************************/ + +#ifndef TX_PORT_H +#define TX_PORT_H + +/* Determine if the optional ThreadX user define file should be used. */ +#ifdef TX_INCLUDE_USER_DEFINE_FILE + +/* Yes, include the user defines in tx_user.h. The defines in this file may + alternately be defined on the command line. */ + +#include "tx_user.h" +#endif /* TX_INCLUDE_USER_DEFINE_FILE */ + +/* Define compiler library include files. */ + +#include +#include + +#ifdef __ICCARM__ +#include /* IAR Intrinsics */ +#define __asm__ __asm /* Define to make all inline asm from each compiler look similar */ +#define _tx_control_get __get_CONTROL +#define _tx_control_set __set_CONTROL +#define _tx_ipsr_get __get_IPSR +#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT +#include +#endif /* TX_ENABLE_IAR_LIBRARY_SUPPORT */ +#endif /* __ICCARM__ */ + + +/* Define ThreadX basic types for this port. */ + +#define VOID void +typedef char CHAR; +typedef unsigned char UCHAR; +typedef int INT; +typedef unsigned int UINT; +typedef long LONG; +typedef unsigned long ULONG; +typedef unsigned long long ULONG64; +typedef short SHORT; +typedef unsigned short USHORT; +#define ULONG64_DEFINED + +/* Function prototypes for this port. */ +struct TX_THREAD_STRUCT; +UINT _txe_thread_secure_stack_allocate(struct TX_THREAD_STRUCT *thread_ptr, ULONG stack_size); +UINT _txe_thread_secure_stack_free(struct TX_THREAD_STRUCT *thread_ptr); +UINT _tx_thread_secure_stack_allocate(struct TX_THREAD_STRUCT *tx_thread, ULONG stack_size); +UINT _tx_thread_secure_stack_free(struct TX_THREAD_STRUCT *tx_thread); + +/* Define the system API mappings based on the error checking + selected by the user. Note: this section is only applicable to + application source code, hence the conditional that turns off this + stuff when the include file is processed by the ThreadX source. */ + +#ifndef TX_SOURCE_CODE + + +/* Determine if error checking is desired. If so, map API functions + to the appropriate error checking front-ends. Otherwise, map API + functions to the core functions that actually perform the work. + Note: error checking is enabled by default. */ + +#ifdef TX_DISABLE_ERROR_CHECKING + +/* Services without error checking. */ + +#define tx_thread_secure_stack_allocate _tx_thread_secure_stack_allocate +#define tx_thread_secure_stack_free _tx_thread_secure_stack_free + +#else + +/* Services with error checking. */ + +#define tx_thread_secure_stack_allocate _txe_thread_secure_stack_allocate +#define tx_thread_secure_stack_free _txe_thread_secure_stack_free + +#endif /* TX_DISABLE_ERROR_CHECKING */ +#endif /* TX_SOURCE_CODE */ + +/* This port has a usage fault handler in _tx_initialize_low_level for stack exceptions. */ +#define TX_PORT_THREAD_STACK_ERROR_HANDLING + +/* Define the priority levels for ThreadX. Legal values range + from 32 to 1024 and MUST be evenly divisible by 32. */ + +#ifndef TX_MAX_PRIORITIES +#define TX_MAX_PRIORITIES 32 +#endif + + +/* Define the minimum stack for a ThreadX thread on this processor. If the size supplied during + thread creation is less than this value, the thread create call will return an error. */ + +#ifndef TX_MINIMUM_STACK +#define TX_MINIMUM_STACK 200 /* Minimum stack size for this port */ +#endif + + +/* Define the system timer thread's default stack size and priority. These are only applicable + if TX_TIMER_PROCESS_IN_ISR is not defined. */ + +#ifndef TX_TIMER_THREAD_STACK_SIZE +#define TX_TIMER_THREAD_STACK_SIZE 1024 /* Default timer thread stack size */ +#endif + +#ifndef TX_TIMER_THREAD_PRIORITY +#define TX_TIMER_THREAD_PRIORITY 0 /* Default timer thread priority */ +#endif + +/* By default, ThreadX for Cortex-M uses the PRIMASK register to enable/disable interrupts. +If using BASEPRI is desired, define the following two symbols for both c and assembly files: +TX_PORT_USE_BASEPRI - This tells ThreadX to use BASEPRI instead of PRIMASK. +TX_PORT_BASEPRI = (priority_mask << (8 - number_priority_bits)) - this defines the maximum priority level to mask. +Any interrupt with a higher priority than priority_mask will not be masked, thus the interrupt will run. +*/ + +/* Define various constants for the ThreadX Cortex-M port. */ + +#define TX_INT_DISABLE 1 /* Disable interrupts */ +#define TX_INT_ENABLE 0 /* Enable interrupts */ + + +/* Define the clock source for trace event entry time stamp. The following two item are port specific. + For example, if the time source is at the address 0x0a800024 and is 16-bits in size, the clock + source constants would be: + +#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0x0a800024) +#define TX_TRACE_TIME_MASK 0x0000FFFFUL + +*/ + +#ifndef TX_MISRA_ENABLE +#ifndef TX_TRACE_TIME_SOURCE +#define TX_TRACE_TIME_SOURCE *((volatile ULONG *) 0xE0001004) +#endif +#else +ULONG _tx_misra_time_stamp_get(VOID); +#define TX_TRACE_TIME_SOURCE _tx_misra_time_stamp_get() +#endif + +#ifndef TX_TRACE_TIME_MASK +#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL +#endif + + +/* Define the port specific options for the _tx_build_options variable. This variable indicates + how the ThreadX library was built. */ + +#define TX_PORT_SPECIFIC_BUILD_OPTIONS (0) + + +/* Define the in-line initialization constant so that modules with in-line + initialization capabilities can prevent their initialization from being + a function call. */ + +#ifdef TX_MISRA_ENABLE +#define TX_DISABLE_INLINE +#else +#define TX_INLINE_INITIALIZATION +#endif + + +/* Determine whether or not stack checking is enabled. By default, ThreadX stack checking is + disabled. When the following is defined, ThreadX thread stack checking is enabled. If stack + checking is enabled (TX_ENABLE_STACK_CHECKING is defined), the TX_DISABLE_STACK_FILLING + define is negated, thereby forcing the stack fill which is necessary for the stack checking + logic. */ + +#ifndef TX_MISRA_ENABLE +#ifdef TX_ENABLE_STACK_CHECKING +#undef TX_DISABLE_STACK_FILLING +#endif +#endif + + +/* Define the TX_THREAD control block extensions for this port. The main reason + for the multiple macros is so that backward compatibility can be maintained with + existing ThreadX kernel awareness modules. */ + +#define TX_THREAD_EXTENSION_0 +#define TX_THREAD_EXTENSION_1 + +#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT +/* IAR library support */ +#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE) +/* ThreadX in non-secure zone with calls to secure zone. */ +#define TX_THREAD_EXTENSION_2 VOID *tx_thread_secure_stack_context; \ + VOID *tx_thread_iar_tls_pointer; +#else +/* ThreadX in only one zone. */ +#define TX_THREAD_EXTENSION_2 VOID *tx_thread_iar_tls_pointer; +#endif + +#else +/* No IAR library support */ +#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE) +/* ThreadX in non-secure zone with calls to secure zone. */ +#define TX_THREAD_EXTENSION_2 VOID *tx_thread_secure_stack_context; +#else +/* ThreadX in only one zone. */ +#define TX_THREAD_EXTENSION_2 +#endif + +#endif /* TX_ENABLE_IAR_LIBRARY_SUPPORT */ + +#define TX_THREAD_EXTENSION_3 + + +/* Define the port extensions of the remaining ThreadX objects. */ + +#define TX_BLOCK_POOL_EXTENSION +#define TX_BYTE_POOL_EXTENSION +#define TX_EVENT_FLAGS_GROUP_EXTENSION +#define TX_MUTEX_EXTENSION +#define TX_QUEUE_EXTENSION +#define TX_SEMAPHORE_EXTENSION +#define TX_TIMER_EXTENSION + + +/* Define the user extension field of the thread control block. Nothing + additional is needed for this port so it is defined as white space. */ + +#ifndef TX_THREAD_USER_EXTENSION +#define TX_THREAD_USER_EXTENSION +#endif + + +/* Define the macros for processing extensions in tx_thread_create, tx_thread_delete, + tx_thread_shell_entry, and tx_thread_terminate. */ +#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT +void *_tx_iar_create_per_thread_tls_area(void); +void _tx_iar_destroy_per_thread_tls_area(void *tls_ptr); +void __iar_Initlocks(void); +#define TX_THREAD_CREATE_EXTENSION(thread_ptr) thread_ptr -> tx_thread_iar_tls_pointer = _tx_iar_create_per_thread_tls_area(); + +#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE) +#define TX_THREAD_DELETE_EXTENSION(thread_ptr) do {_tx_iar_destroy_per_thread_tls_area(thread_ptr -> tx_thread_iar_tls_pointer); \ + thread_ptr -> tx_thread_iar_tls_pointer = TX_NULL; } while(0); \ + if(thread_ptr -> tx_thread_secure_stack_context){_tx_thread_secure_stack_free(thread_ptr);} +#else +#define TX_THREAD_DELETE_EXTENSION(thread_ptr) do {_tx_iar_destroy_per_thread_tls_area(thread_ptr -> tx_thread_iar_tls_pointer); \ + thread_ptr -> tx_thread_iar_tls_pointer = TX_NULL; } while(0); +#endif +#define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION do {__iar_Initlocks();} while(0); + +#else /* No IAR library support. */ +#define TX_THREAD_CREATE_EXTENSION(thread_ptr) +#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE) +#define TX_THREAD_DELETE_EXTENSION(thread_ptr) if(thread_ptr -> tx_thread_secure_stack_context){_tx_thread_secure_stack_free(thread_ptr);} +#else +#define TX_THREAD_DELETE_EXTENSION(thread_ptr) +#endif +#endif /* TX_ENABLE_IAR_LIBRARY_SUPPORT */ + +#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE) +/* Define the size of the secure stack for the timer thread and use the extension to allocate the secure stack. */ +#define TX_TIMER_THREAD_SECURE_STACK_SIZE 256 +#define TX_TIMER_INITIALIZE_EXTENSION(status) _tx_thread_secure_stack_allocate(&_tx_timer_thread, TX_TIMER_THREAD_SECURE_STACK_SIZE); +#endif + + +#if defined(__ARMVFP__) || defined(__ARM_PCS_VFP) || defined(__ARM_FP) || defined(__TARGET_FPU_VFP) || defined(__VFP__) + +#ifdef TX_MISRA_ENABLE + +ULONG _tx_misra_control_get(void); +void _tx_misra_control_set(ULONG value); +ULONG _tx_misra_fpccr_get(void); +void _tx_misra_vfp_touch(void); + +#else /* TX_MISRA_ENABLE not defined */ + +#ifdef __GNUC__ /* GCC and ARM Compiler 6 */ + +__attribute__( ( always_inline ) ) static inline ULONG _tx_control_get(void) +{ +ULONG control_value; + + __asm__ volatile (" MRS %0,CONTROL ": "=r" (control_value) ); + return(control_value); +} + +__attribute__( ( always_inline ) ) static inline void _tx_control_set(ULONG control_value) +{ + __asm__ volatile (" MSR CONTROL,%0": : "r" (control_value): "memory" ); +} + +#endif /* __GNUC__ */ + +/* Touch VFP register in order to flush. Works for AC6/GCC/IAR compilers. */ +#define TX_VFP_TOUCH() __asm__ volatile ("VMOV.F32 s0, s0"); + +#endif /* TX_MISRA_ENABLE */ + +/* A completed thread falls into _thread_shell_entry and we can simply deactivate the FPU via CONTROL.FPCA + in order to ensure no lazy stacking will occur. */ + +#ifndef TX_MISRA_ENABLE + +#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) { \ + ULONG _tx_vfp_state; \ + _tx_vfp_state = _tx_control_get(); \ + _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \ + _tx_control_set(_tx_vfp_state); \ + } +#else + +#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) { \ + ULONG _tx_vfp_state; \ + _tx_vfp_state = _tx_misra_control_get(); \ + _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \ + _tx_misra_control_set(_tx_vfp_state); \ + } +#endif + +/* A thread can be terminated by another thread, so we first check if it's self-terminating and not in an ISR. + If so, deactivate the FPU via CONTROL.FPCA. Otherwise we are in an interrupt or another thread is terminating + this one, so if the FPCCR.LSPACT bit is set, we need to save the CONTROL.FPCA state, touch the FPU to flush + the lazy FPU save, then restore the CONTROL.FPCA state. */ + +#ifndef TX_MISRA_ENABLE + +#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) { \ + ULONG _tx_system_state; \ + _tx_system_state = TX_THREAD_GET_SYSTEM_STATE(); \ + if ((_tx_system_state == ((ULONG) 0)) && ((thread_ptr) == _tx_thread_current_ptr)) \ + { \ + ULONG _tx_vfp_state; \ + _tx_vfp_state = _tx_control_get(); \ + _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \ + _tx_control_set(_tx_vfp_state); \ + } \ + else \ + { \ + ULONG _tx_fpccr; \ + _tx_fpccr = *((volatile ULONG *) 0xE000EF34); \ + _tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \ + if (_tx_fpccr == ((ULONG) 0x01)) \ + { \ + ULONG _tx_vfp_state; \ + _tx_vfp_state = _tx_control_get(); \ + _tx_vfp_state = _tx_vfp_state & ((ULONG) 0x4); \ + TX_VFP_TOUCH(); \ + if (_tx_vfp_state == ((ULONG) 0)) \ + { \ + _tx_vfp_state = _tx_control_get(); \ + _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \ + _tx_control_set(_tx_vfp_state); \ + } \ + } \ + } \ + } +#else + +#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) { \ + ULONG _tx_system_state; \ + _tx_system_state = TX_THREAD_GET_SYSTEM_STATE(); \ + if ((_tx_system_state == ((ULONG) 0)) && ((thread_ptr) == _tx_thread_current_ptr)) \ + { \ + ULONG _tx_vfp_state; \ + _tx_vfp_state = _tx_misra_control_get(); \ + _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \ + _tx_misra_control_set(_tx_vfp_state); \ + } \ + else \ + { \ + ULONG _tx_fpccr; \ + _tx_fpccr = _tx_misra_fpccr_get(); \ + _tx_fpccr = _tx_fpccr & ((ULONG) 0x01); \ + if (_tx_fpccr == ((ULONG) 0x01)) \ + { \ + ULONG _tx_vfp_state; \ + _tx_vfp_state = _tx_misra_control_get(); \ + _tx_vfp_state = _tx_vfp_state & ((ULONG) 0x4); \ + _tx_misra_vfp_touch(); \ + if (_tx_vfp_state == ((ULONG) 0)) \ + { \ + _tx_vfp_state = _tx_misra_control_get(); \ + _tx_vfp_state = _tx_vfp_state & ~((ULONG) 0x4); \ + _tx_misra_control_set(_tx_vfp_state); \ + } \ + } \ + } \ + } +#endif + +#else /* No VFP in use */ + +#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) +#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) + +#endif /* defined(__ARMVFP__) || defined(__ARM_PCS_VFP) || defined(__ARM_FP) || defined(__TARGET_FPU_VFP) || defined(__VFP__) */ + + +/* Define the ThreadX object creation extensions for the remaining objects. */ + +#define TX_BLOCK_POOL_CREATE_EXTENSION(pool_ptr) +#define TX_BYTE_POOL_CREATE_EXTENSION(pool_ptr) +#define TX_EVENT_FLAGS_GROUP_CREATE_EXTENSION(group_ptr) +#define TX_MUTEX_CREATE_EXTENSION(mutex_ptr) +#define TX_QUEUE_CREATE_EXTENSION(queue_ptr) +#define TX_SEMAPHORE_CREATE_EXTENSION(semaphore_ptr) +#define TX_TIMER_CREATE_EXTENSION(timer_ptr) + + +/* Define the ThreadX object deletion extensions for the remaining objects. */ + +#define TX_BLOCK_POOL_DELETE_EXTENSION(pool_ptr) +#define TX_BYTE_POOL_DELETE_EXTENSION(pool_ptr) +#define TX_EVENT_FLAGS_GROUP_DELETE_EXTENSION(group_ptr) +#define TX_MUTEX_DELETE_EXTENSION(mutex_ptr) +#define TX_QUEUE_DELETE_EXTENSION(queue_ptr) +#define TX_SEMAPHORE_DELETE_EXTENSION(semaphore_ptr) +#define TX_TIMER_DELETE_EXTENSION(timer_ptr) + + +/* Define the get system state macro. */ + +#ifndef TX_THREAD_GET_SYSTEM_STATE +#ifndef TX_MISRA_ENABLE + +#if defined(__GNUC__) /* GCC and AC6 */ +__attribute__( ( always_inline ) ) static inline UINT _tx_ipsr_get(void) +{ +UINT ipsr_value; + __asm__ volatile (" MRS %0,IPSR ": "=r" (ipsr_value) ); + return(ipsr_value); +} +#endif /* GCC and AC6 IPSR_get function. */ + +#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | _tx_ipsr_get()) + +#else /* TX_MISRA_ENABLE is defined, use MISRA function. */ +ULONG _tx_misra_ipsr_get(VOID); +#define TX_THREAD_GET_SYSTEM_STATE() (_tx_thread_system_state | _tx_misra_ipsr_get()) +#endif /* TX_MISRA_ENABLE */ +#endif /* TX_THREAD_GET_SYSTEM_STATE */ + + +/* Define the check for whether or not to call the _tx_thread_system_return function. A non-zero value + indicates that _tx_thread_system_return should not be called. This overrides the definition in tx_thread.h + for Cortex-M since so we don't waste time checking the _tx_thread_system_state variable that is always + zero after initialization for Cortex-M ports. */ + +#ifndef TX_THREAD_SYSTEM_RETURN_CHECK +#define TX_THREAD_SYSTEM_RETURN_CHECK(c) (c) = ((ULONG) _tx_thread_preempt_disable); +#endif + +#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE) +/* Initialize secure stacks for threads calling secure functions. */ +extern void _tx_thread_secure_stack_initialize(void); +#define TX_PORT_SPECIFIC_PRE_INITIALIZATION _tx_thread_secure_stack_initialize(); +#endif + +/* Define the macro to ensure _tx_thread_preempt_disable is set early in initialization in order to + prevent early scheduling on Cortex-M parts. */ + +#define TX_PORT_SPECIFIC_POST_INITIALIZATION _tx_thread_preempt_disable++; + + + + +#ifndef TX_DISABLE_INLINE + +/* Define the TX_LOWEST_SET_BIT_CALCULATE macro for each compiler. */ +#ifdef __ICCARM__ /* IAR Compiler */ +#define TX_LOWEST_SET_BIT_CALCULATE(m, b) (b) = (UINT) __CLZ(__RBIT((m))); +#elif defined(__GNUC__) /* GCC and AC6 Compiler */ +#define TX_LOWEST_SET_BIT_CALCULATE(m, b) __asm__ volatile (" RBIT %0,%1 ": "=r" (m) : "r" (m) ); \ + __asm__ volatile (" CLZ %0,%1 ": "=r" (b) : "r" (m) ); +#else +#error "Compiler not supported." +#endif + + + +/* Define the interrupt disable/restore macros. */ + +__attribute__( ( always_inline ) ) static inline UINT __get_interrupt_posture(void) +{ +UINT posture; +#ifdef TX_PORT_USE_BASEPRI + __asm__ volatile ("MRS %0, BASEPRI ": "=r" (posture)); +#else + __asm__ volatile ("MRS %0, PRIMASK ": "=r" (posture)); +#endif + return(posture); +} + +#ifdef TX_PORT_USE_BASEPRI +__attribute__( ( always_inline ) ) static inline void __set_basepri_value(UINT basepri_value) +{ + __asm__ volatile ("MSR BASEPRI,%0 ": : "r" (basepri_value) : "memory"); +} +#else +__attribute__( ( always_inline ) ) static inline void __enable_interrupts(void) +{ + __asm__ volatile ("CPSIE i": : : "memory"); +} +#endif + +__attribute__( ( always_inline ) ) static inline void __restore_interrupt(UINT int_posture) +{ +#ifdef TX_PORT_USE_BASEPRI + __set_basepri_value(int_posture); + __asm__ volatile ("" : : : "memory"); +#else + __asm__ volatile ("MSR PRIMASK,%0": : "r" (int_posture): "memory"); +#endif +} + +__attribute__( ( always_inline ) ) static inline UINT __disable_interrupts(void) +{ +UINT int_posture; + + int_posture = __get_interrupt_posture(); + +#ifdef TX_PORT_USE_BASEPRI + __set_basepri_value(TX_PORT_BASEPRI); +#else + __asm__ volatile ("CPSID i" : : : "memory"); +#endif + return(int_posture); +} + +__attribute__( ( always_inline ) ) static inline void _tx_thread_system_return_inline(void) +{ +UINT interrupt_save; + + /* Set PendSV to invoke ThreadX scheduler. */ + *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); + __asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory"); + if (_tx_ipsr_get() == 0) + { + interrupt_save = __get_interrupt_posture(); +#ifdef TX_PORT_USE_BASEPRI + __set_basepri_value(0); +#else + __enable_interrupts(); +#endif + __restore_interrupt(interrupt_save); + __asm__ volatile ("isb 0xF " : : : "memory"); + } +} + +#define TX_INTERRUPT_SAVE_AREA UINT interrupt_save; +#define TX_DISABLE interrupt_save = __disable_interrupts(); +#define TX_RESTORE __restore_interrupt(interrupt_save); + +/* Redefine _tx_thread_system_return for improved performance. */ +#define _tx_thread_system_return _tx_thread_system_return_inline + +#else /* TX_DISABLE_INLINE is defined */ + +UINT _tx_thread_interrupt_disable(VOID); +VOID _tx_thread_interrupt_restore(UINT previous_posture); + +#define TX_INTERRUPT_SAVE_AREA register UINT interrupt_save; + +#define TX_DISABLE interrupt_save = _tx_thread_interrupt_disable(); +#define TX_RESTORE _tx_thread_interrupt_restore(interrupt_save); +#endif /* TX_DISABLE_INLINE */ + +/* Define the version ID of ThreadX. This may be utilized by the application. */ + +#ifdef TX_THREAD_INIT +CHAR _tx_version_id[] = + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M52/IAR Version 6.5.1.202602a *"; +#else +#ifdef TX_MISRA_ENABLE +extern CHAR _tx_version_id[100]; +#else +extern CHAR _tx_version_id[]; +#endif +#endif + +#endif diff --git a/ports/cortex_m52/iar/inc/tx_secure_interface.h b/ports/cortex_m52/iar/inc/tx_secure_interface.h new file mode 100644 index 000000000..5ac37fbf4 --- /dev/null +++ b/ports/cortex_m52/iar/inc/tx_secure_interface.h @@ -0,0 +1,55 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* COMPONENT DEFINITION RELEASE */ +/* */ +/* tx_secure_interface.h PORTABLE C */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file defines the ThreadX secure thread stack components, */ +/* including data types and external references. */ +/* It is assumed that tx_api.h and tx_port.h have already been */ +/* included. */ +/* */ +/**************************************************************************/ + +#ifndef TX_SECURE_INTERFACE_H +#define TX_SECURE_INTERFACE_H + +/* Define internal secure thread stack function prototypes. */ + +extern UINT _tx_thread_secure_mode_stack_initialize(void); +extern UINT _tx_thread_secure_mode_stack_allocate(TX_THREAD *thread_ptr, ULONG stack_size); +extern UINT _tx_thread_secure_mode_stack_free(TX_THREAD *thread_ptr); +extern void _tx_thread_secure_stack_initialize(void); +extern void _tx_thread_secure_stack_context_save(TX_THREAD *thread_ptr); +extern void _tx_thread_secure_stack_context_restore(TX_THREAD *thread_ptr); + +#endif diff --git a/ports/cortex_m52/iar/readme_threadx.txt b/ports/cortex_m52/iar/readme_threadx.txt new file mode 100644 index 000000000..116fadead --- /dev/null +++ b/ports/cortex_m52/iar/readme_threadx.txt @@ -0,0 +1,221 @@ + Microsoft's Azure RTOS ThreadX for Cortex-M52 + + Using the IAR Tools + + +1. Building the ThreadX run-time Library + +Import all ThreadX common and port-specific source files into an IAR project. +Configure the project to build a library rather than an executable. This +results in the ThreadX run-time library file tx.a, which is needed by +the application. +Files tx_thread_stack_error_handler.c and tx_thread_stack_error_notify.c +replace the common files of the same name. + +2. Demonstration System + +No demonstration is provided because the IAR EWARM 8.50 simulator does +not simulate the Cortex-M52 correctly. + + +3. System Initialization + +The entry point in ThreadX for the Cortex-M52 using IAR tools is at label +__iar_program_start. This is defined within the IAR compiler's startup code. +In addition, this is where all static and global preset C variable +initialization processing takes place. + +The ThreadX tx_initialize_low_level.s file is responsible for setting up +various system data structures, and a periodic timer interrupt source. + +The _tx_initialize_low_level function inside of tx_initialize_low_level.s +also determines the first available address for use by the application, which +is supplied as the sole input parameter to your application definition function, +tx_application_define. To accomplish this, a section is created in +tx_initialize_low_level.s called FREE_MEM, which must be located after all +other RAM sections in memory. + + +4. Register Usage and Stack Frames + +The following defines the saved context stack frames for context switches +that occur as a result of interrupt handling or from thread-level API calls. +All suspended threads have the same stack frame in the Cortex-M52 version of +ThreadX. The top of the suspended thread's stack is pointed to by +tx_thread_stack_ptr in the associated thread control block TX_THREAD. + +Non-FPU Stack Frame: + + Stack Offset Stack Contents + + 0x00 LR Interrupted LR (LR at time of PENDSV) + 0x04 r4 Software stacked GP registers + 0x08 r5 + 0x0C r6 + 0x10 r7 + 0x14 r8 + 0x18 r9 + 0x1C r10 + 0x20 r11 + 0x24 r0 Hardware stacked registers + 0x28 r1 + 0x2C r2 + 0x30 r3 + 0x34 r12 + 0x38 lr + 0x3C pc + 0x40 xPSR + +FPU Stack Frame (only interrupted thread with FPU enabled): + + Stack Offset Stack Contents + + 0x00 LR Interrupted LR (LR at time of PENDSV) + 0x04 s16 Software stacked FPU registers + 0x08 s17 + 0x0C s18 + 0x10 s19 + 0x14 s20 + 0x18 s21 + 0x1C s22 + 0x20 s23 + 0x24 s24 + 0x28 s25 + 0x2C s26 + 0x30 s27 + 0x34 s28 + 0x38 s29 + 0x3C s30 + 0x40 s31 + 0x44 r4 Software stacked registers + 0x48 r5 + 0x4C r6 + 0x50 r7 + 0x54 r8 + 0x58 r9 + 0x5C r10 + 0x60 r11 + 0x64 r0 Hardware stacked registers + 0x68 r1 + 0x6C r2 + 0x70 r3 + 0x74 r12 + 0x78 lr + 0x7C pc + 0x80 xPSR + 0x84 s0 Hardware stacked FPU registers + 0x88 s1 + 0x8C s2 + 0x90 s3 + 0x94 s4 + 0x98 s5 + 0x9C s6 + 0xA0 s7 + 0xA4 s8 + 0xA8 s9 + 0xAC s10 + 0xB0 s11 + 0xB4 s12 + 0xB8 s13 + 0xBC s14 + 0xC0 s15 + 0xC4 fpscr + + +5. Improving Performance + +To make ThreadX and the application(s) run faster, you can enable +all compiler optimizations. + +In addition, you can eliminate the ThreadX basic API error checking by +compiling your application code with the symbol TX_DISABLE_ERROR_CHECKING +defined. + + +6. Interrupt Handling + +The Cortex-M52 vectors start at the label __vector_table and is typically defined in a +startup.s file (or similar). The application may modify the vector area according to its needs. + + +6.1 Managed Interrupts + +ISRs for Cortex-M using the IAR tools can be written completely in C (or assembly +language) without any calls to _tx_thread_context_save or _tx_thread_context_restore. +These ISRs are allowed access to the ThreadX API that is available to ISRs. + +ISRs written in C will take the form (where "your_C_isr" is an entry in the vector table): + +void your_C_isr(void) +{ + + /* ISR processing goes here, including any needed function calls. */ +} + +ISRs written in assembly language will take the form: + + PUBLIC your_assembly_isr +your_assembly_isr: + + PUSH {r0, lr} + + ; ISR processing goes here, including any needed function calls. + + POP {r0, lr} + BX lr + + +7. IAR Thread-safe Library Support + +Thread-safe support for the IAR tools is easily enabled by building the ThreadX library +and the application with TX_ENABLE_IAR_LIBRARY_SUPPORT. Also, the linker control file +should have the following line added (if not already in place): + +initialize by copy with packing = none { section __DLIB_PERTHREAD }; // Required in a multi-threaded application + + +7. IAR Thread-safe Library Support + +Thread-safe support for the IAR tools is easily enabled by building the ThreadX library +and the application with TX_ENABLE_IAR_LIBRARY_SUPPORT. Also, the linker control file +should have the following line added (if not already in place): + +initialize by copy with packing = none { section __DLIB_PERTHREAD }; // Required in a multi-threaded application + +The project options "General Options -> Library Configuration" should also have the +"Enable thread support in library" box selected. + + +8. VFP Support + +ThreadX for Cortex-M52 supports automatic ("lazy") VFP support, which means that applications threads +can simply use the VFP and ThreadX automatically maintains the VFP registers as part of the thread +context. + + +9. Revision History + +For generic code revision information, please refer to the readme_threadx_generic.txt +file, which is included in your distribution. The following details the revision +information associated with this specific port of ThreadX: + +06-02-2021 Release 6.1.7 changes: + tx_thread_secure_stack_initialize.s New file + tx_thread_schedule.s Added secure stack initialize to SVC hander + tx_thread_secure_stack.c Fixed stack pointer save, initialize in handler mode + +04-02-2021 Release 6.1.6 changes: + tx_port.h Updated macro definition + tx_thread_schedule.s Added low power support + +03-02-2021 The following files were changed/added for version 6.1.5: + tx_port.h Added ULONG64_DEFINED + +09-30-2020 Initial ThreadX 6.1 version for Cortex-M52 using IAR's ARM tools. + + +Copyright(c) 1996-2020 Microsoft Corporation + + +https://azure.com/rtos + diff --git a/ports/cortex_m52/iar/src/tx_iar.c b/ports/cortex_m52/iar/src/tx_iar.c new file mode 100644 index 000000000..238b485ee --- /dev/null +++ b/ports/cortex_m52/iar/src/tx_iar.c @@ -0,0 +1,804 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** IAR Multithreaded Library Support */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Define IAR library for tools prior to version 8. */ + +#if (__VER__ < 8000000) + + +/* IAR version 7 and below. */ + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_initialize.h" +#include "tx_thread.h" +#include "tx_mutex.h" + + +/* This implementation requires that the following macros are defined in the + tx_port.h file and is included with the following code segments: + +#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT +#include +#endif + +#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT +#define TX_THREAD_EXTENSION_2 VOID *tx_thread_iar_tls_pointer; +#else +#define TX_THREAD_EXTENSION_2 +#endif + +#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT +#define TX_THREAD_CREATE_EXTENSION(thread_ptr) thread_ptr -> tx_thread_iar_tls_pointer = __iar_dlib_perthread_allocate(); +#define TX_THREAD_DELETE_EXTENSION(thread_ptr) __iar_dlib_perthread_deallocate(thread_ptr -> tx_thread_iar_tls_pointer); \ + thread_ptr -> tx_thread_iar_tls_pointer = TX_NULL; +#define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION __iar_dlib_perthread_access(0); +#else +#define TX_THREAD_CREATE_EXTENSION(thread_ptr) +#define TX_THREAD_DELETE_EXTENSION(thread_ptr) +#endif + + This should be done automatically if TX_ENABLE_IAR_LIBRARY_SUPPORT is defined while building the ThreadX library and the + application. + + Finally, the project options General Options -> Library Configuration should have the "Enable thread support in library" box selected. +*/ + +#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT + +#include + + +#if _MULTI_THREAD + +TX_MUTEX __tx_iar_system_lock_mutexes[_MAX_LOCK]; +UINT __tx_iar_system_lock_next_free_mutex = 0; + + +/* Define error counters, just for debug purposes. */ + +UINT __tx_iar_system_lock_no_mutexes; +UINT __tx_iar_system_lock_internal_errors; +UINT __tx_iar_system_lock_isr_caller; + + +/* Define the TLS access function for the IAR library. */ + +void _DLIB_TLS_MEMORY *__iar_dlib_perthread_access(void _DLIB_TLS_MEMORY *symbp) +{ + +char _DLIB_TLS_MEMORY *p = 0; + + /* Is there a current thread? */ + if (_tx_thread_current_ptr) + p = (char _DLIB_TLS_MEMORY *) _tx_thread_current_ptr -> tx_thread_iar_tls_pointer; + else + p = (void _DLIB_TLS_MEMORY *) __segment_begin("__DLIB_PERTHREAD"); + p += __IAR_DLIB_PERTHREAD_SYMBOL_OFFSET(symbp); + return (void _DLIB_TLS_MEMORY *) p; +} + + +/* Define mutexes for IAR library. */ + +void __iar_system_Mtxinit(__iar_Rmtx *m) +{ + +UINT i; +UINT status; +TX_MUTEX *mutex_ptr; + + + /* First, find a free mutex in the list. */ + for (i = 0; i < _MAX_LOCK; i++) + { + + /* Setup a pointer to the start of the next free mutex. */ + mutex_ptr = &__tx_iar_system_lock_mutexes[__tx_iar_system_lock_next_free_mutex++]; + + /* Check for wrap-around on the next free mutex. */ + if (__tx_iar_system_lock_next_free_mutex >= _MAX_LOCK) + { + + /* Yes, set the free index back to 0. */ + __tx_iar_system_lock_next_free_mutex = 0; + } + + /* Is this mutex free? */ + if (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID) + { + + /* Yes, this mutex is free, get out of the loop! */ + break; + } + } + + /* Determine if a free mutex was found. */ + if (i >= _MAX_LOCK) + { + + /* Error! No more free mutexes! */ + + /* Increment the no mutexes error counter. */ + __tx_iar_system_lock_no_mutexes++; + + /* Set return pointer to NULL. */ + *m = TX_NULL; + + /* Return. */ + return; + } + + /* Now create the ThreadX mutex for the IAR library. */ + status = _tx_mutex_create(mutex_ptr, "IAR System Library Lock", TX_NO_INHERIT); + + /* Determine if the creation was successful. */ + if (status == TX_SUCCESS) + { + + /* Yes, successful creation, return mutex pointer. */ + *m = (VOID *) mutex_ptr; + } + else + { + + /* Increment the internal error counter. */ + __tx_iar_system_lock_internal_errors++; + + /* Return a NULL pointer to indicate an error. */ + *m = TX_NULL; + } +} + +void __iar_system_Mtxdst(__iar_Rmtx *m) +{ + + /* Simply delete the mutex. */ + _tx_mutex_delete((TX_MUTEX *) *m); +} + +void __iar_system_Mtxlock(__iar_Rmtx *m) +{ + +UINT status; + + + /* Determine the caller's context. Mutex locks are only available from initialization and + threads. */ + if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS)) + { + + /* Get the mutex. */ + status = _tx_mutex_get((TX_MUTEX *) *m, TX_WAIT_FOREVER); + + /* Check the status of the mutex release. */ + if (status) + { + + /* Internal error, increment the counter. */ + __tx_iar_system_lock_internal_errors++; + } + } + else + { + + /* Increment the ISR caller error. */ + __tx_iar_system_lock_isr_caller++; + } +} + +void __iar_system_Mtxunlock(__iar_Rmtx *m) +{ + +UINT status; + + + /* Determine the caller's context. Mutex unlocks are only available from initialization and + threads. */ + if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS)) + { + + /* Release the mutex. */ + status = _tx_mutex_put((TX_MUTEX *) *m); + + /* Check the status of the mutex release. */ + if (status) + { + + /* Internal error, increment the counter. */ + __tx_iar_system_lock_internal_errors++; + } + } + else + { + + /* Increment the ISR caller error. */ + __tx_iar_system_lock_isr_caller++; + } +} + + +#if _DLIB_FILE_DESCRIPTOR + +TX_MUTEX __tx_iar_file_lock_mutexes[_MAX_FLOCK]; +UINT __tx_iar_file_lock_next_free_mutex = 0; + + +/* Define error counters, just for debug purposes. */ + +UINT __tx_iar_file_lock_no_mutexes; +UINT __tx_iar_file_lock_internal_errors; +UINT __tx_iar_file_lock_isr_caller; + + +void __iar_file_Mtxinit(__iar_Rmtx *m) +{ + +UINT i; +UINT status; +TX_MUTEX *mutex_ptr; + + + /* First, find a free mutex in the list. */ + for (i = 0; i < _MAX_FLOCK; i++) + { + + /* Setup a pointer to the start of the next free mutex. */ + mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; + + /* Check for wrap-around on the next free mutex. */ + if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + { + + /* Yes, set the free index back to 0. */ + __tx_iar_file_lock_next_free_mutex = 0; + } + + /* Is this mutex free? */ + if (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID) + { + + /* Yes, this mutex is free, get out of the loop! */ + break; + } + } + + /* Determine if a free mutex was found. */ + if (i >= _MAX_LOCK) + { + + /* Error! No more free mutexes! */ + + /* Increment the no mutexes error counter. */ + __tx_iar_file_lock_no_mutexes++; + + /* Set return pointer to NULL. */ + *m = TX_NULL; + + /* Return. */ + return; + } + + /* Now create the ThreadX mutex for the IAR library. */ + status = _tx_mutex_create(mutex_ptr, "IAR File Library Lock", TX_NO_INHERIT); + + /* Determine if the creation was successful. */ + if (status == TX_SUCCESS) + { + + /* Yes, successful creation, return mutex pointer. */ + *m = (VOID *) mutex_ptr; + } + else + { + + /* Increment the internal error counter. */ + __tx_iar_file_lock_internal_errors++; + + /* Return a NULL pointer to indicate an error. */ + *m = TX_NULL; + } +} + +void __iar_file_Mtxdst(__iar_Rmtx *m) +{ + + /* Simply delete the mutex. */ + _tx_mutex_delete((TX_MUTEX *) *m); +} + +void __iar_file_Mtxlock(__iar_Rmtx *m) +{ + +UINT status; + + + /* Determine the caller's context. Mutex locks are only available from initialization and + threads. */ + if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS)) + { + + /* Get the mutex. */ + status = _tx_mutex_get((TX_MUTEX *) *m, TX_WAIT_FOREVER); + + /* Check the status of the mutex release. */ + if (status) + { + + /* Internal error, increment the counter. */ + __tx_iar_file_lock_internal_errors++; + } + } + else + { + + /* Increment the ISR caller error. */ + __tx_iar_file_lock_isr_caller++; + } +} + +void __iar_file_Mtxunlock(__iar_Rmtx *m) +{ + +UINT status; + + + /* Determine the caller's context. Mutex unlocks are only available from initialization and + threads. */ + if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS)) + { + + /* Release the mutex. */ + status = _tx_mutex_put((TX_MUTEX *) *m); + + /* Check the status of the mutex release. */ + if (status) + { + + /* Internal error, increment the counter. */ + __tx_iar_file_lock_internal_errors++; + } + } + else + { + + /* Increment the ISR caller error. */ + __tx_iar_file_lock_isr_caller++; + } +} +#endif /* _DLIB_FILE_DESCRIPTOR */ + +#endif /* _MULTI_THREAD */ + +#endif /* TX_ENABLE_IAR_LIBRARY_SUPPORT */ + +#else /* IAR version 8 and above. */ + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_initialize.h" +#include "tx_thread.h" +#include "tx_mutex.h" + +/* This implementation requires that the following macros are defined in the + tx_port.h file and is included with the following code segments: + +#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT +#include +#endif + +#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT +#define TX_THREAD_EXTENSION_2 VOID *tx_thread_iar_tls_pointer; +#else +#define TX_THREAD_EXTENSION_2 +#endif + +#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT +void *_tx_iar_create_per_thread_tls_area(void); +void _tx_iar_destroy_per_thread_tls_area(void *tls_ptr); +void __iar_Initlocks(void); + +#define TX_THREAD_CREATE_EXTENSION(thread_ptr) thread_ptr -> tx_thread_iar_tls_pointer = __iar_dlib_perthread_allocate(); +#define TX_THREAD_DELETE_EXTENSION(thread_ptr) do {__iar_dlib_perthread_deallocate(thread_ptr -> tx_thread_iar_tls_pointer); \ + thread_ptr -> tx_thread_iar_tls_pointer = TX_NULL; } while(0); +#define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION do {__iar_Initlocks();} while(0); +#else +#define TX_THREAD_CREATE_EXTENSION(thread_ptr) +#define TX_THREAD_DELETE_EXTENSION(thread_ptr) +#endif + + This should be done automatically if TX_ENABLE_IAR_LIBRARY_SUPPORT is defined while building the ThreadX library and the + application. + + Finally, the project options General Options -> Library Configuration should have the "Enable thread support in library" box selected. +*/ + +#ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT + +#include + + +void * __aeabi_read_tp(); + +void* _tx_iar_create_per_thread_tls_area(); +void _tx_iar_destroy_per_thread_tls_area(void *tls_ptr); + +#pragma section="__iar_tls$$DATA" + +/* Define the TLS access function for the IAR library. */ +void * __aeabi_read_tp(void) +{ + void *p = 0; + TX_THREAD *thread_ptr = _tx_thread_current_ptr; + if (thread_ptr) + { + p = thread_ptr->tx_thread_iar_tls_pointer; + } + else + { + p = __section_begin("__iar_tls$$DATA"); + } + return p; +} + +/* Define the TLS creation and destruction to use malloc/free. */ + +void* _tx_iar_create_per_thread_tls_area() +{ + UINT tls_size = __iar_tls_size(); + + /* Get memory for TLS. */ + void *p = malloc(tls_size); + + /* Initialize TLS-area and run constructors for objects in TLS */ + __iar_tls_init(p); + return p; +} + +void _tx_iar_destroy_per_thread_tls_area(void *tls_ptr) +{ + /* Destroy objects living in TLS */ + __call_thread_dtors(); + free(tls_ptr); +} + +#ifndef _MAX_LOCK +#define _MAX_LOCK 4 +#endif + +static TX_MUTEX __tx_iar_system_lock_mutexes[_MAX_LOCK]; +static UINT __tx_iar_system_lock_next_free_mutex = 0; + + +/* Define error counters, just for debug purposes. */ + +UINT __tx_iar_system_lock_no_mutexes; +UINT __tx_iar_system_lock_internal_errors; +UINT __tx_iar_system_lock_isr_caller; + + +/* Define mutexes for IAR library. */ + +void __iar_system_Mtxinit(__iar_Rmtx *m) +{ + +UINT i; +UINT status; +TX_MUTEX *mutex_ptr; + + + /* First, find a free mutex in the list. */ + for (i = 0; i < _MAX_LOCK; i++) + { + + /* Setup a pointer to the start of the next free mutex. */ + mutex_ptr = &__tx_iar_system_lock_mutexes[__tx_iar_system_lock_next_free_mutex++]; + + /* Check for wrap-around on the next free mutex. */ + if (__tx_iar_system_lock_next_free_mutex >= _MAX_LOCK) + { + + /* Yes, set the free index back to 0. */ + __tx_iar_system_lock_next_free_mutex = 0; + } + + /* Is this mutex free? */ + if (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID) + { + + /* Yes, this mutex is free, get out of the loop! */ + break; + } + } + + /* Determine if a free mutex was found. */ + if (i >= _MAX_LOCK) + { + + /* Error! No more free mutexes! */ + + /* Increment the no mutexes error counter. */ + __tx_iar_system_lock_no_mutexes++; + + /* Set return pointer to NULL. */ + *m = TX_NULL; + + /* Return. */ + return; + } + + /* Now create the ThreadX mutex for the IAR library. */ + status = _tx_mutex_create(mutex_ptr, "IAR System Library Lock", TX_NO_INHERIT); + + /* Determine if the creation was successful. */ + if (status == TX_SUCCESS) + { + + /* Yes, successful creation, return mutex pointer. */ + *m = (VOID *) mutex_ptr; + } + else + { + + /* Increment the internal error counter. */ + __tx_iar_system_lock_internal_errors++; + + /* Return a NULL pointer to indicate an error. */ + *m = TX_NULL; + } +} + +void __iar_system_Mtxdst(__iar_Rmtx *m) +{ + + /* Simply delete the mutex. */ + _tx_mutex_delete((TX_MUTEX *) *m); +} + +void __iar_system_Mtxlock(__iar_Rmtx *m) +{ + if (*m) + { + UINT status; + + /* Determine the caller's context. Mutex locks are only available from initialization and + threads. */ + if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS)) + { + + /* Get the mutex. */ + status = _tx_mutex_get((TX_MUTEX *) *m, TX_WAIT_FOREVER); + + /* Check the status of the mutex release. */ + if (status) + { + + /* Internal error, increment the counter. */ + __tx_iar_system_lock_internal_errors++; + } + } + else + { + + /* Increment the ISR caller error. */ + __tx_iar_system_lock_isr_caller++; + } + } +} + +void __iar_system_Mtxunlock(__iar_Rmtx *m) +{ + if (*m) + { + UINT status; + + /* Determine the caller's context. Mutex unlocks are only available from initialization and + threads. */ + if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS)) + { + + /* Release the mutex. */ + status = _tx_mutex_put((TX_MUTEX *) *m); + + /* Check the status of the mutex release. */ + if (status) + { + + /* Internal error, increment the counter. */ + __tx_iar_system_lock_internal_errors++; + } + } + else + { + + /* Increment the ISR caller error. */ + __tx_iar_system_lock_isr_caller++; + } + } +} + + +#if _DLIB_FILE_DESCRIPTOR + +#include /* Added to get access to FOPEN_MAX */ +#ifndef _MAX_FLOCK +#define _MAX_FLOCK FOPEN_MAX /* Define _MAX_FLOCK as the maximum number of open files */ +#endif + + +TX_MUTEX __tx_iar_file_lock_mutexes[_MAX_FLOCK]; +UINT __tx_iar_file_lock_next_free_mutex = 0; + + +/* Define error counters, just for debug purposes. */ + +UINT __tx_iar_file_lock_no_mutexes; +UINT __tx_iar_file_lock_internal_errors; +UINT __tx_iar_file_lock_isr_caller; + + +void __iar_file_Mtxinit(__iar_Rmtx *m) +{ + +UINT i; +UINT status; +TX_MUTEX *mutex_ptr; + + + /* First, find a free mutex in the list. */ + for (i = 0; i < _MAX_FLOCK; i++) + { + + /* Setup a pointer to the start of the next free mutex. */ + mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; + + /* Check for wrap-around on the next free mutex. */ + if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + { + + /* Yes, set the free index back to 0. */ + __tx_iar_file_lock_next_free_mutex = 0; + } + + /* Is this mutex free? */ + if (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID) + { + + /* Yes, this mutex is free, get out of the loop! */ + break; + } + } + + /* Determine if a free mutex was found. */ + if (i >= _MAX_LOCK) + { + + /* Error! No more free mutexes! */ + + /* Increment the no mutexes error counter. */ + __tx_iar_file_lock_no_mutexes++; + + /* Set return pointer to NULL. */ + *m = TX_NULL; + + /* Return. */ + return; + } + + /* Now create the ThreadX mutex for the IAR library. */ + status = _tx_mutex_create(mutex_ptr, "IAR File Library Lock", TX_NO_INHERIT); + + /* Determine if the creation was successful. */ + if (status == TX_SUCCESS) + { + + /* Yes, successful creation, return mutex pointer. */ + *m = (VOID *) mutex_ptr; + } + else + { + + /* Increment the internal error counter. */ + __tx_iar_file_lock_internal_errors++; + + /* Return a NULL pointer to indicate an error. */ + *m = TX_NULL; + } +} + +void __iar_file_Mtxdst(__iar_Rmtx *m) +{ + + /* Simply delete the mutex. */ + _tx_mutex_delete((TX_MUTEX *) *m); +} + +void __iar_file_Mtxlock(__iar_Rmtx *m) +{ + +UINT status; + + + /* Determine the caller's context. Mutex locks are only available from initialization and + threads. */ + if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS)) + { + + /* Get the mutex. */ + status = _tx_mutex_get((TX_MUTEX *) *m, TX_WAIT_FOREVER); + + /* Check the status of the mutex release. */ + if (status) + { + + /* Internal error, increment the counter. */ + __tx_iar_file_lock_internal_errors++; + } + } + else + { + + /* Increment the ISR caller error. */ + __tx_iar_file_lock_isr_caller++; + } +} + +void __iar_file_Mtxunlock(__iar_Rmtx *m) +{ + +UINT status; + + + /* Determine the caller's context. Mutex unlocks are only available from initialization and + threads. */ + if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS)) + { + + /* Release the mutex. */ + status = _tx_mutex_put((TX_MUTEX *) *m); + + /* Check the status of the mutex release. */ + if (status) + { + + /* Internal error, increment the counter. */ + __tx_iar_file_lock_internal_errors++; + } + } + else + { + + /* Increment the ISR caller error. */ + __tx_iar_file_lock_isr_caller++; + } +} +#endif /* _DLIB_FILE_DESCRIPTOR */ + +#endif /* TX_ENABLE_IAR_LIBRARY_SUPPORT */ + +#endif /* IAR version 8 and above. */ diff --git a/ports/cortex_m52/iar/src/tx_initialize_low_level.s b/ports/cortex_m52/iar/src/tx_initialize_low_level.s new file mode 100644 index 000000000..2cb79d4a5 --- /dev/null +++ b/ports/cortex_m52/iar/src/tx_initialize_low_level.s @@ -0,0 +1,237 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Initialize */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + + EXTERN _tx_thread_system_stack_ptr + EXTERN _tx_initialize_unused_memory + EXTERN _tx_timer_interrupt + EXTERN __main + EXTERN __vector_table + EXTERN _tx_thread_current_ptr + EXTERN _tx_thread_stack_error_handler + +SYSTEM_CLOCK EQU 96000000 +SYSTICK_CYCLES EQU ((SYSTEM_CLOCK / 100) -1) + + RSEG FREE_MEM:DATA + PUBLIC __tx_free_memory_start +__tx_free_memory_start + DS32 4 + + SECTION `.text`:CODE:NOROOT(2) + THUMB +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_initialize_low_level Cortex-M52/IAR */ +/* 6.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 */ +/**************************************************************************/ +// VOID _tx_initialize_low_level(VOID) +// { + PUBLIC _tx_initialize_low_level +_tx_initialize_low_level: + + /* Disable interrupts during ThreadX initialization. */ + CPSID i + + /* Set base of available memory to end of non-initialised RAM area. */ + LDR r0, =_tx_initialize_unused_memory // Build address of unused memory pointer + LDR r1, =__tx_free_memory_start // Build first free address + STR r1, [r0] // Setup first unused memory pointer + + /* Setup Vector Table Offset Register. */ + MOV r0, #0xE000E000 // Build address of NVIC registers + LDR r1, =__vector_table // Pickup address of vector table + STR r1, [r0, #0xD08] // Set vector table address + + /* Enable the cycle count register. */ +// LDR r0, =0xE0001000 // Build address of DWT register +// LDR r1, [r0] // Pickup the current value +// ORR r1, r1, #1 // Set the CYCCNTENA bit +// STR r1, [r0] // Enable the cycle count register + + /* Set system stack pointer from vector value. */ + LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer + LDR r1, =__vector_table // Pickup address of vector table + LDR r1, [r1] // Pickup reset stack pointer + STR r1, [r0] // Save system stack pointer + + /* Configure SysTick. */ + MOV r0, #0xE000E000 // Build address of NVIC registers + MOV r1, #0 // Build value for SysTick reset + STR r1, [r0, #0x10] // Reset SysTick Control + STR r1, [r0, #0x18] // Reset SysTick Counter Value + LDR r1, =SYSTICK_CYCLES + STR r1, [r0, #0x14] // Setup SysTick Reload Value + MOV r1, #0x7 // Build SysTick Control Enable Value + STR r1, [r0, #0x10] // Setup SysTick Control + + /* Configure handler priorities. */ + LDR r1, =0x00000000 // Rsrv, UsgF, BusF, MemM + STR r1, [r0, #0xD18] // Setup System Handlers 4-7 Priority Registers + LDR r1, =0xFF000000 // SVCl, Rsrv, Rsrv, Rsrv + STR r1, [r0, #0xD1C] // Setup System Handlers 8-11 Priority Registers + // Note: SVC must be lowest priority, which is 0xFF + LDR r1, =0x40FF0000 // SysT, PnSV, Rsrv, DbgM + STR r1, [r0, #0xD20] // Setup System Handlers 12-15 Priority Registers + // Note: PnSV must be lowest priority, which is 0xFF + + /* Return to caller. */ + BX lr +// } + + +/* Define shells for each of the unused vectors. */ + + PUBLIC __tx_BadHandler +__tx_BadHandler: + B __tx_BadHandler + + + PUBLIC __tx_IntHandler +__tx_IntHandler: +// VOID InterruptHandler (VOID) +// { + PUSH {r0,lr} // Save LR (and dummy r0 to maintain stack alignment) +#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)) + BL _tx_execution_isr_enter // Call the ISR enter function +#endif + /* Do interrupt handler work here */ + /* .... */ +#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)) + BL _tx_execution_isr_exit // Call the ISR exit function +#endif + POP {r0,lr} + BX lr +// } + + + PUBLIC __tx_SysTickHandler + PUBLIC SysTick_Handler +SysTick_Handler: +__tx_SysTickHandler: +// VOID TimerInterruptHandler (VOID) +// { + PUSH {r0,lr} // Save LR (and dummy r0 to maintain stack alignment) +#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)) + BL _tx_execution_isr_enter // Call the ISR enter function +#endif + BL _tx_timer_interrupt +#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)) + BL _tx_execution_isr_exit // Call the ISR exit function +#endif + POP {r0,lr} + BX lr +// } + + PUBLIC HardFault_Handler +HardFault_Handler: + B HardFault_Handler + + + PUBLIC UsageFault_Handler +UsageFault_Handler: + CPSID i // Disable interrupts + // Check for stack limit fault + LDR r0, =0xE000ED28 // CFSR address + LDR r1,[r0] // Pick up CFSR + TST r1, #0x00100000 // Check for Stack Overflow +_unhandled_usage_loop + BEQ _unhandled_usage_loop // If not stack overflow then loop + + // Handle stack overflow + STR r1, [r0] // Clear CFSR flag(s) + +#ifdef __ARMVFP__ + LDR r0, =0xE000EF34 // Cleanup FPU context: Load FPCCR address + LDR r1, [r0] // Load FPCCR + BIC r1, r1, #1 // Clear the lazy preservation active bit + STR r1, [r0] // Store the value +#endif + + LDR r0, =_tx_thread_current_ptr // Build current thread pointer address + LDR r0,[r0] // Pick up current thread pointer + PUSH {r0,lr} // Save LR (and r0 to maintain stack alignment) + BL _tx_thread_stack_error_handler // Call ThreadX/user handler + POP {r0,lr} // Restore LR and dummy reg + +#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)) + // Call the thread exit function to indicate the thread is no longer executing. + PUSH {r0, lr} // Save LR (and r0 just for alignment) + BL _tx_execution_thread_exit // Call the thread exit function + POP {r0, lr} // Recover LR +#endif + + MOV r1, #0 // Build NULL value + LDR r0, =_tx_thread_current_ptr // Pickup address of current thread pointer + STR r1, [r0] // Clear current thread pointer + + // Return from UsageFault_Handler exception + LDR r0, =0xE000ED04 // Load ICSR + LDR r1, =0x10000000 // Set PENDSVSET bit + STR r1, [r0] // Store ICSR + DSB // Wait for memory access to complete + CPSIE i // Enable interrupts + BX lr // Return from exception + + + PUBLIC __tx_NMIHandler +__tx_NMIHandler: + B __tx_NMIHandler + + + PUBLIC __tx_DBGHandler +__tx_DBGHandler: + B __tx_DBGHandler + + END diff --git a/ports/cortex_m52/iar/src/tx_misra.s b/ports/cortex_m52/iar/src/tx_misra.s new file mode 100644 index 000000000..642bb89e4 --- /dev/null +++ b/ports/cortex_m52/iar/src/tx_misra.s @@ -0,0 +1,767 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** ThreadX MISRA Compliance */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + + #define SHT_PROGBITS 0x1 + + EXTERN __aeabi_memset + EXTERN _tx_thread_current_ptr + EXTERN _tx_thread_interrupt_disable + EXTERN _tx_thread_interrupt_restore + EXTERN _tx_thread_stack_analyze + EXTERN _tx_thread_stack_error_handler + EXTERN _tx_thread_system_state +#ifdef TX_ENABLE_EVENT_TRACE + EXTERN _tx_trace_buffer_current_ptr + EXTERN _tx_trace_buffer_end_ptr + EXTERN _tx_trace_buffer_start_ptr + EXTERN _tx_trace_event_enable_bits + EXTERN _tx_trace_full_notify_function + EXTERN _tx_trace_header_ptr +#endif + + PUBLIC _tx_misra_always_true + PUBLIC _tx_misra_block_pool_to_uchar_pointer_convert + PUBLIC _tx_misra_byte_pool_to_uchar_pointer_convert + PUBLIC _tx_misra_char_to_uchar_pointer_convert + PUBLIC _tx_misra_const_char_to_char_pointer_convert +#ifdef TX_ENABLE_EVENT_TRACE + PUBLIC _tx_misra_entry_to_uchar_pointer_convert +#endif + PUBLIC _tx_misra_indirect_void_to_uchar_pointer_convert + PUBLIC _tx_misra_memset + PUBLIC _tx_misra_message_copy +#ifdef TX_ENABLE_EVENT_TRACE + PUBLIC _tx_misra_object_to_uchar_pointer_convert +#endif + PUBLIC _tx_misra_pointer_to_ulong_convert + PUBLIC _tx_misra_status_get + PUBLIC _tx_misra_thread_stack_check +#ifdef TX_ENABLE_EVENT_TRACE + PUBLIC _tx_misra_time_stamp_get +#endif + PUBLIC _tx_misra_timer_indirect_to_void_pointer_convert + PUBLIC _tx_misra_timer_pointer_add + PUBLIC _tx_misra_timer_pointer_dif +#ifdef TX_ENABLE_EVENT_TRACE + PUBLIC _tx_misra_trace_event_insert +#endif + PUBLIC _tx_misra_uchar_pointer_add + PUBLIC _tx_misra_uchar_pointer_dif + PUBLIC _tx_misra_uchar_pointer_sub + PUBLIC _tx_misra_uchar_to_align_type_pointer_convert + PUBLIC _tx_misra_uchar_to_block_pool_pointer_convert +#ifdef TX_ENABLE_EVENT_TRACE + PUBLIC _tx_misra_uchar_to_entry_pointer_convert + PUBLIC _tx_misra_uchar_to_header_pointer_convert +#endif + PUBLIC _tx_misra_uchar_to_indirect_byte_pool_pointer_convert + PUBLIC _tx_misra_uchar_to_indirect_uchar_pointer_convert +#ifdef TX_ENABLE_EVENT_TRACE + PUBLIC _tx_misra_uchar_to_object_pointer_convert +#endif + PUBLIC _tx_misra_uchar_to_void_pointer_convert + PUBLIC _tx_misra_ulong_pointer_add + PUBLIC _tx_misra_ulong_pointer_dif + PUBLIC _tx_misra_ulong_pointer_sub + PUBLIC _tx_misra_ulong_to_pointer_convert + PUBLIC _tx_misra_ulong_to_thread_pointer_convert + PUBLIC _tx_misra_user_timer_pointer_get + PUBLIC _tx_misra_void_to_block_pool_pointer_convert + PUBLIC _tx_misra_void_to_byte_pool_pointer_convert + PUBLIC _tx_misra_void_to_event_flags_pointer_convert + PUBLIC _tx_misra_void_to_indirect_uchar_pointer_convert + PUBLIC _tx_misra_void_to_mutex_pointer_convert + PUBLIC _tx_misra_void_to_queue_pointer_convert + PUBLIC _tx_misra_void_to_semaphore_pointer_convert + PUBLIC _tx_misra_void_to_thread_pointer_convert + PUBLIC _tx_misra_void_to_uchar_pointer_convert + PUBLIC _tx_misra_void_to_ulong_pointer_convert + PUBLIC _tx_misra_ipsr_get + PUBLIC _tx_misra_control_get + PUBLIC _tx_misra_control_set +#ifdef __ARMVFP__ + PUBLIC _tx_misra_fpccr_get + PUBLIC _tx_misra_vfp_touch +#endif + + PUBLIC _tx_misra_event_flags_group_not_used + PUBLIC _tx_misra_event_flags_set_notify_not_used + PUBLIC _tx_misra_queue_not_used + PUBLIC _tx_misra_queue_send_notify_not_used + PUBLIC _tx_misra_semaphore_not_used + PUBLIC _tx_misra_semaphore_put_notify_not_used + PUBLIC _tx_misra_thread_entry_exit_notify_not_used + PUBLIC _tx_misra_thread_not_used + +#ifdef TX_MISRA_ENABLE + PUBLIC _tx_version_id + + SECTION `.data`:DATA:REORDER:NOROOT(2) + DATA +// 51 CHAR _tx_version_id[100] = "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX 6.1 MISRA C Compliant *"; +_tx_version_id: + DC8 43H, 6FH, 70H, 79H, 72H, 69H, 67H, 68H + DC8 74H, 20H, 28H, 63H, 29H, 20H, 31H, 39H + DC8 39H, 36H, 2DH, 32H, 30H, 31H, 38H, 20H + DC8 45H, 78H, 70H, 72H, 65H, 73H, 73H, 20H + DC8 4CH, 6FH, 67H, 69H, 63H, 20H, 49H, 6EH + DC8 63H, 2EH, 20H, 2AH, 20H, 54H, 68H, 72H + DC8 65H, 61H, 64H, 58H, 20H, 36H, 2EH, 31H + DC8 20H, 4DH, 49H, 53H, 52H, 41H, 20H, 43H + DC8 20H, 43H, 6FH, 6DH, 70H, 6CH, 69H, 61H + DC8 6EH, 74H, 20H, 2AH, 0 + DC8 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +#endif //TX_MISRA_ENABLE + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** VOID _tx_misra_memset(VOID *ptr, UINT value, UINT size); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_memset: + PUSH {R4,LR} + MOVS R4,R0 + MOVS R0,R2 + MOVS R2,R1 + MOVS R1,R0 + MOVS R0,R4 + BL __aeabi_memset + POP {R4,PC} // return + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** UCHAR *_tx_misra_uchar_pointer_add(UCHAR *ptr, ULONG amount); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_uchar_pointer_add: + ADD R0,R0,R1 + BX LR // return + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** UCHAR *_tx_misra_uchar_pointer_sub(UCHAR *ptr, ULONG amount); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_uchar_pointer_sub: + RSBS R1,R1,#+0 + ADD R0,R0,R1 + BX LR // return + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ULONG _tx_misra_uchar_pointer_dif(UCHAR *ptr1, UCHAR *ptr2); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_uchar_pointer_dif: + SUBS R0,R0,R1 + BX LR // return + + +/************************************************************************************************************************************/ +/************************************************************************************************************************************/ +/** */ +/** This single function serves all of the below prototypes. */ +/** */ +/** ULONG _tx_misra_pointer_to_ulong_convert(VOID *ptr); */ +/** VOID *_tx_misra_ulong_to_pointer_convert(ULONG input); */ +/** UCHAR **_tx_misra_indirect_void_to_uchar_pointer_convert(VOID **return_ptr); */ +/** UCHAR **_tx_misra_uchar_to_indirect_uchar_pointer_convert(UCHAR *pointer); */ +/** UCHAR *_tx_misra_block_pool_to_uchar_pointer_convert(TX_BLOCK_POOL *pool); */ +/** TX_BLOCK_POOL *_tx_misra_void_to_block_pool_pointer_convert(VOID *pointer); */ +/** UCHAR *_tx_misra_void_to_uchar_pointer_convert(VOID *pointer); */ +/** TX_BLOCK_POOL *_tx_misra_uchar_to_block_pool_pointer_convert(UCHAR *pointer); */ +/** UCHAR **_tx_misra_void_to_indirect_uchar_pointer_convert(VOID *pointer); */ +/** TX_BYTE_POOL *_tx_misra_void_to_byte_pool_pointer_convert(VOID *pointer); */ +/** UCHAR *_tx_misra_byte_pool_to_uchar_pointer_convert(TX_BYTE_POOL *pool); */ +/** ALIGN_TYPE *_tx_misra_uchar_to_align_type_pointer_convert(UCHAR *pointer); */ +/** TX_BYTE_POOL **_tx_misra_uchar_to_indirect_byte_pool_pointer_convert(UCHAR *pointer); */ +/** TX_EVENT_FLAGS_GROUP *_tx_misra_void_to_event_flags_pointer_convert(VOID *pointer); */ +/** ULONG *_tx_misra_void_to_ulong_pointer_convert(VOID *pointer); */ +/** TX_MUTEX *_tx_misra_void_to_mutex_pointer_convert(VOID *pointer); */ +/** TX_QUEUE *_tx_misra_void_to_queue_pointer_convert(VOID *pointer); */ +/** TX_SEMAPHORE *_tx_misra_void_to_semaphore_pointer_convert(VOID *pointer); */ +/** VOID *_tx_misra_uchar_to_void_pointer_convert(UCHAR *pointer); */ +/** TX_THREAD *_tx_misra_ulong_to_thread_pointer_convert(ULONG value); */ +/** VOID *_tx_misra_timer_indirect_to_void_pointer_convert(TX_TIMER_INTERNAL **pointer); */ +/** CHAR *_tx_misra_const_char_to_char_pointer_convert(const char *pointer); */ +/** TX_THREAD *_tx_misra_void_to_thread_pointer_convert(void *pointer); */ +/** UCHAR *_tx_misra_object_to_uchar_pointer_convert(TX_TRACE_OBJECT_ENTRY *pointer); */ +/** TX_TRACE_OBJECT_ENTRY *_tx_misra_uchar_to_object_pointer_convert(UCHAR *pointer); */ +/** TX_TRACE_HEADER *_tx_misra_uchar_to_header_pointer_convert(UCHAR *pointer); */ +/** TX_TRACE_BUFFER_ENTRY *_tx_misra_uchar_to_entry_pointer_convert(UCHAR *pointer); */ +/** UCHAR *_tx_misra_entry_to_uchar_pointer_convert(TX_TRACE_BUFFER_ENTRY *pointer); */ +/** UCHAR *_tx_misra_char_to_uchar_pointer_convert(CHAR *pointer); */ +/** VOID _tx_misra_event_flags_group_not_used(TX_EVENT_FLAGS_GROUP *group_ptr); */ +/** VOID _tx_misra_event_flags_set_notify_not_used(VOID (*events_set_notify)(TX_EVENT_FLAGS_GROUP *notify_group_ptr)); */ +/** VOID _tx_misra_queue_not_used(TX_QUEUE *queue_ptr); */ +/** VOID _tx_misra_queue_send_notify_not_used(VOID (*queue_send_notify)(TX_QUEUE *notify_queue_ptr)); */ +/** VOID _tx_misra_semaphore_not_used(TX_SEMAPHORE *semaphore_ptr); */ +/** VOID _tx_misra_semaphore_put_notify_not_used(VOID (*semaphore_put_notify)(TX_SEMAPHORE *notify_semaphore_ptr)); */ +/** VOID _tx_misra_thread_not_used(TX_THREAD *thread_ptr); */ +/** VOID _tx_misra_thread_entry_exit_notify_not_used(VOID (*thread_entry_exit_notify)(TX_THREAD *notify_thread_ptr, UINT id)); */ +/** */ +/************************************************************************************************************************************/ +/************************************************************************************************************************************/ + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_pointer_to_ulong_convert: +_tx_misra_ulong_to_pointer_convert: +_tx_misra_indirect_void_to_uchar_pointer_convert: +_tx_misra_uchar_to_indirect_uchar_pointer_convert: +_tx_misra_block_pool_to_uchar_pointer_convert: +_tx_misra_void_to_block_pool_pointer_convert: +_tx_misra_void_to_uchar_pointer_convert: +_tx_misra_uchar_to_block_pool_pointer_convert: +_tx_misra_void_to_indirect_uchar_pointer_convert: +_tx_misra_void_to_byte_pool_pointer_convert: +_tx_misra_byte_pool_to_uchar_pointer_convert: +_tx_misra_uchar_to_align_type_pointer_convert: +_tx_misra_uchar_to_indirect_byte_pool_pointer_convert: +_tx_misra_void_to_event_flags_pointer_convert: +_tx_misra_void_to_ulong_pointer_convert: +_tx_misra_void_to_mutex_pointer_convert: +_tx_misra_void_to_queue_pointer_convert: +_tx_misra_void_to_semaphore_pointer_convert: +_tx_misra_uchar_to_void_pointer_convert: +_tx_misra_ulong_to_thread_pointer_convert: +_tx_misra_timer_indirect_to_void_pointer_convert: +_tx_misra_const_char_to_char_pointer_convert: +_tx_misra_void_to_thread_pointer_convert: +#ifdef TX_ENABLE_EVENT_TRACE +_tx_misra_object_to_uchar_pointer_convert: +_tx_misra_uchar_to_object_pointer_convert: +_tx_misra_uchar_to_header_pointer_convert: +_tx_misra_uchar_to_entry_pointer_convert: +_tx_misra_entry_to_uchar_pointer_convert: +#endif +_tx_misra_char_to_uchar_pointer_convert: +_tx_misra_event_flags_group_not_used: +_tx_misra_event_flags_set_notify_not_used: +_tx_misra_queue_not_used: +_tx_misra_queue_send_notify_not_used: +_tx_misra_semaphore_not_used: +_tx_misra_semaphore_put_notify_not_used: +_tx_misra_thread_entry_exit_notify_not_used: +_tx_misra_thread_not_used: + + BX LR // return + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ULONG *_tx_misra_ulong_pointer_add(ULONG *ptr, ULONG amount); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_ulong_pointer_add: + ADD R0,R0,R1, LSL #+2 + BX LR // return + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ULONG *_tx_misra_ulong_pointer_sub(ULONG *ptr, ULONG amount); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_ulong_pointer_sub: + MVNS R2,#+3 + MULS R1,R2,R1 + ADD R0,R0,R1 + BX LR // return + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ULONG _tx_misra_ulong_pointer_dif(ULONG *ptr1, ULONG *ptr2); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_ulong_pointer_dif: + SUBS R0,R0,R1 + ASRS R0,R0,#+2 + BX LR // return + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** VOID _tx_misra_message_copy(ULONG **source, ULONG **destination, */ +/** UINT size); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_message_copy: + PUSH {R4,R5} + LDR R3,[R0, #+0] + LDR R4,[R1, #+0] + LDR R5,[R3, #+0] + STR R5,[R4, #+0] + ADDS R4,R4,#+4 + ADDS R3,R3,#+4 + CMP R2,#+2 + BCC.N ??_tx_misra_message_copy_0 + SUBS R2,R2,#+1 + B.N ??_tx_misra_message_copy_1 +??_tx_misra_message_copy_2: + LDR R5,[R3, #+0] + STR R5,[R4, #+0] + ADDS R4,R4,#+4 + ADDS R3,R3,#+4 + SUBS R2,R2,#+1 +??_tx_misra_message_copy_1: + CMP R2,#+0 + BNE.N ??_tx_misra_message_copy_2 +??_tx_misra_message_copy_0: + STR R3,[R0, #+0] + STR R4,[R1, #+0] + POP {R4,R5} + BX LR // return + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ULONG _tx_misra_timer_pointer_dif(TX_TIMER_INTERNAL **ptr1, */ +/** TX_TIMER_INTERNAL **ptr2); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_timer_pointer_dif: + SUBS R0,R0,R1 + ASRS R0,R0,#+2 + BX LR // return + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** TX_TIMER_INTERNAL **_tx_misra_timer_pointer_add(TX_TIMER_INTERNAL */ +/** **ptr1, ULONG size); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_timer_pointer_add: + ADD R0,R0,R1, LSL #+2 + BX LR // return + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** VOID _tx_misra_user_timer_pointer_get(TX_TIMER_INTERNAL */ +/** *internal_timer, TX_TIMER **user_timer); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_user_timer_pointer_get: + SUBS R0,#8 + STR R0,[R1, #+0] + BX LR // return + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** VOID _tx_misra_thread_stack_check(TX_THREAD *thread_ptr, */ +/** VOID **highest_stack); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_thread_stack_check: + PUSH {R3-R5,LR} + MOVS R4,R0 + MOVS R5,R1 + BL _tx_thread_interrupt_disable + CMP R4,#+0 + BEQ.N ??_tx_misra_thread_stack_check_0 + LDR R1,[R4, #+0] + LDR.N R2,??DataTable2 // 0x54485244 + CMP R1,R2 + BNE.N ??_tx_misra_thread_stack_check_0 + LDR R1,[R4, #+8] + LDR R2,[R5, #+0] + CMP R1,R2 + BCS.N ??_tx_misra_thread_stack_check_1 + LDR R1,[R4, #+8] + STR R1,[R5, #+0] +??_tx_misra_thread_stack_check_1: + LDR R1,[R4, #+12] + LDR R1,[R1, #+0] + CMP R1,#-269488145 + BNE.N ??_tx_misra_thread_stack_check_2 + LDR R1,[R4, #+16] + LDR R1,[R1, #+1] + CMP R1,#-269488145 + BNE.N ??_tx_misra_thread_stack_check_2 + LDR R1,[R5, #+0] + LDR R2,[R4, #+12] + CMP R1,R2 + BCS.N ??_tx_misra_thread_stack_check_3 +??_tx_misra_thread_stack_check_2: + BL _tx_thread_interrupt_restore + MOVS R0,R4 + BL _tx_thread_stack_error_handler + BL _tx_thread_interrupt_disable +??_tx_misra_thread_stack_check_3: + LDR R1,[R5, #+0] + LDR R1,[R1, #-4] + CMP R1,#-269488145 + BEQ.N ??_tx_misra_thread_stack_check_0 + BL _tx_thread_interrupt_restore + MOVS R0,R4 + BL _tx_thread_stack_analyze + BL _tx_thread_interrupt_disable +??_tx_misra_thread_stack_check_0: + BL _tx_thread_interrupt_restore + POP {R0,R4,R5,PC} // return + +#ifdef TX_ENABLE_EVENT_TRACE + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** VOID _tx_misra_trace_event_insert(ULONG event_id, */ +/** VOID *info_field_1, ULONG info_field_2, ULONG info_field_3, */ +/** ULONG info_field_4, ULONG filter, ULONG time_stamp); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_trace_event_insert: + PUSH {R3-R7,LR} + LDR.N R4,??DataTable2_1 + LDR R4,[R4, #+0] + CMP R4,#+0 + BEQ.N ??_tx_misra_trace_event_insert_0 + LDR.N R5,??DataTable2_2 + LDR R5,[R5, #+0] + LDR R6,[SP, #+28] + TST R5,R6 + BEQ.N ??_tx_misra_trace_event_insert_0 + LDR.N R5,??DataTable2_3 + LDR R5,[R5, #+0] + LDR.N R6,??DataTable2_4 + LDR R6,[R6, #+0] + CMP R5,#+0 + BNE.N ??_tx_misra_trace_event_insert_1 + LDR R5,[R6, #+44] + LDR R7,[R6, #+60] + LSLS R7,R7,#+16 + ORRS R7,R7,#0x80000000 + ORRS R5,R7,R5 + B.N ??_tx_misra_trace_event_insert_2 +??_tx_misra_trace_event_insert_1: + CMP R5,#-252645136 + BCS.N ??_tx_misra_trace_event_insert_3 + MOVS R5,R6 + MOVS R6,#-1 + B.N ??_tx_misra_trace_event_insert_2 +??_tx_misra_trace_event_insert_3: + MOVS R6,#-252645136 + MOVS R5,#+0 +??_tx_misra_trace_event_insert_2: + STR R6,[R4, #+0] + STR R5,[R4, #+4] + STR R0,[R4, #+8] + LDR R0,[SP, #+32] + STR R0,[R4, #+12] + STR R1,[R4, #+16] + STR R2,[R4, #+20] + STR R3,[R4, #+24] + LDR R0,[SP, #+24] + STR R0,[R4, #+28] + ADDS R4,R4,#+32 + LDR.N R0,??DataTable2_5 + LDR R0,[R0, #+0] + CMP R4,R0 + BCC.N ??_tx_misra_trace_event_insert_4 + LDR.N R0,??DataTable2_6 + LDR R4,[R0, #+0] + LDR.N R0,??DataTable2_1 + STR R4,[R0, #+0] + LDR.N R0,??DataTable2_7 + LDR R0,[R0, #+0] + STR R4,[R0, #+32] + LDR.N R0,??DataTable2_8 + LDR R0,[R0, #+0] + CMP R0,#+0 + BEQ.N ??_tx_misra_trace_event_insert_0 + LDR.N R0,??DataTable2_7 + LDR R0,[R0, #+0] + LDR.N R1,??DataTable2_8 + LDR R1,[R1, #+0] + BLX R1 + B.N ??_tx_misra_trace_event_insert_0 +??_tx_misra_trace_event_insert_4: + LDR.N R0,??DataTable2_1 + STR R4,[R0, #+0] + LDR.N R0,??DataTable2_7 + LDR R0,[R0, #+0] + STR R4,[R0, #+32] +??_tx_misra_trace_event_insert_0: + POP {R0,R4-R7,PC} // return + + + SECTION `.text`:CODE:NOROOT(2) + SECTION_TYPE SHT_PROGBITS, 0 + DATA +??DataTable2_1: + DC32 _tx_trace_buffer_current_ptr + + SECTION `.text`:CODE:NOROOT(2) + SECTION_TYPE SHT_PROGBITS, 0 + DATA +??DataTable2_2: + DC32 _tx_trace_event_enable_bits + + SECTION `.text`:CODE:NOROOT(2) + SECTION_TYPE SHT_PROGBITS, 0 + DATA +??DataTable2_5: + DC32 _tx_trace_buffer_end_ptr + + SECTION `.text`:CODE:NOROOT(2) + SECTION_TYPE SHT_PROGBITS, 0 + DATA +??DataTable2_6: + DC32 _tx_trace_buffer_start_ptr + + SECTION `.text`:CODE:NOROOT(2) + SECTION_TYPE SHT_PROGBITS, 0 + DATA +??DataTable2_7: + DC32 _tx_trace_header_ptr + + SECTION `.text`:CODE:NOROOT(2) + SECTION_TYPE SHT_PROGBITS, 0 + DATA +??DataTable2_8: + DC32 _tx_trace_full_notify_function + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ULONG _tx_misra_time_stamp_get(VOID); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_time_stamp_get: + MOVS R0,#+0 + BX LR // return + +#endif + + SECTION `.text`:CODE:NOROOT(2) + SECTION_TYPE SHT_PROGBITS, 0 + DATA +??DataTable2: + DC32 0x54485244 + + SECTION `.text`:CODE:NOROOT(2) + SECTION_TYPE SHT_PROGBITS, 0 + DATA +??DataTable2_3: + DC32 _tx_thread_system_state + + SECTION `.text`:CODE:NOROOT(2) + SECTION_TYPE SHT_PROGBITS, 0 + DATA +??DataTable2_4: + DC32 _tx_thread_current_ptr + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** UINT _tx_misra_always_true(void); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_always_true: + MOVS R0,#+1 + BX LR // return + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** UINT _tx_misra_status_get(UINT status); */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_status_get: + MOVS R0,#+0 + BX LR // return + + +/***********************************************************************************************/ +/***********************************************************************************************/ +/** */ +/** ULONG _tx_misra_ipsr_get(void); */ +/** */ +/***********************************************************************************************/ +/***********************************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_ipsr_get: + MRS R0, IPSR + BX LR // return + + +/***********************************************************************************************/ +/***********************************************************************************************/ +/** */ +/** ULONG _tx_misra_control_get(void); */ +/** */ +/***********************************************************************************************/ +/***********************************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_control_get: + MRS R0, CONTROL + BX LR // return + + +/***********************************************************************************************/ +/***********************************************************************************************/ +/** */ +/** void _tx_misra_control_set(ULONG value); */ +/** */ +/***********************************************************************************************/ +/***********************************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_control_set: + MSR CONTROL, R0 + BX LR // return + + +#ifdef __ARMVFP__ + +/***********************************************************************************************/ +/***********************************************************************************************/ +/** */ +/** ULONG _tx_misra_fpccr_get(void); */ +/** */ +/***********************************************************************************************/ +/***********************************************************************************************/ + + SECTION `.text`:CODE:NOROOT(2) + THUMB +_tx_misra_fpccr_get: + LDR r0, =0xE000EF34 // Build FPCCR address + LDR r0, [r0] // Load FPCCR value + BX LR // return + + +/***********************************************************************************************/ +/***********************************************************************************************/ +/** */ +/** void _tx_misra_vfp_touch(void); */ +/** */ +/***********************************************************************************************/ +/***********************************************************************************************/ + + SECTION `.text`:CODE:NOROOT(1) + THUMB +_tx_misra_vfp_touch: + vmov.f32 s0, s0 + BX LR // return + +#endif + + + SECTION `.iar_vfe_header`:DATA:NOALLOC:NOROOT(2) + SECTION_TYPE SHT_PROGBITS, 0 + DATA + DC32 0 + + END diff --git a/ports/cortex_m52/iar/src/tx_thread_context_restore.s b/ports/cortex_m52/iar/src/tx_thread_context_restore.s new file mode 100644 index 000000000..40e407f63 --- /dev/null +++ b/ports/cortex_m52/iar/src/tx_thread_context_restore.s @@ -0,0 +1,74 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + + EXTERN _tx_execution_isr_exit + SECTION `.text`:CODE:NOROOT(2) + THUMB +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_context_restore Cortex-M52/IAR */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is not needed for Cortex-M. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* [_tx_execution_isr_exit] Execution profiling ISR exit */ +/* */ +/* CALLED BY */ +/* */ +/* ISRs Interrupt Service Routines */ +/**************************************************************************/ +// VOID _tx_thread_context_restore(VOID) +// { + PUBLIC _tx_thread_context_restore +_tx_thread_context_restore: + +#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)) + /* Call the ISR exit function to indicate an ISR is complete. */ + PUSH {r0, lr} // Save return address + BL _tx_execution_isr_exit // Call the ISR exit function + POP {r0, lr} // Recover return address +#endif + + BX lr +// } + END diff --git a/ports/cortex_m52/iar/src/tx_thread_context_save.s b/ports/cortex_m52/iar/src/tx_thread_context_save.s new file mode 100644 index 000000000..f3d2942df --- /dev/null +++ b/ports/cortex_m52/iar/src/tx_thread_context_save.s @@ -0,0 +1,74 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + + EXTERN _tx_execution_isr_enter + SECTION `.text`:CODE:NOROOT(2) + THUMB +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_context_save Cortex-M52/IAR */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is not needed for Cortex-M. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* [_tx_execution_isr_enter] Execution profiling ISR enter */ +/* */ +/* CALLED BY */ +/* */ +/* ISRs */ +/**************************************************************************/ +// VOID _tx_thread_context_save(VOID) +// { + PUBLIC _tx_thread_context_save +_tx_thread_context_save: + +#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)) + /* Call the ISR enter function to indicate an ISR is starting. */ + PUSH {r0, lr} // Save return address + BL _tx_execution_isr_enter // Call the ISR enter function + POP {r0, lr} // Recover return address +#endif + + BX lr +// } + END diff --git a/ports/cortex_m52/iar/src/tx_thread_interrupt_control.s b/ports/cortex_m52/iar/src/tx_thread_interrupt_control.s new file mode 100644 index 000000000..ec01a09bd --- /dev/null +++ b/ports/cortex_m52/iar/src/tx_thread_interrupt_control.s @@ -0,0 +1,75 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + + SECTION `.text`:CODE:NOROOT(2) + THUMB +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_interrupt_control Cortex-M52/IAR */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is responsible for changing the interrupt lockout */ +/* posture of the system. */ +/* */ +/* INPUT */ +/* */ +/* new_posture New interrupt lockout posture */ +/* */ +/* OUTPUT */ +/* */ +/* old_posture Old interrupt lockout posture */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/**************************************************************************/ +// UINT _tx_thread_interrupt_control(UINT new_posture) +// { + PUBLIC _tx_thread_interrupt_control +_tx_thread_interrupt_control: +#ifdef TX_PORT_USE_BASEPRI + MRS r1, BASEPRI // Pickup current interrupt posture + MSR BASEPRI, r0 // Apply the new interrupt posture + MOV r0, r1 // Transfer old to return register +#else + MRS r1, PRIMASK // Pickup current interrupt lockout + MSR PRIMASK, r0 // Apply the new interrupt lockout + MOV r0, r1 // Transfer old to return register +#endif + BX lr // Return to caller +// } + END diff --git a/ports/cortex_m52/iar/src/tx_thread_interrupt_disable.s b/ports/cortex_m52/iar/src/tx_thread_interrupt_disable.s new file mode 100644 index 000000000..c5c22d59e --- /dev/null +++ b/ports/cortex_m52/iar/src/tx_thread_interrupt_disable.s @@ -0,0 +1,75 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + + SECTION `.text`:CODE:NOROOT(2) + THUMB +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_interrupt_disable Cortex-M52/IAR */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is responsible for disabling interrupts and returning */ +/* the previous interrupt lockout posture. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* old_posture Old interrupt lockout posture */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/**************************************************************************/ +// UINT _tx_thread_interrupt_disable(VOID) +// { + PUBLIC _tx_thread_interrupt_disable +_tx_thread_interrupt_disable: + /* Return current interrupt lockout posture. */ +#ifdef TX_PORT_USE_BASEPRI + MRS r0, BASEPRI + LDR r1, =TX_PORT_BASEPRI + MSR BASEPRI, r1 +#else + MRS r0, PRIMASK + CPSID i +#endif + BX lr +// } + END diff --git a/ports/cortex_m52/iar/src/tx_thread_interrupt_restore.s b/ports/cortex_m52/iar/src/tx_thread_interrupt_restore.s new file mode 100644 index 000000000..76fe33251 --- /dev/null +++ b/ports/cortex_m52/iar/src/tx_thread_interrupt_restore.s @@ -0,0 +1,72 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + + SECTION `.text`:CODE:NOROOT(2) + THUMB +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_interrupt_restore Cortex-M52/IAR */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is responsible for restoring the previous */ +/* interrupt lockout posture. */ +/* */ +/* INPUT */ +/* */ +/* previous_posture Previous interrupt posture */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/**************************************************************************/ +// VOID _tx_thread_interrupt_restore(UINT previous_posture) +// { + PUBLIC _tx_thread_interrupt_restore +_tx_thread_interrupt_restore: + /* Restore previous interrupt lockout posture. */ +#ifdef TX_PORT_USE_BASEPRI + MSR BASEPRI, r0 +#else + MSR PRIMASK, r0 +#endif + BX lr +// } + END diff --git a/ports/cortex_m52/iar/src/tx_thread_schedule.s b/ports/cortex_m52/iar/src/tx_thread_schedule.s new file mode 100644 index 000000000..b5a1c9979 --- /dev/null +++ b/ports/cortex_m52/iar/src/tx_thread_schedule.s @@ -0,0 +1,370 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + + EXTERN _tx_thread_current_ptr + EXTERN _tx_thread_execute_ptr + EXTERN _tx_timer_time_slice + EXTERN _tx_thread_system_stack_ptr + EXTERN _tx_thread_preempt_disable + EXTERN _tx_execution_thread_enter + EXTERN _tx_execution_thread_exit + EXTERN _tx_thread_secure_stack_context_restore + EXTERN _tx_thread_secure_stack_context_save + EXTERN _tx_thread_secure_mode_stack_allocate + EXTERN _tx_thread_secure_mode_stack_free + EXTERN _tx_thread_secure_mode_stack_initialize +#ifdef TX_LOW_POWER + EXTERN tx_low_power_enter + EXTERN tx_low_power_exit +#endif + SECTION `.text`:CODE:NOROOT(2) + THUMB +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_schedule Cortex-M52/IAR */ +/* 6.2.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function waits for a thread control block pointer to appear in */ +/* the _tx_thread_execute_ptr variable. Once a thread pointer appears */ +/* in the variable, the corresponding thread is resumed. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_initialize_kernel_enter ThreadX entry function */ +/* _tx_thread_system_return Return to system from thread */ +/**************************************************************************/ +// VOID _tx_thread_schedule(VOID) +// { + PUBLIC _tx_thread_schedule +_tx_thread_schedule: + /* This function should only ever be called on Cortex-M + from the first schedule request. Subsequent scheduling occurs + from the PendSV handling routine below. */ + + /* Clear the preempt-disable flag to enable rescheduling after initialization on Cortex-M targets. */ + MOV r0, #0 // Build value for TX_FALSE + LDR r2, =_tx_thread_preempt_disable // Build address of preempt disable flag + STR r0, [r2, #0] // Clear preempt disable flag + +#ifdef __ARMVFP__ + /* Clear CONTROL.FPCA bit so VFP registers aren't unnecessarily stacked. */ + MRS r0, CONTROL // Pickup current CONTROL register + BIC r0, r0, #4 // Clear the FPCA bit + MSR CONTROL, r0 // Setup new CONTROL register +#endif + + /* Enable interrupts */ + CPSIE i + + /* Enter the scheduler for the first time. */ + MOV r0, #0x10000000 // Load PENDSVSET bit + MOV r1, #0xE000E000 // Load NVIC base + STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR + DSB // Complete all memory accesses + ISB // Flush pipeline + + /* Wait here for the PendSV to take place. */ + +__tx_wait_here: + B __tx_wait_here // Wait for the PendSV to happen +// } + + /* Generic context switching PendSV handler. */ + + PUBLIC PendSV_Handler +PendSV_Handler: +__tx_ts_handler: + +#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)) + /* Call the thread exit function to indicate the thread is no longer executing. */ +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI + MSR BASEPRI, r1 +#else + CPSID i // Disable interrupts +#endif /* TX_PORT_USE_BASEPRI */ + PUSH {r0, lr} // Save LR (and r0 just for alignment) + BL _tx_execution_thread_exit // Call the thread exit function + POP {r0, lr} // Recover LR +#ifdef TX_PORT_USE_BASEPRI + MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MSR BASEPRI, r0 +#else + CPSIE i // Enable interrupts +#endif /* TX_PORT_USE_BASEPRI */ +#endif /* EXECUTION PROFILE */ + + LDR r0, =_tx_thread_current_ptr // Build current thread pointer address + LDR r2, =_tx_thread_execute_ptr // Build execute thread pointer address + MOV r3, #0 // Build NULL value + LDR r1, [r0] // Pickup current thread pointer + + /* Determine if there is a current thread to finish preserving. */ + + CBZ r1, __tx_ts_new // If NULL, skip preservation + + /* Recover PSP and preserve current thread context. */ + + STR r3, [r0] // Set _tx_thread_current_ptr to NULL + MRS r12, PSP // Pickup PSP pointer (thread's stack pointer) + STMDB r12!, {r4-r11} // Save its remaining registers +#ifdef __ARMVFP__ + TST LR, #0x10 // Determine if the VFP extended frame is present + BNE _skip_vfp_save + VSTMDB r12!,{s16-s31} // Yes, save additional VFP registers +_skip_vfp_save: +#endif + LDR r4, =_tx_timer_time_slice // Build address of time-slice variable + STMDB r12!, {LR} // Save LR on the stack + STR r12, [r1, #8] // Save the thread stack pointer + +#if (!defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE)) + // Save secure context + LDR r5, [r1,#0x90] // Load secure stack index + CBZ r5, _skip_secure_save // Skip save if there is no secure context + PUSH {r0,r1,r2,r3} // Save scratch registers + MOV r0, r1 // Move thread ptr to r0 + BL _tx_thread_secure_stack_context_save // Save secure stack + POP {r0,r1,r2,r3} // Restore secure registers +_skip_secure_save: +#endif + + /* Determine if time-slice is active. If it isn't, skip time handling processing. */ + + LDR r5, [r4] // Pickup current time-slice + CBZ r5, __tx_ts_new // If not active, skip processing + + /* Time-slice is active, save the current thread's time-slice and clear the global time-slice variable. */ + + STR r5, [r1, #24] // Save current time-slice + + /* Clear the global time-slice. */ + + STR r3, [r4] // Clear time-slice + + /* Executing thread is now completely preserved!!! */ + +__tx_ts_new: + + /* Now we are looking for a new thread to execute! */ + +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI + MSR BASEPRI, r1 +#else + CPSID i // Disable interrupts +#endif + LDR r1, [r2] // Is there another thread ready to execute? + CBZ r1, __tx_ts_wait // No, skip to the wait processing + + /* Yes, another thread is ready for else, make the current thread the new thread. */ + + STR r1, [r0] // Setup the current thread pointer to the new thread +#ifdef TX_PORT_USE_BASEPRI + MOV r4, #0 // Disable BASEPRI masking (enable interrupts) + MSR BASEPRI, r4 +#else + CPSIE i // Enable interrupts +#endif + + /* Increment the thread run count. */ + +__tx_ts_restore: + LDR r7, [r1, #4] // Pickup the current thread run count + LDR r4, =_tx_timer_time_slice // Build address of time-slice variable + LDR r5, [r1, #24] // Pickup thread's current time-slice + ADD r7, r7, #1 // Increment the thread run count + STR r7, [r1, #4] // Store the new run count + + /* Setup global time-slice with thread's current time-slice. */ + + STR r5, [r4] // Setup global time-slice + +#if (defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE)) + /* Call the thread entry function to indicate the thread is executing. */ + PUSH {r0, r1} // Save r0 and r1 + BL _tx_execution_thread_enter // Call the thread execution enter function + POP {r0, r1} // Recover r0 and r1 +#endif + +#if (!defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE)) + // Restore secure context + LDR r0, [r1,#0x90] // Load secure stack index + CBZ r0, _skip_secure_restore // Skip restore if there is no secure context + PUSH {r0,r1} // Save r1 (and dummy r0) + MOV r0, r1 // Move thread ptr to r0 + BL _tx_thread_secure_stack_context_restore // Restore secure stack + POP {r0,r1} // Restore r1 (and dummy r0) +_skip_secure_restore: +#endif + + /* Restore the thread context and PSP. */ + LDR r12, [r1, #12] // Get stack start + MSR PSPLIM, r12 // Set stack limit + LDR r12, [r1, #8] // Pickup thread's stack pointer + LDMIA r12!, {LR} // Pickup LR +#ifdef __ARMVFP__ + TST LR, #0x10 // Determine if the VFP extended frame is present + BNE _skip_vfp_restore // If not, skip VFP restore + VLDMIA r12!, {s16-s31} // Yes, restore additional VFP registers +_skip_vfp_restore: +#endif + LDMIA r12!, {r4-r11} // Recover thread's registers + MSR PSP, r12 // Setup the thread's stack pointer + + BX lr // Return to thread! + + /* The following is the idle wait processing... in this case, no threads are ready for execution and the + system will simply be idle until an interrupt occurs that makes a thread ready. Note that interrupts + are disabled to allow use of WFI for waiting for a thread to arrive. */ + +__tx_ts_wait: +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Mask interrupt priorities =< TX_PORT_BASEPRI + MSR BASEPRI, r1 +#else + CPSID i // Disable interrupts +#endif + LDR r1, [r2] // Pickup the next thread to execute pointer + STR r1, [r0] // Store it in the current pointer + CBNZ r1, __tx_ts_ready // If non-NULL, a new thread is ready! + +#ifdef TX_LOW_POWER + PUSH {r0-r3} + BL tx_low_power_enter // Possibly enter low power mode + POP {r0-r3} +#endif + +#ifdef TX_ENABLE_WFI + DSB // Ensure no outstanding memory transactions + WFI // Wait for interrupt + ISB // Ensure pipeline is flushed +#endif + +#ifdef TX_LOW_POWER + PUSH {r0-r3} + BL tx_low_power_exit // Exit low power mode + POP {r0-r3} +#endif + +#ifdef TX_PORT_USE_BASEPRI + MOV r4, #0 // Disable BASEPRI masking (enable interrupts) + MSR BASEPRI, r4 +#else + CPSIE i // Enable interrupts +#endif + B __tx_ts_wait // Loop to continue waiting + + /* At this point, we have a new thread ready to go. Clear any newly pended PendSV - since we are + already in the handler! */ +__tx_ts_ready: + MOV r7, #0x08000000 // Build clear PendSV value + MOV r8, #0xE000E000 // Build base NVIC address + STR r7, [r8, #0xD04] // Clear any PendSV + + /* Re-enable interrupts and restore new thread. */ +#ifdef TX_PORT_USE_BASEPRI + MOV r4, #0 // Disable BASEPRI masking (enable interrupts) + MSR BASEPRI, r4 +#else + CPSIE i // Enable interrupts +#endif + B __tx_ts_restore // Restore the thread +// } + + +#if (!defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE)) + // SVC_Handler is not needed when ThreadX is running in single mode. + PUBLIC SVC_Handler +SVC_Handler: + TST lr, #0x04 // Determine return stack from EXC_RETURN bit 2 + ITE EQ + MRSEQ r0, MSP // Get MSP if return stack is MSP + MRSNE r0, PSP // Get PSP if return stack is PSP + + LDR r1, [r0,#24] // Load saved PC from stack + LDRB r1, [r1,#-2] // Load SVC number + + CMP r1, #1 // Is it a secure stack allocate request? + BEQ _tx_svc_secure_alloc // Yes, go there + + CMP r1, #2 // Is it a secure stack free request? + BEQ _tx_svc_secure_free // Yes, go there + + CMP r1, #3 // Is it a secure stack init request? + BEQ _tx_svc_secure_init // Yes, go there + + // Unknown SVC argument - just return + BX lr + +_tx_svc_secure_alloc: + PUSH {r0,lr} // Save SP and EXC_RETURN + LDM r0, {r0-r3} // Load function parameters from stack + BL _tx_thread_secure_mode_stack_allocate + POP {r12,lr} // Restore SP and EXC_RETURN + STR r0,[r12] // Store function return value + BX lr +_tx_svc_secure_free: + PUSH {r0,lr} // Save SP and EXC_RETURN + LDM r0, {r0-r3} // Load function parameters from stack + BL _tx_thread_secure_mode_stack_free + POP {r12,lr} // Restore SP and EXC_RETURN + STR r0,[r12] // Store function return value + BX lr +_tx_svc_secure_init: + PUSH {r0,lr} // Save SP and EXC_RETURN + BL _tx_thread_secure_mode_stack_initialize + POP {r12,lr} // Restore SP and EXC_RETURN + BX lr +#endif // End of ifndef TX_SINGLE_MODE_SECURE, TX_SINGLE_MODE_NON_SECURE + + + PUBLIC _tx_vfp_access +_tx_vfp_access: +#ifdef __ARMVFP__ + VMOV.F32 s0, s0 // Simply access the VFP +#endif + BX lr // Return to caller + END diff --git a/ports/cortex_m52/iar/src/tx_thread_secure_stack.c b/ports/cortex_m52/iar/src/tx_thread_secure_stack.c new file mode 100644 index 000000000..5eafc96c3 --- /dev/null +++ b/ports/cortex_m52/iar/src/tx_thread_secure_stack.c @@ -0,0 +1,583 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +#include "tx_api.h" + +/* If TX_SINGLE_MODE_SECURE or TX_SINGLE_MODE_NON_SECURE is defined, + no secure stack functionality is needed. */ +#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE) + +#define TX_SOURCE_CODE + +#include /* For intrinsic functions. */ +#include "tx_secure_interface.h" /* Interface for NS code. */ + +/* Minimum size of secure stack. */ +#ifndef TX_THREAD_SECURE_STACK_MINIMUM +#define TX_THREAD_SECURE_STACK_MINIMUM 256 +#endif +/* Maximum size of secure stack. */ +#ifndef TX_THREAD_SECURE_STACK_MAXIMUM +#define TX_THREAD_SECURE_STACK_MAXIMUM 1024 +#endif + +/* 8 bytes added to stack size to "seal" stack. */ +#define TX_THREAD_STACK_SEAL_SIZE 8 +#define TX_THREAD_STACK_SEAL_VALUE 0xFEF5EDA5 + +/* max number of Secure context */ +#ifndef TX_MAX_SECURE_CONTEXTS +#define TX_MAX_SECURE_CONTEXTS 32 +#endif +#define TX_INVALID_SECURE_CONTEXT_IDX (-1) + +/* Secure stack info struct to hold stack start, stack limit, + current stack pointer, and pointer to owning thread. + This will be allocated for each thread with a secure stack. */ +typedef struct TX_THREAD_SECURE_STACK_INFO_STRUCT +{ + VOID *tx_thread_secure_stack_ptr; /* Thread's secure stack current pointer */ + VOID *tx_thread_secure_stack_start; /* Thread's secure stack start address */ + VOID *tx_thread_secure_stack_limit; /* Thread's secure stack limit */ + TX_THREAD *tx_thread_ptr; /* Keep track of thread for error handling */ + INT tx_next_free_index; /* Next free index of free secure context */ +} TX_THREAD_SECURE_STACK_INFO; + +/* Static secure contexts */ +static TX_THREAD_SECURE_STACK_INFO tx_thread_secure_context[TX_MAX_SECURE_CONTEXTS]; +/* Head of free secure context */ +static INT tx_head_free_index = 0U; + + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_secure_mode_stack_initialize Cortex-M52/IAR */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function initializes secure mode to use PSP stack. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* status */ +/* */ +/* CALLS */ +/* */ +/* __get_CONTROL Intrinsic to get CONTROL */ +/* __set_CONTROL Intrinsic to set CONTROL */ +/* __set_PSPLIM Intrinsic to set PSP limit */ +/* __set_PSP Intrinsic to set PSP */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_initialize_kernel_enter */ +/* */ +/**************************************************************************/ +__attribute__((cmse_nonsecure_entry)) +UINT _tx_thread_secure_mode_stack_initialize(void) +{ +UINT status; +INT index; + + /* Make sure function is called from interrupt (threads should not call). */ + if (__get_IPSR() == 0) + { + status = TX_CALLER_ERROR; + } + else + { + /* Set secure mode to use PSP. */ + __set_CONTROL(__get_CONTROL() | 2); + + /* Set process stack pointer and stack limit to 0 to throw exception when a thread + without a secure stack calls a secure function that tries to use secure stack. */ + __set_PSPLIM(0); + __set_PSP(0); + + for (index = 0; index < TX_MAX_SECURE_CONTEXTS; index++) + { + + /* Check last index and mark next free to invalid index */ + if(index == (TX_MAX_SECURE_CONTEXTS - 1)) + { + tx_thread_secure_context[index].tx_next_free_index = TX_INVALID_SECURE_CONTEXT_IDX; + } + else + { + tx_thread_secure_context[index].tx_next_free_index = index + 1; + } + } + + status = TX_SUCCESS; + } + return status; +} + + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_secure_mode_stack_allocate Cortex-M52/IAR */ +/* 6.1.11a */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function allocates a thread's secure stack. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Thread control block pointer */ +/* stack_size Size of stack to allocates */ +/* */ +/* OUTPUT */ +/* */ +/* TX_THREAD_ERROR Invalid thread pointer */ +/* TX_SIZE_ERROR Invalid stack size */ +/* TX_CALLER_ERROR Invalid caller of function */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* __get_IPSR Intrinsic to get IPSR */ +/* malloc Compiler's malloc function */ +/* __set_PSPLIM Intrinsic to set PSP limit */ +/* __set_PSP Intrinsic to set PSP */ +/* __TZ_get_PSPLIM_NS Intrinsic to get NS PSP */ +/* */ +/* CALLED BY */ +/* */ +/* SVC Handler */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 09-30-2020 Scott Larson Initial Version 6.1 */ +/* 10-16-2020 Scott Larson Modified comment(s), */ +/* added stack sealing, */ +/* resulting in version 6.1.1 */ +/* 01-31-2022 Himanshu Gupta Modified comments(s), updated */ +/* secure stack allocation, */ +/* resulting in version 6.1.10 */ +/* 05-02-2022 Scott Larson Modified comment(s), added */ +/* TX_INTERRUPT_SAVE_AREA, */ +/* resulting in version 6.1.11a*/ +/* */ +/**************************************************************************/ +__attribute__((cmse_nonsecure_entry)) +UINT _tx_thread_secure_mode_stack_allocate(TX_THREAD *thread_ptr, ULONG stack_size) +{ +TX_INTERRUPT_SAVE_AREA +UINT status; +TX_THREAD_SECURE_STACK_INFO *info_ptr; +UCHAR *stack_mem; +INT secure_context_index; + + status = TX_SUCCESS; + + /* Make sure function is called from interrupt (threads should not call). */ + if (__get_IPSR() == 0) + { + status = TX_CALLER_ERROR; + } + else if (stack_size < TX_THREAD_SECURE_STACK_MINIMUM || stack_size > TX_THREAD_SECURE_STACK_MAXIMUM) + { + status = TX_SIZE_ERROR; + } + + /* Check if thread already has secure stack allocated. */ + else if (thread_ptr -> tx_thread_secure_stack_context != 0) + { + status = TX_THREAD_ERROR; + } + + else + { + TX_DISABLE + + /* Allocate free index for secure stack info. */ + if(tx_head_free_index != TX_INVALID_SECURE_CONTEXT_IDX) + { + secure_context_index = tx_head_free_index; + tx_head_free_index = tx_thread_secure_context[tx_head_free_index].tx_next_free_index; + tx_thread_secure_context[secure_context_index].tx_next_free_index = TX_INVALID_SECURE_CONTEXT_IDX; + } + else + { + secure_context_index = TX_INVALID_SECURE_CONTEXT_IDX; + } + + TX_RESTORE + + if(secure_context_index != TX_INVALID_SECURE_CONTEXT_IDX) + { + info_ptr = &tx_thread_secure_context[secure_context_index]; + + /* If stack info allocated, allocate a stack & seal. */ + stack_mem = malloc(stack_size + TX_THREAD_STACK_SEAL_SIZE); + + if(stack_mem != TX_NULL) + { + /* Secure stack has been allocated, save in the stack info struct. */ + info_ptr -> tx_thread_secure_stack_limit = stack_mem; + info_ptr -> tx_thread_secure_stack_start = stack_mem + stack_size; + info_ptr -> tx_thread_secure_stack_ptr = info_ptr -> tx_thread_secure_stack_start; + info_ptr -> tx_thread_ptr = thread_ptr; + + /* Seal bottom of stack. */ + *(ULONG*)info_ptr -> tx_thread_secure_stack_start = TX_THREAD_STACK_SEAL_VALUE; + + /* Save secure context id (i.e non-zero base index) in thread. */ + thread_ptr -> tx_thread_secure_stack_context = (VOID *)(secure_context_index + 1); + + /* Check if this thread is running by looking at its stack start and PSPLIM_NS */ + if(((ULONG) thread_ptr -> tx_thread_stack_start & 0xFFFFFFF8) == __TZ_get_PSPLIM_NS()) + { + /* If this thread is running, set Secure PSP and PSPLIM. */ + __set_PSPLIM((ULONG)(info_ptr -> tx_thread_secure_stack_limit)); + __set_PSP((ULONG)(info_ptr -> tx_thread_secure_stack_ptr)); + } + } + + else + { + TX_DISABLE + + /* Stack not allocated, free the info struct. */ + tx_thread_secure_context[secure_context_index].tx_next_free_index = tx_head_free_index; + tx_head_free_index = secure_context_index; + TX_RESTORE + + status = TX_NO_MEMORY; + } + } + + else + { + status = TX_NO_MEMORY; + } + } + + return(status); +} + + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_secure_mode_stack_free Cortex-M52/IAR */ +/* 6.1.11a */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function frees a thread's secure stack. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Thread control block pointer */ +/* */ +/* OUTPUT */ +/* */ +/* TX_THREAD_ERROR Invalid thread pointer */ +/* TX_CALLER_ERROR Invalid caller of function */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* __get_IPSR Intrinsic to get IPSR */ +/* free Compiler's free() function */ +/* */ +/* CALLED BY */ +/* */ +/* SVC Handler */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 09-30-2020 Scott Larson Initial Version 6.1 */ +/* 10-16-2020 Scott Larson Modified comment(s), */ +/* resulting in version 6.1.1 */ +/* 01-31-2022 Himanshu Gupta Modified comments(s), updated */ +/* secure stack allocation, */ +/* resulting in version 6.1.10 */ +/* 05-02-2022 Scott Larson Modified comment(s), added */ +/* TX_INTERRUPT_SAVE_AREA, */ +/* resulting in version 6.1.11a*/ +/* */ +/**************************************************************************/ +__attribute__((cmse_nonsecure_entry)) +UINT _tx_thread_secure_mode_stack_free(TX_THREAD *thread_ptr) +{ +TX_INTERRUPT_SAVE_AREA +UINT status; +TX_THREAD_SECURE_STACK_INFO *info_ptr; +INT secure_context_index; + + status = TX_SUCCESS; + + /* Pickup stack info id from thread. */ + secure_context_index = (INT)thread_ptr -> tx_thread_secure_stack_context - 1; + + /* Make sure function is called from interrupt (threads should not call). */ + if (__get_IPSR() == 0) + { + status = TX_CALLER_ERROR; + } + + /* Check if secure context index is in valid range. */ + else if (secure_context_index < 0 || secure_context_index >= TX_MAX_SECURE_CONTEXTS) + { + status = TX_THREAD_ERROR; + } + else + { + + /* Pickup stack info from static array of secure contexts. */ + info_ptr = &tx_thread_secure_context[secure_context_index]; + + /* Check that this secure context is for this thread. */ + if (info_ptr -> tx_thread_ptr != thread_ptr) + { + status = TX_THREAD_ERROR; + } + + else + { + + /* Free secure stack. */ + free(info_ptr -> tx_thread_secure_stack_limit); + + TX_DISABLE + + /* Free info struct. */ + tx_thread_secure_context[secure_context_index].tx_next_free_index = tx_head_free_index; + tx_head_free_index = secure_context_index; + TX_RESTORE + + /* Clear secure context from thread. */ + thread_ptr -> tx_thread_secure_stack_context = 0; + } + } + + return(status); +} + + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_secure_stack_context_save Cortex-M52/IAR */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function saves context of the secure stack. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Thread control block pointer */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* __get_IPSR Intrinsic to get IPSR */ +/* __get_PSP Intrinsic to get PSP */ +/* __set_PSPLIM Intrinsic to set PSP limit */ +/* __set_PSP Intrinsic to set PSP */ +/* */ +/* CALLED BY */ +/* */ +/* PendSV Handler */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 09-30-2020 Scott Larson Initial Version 6.1 */ +/* 10-16-2020 Scott Larson Modified comment(s), */ +/* resulting in version 6.1.1 */ +/* 06-02-2021 Scott Larson Fix stack pointer save, */ +/* resulting in version 6.1.7 */ +/* 01-31-2022 Himanshu Gupta Modified comments(s), updated */ +/* secure stack allocation, */ +/* resulting in version 6.1.10 */ +/* */ +/**************************************************************************/ +__attribute__((cmse_nonsecure_entry)) +void _tx_thread_secure_stack_context_save(TX_THREAD *thread_ptr) +{ +TX_THREAD_SECURE_STACK_INFO *info_ptr; +ULONG sp; +INT secure_context_index = (INT)thread_ptr -> tx_thread_secure_stack_context - 1; + + /* This function should be called from scheduler only. */ + if (__get_IPSR() == 0) + { + return; + } + + /* Check if secure context index is in valid range. */ + else if (secure_context_index < 0 || secure_context_index >= TX_MAX_SECURE_CONTEXTS) + { + return; + } + + /* Pickup the secure context pointer. */ + info_ptr = &tx_thread_secure_context[secure_context_index]; + + /* Check that this secure context is for this thread. */ + if (info_ptr -> tx_thread_ptr != thread_ptr) + { + return; + } + + /* Check that stack pointer is in range */ + sp = __get_PSP(); + if ((sp < (ULONG)info_ptr -> tx_thread_secure_stack_limit) || + (sp > (ULONG)info_ptr -> tx_thread_secure_stack_start)) + { + return; + } + + /* Save stack pointer. */ + info_ptr -> tx_thread_secure_stack_ptr = (VOID *) sp; + + /* Set process stack pointer and stack limit to 0 to throw exception when a thread + without a secure stack calls a secure function that tries to use secure stack. */ + __set_PSPLIM(0); + __set_PSP(0); + + return; +} + + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_secure_stack_context_restore Cortex-M52/IAR */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function restores context of the secure stack. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Thread control block pointer */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* __get_IPSR Intrinsic to get IPSR */ +/* __set_PSPLIM Intrinsic to set PSP limit */ +/* __set_PSP Intrinsic to set PSP */ +/* */ +/* CALLED BY */ +/* */ +/* PendSV Handler */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 09-30-2020 Scott Larson Initial Version 6.1 */ +/* 10-16-2020 Scott Larson Modified comment(s), */ +/* resulting in version 6.1.1 */ +/* 01-31-2022 Himanshu Gupta Modified comments(s), updated */ +/* secure stack allocation, */ +/* resulting in version 6.1.10 */ +/* */ +/**************************************************************************/ +__attribute__((cmse_nonsecure_entry)) +void _tx_thread_secure_stack_context_restore(TX_THREAD *thread_ptr) +{ +TX_THREAD_SECURE_STACK_INFO *info_ptr; +INT secure_context_index = (INT)thread_ptr -> tx_thread_secure_stack_context - 1; + + /* This function should be called from scheduler only. */ + if (__get_IPSR() == 0) + { + return; + } + + /* Check if secure context index is in valid range. */ + else if (secure_context_index < 0 || secure_context_index >= TX_MAX_SECURE_CONTEXTS) + { + return; + } + + /* Pickup the secure context pointer. */ + info_ptr = &tx_thread_secure_context[secure_context_index]; + + /* Check that this secure context is for this thread. */ + if (info_ptr -> tx_thread_ptr != thread_ptr) + { + return; + } + + /* Set stack pointer and limit. */ + __set_PSPLIM((ULONG)info_ptr -> tx_thread_secure_stack_limit); + __set_PSP ((ULONG)info_ptr -> tx_thread_secure_stack_ptr); + + return; +} + +#endif diff --git a/ports/cortex_m52/iar/src/tx_thread_secure_stack_allocate.s b/ports/cortex_m52/iar/src/tx_thread_secure_stack_allocate.s new file mode 100644 index 000000000..99d160a37 --- /dev/null +++ b/ports/cortex_m52/iar/src/tx_thread_secure_stack_allocate.s @@ -0,0 +1,77 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + + SECTION `.text`:CODE:NOROOT(2) + THUMB +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_secure_stack_allocate Cortex-M52/IAR */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function enters the SVC handler to allocate a secure stack. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Thread control block pointer */ +/* stack_size Size of secure stack to */ +/* allocate */ +/* */ +/* OUTPUT */ +/* */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* SVC 1 */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/**************************************************************************/ +// UINT _tx_thread_secure_stack_allocate(TX_THREAD *thread_ptr, ULONG stack_size) +// { + EXPORT _tx_thread_secure_stack_allocate +_tx_thread_secure_stack_allocate: +#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE) + MRS r3, PRIMASK // Save interrupt mask + CPSIE i // Enable interrupts for SVC call + SVC 1 + CMP r3, #0 // If interrupts enabled, just return + BEQ _alloc_return_interrupt_enabled + CPSID i // Otherwise, disable interrupts +#else + MOV r0, #0xFF // Feature not enabled +#endif +_alloc_return_interrupt_enabled + BX lr + END diff --git a/ports/cortex_m52/iar/src/tx_thread_secure_stack_free.s b/ports/cortex_m52/iar/src/tx_thread_secure_stack_free.s new file mode 100644 index 000000000..59f2a12ac --- /dev/null +++ b/ports/cortex_m52/iar/src/tx_thread_secure_stack_free.s @@ -0,0 +1,75 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + + SECTION `.text`:CODE:NOROOT(2) + THUMB +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_secure_stack_free Cortex-M52/IAR */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function enters the SVC handler to free a secure stack. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Thread control block pointer */ +/* */ +/* OUTPUT */ +/* */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* SVC 2 */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/**************************************************************************/ +// UINT _tx_thread_secure_stack_free(TX_THREAD *thread_ptr) +// { + EXPORT _tx_thread_secure_stack_free +_tx_thread_secure_stack_free: +#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE) + MRS r3, PRIMASK // Save interrupt mask + CPSIE i // Enable interrupts for SVC call + SVC 2 + CMP r3, #0 // If interrupts enabled, just return + BEQ _free_return_interrupt_enabled + CPSID i // Otherwise, disable interrupts +#else + MOV r0, #0xFF // Feature not enabled +#endif +_free_return_interrupt_enabled + BX lr + END diff --git a/ports/cortex_m52/iar/src/tx_thread_secure_stack_initialize.s b/ports/cortex_m52/iar/src/tx_thread_secure_stack_initialize.s new file mode 100644 index 000000000..5b3a1e9d8 --- /dev/null +++ b/ports/cortex_m52/iar/src/tx_thread_secure_stack_initialize.s @@ -0,0 +1,71 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + + SECTION `.text`:CODE:NOROOT(2) + THUMB +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_secure_stack_initialize Cortex-M52/IAR */ +/* 6.1.12 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function enters the SVC handler to initialize a secure stack. */ +/* */ +/* INPUT */ +/* */ +/* none */ +/* */ +/* OUTPUT */ +/* */ +/* none */ +/* */ +/* CALLS */ +/* */ +/* SVC 3 */ +/* */ +/* CALLED BY */ +/* */ +/* TX_PORT_SPECIFIC_PRE_INITIALIZATION */ +/**************************************************************************/ +// VOID _tx_thread_secure_stack_initialize(VOID) +// { + EXPORT _tx_thread_secure_stack_initialize +_tx_thread_secure_stack_initialize: +#if !defined(TX_SINGLE_MODE_SECURE) && !defined(TX_SINGLE_MODE_NON_SECURE) + CPSIE i // Enable interrupts for SVC call + SVC 3 + CPSID i // Disable interrupts +#else + MOV r0, #0xFF // Feature not enabled +#endif + BX lr + END diff --git a/ports/cortex_m52/iar/src/tx_thread_stack_build.s b/ports/cortex_m52/iar/src/tx_thread_stack_build.s new file mode 100644 index 000000000..faa3c728c --- /dev/null +++ b/ports/cortex_m52/iar/src/tx_thread_stack_build.s @@ -0,0 +1,132 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + + SECTION `.text`:CODE:NOROOT(2) + THUMB +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_stack_build Cortex-M52/IAR */ +/* 6.1.8 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function builds a stack frame on the supplied thread's stack. */ +/* The stack frame results in a fake interrupt return to the supplied */ +/* function pointer. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Pointer to thread control blk */ +/* function_ptr Pointer to return function */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_thread_create Create thread service */ +/**************************************************************************/ +// VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID)) +// { + PUBLIC _tx_thread_stack_build +_tx_thread_stack_build: + /* Build a fake interrupt frame. The form of the fake interrupt stack + on the Cortex-M should look like the following after it is built: + + Stack Top: + LR Interrupted LR (LR at time of PENDSV) + r4 Initial value for r4 + r5 Initial value for r5 + r6 Initial value for r6 + r7 Initial value for r7 + r8 Initial value for r8 + r9 Initial value for r9 + r10 Initial value for r10 + r11 Initial value for r11 + r0 Initial value for r0 (Hardware stack starts here!!) + r1 Initial value for r1 + r2 Initial value for r2 + r3 Initial value for r3 + r12 Initial value for r12 + lr Initial value for lr + pc Initial value for pc + xPSR Initial value for xPSR + + Stack Bottom: (higher memory address) */ + + LDR r2, [r0, #16] // Pickup end of stack area + BIC r2, r2, #0x7 // Align frame for 8-byte alignment + SUB r2, r2, #68 // Subtract frame size +#ifdef TX_SINGLE_MODE_SECURE + LDR r3, =0xFFFFFFFD // Build initial LR value for secure mode +#else + LDR r3, =0xFFFFFFBC // Build initial LR value to return to non-secure PSP +#endif + STR r3, [r2, #0] // Save on the stack + + /* Actually build the stack frame. */ + + MOV r3, #0 // Build initial register value + STR r3, [r2, #4] // Store initial r4 + STR r3, [r2, #8] // Store initial r5 + STR r3, [r2, #12] // Store initial r6 + STR r3, [r2, #16] // Store initial r7 + STR r3, [r2, #20] // Store initial r8 + STR r3, [r2, #24] // Store initial r9 + STR r3, [r2, #28] // Store initial r10 + STR r3, [r2, #32] // Store initial r11 + + /* Hardware stack follows. */ + + STR r3, [r2, #36] // Store initial r0 + STR r3, [r2, #40] // Store initial r1 + STR r3, [r2, #44] // Store initial r2 + STR r3, [r2, #48] // Store initial r3 + STR r3, [r2, #52] // Store initial r12 + MOV r3, #0xFFFFFFFF // Poison EXC_RETURN value + STR r3, [r2, #56] // Store initial lr + STR r1, [r2, #60] // Store initial pc + MOV r3, #0x01000000 // Only T-bit need be set + STR r3, [r2, #64] // Store initial xPSR + + /* Setup stack pointer. */ + // thread_ptr -> tx_thread_stack_ptr = r2; + + STR r2, [r0, #8] // Save stack pointer in thread's + // control block + BX lr // Return to caller +// } + END diff --git a/ports/cortex_m52/iar/src/tx_thread_system_return.s b/ports/cortex_m52/iar/src/tx_thread_system_return.s new file mode 100644 index 000000000..cc5be4596 --- /dev/null +++ b/ports/cortex_m52/iar/src/tx_thread_system_return.s @@ -0,0 +1,95 @@ +;*************************************************************************** +;* Copyright (c) 2024 Microsoft Corporation +;* Copyright (c) 2026-present 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 +;************************************************************************** + +; Some portions generated by Gemini (Gemini 2.0 Flash). + + +;************************************************************************** + +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + + SECTION `.text`:CODE:NOROOT(2) + THUMB +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_system_return Cortex-M52/IAR */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is target processor specific. It is used to transfer */ +/* control from a thread back to the ThreadX system. Only a */ +/* minimal context is saved since the compiler assumes temp registers */ +/* are going to get slicked by a function call anyway. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_schedule Thread scheduling loop */ +/* */ +/* CALLED BY */ +/* */ +/* ThreadX components */ +/**************************************************************************/ +// VOID _tx_thread_system_return(VOID) +// { + PUBLIC _tx_thread_system_return +_tx_thread_system_return: + /* Return to real scheduler via PendSV. Note that this routine is often + replaced with in-line assembly in tx_port.h to improved performance. */ + + MOV r0, #0x10000000 // Load PENDSVSET bit + MOV r1, #0xE000E000 // Load NVIC base + STR r0, [r1, #0xD04] // Set PENDSVBIT in ICSR + DSB SY // Ensure memory access is complete + ISB SY // Flush pipeline + MRS r0, IPSR // Pickup IPSR + CMP r0, #0 // Is it a thread returning? + BNE _isr_context // If ISR, skip interrupt enable +#ifdef TX_PORT_USE_BASEPRI + MRS r1, BASEPRI // Thread context returning, pickup BASEPRI + MOV r0, #0 + MSR BASEPRI, r0 // Enable interrupts + MSR BASEPRI, r1 // Restore original interrupt posture + ISB SY // Flush pipeline +#else + MRS r1, PRIMASK // Thread context returning, pickup PRIMASK + CPSIE i // Enable interrupts + MSR PRIMASK, r1 // Restore original interrupt posture + ISB SY // Flush pipeline +#endif +_isr_context: + BX lr // Return to caller +// } + END diff --git a/ports/cortex_m52/iar/src/tx_timer_interrupt.s b/ports/cortex_m52/iar/src/tx_timer_interrupt.s new file mode 100644 index 000000000..c4095743b --- /dev/null +++ b/ports/cortex_m52/iar/src/tx_timer_interrupt.s @@ -0,0 +1,248 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Timer */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + + EXTERN _tx_timer_time_slice + EXTERN _tx_timer_system_clock + EXTERN _tx_timer_current_ptr + EXTERN _tx_timer_list_start + EXTERN _tx_timer_list_end + EXTERN _tx_timer_expired_time_slice + EXTERN _tx_timer_expired + EXTERN _tx_thread_time_slice + EXTERN _tx_timer_expiration_process + EXTERN _tx_thread_current_ptr + EXTERN _tx_thread_execute_ptr + EXTERN _tx_thread_preempt_disable + + SECTION `.text`:CODE:NOROOT(2) + THUMB +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_timer_interrupt Cortex-M52/IAR */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function processes the hardware timer interrupt. This */ +/* processing includes incrementing the system clock and checking for */ +/* time slice and/or timer expiration. If either is found, the */ +/* expiration functions are called. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _tx_timer_expiration_process Timer expiration processing */ +/* _tx_thread_time_slice Time slice interrupted thread */ +/* */ +/* CALLED BY */ +/* */ +/* interrupt vector */ +/**************************************************************************/ +// VOID _tx_timer_interrupt(VOID) +// { + PUBLIC _tx_timer_interrupt +_tx_timer_interrupt: + + /* Upon entry to this routine, it is assumed that the compiler scratch registers are available + for use. */ + + /* Increment the system clock. */ + // _tx_timer_system_clock++; + + LDR r1, =_tx_timer_system_clock // Pickup address of system clock + LDR r0, [r1, #0] // Pickup system clock + ADD r0, r0, #1 // Increment system clock + STR r0, [r1, #0] // Store new system clock + + /* Test for time-slice expiration. */ + // if (_tx_timer_time_slice) + // { + + LDR r3, =_tx_timer_time_slice // Pickup address of time-slice + LDR r2, [r3, #0] // Pickup time-slice + CBZ r2, __tx_timer_no_time_slice // Is it non-active? + // Yes, skip time-slice processing + + /* Decrement the time_slice. */ + // _tx_timer_time_slice--; + + SUB r2, r2, #1 // Decrement the time-slice + STR r2, [r3, #0] // Store new time-slice value + + /* Check for expiration. */ + // if (__tx_timer_time_slice == 0) + + CBNZ r2, __tx_timer_no_time_slice // Has it expired? + // No, skip expiration processing + + /* Set the time-slice expired flag. */ + // _tx_timer_expired_time_slice = TX_TRUE; + + LDR r3, =_tx_timer_expired_time_slice // Pickup address of expired flag + MOV r0, #1 // Build expired value + STR r0, [r3, #0] // Set time-slice expiration flag + + // } + +__tx_timer_no_time_slice: + + /* Test for timer expiration. */ + // if (*_tx_timer_current_ptr) + // { + + LDR r1, =_tx_timer_current_ptr // Pickup current timer pointer address + LDR r0, [r1, #0] // Pickup current timer + LDR r2, [r0, #0] // Pickup timer list entry + CBZ r2, __tx_timer_no_timer // Is there anything in the list? + // No, just increment the timer + + /* Set expiration flag. */ + // _tx_timer_expired = TX_TRUE; + + LDR r3, =_tx_timer_expired // Pickup expiration flag address + MOV r2, #1 // Build expired value + STR r2, [r3, #0] // Set expired flag + B __tx_timer_done // Finished timer processing + + // } + // else + // { +__tx_timer_no_timer: + + /* No timer expired, increment the timer pointer. */ + // _tx_timer_current_ptr++; + + ADD r0, r0, #4 // Move to next timer + + /* Check for wrap-around. */ + // if (_tx_timer_current_ptr == _tx_timer_list_end) + + LDR r3, =_tx_timer_list_end // Pickup addr of timer list end + LDR r2, [r3, #0] // Pickup list end + CMP r0, r2 // Are we at list end? + BNE __tx_timer_skip_wrap // No, skip wrap-around logic + + /* Wrap to beginning of list. */ + // _tx_timer_current_ptr = _tx_timer_list_start; + + LDR r3, =_tx_timer_list_start // Pickup addr of timer list start + LDR r0, [r3, #0] // Set current pointer to list start + +__tx_timer_skip_wrap: + + STR r0, [r1, #0] // Store new current timer pointer + // } + +__tx_timer_done: + + /* See if anything has expired. */ + // if ((_tx_timer_expired_time_slice) || (_tx_timer_expired)) + // { + + LDR r3, =_tx_timer_expired_time_slice // Pickup addr of expired flag + LDR r2, [r3, #0] // Pickup time-slice expired flag + CBNZ r2, __tx_something_expired // Did a time-slice expire? + // If non-zero, time-slice expired + LDR r1, =_tx_timer_expired // Pickup addr of other expired flag + LDR r0, [r1, #0] // Pickup timer expired flag + CBZ r0, __tx_timer_nothing_expired // Did a timer expire? + // No, nothing expired + +__tx_something_expired: + + PUSH {r0, lr} // Save the lr register on the stack + // and save r0 just to keep 8-byte alignment + + /* Did a timer expire? */ + // if (_tx_timer_expired) + // { + + LDR r1, =_tx_timer_expired // Pickup addr of expired flag + LDR r0, [r1, #0] // Pickup timer expired flag + CBZ r0, __tx_timer_dont_activate // Check for timer expiration + // If not set, skip timer activation + + /* Process timer expiration. */ + // _tx_timer_expiration_process(); + + BL _tx_timer_expiration_process // Call the timer expiration handling routine + + // } +__tx_timer_dont_activate: + + /* Did time slice expire? */ + // if (_tx_timer_expired_time_slice) + // { + + LDR r3, =_tx_timer_expired_time_slice // Pickup addr of time-slice expired + LDR r2, [r3, #0] // Pickup the actual flag + CBZ r2, __tx_timer_not_ts_expiration // See if the flag is set + // No, skip time-slice processing + + /* Time slice interrupted thread. */ + // _tx_thread_time_slice(); + + BL _tx_thread_time_slice // Call time-slice processing + LDR r0, =_tx_thread_preempt_disable // Build address of preempt disable flag + LDR r1, [r0] // Is the preempt disable flag set? + CBNZ r1, __tx_timer_skip_time_slice // Yes, skip the PendSV logic + LDR r0, =_tx_thread_current_ptr // Build current thread pointer address + LDR r1, [r0] // Pickup the current thread pointer + LDR r2, =_tx_thread_execute_ptr // Build execute thread pointer address + LDR r3, [r2] // Pickup the execute thread pointer + LDR r0, =0xE000ED04 // Build address of control register + LDR r2, =0x10000000 // Build value for PendSV bit + CMP r1, r3 // Are they the same? + BEQ __tx_timer_skip_time_slice // If the same, there was no time-slice performed + STR r2, [r0] // Not the same, issue the PendSV for preemption +__tx_timer_skip_time_slice: + // } + +__tx_timer_not_ts_expiration: + + POP {r0, lr} // Recover lr register (r0 is just there for + // the 8-byte stack alignment + + // } + +__tx_timer_nothing_expired: + + DSB // Complete all memory access + BX lr // Return to caller +// } + END diff --git a/ports/cortex_m52/iar/src/txe_thread_secure_stack_allocate.c b/ports/cortex_m52/iar/src/txe_thread_secure_stack_allocate.c new file mode 100644 index 000000000..a37436dd7 --- /dev/null +++ b/ports/cortex_m52/iar/src/txe_thread_secure_stack_allocate.c @@ -0,0 +1,113 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_initialize.h" +#include "tx_thread.h" + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_thread_secure_stack_allocate Cortex-M52 */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the secure stack allocate */ +/* function call. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Thread control block pointer */ +/* stack_size Size of secure stack to */ +/* allocate */ +/* */ +/* OUTPUT */ +/* */ +/* TX_THREAD_ERROR Invalid thread pointer */ +/* TX_CALLER_ERROR Invalid caller of function */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_secure_stack_allocate Actual stack alloc function */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/**************************************************************************/ +UINT _txe_thread_secure_stack_allocate(TX_THREAD *thread_ptr, ULONG stack_size) +{ +#if defined(TX_SINGLE_MODE_SECURE) || defined(TX_SINGLE_MODE_NON_SECURE) + return(TX_FEATURE_NOT_ENABLED); +#else +UINT status; + + /* Default status to success. */ + status = TX_SUCCESS; + + /* Check for an invalid thread pointer. */ + if (thread_ptr == TX_NULL) + { + /* Thread pointer is invalid, return appropriate error code. */ + status = TX_THREAD_ERROR; + } + + /* Now check for invalid thread ID. */ + else if (thread_ptr -> tx_thread_id != TX_THREAD_ID) + { + /* Thread pointer is invalid, return appropriate error code. */ + status = TX_THREAD_ERROR; + } + + /* Check for interrupt call. */ + if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0)) + { + /* Is call from an interrupt and not initialization? */ + if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS) + { + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } + } + + /* Determine if everything is okay. */ + if (status == TX_SUCCESS) + { + /* Call actual secure stack allocate function. */ + status = _tx_thread_secure_stack_allocate(thread_ptr, stack_size); + } + + /* Return completion status. */ + return(status); +#endif +} diff --git a/ports/cortex_m52/iar/src/txe_thread_secure_stack_free.c b/ports/cortex_m52/iar/src/txe_thread_secure_stack_free.c new file mode 100644 index 000000000..b7e4b7d5c --- /dev/null +++ b/ports/cortex_m52/iar/src/txe_thread_secure_stack_free.c @@ -0,0 +1,114 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Thread */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + + +/* Include necessary system files. */ + +#include "tx_api.h" +#include "tx_initialize.h" +#include "tx_thread.h" + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txe_thread_secure_stack_free Cortex-M52 */ +/* 6.1 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks for errors in the secure stack free */ +/* function call. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Thread control block pointer */ +/* */ +/* OUTPUT */ +/* */ +/* TX_THREAD_ERROR Invalid thread pointer */ +/* TX_CALLER_ERROR Invalid caller of function */ +/* status Actual completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_secure_stack_free Actual stack free function */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/**************************************************************************/ +UINT _txe_thread_secure_stack_free(TX_THREAD *thread_ptr) +{ +#if defined(TX_SINGLE_MODE_SECURE) || defined(TX_SINGLE_MODE_NON_SECURE) + return(TX_FEATURE_NOT_ENABLED); +#else +UINT status; + + /* Default status to success. */ + status = TX_SUCCESS; + + /* Check for an invalid thread pointer. */ + if (thread_ptr == TX_NULL) + { + + /* Thread pointer is invalid, return appropriate error code. */ + status = TX_THREAD_ERROR; + } + + /* Now check for invalid thread ID. */ + else if (thread_ptr -> tx_thread_id != TX_THREAD_ID) + { + + /* Thread pointer is invalid, return appropriate error code. */ + status = TX_THREAD_ERROR; + } + + /* Check for interrupt call. */ + if (TX_THREAD_GET_SYSTEM_STATE() != ((ULONG) 0)) + { + /* Is call from an interrupt and not initialization? */ + if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS) + { + /* Invalid caller of this function, return appropriate error code. */ + status = TX_CALLER_ERROR; + } + } + + /* Determine if everything is okay. */ + if (status == TX_SUCCESS) + { + + /* Call actual secure stack allocate function. */ + status = _tx_thread_secure_stack_free(thread_ptr); + } + + /* Return completion status. */ + return(status); +#endif +} diff --git a/scripts/check_clang.sh b/scripts/check_clang.sh index 5f13c4914..ca646f312 100755 --- a/scripts/check_clang.sh +++ b/scripts/check_clang.sh @@ -96,6 +96,7 @@ declare -A PORT_TARGET=( [cortex_m7]="arm-none-eabi cortex-m7 -mthumb" [cortex_m23]="arm-none-eabi cortex-m23 -mthumb" [cortex_m33]="arm-none-eabi cortex-m33 -mthumb" + [cortex_m52]="arm-none-eabi cortex-m52 -mthumb -mfloat-abi=hard" [cortex_m55]="arm-none-eabi cortex-m55 -mthumb -mfloat-abi=hard" [cortex_m85]="arm-none-eabi cortex-m85 -mthumb -mfloat-abi=hard" [cortex_a5]="arm-none-eabi cortex-a5" diff --git a/scripts/copy_armv8_m.sh b/scripts/copy_armv8_m.sh index c66cc11ed..f17d7bb91 100755 --- a/scripts/copy_armv8_m.sh +++ b/scripts/copy_armv8_m.sh @@ -18,7 +18,7 @@ set -e ports_folder="ports" source_folder="ports_arch/ARMv8-M/threadx" -target_mcu="cortex_m33 cortex_m55 cortex_m85" +target_mcu="cortex_m33 cortex_m52 cortex_m55 cortex_m85" source_inc_folder="$source_folder/inc" target_inc_mcu=$target_mcu target_inc_ide="ac6 gnu iar" @@ -112,4 +112,4 @@ do rm -f $target cp -f $src $target done -done \ No newline at end of file +done From 0e7db2bf793e624ed50855baf2a2a0ad1d0d7cc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Sun, 16 Aug 2026 08:42:53 -0400 Subject: [PATCH 051/181] Stopped the generated Armv8-M readmes claiming a false origin date (#623) Every Armv8-M port readme ends with 09-30-2020 Initial ThreadX 6.1 version for Cortex-M85 using GNU tools. with the core name substituted in by scripts/copy_armv8_m.sh. The date is the shared port's, so each core inherits it whatever its own history: Cortex-M85 was announced in 2022 and its readme claims a 2020 origin, and any core added later gets the same treatment the moment its name joins the generator's list. The rest of the history block is accurate, since it records changes to the shared files. Only the closing line asserts something per-core. Reword it to describe the Armv8-M port itself, and say where a given core's real starting point is. Regenerating updates the twelve readmes for cortex_m33, cortex_m52, cortex_m55 and cortex_m85 across the three toolchains. Cortex-M52 makes the point: it arrived in #519 and its readme immediately claimed a 2020 origin for a core announced in 2023. The ARMv7-M templates say "Initial ThreadX version 6.1.7 for Cortex-M", with no placeholder to substitute, so they make no per-core claim and are left alone. Assisted-by: Claude Code (Opus 5) --- ports/cortex_m33/ac6/readme_threadx.txt | 7 ++++++- ports/cortex_m33/gnu/readme_threadx.txt | 7 ++++++- ports/cortex_m33/iar/readme_threadx.txt | 7 ++++++- ports/cortex_m52/ac6/readme_threadx.txt | 7 ++++++- ports/cortex_m52/gnu/readme_threadx.txt | 7 ++++++- ports/cortex_m52/iar/readme_threadx.txt | 7 ++++++- ports/cortex_m55/ac6/readme_threadx.txt | 7 ++++++- ports/cortex_m55/gnu/readme_threadx.txt | 7 ++++++- ports/cortex_m55/iar/readme_threadx.txt | 7 ++++++- ports/cortex_m85/ac6/readme_threadx.txt | 7 ++++++- ports/cortex_m85/gnu/readme_threadx.txt | 7 ++++++- ports/cortex_m85/iar/readme_threadx.txt | 7 ++++++- ports_arch/ARMv8-M/threadx/ac6/readme_threadx.txt | 7 ++++++- ports_arch/ARMv8-M/threadx/gnu/readme_threadx.txt | 7 ++++++- ports_arch/ARMv8-M/threadx/iar/readme_threadx.txt | 7 ++++++- 15 files changed, 90 insertions(+), 15 deletions(-) diff --git a/ports/cortex_m33/ac6/readme_threadx.txt b/ports/cortex_m33/ac6/readme_threadx.txt index a99a096a6..72edd57ea 100644 --- a/ports/cortex_m33/ac6/readme_threadx.txt +++ b/ports/cortex_m33/ac6/readme_threadx.txt @@ -218,7 +218,12 @@ information associated with this specific port of ThreadX: 03-02-2021 The following files were changed/added for version 6.1.5: tx_port.h Added ULONG64_DEFINED -09-30-2020 Initial ThreadX 6.1 version for Cortex-M33 using AC6 tools. +09-30-2020 Initial ThreadX 6.1 version of this Armv8-M port using AC6 tools. + + The dates above belong to this shared port, which every Armv8-M + core is generated from. They are not the date a particular core + gained a ThreadX port: that is when its name was added to + scripts/copy_armv8_m.sh. Copyright(c) 1996-2020 Microsoft Corporation diff --git a/ports/cortex_m33/gnu/readme_threadx.txt b/ports/cortex_m33/gnu/readme_threadx.txt index 79efe0eb8..ac337d552 100644 --- a/ports/cortex_m33/gnu/readme_threadx.txt +++ b/ports/cortex_m33/gnu/readme_threadx.txt @@ -200,7 +200,12 @@ information associated with this specific port of ThreadX: 03-02-2021 The following files were changed/added for version 6.1.5: tx_port.h Added ULONG64_DEFINED -09-30-2020 Initial ThreadX 6.1 version for Cortex-M33 using GNU tools. +09-30-2020 Initial ThreadX 6.1 version of this Armv8-M port using GNU tools. + + The dates above belong to this shared port, which every Armv8-M + core is generated from. They are not the date a particular core + gained a ThreadX port: that is when its name was added to + scripts/copy_armv8_m.sh. Copyright(c) 1996-2020 Microsoft Corporation diff --git a/ports/cortex_m33/iar/readme_threadx.txt b/ports/cortex_m33/iar/readme_threadx.txt index ee6af2fa2..1fca923a7 100644 --- a/ports/cortex_m33/iar/readme_threadx.txt +++ b/ports/cortex_m33/iar/readme_threadx.txt @@ -211,7 +211,12 @@ information associated with this specific port of ThreadX: 03-02-2021 The following files were changed/added for version 6.1.5: tx_port.h Added ULONG64_DEFINED -09-30-2020 Initial ThreadX 6.1 version for Cortex-M33 using IAR's ARM tools. +09-30-2020 Initial ThreadX 6.1 version of this Armv8-M port using IAR's ARM tools. + + The dates above belong to this shared port, which every Armv8-M + core is generated from. They are not the date a particular core + gained a ThreadX port: that is when its name was added to + scripts/copy_armv8_m.sh. Copyright(c) 1996-2020 Microsoft Corporation diff --git a/ports/cortex_m52/ac6/readme_threadx.txt b/ports/cortex_m52/ac6/readme_threadx.txt index 2149ab351..b05b6f860 100644 --- a/ports/cortex_m52/ac6/readme_threadx.txt +++ b/ports/cortex_m52/ac6/readme_threadx.txt @@ -218,7 +218,12 @@ information associated with this specific port of ThreadX: 03-02-2021 The following files were changed/added for version 6.1.5: tx_port.h Added ULONG64_DEFINED -09-30-2020 Initial ThreadX 6.1 version for Cortex-M52 using AC6 tools. +09-30-2020 Initial ThreadX 6.1 version of this Armv8-M port using AC6 tools. + + The dates above belong to this shared port, which every Armv8-M + core is generated from. They are not the date a particular core + gained a ThreadX port: that is when its name was added to + scripts/copy_armv8_m.sh. Copyright(c) 1996-2020 Microsoft Corporation diff --git a/ports/cortex_m52/gnu/readme_threadx.txt b/ports/cortex_m52/gnu/readme_threadx.txt index 9278ed82c..ab851d198 100644 --- a/ports/cortex_m52/gnu/readme_threadx.txt +++ b/ports/cortex_m52/gnu/readme_threadx.txt @@ -200,7 +200,12 @@ information associated with this specific port of ThreadX: 03-02-2021 The following files were changed/added for version 6.1.5: tx_port.h Added ULONG64_DEFINED -09-30-2020 Initial ThreadX 6.1 version for Cortex-M52 using GNU tools. +09-30-2020 Initial ThreadX 6.1 version of this Armv8-M port using GNU tools. + + The dates above belong to this shared port, which every Armv8-M + core is generated from. They are not the date a particular core + gained a ThreadX port: that is when its name was added to + scripts/copy_armv8_m.sh. Copyright(c) 1996-2020 Microsoft Corporation diff --git a/ports/cortex_m52/iar/readme_threadx.txt b/ports/cortex_m52/iar/readme_threadx.txt index 116fadead..a2d638b29 100644 --- a/ports/cortex_m52/iar/readme_threadx.txt +++ b/ports/cortex_m52/iar/readme_threadx.txt @@ -211,7 +211,12 @@ information associated with this specific port of ThreadX: 03-02-2021 The following files were changed/added for version 6.1.5: tx_port.h Added ULONG64_DEFINED -09-30-2020 Initial ThreadX 6.1 version for Cortex-M52 using IAR's ARM tools. +09-30-2020 Initial ThreadX 6.1 version of this Armv8-M port using IAR's ARM tools. + + The dates above belong to this shared port, which every Armv8-M + core is generated from. They are not the date a particular core + gained a ThreadX port: that is when its name was added to + scripts/copy_armv8_m.sh. Copyright(c) 1996-2020 Microsoft Corporation diff --git a/ports/cortex_m55/ac6/readme_threadx.txt b/ports/cortex_m55/ac6/readme_threadx.txt index 63e8196e4..a38a97946 100644 --- a/ports/cortex_m55/ac6/readme_threadx.txt +++ b/ports/cortex_m55/ac6/readme_threadx.txt @@ -218,7 +218,12 @@ information associated with this specific port of ThreadX: 03-02-2021 The following files were changed/added for version 6.1.5: tx_port.h Added ULONG64_DEFINED -09-30-2020 Initial ThreadX 6.1 version for Cortex-M55 using AC6 tools. +09-30-2020 Initial ThreadX 6.1 version of this Armv8-M port using AC6 tools. + + The dates above belong to this shared port, which every Armv8-M + core is generated from. They are not the date a particular core + gained a ThreadX port: that is when its name was added to + scripts/copy_armv8_m.sh. Copyright(c) 1996-2020 Microsoft Corporation diff --git a/ports/cortex_m55/gnu/readme_threadx.txt b/ports/cortex_m55/gnu/readme_threadx.txt index 3358694de..b76a0bed4 100644 --- a/ports/cortex_m55/gnu/readme_threadx.txt +++ b/ports/cortex_m55/gnu/readme_threadx.txt @@ -200,7 +200,12 @@ information associated with this specific port of ThreadX: 03-02-2021 The following files were changed/added for version 6.1.5: tx_port.h Added ULONG64_DEFINED -09-30-2020 Initial ThreadX 6.1 version for Cortex-M55 using GNU tools. +09-30-2020 Initial ThreadX 6.1 version of this Armv8-M port using GNU tools. + + The dates above belong to this shared port, which every Armv8-M + core is generated from. They are not the date a particular core + gained a ThreadX port: that is when its name was added to + scripts/copy_armv8_m.sh. Copyright(c) 1996-2020 Microsoft Corporation diff --git a/ports/cortex_m55/iar/readme_threadx.txt b/ports/cortex_m55/iar/readme_threadx.txt index dcbee39eb..92162e2f3 100644 --- a/ports/cortex_m55/iar/readme_threadx.txt +++ b/ports/cortex_m55/iar/readme_threadx.txt @@ -211,7 +211,12 @@ information associated with this specific port of ThreadX: 03-02-2021 The following files were changed/added for version 6.1.5: tx_port.h Added ULONG64_DEFINED -09-30-2020 Initial ThreadX 6.1 version for Cortex-M55 using IAR's ARM tools. +09-30-2020 Initial ThreadX 6.1 version of this Armv8-M port using IAR's ARM tools. + + The dates above belong to this shared port, which every Armv8-M + core is generated from. They are not the date a particular core + gained a ThreadX port: that is when its name was added to + scripts/copy_armv8_m.sh. Copyright(c) 1996-2020 Microsoft Corporation diff --git a/ports/cortex_m85/ac6/readme_threadx.txt b/ports/cortex_m85/ac6/readme_threadx.txt index abe80bf85..ea35c52de 100644 --- a/ports/cortex_m85/ac6/readme_threadx.txt +++ b/ports/cortex_m85/ac6/readme_threadx.txt @@ -218,7 +218,12 @@ information associated with this specific port of ThreadX: 03-02-2021 The following files were changed/added for version 6.1.5: tx_port.h Added ULONG64_DEFINED -09-30-2020 Initial ThreadX 6.1 version for Cortex-M85 using AC6 tools. +09-30-2020 Initial ThreadX 6.1 version of this Armv8-M port using AC6 tools. + + The dates above belong to this shared port, which every Armv8-M + core is generated from. They are not the date a particular core + gained a ThreadX port: that is when its name was added to + scripts/copy_armv8_m.sh. Copyright(c) 1996-2020 Microsoft Corporation diff --git a/ports/cortex_m85/gnu/readme_threadx.txt b/ports/cortex_m85/gnu/readme_threadx.txt index d497b0376..afebaf3ed 100644 --- a/ports/cortex_m85/gnu/readme_threadx.txt +++ b/ports/cortex_m85/gnu/readme_threadx.txt @@ -200,7 +200,12 @@ information associated with this specific port of ThreadX: 03-02-2021 The following files were changed/added for version 6.1.5: tx_port.h Added ULONG64_DEFINED -09-30-2020 Initial ThreadX 6.1 version for Cortex-M85 using GNU tools. +09-30-2020 Initial ThreadX 6.1 version of this Armv8-M port using GNU tools. + + The dates above belong to this shared port, which every Armv8-M + core is generated from. They are not the date a particular core + gained a ThreadX port: that is when its name was added to + scripts/copy_armv8_m.sh. Copyright(c) 1996-2020 Microsoft Corporation diff --git a/ports/cortex_m85/iar/readme_threadx.txt b/ports/cortex_m85/iar/readme_threadx.txt index 6436cfa82..29a246cbb 100644 --- a/ports/cortex_m85/iar/readme_threadx.txt +++ b/ports/cortex_m85/iar/readme_threadx.txt @@ -211,7 +211,12 @@ information associated with this specific port of ThreadX: 03-02-2021 The following files were changed/added for version 6.1.5: tx_port.h Added ULONG64_DEFINED -09-30-2020 Initial ThreadX 6.1 version for Cortex-M85 using IAR's ARM tools. +09-30-2020 Initial ThreadX 6.1 version of this Armv8-M port using IAR's ARM tools. + + The dates above belong to this shared port, which every Armv8-M + core is generated from. They are not the date a particular core + gained a ThreadX port: that is when its name was added to + scripts/copy_armv8_m.sh. Copyright(c) 1996-2020 Microsoft Corporation diff --git a/ports_arch/ARMv8-M/threadx/ac6/readme_threadx.txt b/ports_arch/ARMv8-M/threadx/ac6/readme_threadx.txt index 87556be57..e835b1093 100644 --- a/ports_arch/ARMv8-M/threadx/ac6/readme_threadx.txt +++ b/ports_arch/ARMv8-M/threadx/ac6/readme_threadx.txt @@ -218,7 +218,12 @@ information associated with this specific port of ThreadX: 03-02-2021 The following files were changed/added for version 6.1.5: tx_port.h Added ULONG64_DEFINED -09-30-2020 Initial ThreadX 6.1 version for Cortex-Mxx using AC6 tools. +09-30-2020 Initial ThreadX 6.1 version of this Armv8-M port using AC6 tools. + + The dates above belong to this shared port, which every Armv8-M + core is generated from. They are not the date a particular core + gained a ThreadX port: that is when its name was added to + scripts/copy_armv8_m.sh. Copyright(c) 1996-2020 Microsoft Corporation diff --git a/ports_arch/ARMv8-M/threadx/gnu/readme_threadx.txt b/ports_arch/ARMv8-M/threadx/gnu/readme_threadx.txt index 2cce95a4b..907d63356 100644 --- a/ports_arch/ARMv8-M/threadx/gnu/readme_threadx.txt +++ b/ports_arch/ARMv8-M/threadx/gnu/readme_threadx.txt @@ -200,7 +200,12 @@ information associated with this specific port of ThreadX: 03-02-2021 The following files were changed/added for version 6.1.5: tx_port.h Added ULONG64_DEFINED -09-30-2020 Initial ThreadX 6.1 version for Cortex-Mxx using GNU tools. +09-30-2020 Initial ThreadX 6.1 version of this Armv8-M port using GNU tools. + + The dates above belong to this shared port, which every Armv8-M + core is generated from. They are not the date a particular core + gained a ThreadX port: that is when its name was added to + scripts/copy_armv8_m.sh. Copyright(c) 1996-2020 Microsoft Corporation diff --git a/ports_arch/ARMv8-M/threadx/iar/readme_threadx.txt b/ports_arch/ARMv8-M/threadx/iar/readme_threadx.txt index e0f46665a..0cd743bd9 100644 --- a/ports_arch/ARMv8-M/threadx/iar/readme_threadx.txt +++ b/ports_arch/ARMv8-M/threadx/iar/readme_threadx.txt @@ -211,7 +211,12 @@ information associated with this specific port of ThreadX: 03-02-2021 The following files were changed/added for version 6.1.5: tx_port.h Added ULONG64_DEFINED -09-30-2020 Initial ThreadX 6.1 version for Cortex-Mxx using IAR's ARM tools. +09-30-2020 Initial ThreadX 6.1 version of this Armv8-M port using IAR's ARM tools. + + The dates above belong to this shared port, which every Armv8-M + core is generated from. They are not the date a particular core + gained a ThreadX port: that is when its name was added to + scripts/copy_armv8_m.sh. Copyright(c) 1996-2020 Microsoft Corporation From 2f378a4c8e934b1694adb93cd666318455115b9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Sun, 16 Aug 2026 09:45:23 -0400 Subject: [PATCH 052/181] Stopped POSIX mq_send() leaking the message buffer when the send fails (#624) mq_send() allocates a private buffer from the queue's own byte pool, copies the caller's message into it, and passes the buffer's address through the queue. The receiver takes ownership: px_mq_receive.c releases the buffer once it has copied the message out. If tx_queue_send() fails, the message never reaches the queue, so no receiver will ever release that buffer. mq_send() returned ERROR while still holding the only pointer to it, leaking it from the pool. The failure is reachable. With TX_WAIT_FOREVER the send suspends, and tx_queue_send() then returns the thread's suspend status. tx_thread_wait_abort() sets TX_WAIT_ABORTED on a suspended sender, and the queue survives that, so the pool keeps shrinking with every aborted send. Queue deletion also reaches the branch, via TX_DELETED, but vq_message_area is a TX_BYTE_POOL embedded in the queue structure and destroyed with it, so nothing outlives the failure there. Exhausting the pool does not merely make later calls fail. tx_byte_allocate() failure runs into posix_internal_error(9999), which busy-loops forever on a non-zero code, so a caller hangs rather than getting an error back. Release the buffer before returning. The EINTR reporting is unchanged, since TX_WAIT_ABORTED maps onto it reasonably. Reported-by: K-ANOY Assisted-by: Claude Code (Opus 5) --- utility/rtos_compatibility_layers/posix/px_mq_send.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/utility/rtos_compatibility_layers/posix/px_mq_send.c b/utility/rtos_compatibility_layers/posix/px_mq_send.c index 464af01f0..d47028080 100644 --- a/utility/rtos_compatibility_layers/posix/px_mq_send.c +++ b/utility/rtos_compatibility_layers/posix/px_mq_send.c @@ -60,6 +60,7 @@ /* */ /* tx_thread_identify returns currently running thread */ /* tx_byte_allocate allocate memory */ +/* tx_byte_release release memory */ /* tx_queue_send ThreadX queue send */ /* posix_priority_search search message for same priority */ /* */ @@ -201,9 +202,14 @@ ULONG msg[TX_POSIX_MESSAGE_SIZE]; temp1 = tx_queue_send(Queue, msg, TX_WAIT_FOREVER); if ( temp1 != TX_SUCCESS) { + /* The message was never handed over to the queue, so this function + still owns the private buffer. Release it before returning, + otherwise it is leaked from the queue's byte pool. */ + tx_byte_release(bp); + /* POSIX doesn't have error for this, hence give default. */ posix_errno = EINTR ; - posix_set_pthread_errno(EINTR); + posix_set_pthread_errno(EINTR); /* Return ERROR. */ return(ERROR); From 3501c5c31d9945b77649fec94382821f50d6148e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Sun, 16 Aug 2026 18:24:25 -0400 Subject: [PATCH 053/181] Stopped two POSIX call sites falling through their error handler (#625) posix_internal_error() never comes back for a non-zero code: its body is "while (error_code) { ; }". Most callers in the layer still follow it with an explicit error return. Two do not, and both fall through into a pointer dereference, so they are only correct because the handler happens to hang. That is a fragile thing to rely on. The C standard permits an implementation to assume a loop with no side effects terminates (C11 6.8.5p6), so the guarantee is a property of the toolchain rather than of the language. Both toolchains the project supports do preserve the loop today - checked with GCC 14.3 at -O0, -O1, -O2 and -Os, and with Clang 22 at -O0 and -O2 - so nothing is broken right now. Neither call site should depend on that. mq_send() falls through with bp indeterminate, having just been told the allocation failed, and would copy msg_len bytes through it. Report ENOMEM and return ERROR instead. posix_thread2tid() falls through with thread_ptr NULL. posix_thread2tcb() returns NULL for that input, and the next line reads p_tcb->pthreadID. Return zero, which is never a valid pthread ID because px_pth_create.c assigns the address of the TCB as the ID. No behaviour changes while the handler keeps hanging; both additions are unreachable today. Assisted-by: Claude Code (Opus 5) --- utility/rtos_compatibility_layers/posix/px_mq_send.c | 11 ++++++++++- utility/rtos_compatibility_layers/posix/px_pth_init.c | 8 +++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/utility/rtos_compatibility_layers/posix/px_mq_send.c b/utility/rtos_compatibility_layers/posix/px_mq_send.c index d47028080..f641419a4 100644 --- a/utility/rtos_compatibility_layers/posix/px_mq_send.c +++ b/utility/rtos_compatibility_layers/posix/px_mq_send.c @@ -167,7 +167,16 @@ ULONG msg[TX_POSIX_MESSAGE_SIZE]; if (temp1 != TX_SUCCESS) { - posix_internal_error(9999); + posix_internal_error(9999); + + /* posix_internal_error() does not return today, but do not depend on + that: bp is indeterminate here, so falling through would copy + msg_len bytes through an unset pointer. */ + posix_errno = ENOMEM; + posix_set_pthread_errno(ENOMEM); + + /* Return ERROR. */ + return(ERROR); } /* Got the memory , Setup source and destination pointers Cast them in UCHAR as message length is in bytes. */ diff --git a/utility/rtos_compatibility_layers/posix/px_pth_init.c b/utility/rtos_compatibility_layers/posix/px_pth_init.c index 5d2f36adc..a2f97be7d 100644 --- a/utility/rtos_compatibility_layers/posix/px_pth_init.c +++ b/utility/rtos_compatibility_layers/posix/px_pth_init.c @@ -538,7 +538,13 @@ POSIX_TCB *p_tcb; if (!thread_ptr) { /* Not called from a thread - error! */ - posix_internal_error(222); + posix_internal_error(222); + + /* posix_internal_error() does not return today, but do not depend on + that: posix_thread2tcb() hands back NULL for this input and the read + below would dereference it. A pthread ID is the address of the TCB, + so zero is never a valid one. */ + return((pthread_t) 0); } /* Get the TCB for this pthread */ From f184531e7f90cafb53b0d61293ccc597e7ede226 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Sun, 16 Aug 2026 18:24:48 -0400 Subject: [PATCH 054/181] Added the POSIX compatibility layer to the CMake build, with regression tests (#626) * Added the POSIX compatibility layer to the CMake build Nothing in the repository built the POSIX layer. The FreeRTOS layer next to it has had a target since the CMake build was introduced, so the POSIX one was the odd one out, and 106 source files went unbuilt by any target, on any architecture. Add a posix-threadx target, following the FreeRTOS layer's shape: a static library, EXCLUDE_FROM_ALL so the default build is unchanged, linking threadx and publishing its own directory as a PUBLIC include path. The sources live in their own CMakeLists.txt rather than the top-level file, as common/ does, because there are 106 of them. The seven posix_*.c files in the same directory are a demo and standalone signal tests, each with its own entry point, so they stay out of the library. The layer does not suit every configuration, and the target is only offered where it can work: - Hosted simulation ports (linux, win32, win64) build against a C library that already provides errno.h, pthread.h and the rest. The layer replaces those. Its pthread.h even uses _PTHREAD_H, the same include guard as glibc's, so its declarations are skipped wholesale and the build fails on missing types. Neutralising that guard only exposes the real problem: 69 conflicting definitions in a single translation unit, for time_t, struct timespec, sigset_t, pthread_t, pthread_mutex_t, sem_t and more. Both the layer and the C library implement POSIX, and only one of them can define those names. The linux port also emulates threads by calling the C library's pthread_create and sem_wait, which the layer exports itself, so linking the two would divert the port into the layer that sits on top of it. - SMP builds. px_int.h declares _tx_thread_current_ptr as a plain pointer, which is a per-core array under SMP, and the layer tracks no current core. Building the layer for the first time exposed one portability defect worth fixing rather than working around. tx_posix.h defined ssize_t as INT, with a comment conceding it should come from . That is correct only where the C library agrees: on AArch64 newlib makes ssize_t 64 bits, and every translation unit that reached a library header failed to compile. Defer to the library when it has declared the type, keyed on the _*_DECLARED guards newlib uses, and do the same for mode_t, which had the same problem waiting. Where no library declaration exists the previous definitions still apply, so the 32-bit targets that did build are unaffected. Verified by building posix-threadx for arm9, arm11, cortex_m0, cortex_m3, cortex_m4, cortex_m7, cortex_m33, cortex_m55, cortex_m85, cortex_a7, cortex_a9, cortex_r4, cortex_r5, cortex_a34, cortex_a53 and cortex_a55 with arm-gnu-toolchain-14.3.rel1, and for risc-v32 and risc-v64 with riscv64-unknown-elf: 18 of 18, 106 objects each. cortex_a78 has no non-SMP port and fails to configure with or without this change. Linking the result against libthreadx.a leaves only tx_application_define, _tx_initialize_low_level, the optional execution profile hooks, and memset and strlen unresolved, all of which the application or its C library supplies. The default build still produces libthreadx.a and no POSIX library. Compiling is not the same as working, and on the 64-bit targets in that list it is not enough. The layer carries a message by putting the address of a private buffer into the queue, and ULONG is 32 bits on every port, so that address only fits when TX_64_BIT is defined. Without it px_mq_send.c truncates the pointer and px_mq_receive.c casts the truncated value back, which GCC reports as nothing worse than a -Wpointer-to-int-cast warning. Defining TX_64_BIT is not a remedy either: tx_api.h then reaches for the extension pointer macros, which need tx_thread_extension_ptr in the thread control block, and outside ports_smp and ports/linux no port declares it. So the target builds everywhere, but the message queues are only sound on the 32-bit ports. That is pre-existing, it is not made worse here, and it is left for a change of its own. Assisted-by: Claude Code (Opus 5) * Added regression tests for the POSIX compatibility layer The POSIX layer had no tests. The seven posix_*.c programs shipped beside it are demos: they print nothing, report no result and end in infinite loops, so they tell a person watching a debugger something and an automated run nothing. Add a suite under test/posix, laid out like the FreeRTOS one and driven the same way, with scripts/build_posix.sh and scripts/test_posix.sh over a run.sh that takes the same arguments as its RISC-V counterpart. The tests run on emulated hardware because they have nowhere else to go. The layer replaces the C library's POSIX headers and exports the same symbols the linux port calls to emulate threads, so a host build is not available to it. The RISC-V QEMU harness that the ThreadX suite already uses is, and this suite reuses its BSP and testcontrol.c rather than growing copies of them. Three tests to start: - posix_mq_basic_test sends a message through a queue and checks the contents and priority survive the round trip. - posix_mq_send_abort_test covers the leak fixed in #624, by filling a queue, blocking a sender on it, aborting the wait and watching the queue's byte pool. Reverting the fix makes it fail on the pool check, so it measures what it claims to. - posix_pthread_basic_test covers pthread creation, a mutex, a semaphore handoff, pthread_self and collecting an exit value through pthread_join. The queue's pool is sized (mq_maxmsg + 1) * (mq_msgsize + 11), which leaves room for about one message beyond a full queue, so the abort test uses small messages and a shallow queue. With a larger message the first leaked buffer exhausts the pool, tx_byte_allocate fails, and the sender disappears into the endless loop in posix_internal_error() instead of reporting anything. Sizing it this way keeps the failure legible as a pool measurement rather than a timeout. riscv32 only, and the reason is the layer rather than the harness. The layer puts the address of a message buffer into the queue, ULONG is 32 bits on every port, and a 64-bit address only fits there when TX_64_BIT is defined. Defining it makes tx_api.h use the extension pointer macros, which need tx_thread_extension_ptr in the thread control block, and no port outside ports_smp and ports/linux declares it. Configuring for risc-v64 stops with that explanation rather than building something that would corrupt a pointer at runtime. Verified with riscv64-unknown-elf and qemu-system-riscv32: 3 tests across default_build, disable_notify_callbacks_build, stack_checking_build and trace_build, 12 of 12 passing. Assisted-by: Claude Code (Opus 5) --- CMakeLists.txt | 18 ++ scripts/build_posix.sh | 17 ++ scripts/test_posix.sh | 17 ++ test/posix/cmake/CMakeLists.txt | 83 ++++++ test/posix/cmake/regression/CMakeLists.txt | 64 ++++ test/posix/cmake/run.sh | 166 +++++++++++ test/posix/regression/posix_mq_basic_test.c | 159 ++++++++++ .../regression/posix_mq_send_abort_test.c | 273 ++++++++++++++++++ .../regression/posix_pthread_basic_test.c | 192 ++++++++++++ .../posix/CMakeLists.txt | 129 +++++++++ .../posix/tx_posix.h | 15 +- 11 files changed, 1132 insertions(+), 1 deletion(-) create mode 100755 scripts/build_posix.sh create mode 100755 scripts/test_posix.sh create mode 100644 test/posix/cmake/CMakeLists.txt create mode 100644 test/posix/cmake/regression/CMakeLists.txt create mode 100755 test/posix/cmake/run.sh create mode 100644 test/posix/regression/posix_mq_basic_test.c create mode 100644 test/posix/regression/posix_mq_send_abort_test.c create mode 100644 test/posix/regression/posix_pthread_basic_test.c create mode 100644 utility/rtos_compatibility_layers/posix/CMakeLists.txt diff --git a/CMakeLists.txt b/CMakeLists.txt index 546606c15..9fbe6982b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -82,6 +82,24 @@ target_sources(freertos-threadx ) target_link_libraries(freertos-threadx PUBLIC threadx) +# Define the POSIX compatibility layer. It supplies its own errno.h, fcntl.h, +# pthread.h, sched.h, signal.h and time.h, so it cannot be combined with the +# hosted simulation ports: those build against a full C library that already +# provides those headers, and the layer's pthread.h even shares the _PTHREAD_H +# include guard with glibc's. Skip it there rather than offering a target that +# could never build. +# +# It is also single-core by construction: px_int.h declares +# _tx_thread_current_ptr as a plain pointer, which is a per-core array in an SMP +# build, and the layer has no notion of which core it is running on. +if(THREADX_ARCH MATCHES "^(linux|win32|win64)$") + message(STATUS "POSIX compatibility layer not available for ${THREADX_ARCH}") +elseif(THREADX_SMP) + message(STATUS "POSIX compatibility layer not available for SMP builds") +else() + add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/utility/rtos_compatibility_layers/posix) +endif() + # If the user provided an override, copy it to the custom directory if (NOT TX_USER_FILE) message(STATUS "Using default tx_user.h file") diff --git a/scripts/build_posix.sh b/scripts/build_posix.sh new file mode 100755 index 000000000..ac81c8ffa --- /dev/null +++ b/scripts/build_posix.sh @@ -0,0 +1,17 @@ +#!/bin/bash +############################################################################## +# 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. +# +# AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +# The AI-generated portions may be considered public domain (CC0-1.0) +# and not subject to the project's licence. The human contributor has +# reviewed and verified that the code is correct. +# +# SPDX-License-Identifier: MIT and CC0-1.0 +############################################################################## + +$(dirname `realpath $0`)/../test/posix/cmake/run.sh riscv32 build all diff --git a/scripts/test_posix.sh b/scripts/test_posix.sh new file mode 100755 index 000000000..ce851cf4b --- /dev/null +++ b/scripts/test_posix.sh @@ -0,0 +1,17 @@ +#!/bin/bash +############################################################################## +# 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. +# +# AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +# The AI-generated portions may be considered public domain (CC0-1.0) +# and not subject to the project's licence. The human contributor has +# reviewed and verified that the code is correct. +# +# SPDX-License-Identifier: MIT and CC0-1.0 +############################################################################## + +$(dirname `realpath $0`)/../test/posix/cmake/run.sh riscv32 test all diff --git a/test/posix/cmake/CMakeLists.txt b/test/posix/cmake/CMakeLists.txt new file mode 100644 index 000000000..830e69bae --- /dev/null +++ b/test/posix/cmake/CMakeLists.txt @@ -0,0 +1,83 @@ +cmake_minimum_required(VERSION 3.13 FATAL_ERROR) +cmake_policy(SET CMP0054 NEW) +cmake_policy(SET CMP0057 NEW) + +# Regression tests for the POSIX compatibility layer. +# +# The layer cannot run on the hosted simulation ports: it supplies its own +# pthread.h, errno.h, time.h and friends, which collide with the C library's, +# and the linux port emulates threads with the very pthread calls the layer +# exports. These tests therefore run on emulated targets, reusing the RISC-V +# BSP and QEMU setup that the ThreadX RISC-V regression suite already uses. + +project(threadx_posix_test LANGUAGES C ASM) + +set(BUILD_CONFIGURATIONS default_build disable_notify_callbacks_build + stack_checking_build trace_build) +set(CMAKE_CONFIGURATION_TYPES + ${BUILD_CONFIGURATIONS} + CACHE STRING "list of supported configuration types" FORCE) +set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS + ${CMAKE_CONFIGURATION_TYPES}) +list(GET CMAKE_CONFIGURATION_TYPES 0 BUILD_TYPE) +if((NOT CMAKE_BUILD_TYPE) OR (NOT ("${CMAKE_BUILD_TYPE}" IN_LIST + CMAKE_CONFIGURATION_TYPES))) + set(CMAKE_BUILD_TYPE + "${BUILD_TYPE}" + CACHE STRING "Build Type of the project" FORCE) +endif() + +message(STATUS "Build type: ${CMAKE_BUILD_TYPE}") +message(STATUS "Using toolchain file: ${CMAKE_TOOLCHAIN_FILE}.") +message(STATUS "THREADX_ARCH: ${THREADX_ARCH}") + +set(default_build -DTX_QUEUE_MESSAGE_MAX_SIZE=32) +set(disable_notify_callbacks_build -DTX_QUEUE_MESSAGE_MAX_SIZE=32 -DTX_DISABLE_NOTIFY_CALLBACKS) +set(stack_checking_build -DTX_QUEUE_MESSAGE_MAX_SIZE=32 -DTX_ENABLE_STACK_CHECKING) +set(trace_build -DTX_QUEUE_MESSAGE_MAX_SIZE=32 -DTX_ENABLE_EVENT_TRACE) + +# These tests are 32-bit only for now, and the reason is a gap in the layer +# rather than a choice about coverage. +# +# The layer passes a message by putting the address of a private buffer into the +# queue. ULONG is 32 bits on every ThreadX port, including the 64-bit ones, so +# on a 64-bit target that address only fits if TX_64_BIT is defined: the layer +# then splits it across two message words and sizes the message accordingly. +# Without it, px_mq_send.c truncates the pointer to 32 bits and px_mq_receive.c +# casts the truncated value back, which the compiler reports only as a warning. +# +# Defining TX_64_BIT is not a way out either: tx_api.h then uses the extension +# pointer macros, which need tx_thread_extension_ptr in the thread control +# block, and no 64-bit port outside ports_smp and ports/linux declares it. +# Closing that gap belongs with the layer, not with its tests. +if(THREADX_ARCH STREQUAL "risc-v64") + message(FATAL_ERROR + "The POSIX layer cannot run on a 64-bit port yet: it needs TX_64_BIT to " + "carry a 64-bit message pointer, and TX_64_BIT needs a port that declares " + "tx_thread_extension_ptr. Use the riscv32 toolchain file for these tests.") +endif() + +add_compile_options( + -std=c99 + -O0 + -g3 + -fdiagnostics-color + -Werror + -ffunction-sections + -fdata-sections + -DTX_REGRESSION_TEST + -DTEST_STACK_SIZE_PRINTF=4096 + -DEXTERNAL_EXIT + ${${CMAKE_BUILD_TYPE}} +) + +enable_testing() + +# ThreadX itself, plus the posix-threadx target the top-level file defines. +add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/../../.. threadx) + +# Reuse the RISC-V BSP from the ThreadX regression suite rather than keeping a +# second copy of the board support in this tree. +add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/../../tx/cmake/riscv/bsp riscv_bsp) + +add_subdirectory(regression) diff --git a/test/posix/cmake/regression/CMakeLists.txt b/test/posix/cmake/regression/CMakeLists.txt new file mode 100644 index 000000000..c8320b05f --- /dev/null +++ b/test/posix/cmake/regression/CMakeLists.txt @@ -0,0 +1,64 @@ +cmake_minimum_required(VERSION 3.13 FATAL_ERROR) +cmake_policy(SET CMP0057 NEW) + +project(posix_regression_test LANGUAGES C ASM) + +set(SOURCE_DIR ${CMAKE_CURRENT_LIST_DIR}/../../regression) +set(TX_TEST_DIR ${CMAKE_CURRENT_LIST_DIR}/../../../tx/regression) +set(BSP_DIR ${CMAKE_CURRENT_LIST_DIR}/../../../tx/cmake/riscv/bsp) + +if(THREADX_ARCH STREQUAL "risc-v64") + set(QEMU_SYSTEM "qemu-system-riscv64") + set(XLEN_TAG "rv64") +else() + set(QEMU_SYSTEM "qemu-system-riscv32") + set(XLEN_TAG "rv32") +endif() + +set(posix_test_cases + ${SOURCE_DIR}/posix_mq_basic_test.c + ${SOURCE_DIR}/posix_mq_send_abort_test.c + ${SOURCE_DIR}/posix_pthread_basic_test.c +) + +set(WEAK_DEFAULTS_SOURCE ${CMAKE_CURRENT_LIST_DIR}/../../../shared/regression/testcontrol_weak_defaults.c) + +# Weak defaults must be an OBJECT library so all objects are always linked into +# each test executable. A STATIC library would have the linker skip them, since +# weak definitions do not satisfy undefined strong references while scanning an +# archive. +add_library(posix_test_weak_defaults OBJECT ${WEAK_DEFAULTS_SOURCE}) +target_compile_definitions(posix_test_weak_defaults PRIVATE + CTEST BATCH_TEST EXTERNAL_EXIT TEST_STACK_SIZE_PRINTF=4096) +target_compile_options(posix_test_weak_defaults PRIVATE -include stdlib.h) +target_link_libraries(posix_test_weak_defaults PRIVATE azrtos::threadx) + +# testcontrol.c supplies main(), tx_application_define() and +# test_control_return(), and is shared with the ThreadX regression suite. +add_library(posix_test_utility ${TX_TEST_DIR}/testcontrol.c) +target_link_libraries(posix_test_utility PUBLIC riscv_bsp azrtos::threadx) +target_compile_definitions(posix_test_utility PUBLIC + CTEST BATCH_TEST EXTERNAL_EXIT TEST_STACK_SIZE_PRINTF=4096) +target_compile_options(posix_test_utility PUBLIC -include stdlib.h) + +function(register_posix_test test_name) + target_link_options(${test_name} PRIVATE + -T ${BSP_DIR}/link.lds -nostartfiles + -Wl,--gc-sections) + add_test( + NAME ${CMAKE_BUILD_TYPE}::${XLEN_TAG}::${test_name} + COMMAND ${QEMU_SYSTEM} -nographic -smp 1 -bios none -m 128M + -machine virt -kernel $ + ) + set_tests_properties(${CMAKE_BUILD_TYPE}::${XLEN_TAG}::${test_name} + PROPERTIES TIMEOUT 120) +endfunction() + +foreach(test_case ${posix_test_cases}) + get_filename_component(test_name ${test_case} NAME_WE) + add_executable(${test_name} ${test_case} $) + target_link_libraries(${test_name} PRIVATE + -Wl,--whole-archive riscv_bsp -Wl,--no-whole-archive + posix_test_utility posix-threadx) + register_posix_test(${test_name}) +endforeach() diff --git a/test/posix/cmake/run.sh b/test/posix/cmake/run.sh new file mode 100755 index 000000000..aa65f7a73 --- /dev/null +++ b/test/posix/cmake/run.sh @@ -0,0 +1,166 @@ +#!/bin/bash +############################################################################## +# 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. +# +# AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +# The AI-generated portions may be considered public domain (CC0-1.0) +# and not subject to the project's licence. The human contributor has +# reviewed and verified that the code is correct. +# +# SPDX-License-Identifier: MIT and CC0-1.0 +############################################################################## + + +set -e + +# POSIX compatibility layer regression test build/test runner. +# Usage: run.sh [all| ...] +# arch: riscv32 +# +# Only riscv32 is available: the layer cannot carry a 64-bit message pointer +# without TX_64_BIT, and TX_64_BIT needs a port that declares +# tx_thread_extension_ptr. See the comment in ../CMakeLists.txt. + +function help() { + echo "Usage: $0 [all| ...]" + echo "" + echo " arch: riscv32" + echo " command: build | test" + echo "" + echo "Available build configurations:" + for build in ${build_configurations[*]}; do + echo " $build" + done + exit 1 +} + +function validate() { + for build in ${build_configurations[*]}; do + if [ "$1" == "$build" ]; then + return + fi + done + help +} + +function generate() { + local arch=$1 + local build=$2 + local toolchain_file + local build_dir + + toolchain_file="${REPO_ROOT}/cmake/riscv32_gnu.cmake" + + build_dir="build/${arch}_${build}" + cmake -B"$build_dir" -GNinja \ + -DCMAKE_TOOLCHAIN_FILE="$toolchain_file" \ + -DCMAKE_BUILD_TYPE="$build" \ + . +} + +function build() { + local arch=$1 + local build=$2 + cmake --build "build/${arch}_${build}" +} + +function run_test() { + local arch=$1 + local build=$2 + local parallel_jobs=$3 + + pushd "build/${arch}_${build}" + [ -z "${CTEST_PARALLEL_LEVEL}" ] && parallel="-j${parallel_jobs}" + if [ -z "${CTEST_REPEAT_FAIL}" ]; then + repeat_fail=2 + else + repeat_fail=${CTEST_REPEAT_FAIL} + fi + ctest $parallel --timeout 1000 \ + -O "${arch}_${build}.txt" \ + -T test --no-compress-output \ + --test-output-size-passed 4194304 \ + --test-output-size-failed 4194304 \ + --output-on-failure \ + --repeat until-pass:${repeat_fail} \ + --output-junit "${arch}_${build}.xml" + popd +} + +# Determine repo root and script directory +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +REPO_ROOT="$(cd "${SCRIPT_DIR}/../../.." && pwd)" +cd "$SCRIPT_DIR" + +# Parse build configurations from CMakeLists.txt +result=$(sed -n "/(BUILD_CONFIGURATIONS/,/)/p" CMakeLists.txt | sed ':label;N;s/\n/ /;b label' | grep -Pzo "[a-zA-Z0-9_]*build[a-zA-Z0-9_]*\s*" | tr -d '\0') +IFS=' ' +read -ra build_configurations <<< "$result" + +if [ $# -lt 2 ]; then + help +fi + +arch=$1 +shift + +if [ "$arch" != "riscv32" ]; then + echo "Error: arch must be 'riscv32'" + help +fi + +command=$1 +shift + +if [ "$#" == "0" ]; then + builds=${build_configurations[0]} +elif [ "$*" == "all" ]; then + builds=${build_configurations[@]} +else + for item in $*; do + validate "$item" + done + builds=$* +fi + +if [ "$command" == "build" ]; then + for item in $builds; do + generate "$arch" "$item" + echo "" + done + + for item in $builds; do + echo "Building ${arch} ${item}" + build "$arch" "$item" + echo "" + done +elif [ "$command" == "test" ]; then + cores=$(nproc) + if [ -z "${CTEST_PARALLEL_LEVEL}" ]; then + build_counts=$(echo $builds | wc -w) + parallel_jobs=$(($cores / $build_counts)) + parallel_jobs=$(($parallel_jobs + 2)) + pids="" + for item in $builds; do + echo "Testing ${arch} ${item}" + run_test "$arch" "$item" "$parallel_jobs" & + pids+=" $!" + done + exit_code=0 + for p in $pids; do + wait $p || exit_code=$? + done + exit $exit_code + else + for item in $builds; do + echo "Testing ${arch} ${item}" + run_test "$arch" "$item" "$parallel_jobs" + done + fi +else + help +fi diff --git a/test/posix/regression/posix_mq_basic_test.c b/test/posix/regression/posix_mq_basic_test.c new file mode 100644 index 000000000..2ecb1ac80 --- /dev/null +++ b/test/posix/regression/posix_mq_basic_test.c @@ -0,0 +1,159 @@ +/***************************************************************************/ +/* 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. */ +/* */ +/* AI Disclosure: This file was largely AI-generated by Claude Code */ +/* (Opus 5). The AI-generated portions may be considered public domain */ +/* (CC0-1.0) and not subject to the project's licence. The human */ +/* contributor has reviewed and verified that the code is correct. */ +/* */ +/* SPDX-License-Identifier: MIT and CC0-1.0 */ +/***************************************************************************/ + +/* This test is designed to test basic POSIX message queue operation: open a + queue, send a message through it, receive the message back and confirm both + the contents and the priority survived the round trip. */ + +#include +#include "tx_api.h" +#include "pthread.h" + +#define TEST_MESSAGE_SIZE 40 +#define TEST_QUEUE_DEPTH 10 +#define TEST_PRIORITY 3 + +/* Memory the POSIX layer carves its own objects out of. */ +static ULONG posix_region[192 * 1024 / sizeof(ULONG)]; + +static pthread_t worker; +static pthread_attr_t worker_attr; +static mqd_t queue_des; +static struct mq_attr queue_attr; + +extern void test_control_return(UINT status); + +static VOID *worker_entry(VOID *input); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void posix_mq_basic_application_define(void *first_unused_memory) +#endif +{ + +struct sched_param param; +VOID *storage_ptr; + + (void) first_unused_memory; + + /* Bring the POSIX layer up. It returns the first address beyond its own + structures, which is where pthread stacks are taken from. */ + storage_ptr = posix_initialize(posix_region); + + queue_attr.mq_maxmsg = TEST_QUEUE_DEPTH; + queue_attr.mq_msgsize = TEST_MESSAGE_SIZE; + + queue_des = mq_open("mq_basic", O_CREAT | O_RDWR, 0, &queue_attr); + if (queue_des == (mqd_t) ERROR) + { + + printf("Running POSIX Message Queue Basic Test............................. ERROR #1\n"); + test_control_return(1); + } + + pthread_attr_init(&worker_attr); + param.sched_priority = 10; + pthread_attr_setschedparam(&worker_attr, ¶m); + pthread_attr_setstackaddr(&worker_attr, storage_ptr); + + if (pthread_create(&worker, &worker_attr, worker_entry, NULL) != OK) + { + + printf("Running POSIX Message Queue Basic Test............................. ERROR #2\n"); + test_control_return(1); + } +} + + +static VOID *worker_entry(VOID *input) +{ + +CHAR sent[TEST_MESSAGE_SIZE]; +CHAR received[TEST_MESSAGE_SIZE]; +ULONG received_priority; +ssize_t received_length; +INT i; + + (void) input; + + printf("Running POSIX Message Queue Basic Test............................. "); + + /* Build a recognisable payload rather than a constant one, so a message + that is dropped or truncated cannot pass by accident. */ + for (i = 0; i < TEST_MESSAGE_SIZE; i++) + { + + sent[i] = (CHAR) (i + 1); + received[i] = (CHAR) 0; + } + + if (mq_send(queue_des, sent, TEST_MESSAGE_SIZE, TEST_PRIORITY) != OK) + { + + printf("ERROR #3\n"); + test_control_return(1); + } + + received_priority = 0; + received_length = mq_receive(queue_des, received, TEST_MESSAGE_SIZE, &received_priority); + + if (received_length != (ssize_t) TEST_MESSAGE_SIZE) + { + + printf("ERROR #4\n"); + test_control_return(1); + } + + if (received_priority != (ULONG) TEST_PRIORITY) + { + + printf("ERROR #5\n"); + test_control_return(1); + } + + for (i = 0; i < TEST_MESSAGE_SIZE; i++) + { + + if (received[i] != sent[i]) + { + + printf("ERROR #6\n"); + test_control_return(1); + } + } + + if (mq_close(queue_des) != OK) + { + + printf("ERROR #7\n"); + test_control_return(1); + } + + if (mq_unlink("mq_basic") != OK) + { + + printf("ERROR #8\n"); + test_control_return(1); + } + + printf("SUCCESS!\n"); + test_control_return(0); + + return (NULL); +} diff --git a/test/posix/regression/posix_mq_send_abort_test.c b/test/posix/regression/posix_mq_send_abort_test.c new file mode 100644 index 000000000..a4e7e7e69 --- /dev/null +++ b/test/posix/regression/posix_mq_send_abort_test.c @@ -0,0 +1,273 @@ +/***************************************************************************/ +/* 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. */ +/* */ +/* AI Disclosure: This file was largely AI-generated by Claude Code */ +/* (Opus 5). The AI-generated portions may be considered public domain */ +/* (CC0-1.0) and not subject to the project's licence. The human */ +/* contributor has reviewed and verified that the code is correct. */ +/* */ +/* SPDX-License-Identifier: MIT and CC0-1.0 */ +/***************************************************************************/ + +/* This test covers the message buffer mq_send() used to leak when the send + failed, reported as issue #568. + + mq_send() allocates a private buffer from the queue's own byte pool, copies + the caller's message into it and passes the address through the queue. The + receiver owns the buffer from then on and releases it. When the send itself + fails the message never reaches a receiver, so mq_send() has to release the + buffer before returning or it is lost. + + The failure is provoked the way an application would meet it: the queue is + filled, a sender blocks on it, and its wait is aborted. The queue survives, + so any buffer that is not released stays lost. Aborting repeatedly and + watching the queue's byte pool separates the two outcomes: with the buffer + released the pool returns to its original size, and without it the pool + shrinks by a message every time. */ + +#include +#include "tx_api.h" +#include "pthread.h" + +/* The queue's pool is sized (mq_maxmsg + 1) * (mq_msgsize + 11), with a floor + of 100 bytes, so it holds barely more than a full queue. Keep the messages + small and the queue shallow: that floor then leaves room for a few leaked + buffers to accumulate and be measured, instead of exhausting the pool on the + first one and hanging the sender inside posix_internal_error(). */ +#define TEST_MESSAGE_SIZE 8 +#define TEST_QUEUE_DEPTH 1 +#define TEST_ABORT_COUNT 2 + +static ULONG posix_region[192 * 1024 / sizeof(ULONG)]; + +static pthread_t sender; +static pthread_attr_t sender_attr; +static pthread_t controller; +static pthread_attr_t controller_attr; + +static mqd_t queue_des; +static struct mq_attr queue_attr; + +/* Written by the sender, read by the controller. */ +static TX_THREAD * volatile sender_thread_ptr; +static volatile INT send_failures; +static volatile INT stop_sending; + +extern void test_control_return(UINT status); + +static VOID *sender_entry(VOID *input); +static VOID *controller_entry(VOID *input); + + +/* Report how many bytes the queue's message pool has free. */ +static ULONG pool_available(void) +{ + +ULONG available; + + available = 0; + tx_byte_pool_info_get(&(queue_des -> f_data -> vq_message_area), + TX_NULL, &available, TX_NULL, TX_NULL, TX_NULL, TX_NULL); + + return (available); +} + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void posix_mq_send_abort_application_define(void *first_unused_memory) +#endif +{ + +struct sched_param param; +VOID *storage_ptr; + + (void) first_unused_memory; + + storage_ptr = posix_initialize(posix_region); + + queue_attr.mq_maxmsg = TEST_QUEUE_DEPTH; + queue_attr.mq_msgsize = TEST_MESSAGE_SIZE; + + queue_des = mq_open("mq_abort", O_CREAT | O_RDWR, 0, &queue_attr); + if (queue_des == (mqd_t) ERROR) + { + + printf("Running POSIX Message Queue Send Abort Test....................... ERROR #1\n"); + test_control_return(1); + } + + /* The controller drives the test and runs above the sender, so it keeps + control while the sender is being unblocked. */ + pthread_attr_init(&controller_attr); + param.sched_priority = 15; + pthread_attr_setschedparam(&controller_attr, ¶m); + pthread_attr_setstackaddr(&controller_attr, storage_ptr); + storage_ptr = (ULONG *) storage_ptr + (4096 / sizeof(ULONG)); + + pthread_attr_init(&sender_attr); + param.sched_priority = 10; + pthread_attr_setschedparam(&sender_attr, ¶m); + pthread_attr_setstackaddr(&sender_attr, storage_ptr); + + if (pthread_create(&controller, &controller_attr, controller_entry, NULL) != OK) + { + + printf("Running POSIX Message Queue Send Abort Test....................... ERROR #2\n"); + test_control_return(1); + } + + if (pthread_create(&sender, &sender_attr, sender_entry, NULL) != OK) + { + + printf("Running POSIX Message Queue Send Abort Test....................... ERROR #3\n"); + test_control_return(1); + } +} + + +/* Sends until told to stop. Every send blocks, because the controller keeps + the queue full, and every one is released by an aborted wait. */ +static VOID *sender_entry(VOID *input) +{ + +CHAR message[TEST_MESSAGE_SIZE]; +INT i; + + (void) input; + + for (i = 0; i < TEST_MESSAGE_SIZE; i++) + { + + message[i] = (CHAR) i; + } + + /* Publish our own thread pointer so the controller can abort our wait + without casting a pthread ID back to a ThreadX thread. */ + sender_thread_ptr = tx_thread_identify(); + + while (stop_sending == 0) + { + + if (mq_send(queue_des, message, TEST_MESSAGE_SIZE, 1) != OK) + { + + send_failures++; + } + } + + return (NULL); +} + + +static VOID *controller_entry(VOID *input) +{ + +CHAR message[TEST_MESSAGE_SIZE]; +ULONG baseline; +ULONG after; +ULONG lost; +INT i; + + (void) input; + + printf("Running POSIX Message Queue Send Abort Test....................... "); + + for (i = 0; i < TEST_MESSAGE_SIZE; i++) + { + + message[i] = (CHAR) i; + } + + /* Fill the queue so that any further send has to wait. */ + if (mq_send(queue_des, message, TEST_MESSAGE_SIZE, 1) != OK) + { + + printf("ERROR #4\n"); + test_control_return(1); + } + + /* Let the sender reach its first blocking send, then take the baseline. + The sender is holding one allocation at this point, which is the state + every later measurement is compared against. */ + tx_thread_sleep(2); + + if (sender_thread_ptr == TX_NULL) + { + + printf("ERROR #5\n"); + test_control_return(1); + } + + baseline = pool_available(); + + for (i = 0; i < TEST_ABORT_COUNT; i++) + { + + /* Release the sender from its wait. Its send fails, and the buffer it + allocated has to come back to the pool. */ + if (tx_thread_wait_abort(sender_thread_ptr) != TX_SUCCESS) + { + + printf("ERROR #6\n"); + test_control_return(1); + } + + /* Give the sender time to return from mq_send() and block again. */ + tx_thread_sleep(2); + } + + if (send_failures != TEST_ABORT_COUNT) + { + + printf("ERROR #7\n"); + test_control_return(1); + } + + /* The sender is blocked again holding exactly one allocation, the same as + at the baseline, so the pool should read the same. */ + after = pool_available(); + + if (after > baseline) + { + + printf("ERROR #8\n"); + test_control_return(1); + } + + lost = baseline - after; + + /* Anything approaching a message means buffers are not coming back. A + leak would cost TEST_ABORT_COUNT messages, so this separates the two + cases comfortably without depending on byte pool overhead. */ + if (lost >= (ULONG) TEST_MESSAGE_SIZE) + { + + printf("ERROR #9\n"); + test_control_return(1); + } + + /* Shut the sender down and confirm the queue still works. */ + stop_sending = 1; + tx_thread_wait_abort(sender_thread_ptr); + tx_thread_sleep(2); + + if (mq_receive(queue_des, message, TEST_MESSAGE_SIZE, TX_NULL) != (ssize_t) TEST_MESSAGE_SIZE) + { + + printf("ERROR #10\n"); + test_control_return(1); + } + + printf("SUCCESS!\n"); + test_control_return(0); + + return (NULL); +} diff --git a/test/posix/regression/posix_pthread_basic_test.c b/test/posix/regression/posix_pthread_basic_test.c new file mode 100644 index 000000000..afb8d4f30 --- /dev/null +++ b/test/posix/regression/posix_pthread_basic_test.c @@ -0,0 +1,192 @@ +/***************************************************************************/ +/* 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. */ +/* */ +/* AI Disclosure: This file was largely AI-generated by Claude Code */ +/* (Opus 5). The AI-generated portions may be considered public domain */ +/* (CC0-1.0) and not subject to the project's licence. The human */ +/* contributor has reviewed and verified that the code is correct. */ +/* */ +/* SPDX-License-Identifier: MIT and CC0-1.0 */ +/***************************************************************************/ + +/* This test covers basic pthread and synchronisation operation: a pthread runs + and reports its own identity, a mutex serialises access to shared state, a + semaphore signals between two pthreads, and a join collects the worker's exit + value. */ + +#include +#include "tx_api.h" +/* The layer ships no semaphore.h; sem_t and the sem_* calls arrive through + pthread.h, which pulls in tx_posix.h. */ +#include "pthread.h" + +#define TEST_STACK_BYTES 4096 + +static ULONG posix_region[192 * 1024 / sizeof(ULONG)]; + +static pthread_t worker; +static pthread_attr_t worker_attr; +static pthread_t driver; +static pthread_attr_t driver_attr; + +static pthread_mutex_t guard; +static sem_t handoff; + +static volatile INT shared_counter; +static pthread_t worker_self_id; + +static INT worker_result = 77; + +extern void test_control_return(UINT status); + +static VOID *worker_entry(VOID *input); +static VOID *driver_entry(VOID *input); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void posix_pthread_basic_application_define(void *first_unused_memory) +#endif +{ + +struct sched_param param; +VOID *storage_ptr; + + (void) first_unused_memory; + + storage_ptr = posix_initialize(posix_region); + + if (pthread_mutex_init(&guard, NULL) != OK) + { + + printf("Running POSIX Pthread Basic Test.................................. ERROR #1\n"); + test_control_return(1); + } + + if (sem_init(&handoff, 0, 0) != OK) + { + + printf("Running POSIX Pthread Basic Test.................................. ERROR #2\n"); + test_control_return(1); + } + + /* The driver runs below the worker so that the worker reaches its first + blocking point before the driver inspects anything. */ + pthread_attr_init(&worker_attr); + param.sched_priority = 15; + pthread_attr_setschedparam(&worker_attr, ¶m); + pthread_attr_setstackaddr(&worker_attr, storage_ptr); + storage_ptr = (ULONG *) storage_ptr + (TEST_STACK_BYTES / sizeof(ULONG)); + + pthread_attr_init(&driver_attr); + param.sched_priority = 10; + pthread_attr_setschedparam(&driver_attr, ¶m); + pthread_attr_setstackaddr(&driver_attr, storage_ptr); + + if (pthread_create(&worker, &worker_attr, worker_entry, NULL) != OK) + { + + printf("Running POSIX Pthread Basic Test.................................. ERROR #3\n"); + test_control_return(1); + } + + if (pthread_create(&driver, &driver_attr, driver_entry, NULL) != OK) + { + + printf("Running POSIX Pthread Basic Test.................................. ERROR #4\n"); + test_control_return(1); + } +} + + +static VOID *worker_entry(VOID *input) +{ + +INT i; + + (void) input; + + /* Record what this pthread believes its own ID to be, for the driver to + compare against the ID pthread_create() handed back. */ + worker_self_id = pthread_self(); + + for (i = 0; i < 100; i++) + { + + pthread_mutex_lock(&guard); + shared_counter++; + pthread_mutex_unlock(&guard); + } + + /* Hand control to the driver. */ + sem_post(&handoff); + + return ((VOID *) &worker_result); +} + + +static VOID *driver_entry(VOID *input) +{ + +VOID *exit_value; + + (void) input; + + printf("Running POSIX Pthread Basic Test.................................. "); + + /* Wait for the worker to finish its counting. */ + if (sem_wait(&handoff) != OK) + { + + printf("ERROR #5\n"); + test_control_return(1); + } + + if (shared_counter != 100) + { + + printf("ERROR #6\n"); + test_control_return(1); + } + + if (worker_self_id != worker) + { + + printf("ERROR #7\n"); + test_control_return(1); + } + + exit_value = NULL; + if (pthread_join(worker, &exit_value) != OK) + { + + printf("ERROR #8\n"); + test_control_return(1); + } + + if (exit_value != (VOID *) &worker_result) + { + + printf("ERROR #9\n"); + test_control_return(1); + } + + if (pthread_mutex_destroy(&guard) != OK) + { + + printf("ERROR #10\n"); + test_control_return(1); + } + + printf("SUCCESS!\n"); + test_control_return(0); + + return (NULL); +} diff --git a/utility/rtos_compatibility_layers/posix/CMakeLists.txt b/utility/rtos_compatibility_layers/posix/CMakeLists.txt new file mode 100644 index 000000000..6ddcd6a8f --- /dev/null +++ b/utility/rtos_compatibility_layers/posix/CMakeLists.txt @@ -0,0 +1,129 @@ +# POSIX compatibility layer for ThreadX. +# +# This target is EXCLUDE_FROM_ALL: it is not part of the default build and is +# only produced when something asks for it, either by name or by linking it. +# +# The include directory is deliberately PUBLIC. The layer ships replacements for +# errno.h, fcntl.h, pthread.h, sched.h, signal.h and time.h, and application code +# has to see those rather than a toolchain's own copies. That is also why the +# layer cannot be used on the hosted simulation ports, where the C library +# already supplies them; the top-level CMakeLists.txt skips it there. + +add_library(posix-threadx EXCLUDE_FROM_ALL) + +target_include_directories(posix-threadx + PUBLIC + ${CMAKE_CURRENT_LIST_DIR} +) + +target_sources(posix-threadx + PRIVATE + ${CMAKE_CURRENT_LIST_DIR}/px_abs_time_to_rel_ticks.c + ${CMAKE_CURRENT_LIST_DIR}/px_clock_getres.c + ${CMAKE_CURRENT_LIST_DIR}/px_clock_gettime.c + ${CMAKE_CURRENT_LIST_DIR}/px_clock_settime.c + ${CMAKE_CURRENT_LIST_DIR}/px_cond_broadcast.c + ${CMAKE_CURRENT_LIST_DIR}/px_cond_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/px_cond_init.c + ${CMAKE_CURRENT_LIST_DIR}/px_cond_signal.c + ${CMAKE_CURRENT_LIST_DIR}/px_cond_timedwait.c + ${CMAKE_CURRENT_LIST_DIR}/px_cond_wait.c + ${CMAKE_CURRENT_LIST_DIR}/px_error.c + ${CMAKE_CURRENT_LIST_DIR}/px_in_thread_context.c + ${CMAKE_CURRENT_LIST_DIR}/px_internal_signal_dispatch.c + ${CMAKE_CURRENT_LIST_DIR}/px_memory_allocate.c + ${CMAKE_CURRENT_LIST_DIR}/px_memory_release.c + ${CMAKE_CURRENT_LIST_DIR}/px_mq_arrange_msg.c + ${CMAKE_CURRENT_LIST_DIR}/px_mq_attr_init.c + ${CMAKE_CURRENT_LIST_DIR}/px_mq_close.c + ${CMAKE_CURRENT_LIST_DIR}/px_mq_create.c + ${CMAKE_CURRENT_LIST_DIR}/px_mq_find_queue.c + ${CMAKE_CURRENT_LIST_DIR}/px_mq_get_new_queue.c + ${CMAKE_CURRENT_LIST_DIR}/px_mq_get_queue_desc.c + ${CMAKE_CURRENT_LIST_DIR}/px_mq_open.c + ${CMAKE_CURRENT_LIST_DIR}/px_mq_priority_search.c + ${CMAKE_CURRENT_LIST_DIR}/px_mq_putback_queue.c + ${CMAKE_CURRENT_LIST_DIR}/px_mq_queue_delete.c + ${CMAKE_CURRENT_LIST_DIR}/px_mq_queue_init.c + ${CMAKE_CURRENT_LIST_DIR}/px_mq_receive.c + ${CMAKE_CURRENT_LIST_DIR}/px_mq_reset_queue.c + ${CMAKE_CURRENT_LIST_DIR}/px_mq_send.c + ${CMAKE_CURRENT_LIST_DIR}/px_mq_unlink.c + ${CMAKE_CURRENT_LIST_DIR}/px_mx_attr_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/px_mx_attr_getprotocol.c + ${CMAKE_CURRENT_LIST_DIR}/px_mx_attr_getpshared.c + ${CMAKE_CURRENT_LIST_DIR}/px_mx_attr_gettype.c + ${CMAKE_CURRENT_LIST_DIR}/px_mx_attr_initi.c + ${CMAKE_CURRENT_LIST_DIR}/px_mx_attr_setprotocol.c + ${CMAKE_CURRENT_LIST_DIR}/px_mx_attr_setpshared.c + ${CMAKE_CURRENT_LIST_DIR}/px_mx_attr_settype.c + ${CMAKE_CURRENT_LIST_DIR}/px_mx_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/px_mx_init.c + ${CMAKE_CURRENT_LIST_DIR}/px_mx_lock.c + ${CMAKE_CURRENT_LIST_DIR}/px_mx_set_default_mutexattr.c + ${CMAKE_CURRENT_LIST_DIR}/px_mx_timedlock.c + ${CMAKE_CURRENT_LIST_DIR}/px_mx_trylock.c + ${CMAKE_CURRENT_LIST_DIR}/px_mx_unlock.c + ${CMAKE_CURRENT_LIST_DIR}/px_nanosleep.c + ${CMAKE_CURRENT_LIST_DIR}/px_pth_attr_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/px_pth_attr_getdetachstate.c + ${CMAKE_CURRENT_LIST_DIR}/px_pth_attr_getinheritsched.c + ${CMAKE_CURRENT_LIST_DIR}/px_pth_attr_getschedparam.c + ${CMAKE_CURRENT_LIST_DIR}/px_pth_attr_getschedpolicy.c + ${CMAKE_CURRENT_LIST_DIR}/px_pth_attr_getstack.c + ${CMAKE_CURRENT_LIST_DIR}/px_pth_attr_getstackaddr.c + ${CMAKE_CURRENT_LIST_DIR}/px_pth_attr_getstacksize.c + ${CMAKE_CURRENT_LIST_DIR}/px_pth_attr_init.c + ${CMAKE_CURRENT_LIST_DIR}/px_pth_attr_setdetachstate.c + ${CMAKE_CURRENT_LIST_DIR}/px_pth_attr_setinheritsched.c + ${CMAKE_CURRENT_LIST_DIR}/px_pth_attr_setschedparam.c + ${CMAKE_CURRENT_LIST_DIR}/px_pth_attr_setschedpolicyl.c + ${CMAKE_CURRENT_LIST_DIR}/px_pth_attr_setstack.c + ${CMAKE_CURRENT_LIST_DIR}/px_pth_attr_setstackaddr.c + ${CMAKE_CURRENT_LIST_DIR}/px_pth_attr_setstacksize.c + ${CMAKE_CURRENT_LIST_DIR}/px_pth_cancel.c + ${CMAKE_CURRENT_LIST_DIR}/px_pth_create.c + ${CMAKE_CURRENT_LIST_DIR}/px_pth_detach.c + ${CMAKE_CURRENT_LIST_DIR}/px_pth_equal.c + ${CMAKE_CURRENT_LIST_DIR}/px_pth_exit.c + ${CMAKE_CURRENT_LIST_DIR}/px_pth_getcanceltype.c + ${CMAKE_CURRENT_LIST_DIR}/px_pth_getschedparam.c + ${CMAKE_CURRENT_LIST_DIR}/px_pth_init.c + ${CMAKE_CURRENT_LIST_DIR}/px_pth_join.c + ${CMAKE_CURRENT_LIST_DIR}/px_pth_kill.c + ${CMAKE_CURRENT_LIST_DIR}/px_pth_once.c + ${CMAKE_CURRENT_LIST_DIR}/px_pth_self.c + ${CMAKE_CURRENT_LIST_DIR}/px_pth_set_default_pthread_attr.c + ${CMAKE_CURRENT_LIST_DIR}/px_pth_setcancelstate.c + ${CMAKE_CURRENT_LIST_DIR}/px_pth_setcanceltype.c + ${CMAKE_CURRENT_LIST_DIR}/px_pth_setschedparam.c + ${CMAKE_CURRENT_LIST_DIR}/px_pth_sigmask.c + ${CMAKE_CURRENT_LIST_DIR}/px_pth_testcancel.c + ${CMAKE_CURRENT_LIST_DIR}/px_pth_yield.c + ${CMAKE_CURRENT_LIST_DIR}/px_px_initialize.c + ${CMAKE_CURRENT_LIST_DIR}/px_sched_get_prio.c + ${CMAKE_CURRENT_LIST_DIR}/px_sched_yield.c + ${CMAKE_CURRENT_LIST_DIR}/px_sem_close.c + ${CMAKE_CURRENT_LIST_DIR}/px_sem_destroy.c + ${CMAKE_CURRENT_LIST_DIR}/px_sem_find_sem.c + ${CMAKE_CURRENT_LIST_DIR}/px_sem_get_new_sem.c + ${CMAKE_CURRENT_LIST_DIR}/px_sem_getvalue.c + ${CMAKE_CURRENT_LIST_DIR}/px_sem_init.c + ${CMAKE_CURRENT_LIST_DIR}/px_sem_open.c + ${CMAKE_CURRENT_LIST_DIR}/px_sem_post.c + ${CMAKE_CURRENT_LIST_DIR}/px_sem_reset.c + ${CMAKE_CURRENT_LIST_DIR}/px_sem_set_sem_name.c + ${CMAKE_CURRENT_LIST_DIR}/px_sem_trywait.c + ${CMAKE_CURRENT_LIST_DIR}/px_sem_unlink.c + ${CMAKE_CURRENT_LIST_DIR}/px_sem_wait.c + ${CMAKE_CURRENT_LIST_DIR}/px_sig_addset.c + ${CMAKE_CURRENT_LIST_DIR}/px_sig_delset.c + ${CMAKE_CURRENT_LIST_DIR}/px_sig_emptyset.c + ${CMAKE_CURRENT_LIST_DIR}/px_sig_fillset.c + ${CMAKE_CURRENT_LIST_DIR}/px_sig_signal.c + ${CMAKE_CURRENT_LIST_DIR}/px_sig_wait.c + ${CMAKE_CURRENT_LIST_DIR}/px_sleep.c + ${CMAKE_CURRENT_LIST_DIR}/px_system_manager.c +) + +target_link_libraries(posix-threadx PUBLIC threadx) diff --git a/utility/rtos_compatibility_layers/posix/tx_posix.h b/utility/rtos_compatibility_layers/posix/tx_posix.h index ce533dd87..3f235cb91 100644 --- a/utility/rtos_compatibility_layers/posix/tx_posix.h +++ b/utility/rtos_compatibility_layers/posix/tx_posix.h @@ -278,9 +278,22 @@ typedef struct pthread_attr_obj } pthread_attr_t; -typedef INT ssize_t ; /* this should be pulled in from sys\types.h */ +/* ssize_t and mode_t belong to . A C library that has already + declared them wins: it knows the target's real widths, and on an LP64 target + ssize_t is 64 bits while INT is not. newlib guards each type with its own + _*_DECLARED macro, so honour those and only define what is missing. A port + whose library uses different guards can predefine them to the same effect. */ +#ifndef _SSIZE_T_DECLARED +typedef INT ssize_t ; +#define _SSIZE_T_DECLARED +#endif + typedef ALIGN_TYPE pthread_t; + +#ifndef _MODE_T_DECLARED typedef ULONG mode_t; +#define _MODE_T_DECLARED +#endif From 2f6945475baa6acc3e34a74834972d9a0a796e11 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Sun, 16 Aug 2026 18:45:16 -0400 Subject: [PATCH 055/181] Stopped pthread_self() faulting when the caller is not a pthread (#627) Nothing prevents an application mixing tx_thread_create() with the POSIX layer, and a thread created that way has no POSIX control block. posix_thread2tcb() returns NULL for it, which posix_thread2tid() then read through: p_tcb = posix_thread2tcb(thread_ptr); thread_ID = p_tcb->pthreadID; pthread_self() went on to compound it, reading the signal fields of a POSIX_TCB out of a thread that is only a TX_THREAD: if (((POSIX_TCB *) thread_ptr) -> signals.signal_handler) The first is a null dereference and the second runs off the end of the control block into whatever the linker put there. Under qemu-system-riscv32 the first one lands first: mcause=0x5, a load access fault, with mtval=0xb4 for the offset of pthreadID. Have posix_thread2tid() report zero for a thread with no control block, which is what px_pth_join.c already does for the same call, and have pthread_self() skip the signal check unless the ID says the caller really is a pthread. Zero cannot collide with a real ID because px_pth_create.c uses the address of the control block as the ID. This also covers the case where there is no current thread at all, from an ISR or before the scheduler starts: tx_thread_identify() returns NULL, and the same zero comes back instead of a fault. Add posix_pthread_self_test, which asks both kinds of thread for their ID: a pthread, which has to report what pthread_create() returned, and a plain ThreadX thread, which has to report zero. Reverting either half of the fix turns the test into the load access fault above. Verified with riscv64-unknown-elf and qemu-system-riscv32: 4 tests across the default build, 4 of 4 passing. Assisted-by: Claude Code (Opus 5) --- test/posix/cmake/regression/CMakeLists.txt | 1 + .../regression/posix_pthread_self_test.c | 177 ++++++++++++++++++ .../posix/px_pth_init.c | 12 ++ .../posix/px_pth_self.c | 17 +- 4 files changed, 203 insertions(+), 4 deletions(-) create mode 100644 test/posix/regression/posix_pthread_self_test.c diff --git a/test/posix/cmake/regression/CMakeLists.txt b/test/posix/cmake/regression/CMakeLists.txt index c8320b05f..8f433bcb3 100644 --- a/test/posix/cmake/regression/CMakeLists.txt +++ b/test/posix/cmake/regression/CMakeLists.txt @@ -19,6 +19,7 @@ set(posix_test_cases ${SOURCE_DIR}/posix_mq_basic_test.c ${SOURCE_DIR}/posix_mq_send_abort_test.c ${SOURCE_DIR}/posix_pthread_basic_test.c + ${SOURCE_DIR}/posix_pthread_self_test.c ) set(WEAK_DEFAULTS_SOURCE ${CMAKE_CURRENT_LIST_DIR}/../../../shared/regression/testcontrol_weak_defaults.c) diff --git a/test/posix/regression/posix_pthread_self_test.c b/test/posix/regression/posix_pthread_self_test.c new file mode 100644 index 000000000..7cbb64509 --- /dev/null +++ b/test/posix/regression/posix_pthread_self_test.c @@ -0,0 +1,177 @@ +/***************************************************************************/ +/* 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. */ +/* */ +/* AI Disclosure: This file was largely AI-generated by Claude Code */ +/* (Opus 5). The AI-generated portions may be considered public domain */ +/* (CC0-1.0) and not subject to the project's licence. The human */ +/* contributor has reviewed and verified that the code is correct. */ +/* */ +/* SPDX-License-Identifier: MIT and CC0-1.0 */ +/***************************************************************************/ + +/* This test covers pthread_self() being called from a thread that is not a + pthread. + + Nothing stops an application mixing tx_thread_create() with the POSIX layer, + and a ThreadX thread created that way has no POSIX control block. + posix_thread2tcb() returns NULL for it, and pthread_self() used to read the + pthread ID through that null pointer, then read the signal fields of a + POSIX_TCB out of a plain TX_THREAD that never had any. + + The test calls pthread_self() from both kinds of thread: a real pthread, + which must get the ID pthread_create() handed back, and a plain ThreadX + thread, which must get zero rather than a fault or a value read out of + whatever follows its control block. */ + +#include +#include "tx_api.h" +#include "pthread.h" + +#define TEST_STACK_BYTES 4096 + +static ULONG posix_region[192 * 1024 / sizeof(ULONG)]; + +static pthread_t worker; +static pthread_attr_t worker_attr; + +/* A plain ThreadX thread, deliberately not created through pthread_create(). */ +static TX_THREAD plain_thread; + +static volatile INT worker_done; +static volatile INT plain_done; +static pthread_t worker_reported_id; +static pthread_t plain_reported_id; + +extern void test_control_return(UINT status); + +static VOID *worker_entry(VOID *input); +static VOID plain_entry(ULONG input); +static VOID checker_entry(ULONG input); + +static TX_THREAD checker_thread; + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void posix_pthread_self_application_define(void *first_unused_memory) +#endif +{ + +struct sched_param param; +VOID *storage_ptr; +CHAR *pointer; + + pointer = (CHAR *) first_unused_memory; + + storage_ptr = posix_initialize(posix_region); + + /* A genuine pthread. */ + pthread_attr_init(&worker_attr); + param.sched_priority = 15; + pthread_attr_setschedparam(&worker_attr, ¶m); + pthread_attr_setstackaddr(&worker_attr, storage_ptr); + + if (pthread_create(&worker, &worker_attr, worker_entry, NULL) != OK) + { + + printf("Running POSIX Pthread Self Test.................................. ERROR #1\n"); + test_control_return(1); + } + + /* A ThreadX thread that the POSIX layer knows nothing about. */ + if (tx_thread_create(&plain_thread, "plain threadx thread", plain_entry, 0, + pointer, TEST_STACK_BYTES, + 20, 20, TX_NO_TIME_SLICE, TX_AUTO_START) != TX_SUCCESS) + { + + printf("Running POSIX Pthread Self Test.................................. ERROR #2\n"); + test_control_return(1); + } + pointer = pointer + TEST_STACK_BYTES; + + /* Runs last and inspects what the other two reported. */ + if (tx_thread_create(&checker_thread, "checker", checker_entry, 0, + pointer, TEST_STACK_BYTES, + 25, 25, TX_NO_TIME_SLICE, TX_AUTO_START) != TX_SUCCESS) + { + + printf("Running POSIX Pthread Self Test.................................. ERROR #3\n"); + test_control_return(1); + } +} + + +static VOID *worker_entry(VOID *input) +{ + + (void) input; + + worker_reported_id = pthread_self(); + worker_done = 1; + + return (NULL); +} + + +/* The case that used to fault: a ThreadX thread asking for its pthread ID. */ +static VOID plain_entry(ULONG input) +{ + + (void) input; + + plain_reported_id = pthread_self(); + plain_done = 1; +} + + +static VOID checker_entry(ULONG input) +{ + + (void) input; + + printf("Running POSIX Pthread Self Test.................................. "); + + /* Both threads run above this one, so they have finished by now. */ + if ((worker_done == 0) || (plain_done == 0)) + { + + printf("ERROR #4\n"); + test_control_return(1); + } + + /* A pthread must report the ID pthread_create() produced. */ + if (worker_reported_id != worker) + { + + printf("ERROR #5\n"); + test_control_return(1); + } + + /* A pthread ID is the address of its control block, so a real one is never + zero. */ + if (worker_reported_id == (pthread_t) 0) + { + + printf("ERROR #6\n"); + test_control_return(1); + } + + /* The plain ThreadX thread has no pthread ID, and must be told so rather + than handed something read out of memory that follows its TX_THREAD. */ + if (plain_reported_id != (pthread_t) 0) + { + + printf("ERROR #7\n"); + test_control_return(1); + } + + printf("SUCCESS!\n"); + test_control_return(0); +} diff --git a/utility/rtos_compatibility_layers/posix/px_pth_init.c b/utility/rtos_compatibility_layers/posix/px_pth_init.c index a2f97be7d..ff0a01a9a 100644 --- a/utility/rtos_compatibility_layers/posix/px_pth_init.c +++ b/utility/rtos_compatibility_layers/posix/px_pth_init.c @@ -550,6 +550,18 @@ POSIX_TCB *p_tcb; /* Get the TCB for this pthread */ p_tcb = posix_thread2tcb(thread_ptr); + + /* A running ThreadX thread that was not created through pthread_create() + has no TCB in the pool, and posix_thread2tcb() returns NULL for it. It + has no pthread ID either, so report zero rather than reading through the + null pointer. Zero can never collide with a real ID, because + px_pth_create.c uses the address of the TCB as the ID. */ + if (!p_tcb) + { + + return((pthread_t) 0); + } + thread_ID = p_tcb->pthreadID; /* All done. */ diff --git a/utility/rtos_compatibility_layers/posix/px_pth_self.c b/utility/rtos_compatibility_layers/posix/px_pth_self.c index fd876459d..2272fa315 100644 --- a/utility/rtos_compatibility_layers/posix/px_pth_self.c +++ b/utility/rtos_compatibility_layers/posix/px_pth_self.c @@ -74,12 +74,21 @@ pthread_t thread_ID; thread_ID = posix_thread2tid(thread_ptr); - /* Determine if this thread is actually the signal thread helper. */ - if (((POSIX_TCB *) thread_ptr) -> signals.signal_handler) + /* Only a pthread has the signal fields read below: they belong to the + POSIX_TCB that surrounds the thread, and reading them through anything + else runs off the end of a plain TX_THREAD. A zero ID means the caller + is not a pthread, either because it is a ThreadX thread created directly + or because there is no current thread at all, so leave it alone. */ + if (thread_ID != (pthread_t) 0) { - /* Yes, override the thread_ID with the non-signal thread ID. */ - thread_ID = (pthread_t) ((POSIX_TCB *) thread_ptr) -> signals.base_thread_ptr; + /* Determine if this thread is actually the signal thread helper. */ + if (((POSIX_TCB *) thread_ptr) -> signals.signal_handler) + { + + /* Yes, override the thread_ID with the non-signal thread ID. */ + thread_ID = (pthread_t) ((POSIX_TCB *) thread_ptr) -> signals.base_thread_ptr; + } } From ff638dae718eed436d11da9830683adca246e86d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 17 Aug 2026 07:59:23 -0400 Subject: [PATCH 056/181] Configured the LINFlexD console twice, because once is not enough at -O2 (#629) The console driver runs its configuration sequence a single time, and that works only because this BSP is built without an optimisation flag. Compiled at -O2 the same sequence leaves the line corrupted: every character partially wrong, in the pattern the file already describes for a misconfigured module. What makes it worth guarding against is that the failure is invisible. UARTCR reads back exactly the value written. LINIBRR and LINFBRR read back exactly the values written. linflexd_init returns LINFLEXD_INIT_OK. The registers are right and the line is wrong, so nothing in the returned status tells the caller the console cannot be trusted. Localised by bisection: with every other file at -O2 and this one at -O0 the output is clean, and with only linflexd_init at -O2 it is corrupted, so the fault is in the configuration sequence rather than in the per-byte transmit path. The mechanism is not understood, and this commit does not claim to explain it. Tested and rejected: a 100x larger bound on the wait for initialisation mode, a settling delay before the first LINSR read, a settling delay after leaving initialisation mode, a barrier and read-back between the two UARTCR writes, and waiting for LINSR to report the exit from initialisation mode. None of those makes a single pass work at -O2. A second pass does, at both optimisation levels, which is what this does. Instrumented with a duplicate of the sequence forced to -O2 and reported through a console repaired afterwards, which is how the register read-backs above were obtained. Verified on the S32Z280-594EVB. The boot image passes six of six probes with the console status still reporting 0x00000000, and the reproducer builds clean and prints correctly at both -O0 and -O2. Assisted-by: Claude Code (Opus 5) --- .../gnu/example_build/s32z280_evb/linflexd.c | 36 ++++++++++++++++++- 1 file changed, 35 insertions(+), 1 deletion(-) diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/linflexd.c b/ports/cortex_r52/gnu/example_build/s32z280_evb/linflexd.c index 0bd780697..cc6a7773c 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/linflexd.c +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/linflexd.c @@ -104,7 +104,10 @@ #define CONSOLE_BASE S32Z_LINFLEX_9_BASE -unsigned int linflexd_init(void) +/* One full pass of the configuration sequence. Called twice by + linflexd_init; see the comment there for why. */ + +static unsigned int linflexd_configure_once(void) { unsigned int status = LINFLEXD_INIT_OK; unsigned int guard; @@ -167,6 +170,37 @@ unsigned int linflexd_init(void) } +unsigned int linflexd_init(void) +{ + unsigned int status; + + /* The sequence runs twice, and one pass is genuinely not enough. + A single pass gives a working console when this file is compiled at -O0 + and a corrupted one at -O2: every character partially wrong, while UARTCR + reads back exactly the value written, LINIBRR and LINFBRR read back + exactly the values written, and the returned status is + LINFLEXD_INIT_OK. The registers are right and the line is wrong, so the + failure is invisible to the caller -- the worst property a console can + have, and the reason this is worth two passes at boot. + + The mechanism is not understood. Tested and rejected as explanations: + the wait for initialisation mode (a bound 100x larger changes nothing), + a settling delay before the first LINSR read, a settling delay after + leaving initialisation mode, a barrier and read-back between the two + UARTCR writes, and waiting for LINSR to report the exit from + initialisation mode. None of those makes a single pass work at -O2. + A second pass does, reliably, at both optimisation levels. + + Verified on the S32Z280-594EVB with the whole BSP at -O0 and at -O2. + If the underlying behaviour is ever identified, revisit this. */ + + status = linflexd_configure_once(); + status |= linflexd_configure_once(); + + return status; +} + + void linflexd_putc(char c) { if (c == '\n') From b2983c08d3df2b799d1a89d89eb248e49c2192d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 17 Aug 2026 09:21:27 -0400 Subject: [PATCH 057/181] Ran the interrupt handler from ATCM, and measured what that buys (#630) The TCM work so far enabled ATCM and left it empty, which buys nothing. This places code in it and measures the result. link.lds gains an ATCM region and an .atcm_text section whose run address is in the bank and whose load address is in CODE. tcm_copy_atcm_text moves it, using 64-bit stores because ECC is enabled on this part and ATCM requires them (Cortex-R52 TRM 6.2.2); both ends of the section are 8-byte aligned so there is no narrower tail to leave without check bits. The copy runs after T4 and T5, which write test patterns to the first and last words of the bank and would otherwise land on top of the code. s32z280_atcm.elf is the same image as s32z280_boot.elf with the interrupt service body placed in ATCM. Both targets exist so the comparison can be repeated on one board in one session without reconfiguring. The service routine is split into a timed wrapper that stays in .text and a body that moves, so the wrapper's own cost appears in both measurements and cancels. Measured in PMU cycles over 64 samples, caches enabled in both: code RAM ATCM change min 454 334 -26.4% mean 458 340 -25.8% max 612 466 -23.9% spread 158 132 -16.5% CNTPCT is not used for this: at 8 MHz it cannot resolve a handler body, let alone the variation in one. The level shift is the solid part. ATCM is a quarter faster even though the caches were on and code RAM had the instruction cache available, which says the handler does not stay resident between interrupts 10 ms apart -- so each one pays a cold fetch from code RAM, which runs at half the core frequency where ATCM runs at full speed with one wait state (S32Z2 RM 6.3.6). The determinism claim deserves less weight than the numbers first suggest. The spread narrows by only 16%, and ATCM's worst case still sits slightly above code RAM's best case, so the two distributions overlap at the tails rather than separating. Whatever jitter remains is not dominated by instruction fetch. Both images pass six of six boot probes. Assisted-by: Claude Code (Opus 5) --- .../example_build/s32z280_evb/CMakeLists.txt | 37 +++++++++ .../gnu/example_build/s32z280_evb/bsp_boot.c | 76 ++++++++++++++++++- .../example_build/s32z280_evb/irq_dispatch.c | 48 ++++++++++++ .../gnu/example_build/s32z280_evb/link.lds | 25 ++++++ .../gnu/example_build/s32z280_evb/tcm.c | 42 ++++++++++ .../gnu/example_build/s32z280_evb/tcm.h | 10 +++ .../gnu/example_build/s32z280_evb/timer.c | 38 ++++++++++ .../gnu/example_build/s32z280_evb/timer.h | 8 ++ 8 files changed, 282 insertions(+), 2 deletions(-) diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/CMakeLists.txt b/ports/cortex_r52/gnu/example_build/s32z280_evb/CMakeLists.txt index 2545b3d06..94fe43301 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/CMakeLists.txt +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/CMakeLists.txt @@ -55,6 +55,43 @@ target_link_options(s32z280_boot.elf PRIVATE ) +# Same image as s32z280_boot.elf with the interrupt service body placed in ATCM +# instead of code RAM, so the two can be compared on the same board in the same +# session. Separate target rather than an option so both exist at once and a +# result can be reproduced without reconfiguring. +add_executable(s32z280_atcm.elf EXCLUDE_FROM_ALL + ${EVB_DIR}/entry.S + ${EVB_DIR}/bsp_boot.c + ${EVB_DIR}/linflexd.c + ${EVB_DIR}/timer.c + ${EVB_DIR}/gic_probe.c + ${EVB_DIR}/mpu.c + ${EVB_DIR}/gicv3.c + ${EVB_DIR}/irq_dispatch.c + ${EVB_DIR}/cache.c + ${EVB_DIR}/tcm.c +) + +target_include_directories(s32z280_atcm.elf PRIVATE ${EVB_DIR}) + +# -g only: this image exists to be inspected through a debugger, and without +# DWARF the identity structure has no type for GDB to walk. No effect on the +# generated code. +target_compile_options(s32z280_atcm.elf PRIVATE -g) + +target_link_options(s32z280_atcm.elf PRIVATE + -T${EVB_DIR}/link.lds + -nostartfiles + -Wl,-Map=s32z280_atcm.map + # Bare metal: one code region and one data region, with access control + # belonging to the MPU rather than to segment permissions. + ${EVB_LINK_QUIET_RWX} +) + + +target_compile_definitions(s32z280_atcm.elf PRIVATE TX_R52_ATCM_ISR) + + # ThreadX demo on silicon: threads, preemption and the timer tick. Separate # target from s32z280_boot.elf, which deliberately does not link the kernel so # that a boot failure there is unambiguously a board problem. diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/bsp_boot.c b/ports/cortex_r52/gnu/example_build/s32z280_evb/bsp_boot.c index 96ee23d75..50d22a2b2 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/bsp_boot.c +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/bsp_boot.c @@ -569,7 +569,26 @@ void bsp_main(void) proves the interrupt is delivered, which is a different claim. */ MARK(0x50); - linflexd_puts("I1 gicv3_init\n"); + /* Copy the handler into ATCM now, and not earlier: T4 and T5 write test + patterns to the first and last words of the bank, which would land on top + of this code. The ECC preload in T3 has already established check bits + for the whole bank, and the 64-bit stores in the copy maintain them for + every location it writes. */ + + linflexd_puts("T6 copying .atcm_text into ATCM\n"); + { + unsigned long copied = tcm_copy_atcm_text(); + + report("atcm bytes", (unsigned int) copied); + if (copied == 0UL) + { + linflexd_puts(" nothing placed in ATCM in this image\n"); + } + } + + timer_cycles_enable(); + + linflexd_puts("I1 gicv3_init\n"); gicv3_init(); MARK(0x51); @@ -595,12 +614,18 @@ void bsp_main(void) MARK(0x53); { + extern unsigned int board_service_count; unsigned int spins = 0U; /* Wait for ticks. Bounded: a missing interrupt must report itself rather than hang the boot. */ - while ((board_irq_count < 5UL) && (spins < 30U)) + /* Wait for a full set of latency samples, not just a few ticks: + the figure of interest is the worst case, and a handful of + samples cannot show it. Still bounded, so a missing interrupt + reports itself rather than hanging the boot. */ + + while ((board_service_count < 64U) && (spins < 400U)) { timer_spin(200000U); spins++; @@ -612,6 +637,53 @@ void bsp_main(void) report("timer INTID", (unsigned int) board_timer_intid); report("spurious ", (unsigned int) board_spurious_count); report("unexpected", (unsigned int) board_unexpected_intid); + + /* Handler body execution time. Reported as min, max and mean rather + than mean alone: the spread is the point. */ + + { + extern unsigned int board_service_cycles[]; + extern unsigned int board_service_count; + + unsigned int i; + unsigned int lo = 0xFFFFFFFFU; + unsigned int hi = 0U; + unsigned long sum = 0UL; + unsigned int n; + + /* Stop the source and snapshot the count before reading any of it. + The timer re-arms inside the handler, so samples keep arriving + otherwise: the first version of this read let the count grow + between computing the extremes and dividing for the mean, and + printed a mean below the minimum. */ + + timer_stop(); + n = board_service_count; + + for (i = 0U; i < n; i++) + { + unsigned int v = board_service_cycles[i]; + + if (v < lo) { lo = v; } + if (v > hi) { hi = v; } + sum += (unsigned long) v; + } + + linflexd_puts("I5 handler body cycles "); +#ifdef TX_R52_ATCM_ISR + linflexd_puts("(body in ATCM)\n"); +#else + linflexd_puts("(body in code RAM)\n"); +#endif + report("samples ", n); + if (n > 0U) + { + report("min ", lo); + report("max ", hi); + report("mean ", (unsigned int) (sum / n)); + report("spread ", hi - lo); + } + } report("first INTID", (unsigned int) board_first_intid); linflexd_puts("I4 interrupt test done\n"); } diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/irq_dispatch.c b/ports/cortex_r52/gnu/example_build/s32z280_evb/irq_dispatch.c index 193f14dea..0ef90b7b4 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/irq_dispatch.c +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/irq_dispatch.c @@ -164,7 +164,55 @@ void board_init(void) /* before nesting starts. Does not acknowledge and does not EOI. */ /**************************************************************************/ +/**************************************************************************/ +/* Handler execution time, and where the handler's instructions live. */ +/* */ +/* TX_R52_ATCM_ISR places the service routine in ATCM. ATCM runs at full */ +/* core speed with one wait state; .text lives in RTU code RAM, which runs */ +/* at half the core frequency (S32Z2 RM 6.3.6). ATCM also has no cache to */ +/* miss, which is the property that matters for a determinism argument. */ +/* */ +/* Measured in cycles from the PMU counter, not CNTPCT: at 8 MHz CNTPCT */ +/* cannot resolve a handler body, let alone the variation in one. */ +/* */ +/* The timing wrapper below stays in .text in both configurations, so its */ +/* own cost appears in every sample and cancels when the two are compared. */ +/* Only the body moves. What matters in the result is the spread: a warm */ +/* instruction cache can match ATCM on the mean and cannot match it on the */ +/* worst case. */ +/**************************************************************************/ + +#define BOARD_LATENCY_SAMPLES 64U + +unsigned int board_service_cycles[BOARD_LATENCY_SAMPLES]; +unsigned int board_service_count; + +#ifdef TX_R52_ATCM_ISR +#define BOARD_ISR_SECTION __attribute__((section(".atcm_text"))) +#else +#define BOARD_ISR_SECTION +#endif + +static BOARD_ISR_SECTION void board_irq_service_body(unsigned long intid); + void board_irq_service(unsigned long intid) +{ + unsigned int before; + unsigned int after; + + before = timer_read_cycles(); + board_irq_service_body(intid); + after = timer_read_cycles(); + + if (board_service_count < BOARD_LATENCY_SAMPLES) + { + board_service_cycles[board_service_count] = after - before; + board_service_count++; + } +} + + +static BOARD_ISR_SECTION void board_irq_service_body(unsigned long intid) { if (intid == GICV3_SPURIOUS_INTID) { diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/link.lds b/ports/cortex_r52/gnu/example_build/s32z280_evb/link.lds index ac0583b3c..1b39be82a 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/link.lds +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/link.lds @@ -44,6 +44,11 @@ __sys_stack_size__ = 0x0800; MEMORY { CODE (rx) : ORIGIN = 0x79900000, LENGTH = 0x00700000 /* 7 MB */ + /* ATCM. entry.S programmes IMP_ATCMREGIONR to this base and enables the + bank before anything runs from it, and mpu.c maps it executable. Code + placed here runs at full core speed with one wait state, where CODE is + RTU code RAM and runs at half the core frequency (S32Z2 RM 6.3.6). */ + ATCM (rwx) : ORIGIN = 0x30000000, LENGTH = 0x00010000 /* 64 KB */ DATA (rwx) : ORIGIN = 0x31780000, LENGTH = 0x00080000 /* 512 KB: DRAM0 + DRAM1, both full core speed */ } @@ -89,6 +94,26 @@ SECTIONS *(.glue_7t) } > CODE + /* Code that runs from tightly-coupled memory. Loaded into CODE and copied + to ATCM by atcm_copy_text() before it is called, because ECC is enabled + on this part and a TCM location must be written before it is read + (Cortex-R52 TRM 6.2.2). The copy uses 64-bit stores for the same + reason: ATCM requires them where BTCM and CTCM accept 32-bit. + + ALIGN(8) at both ends so the copy can move whole 64-bit units without a + tail case, which is what keeps the ECC requirement satisfied for every + location written. */ + + .atcm_text : ALIGN(8) + { + __atcm_text_start__ = .; + *(.atcm_text*) + . = ALIGN(8); + __atcm_text_end__ = .; + } > ATCM AT> CODE + + __atcm_text_load__ = LOADADDR(.atcm_text); + .rodata : { *(.rodata*) diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/tcm.c b/ports/cortex_r52/gnu/example_build/s32z280_evb/tcm.c index a2b9dd68a..081dc4140 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/tcm.c +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/tcm.c @@ -260,3 +260,45 @@ void tcm_preload(unsigned int index, unsigned long base, unsigned long bytes) __asm volatile ("dsb sy" ::: "memory"); } + + +/**************************************************************************/ +/* Copy .atcm_text into ATCM. */ +/**************************************************************************/ + +extern char __atcm_text_start__; +extern char __atcm_text_end__; +extern char __atcm_text_load__; + +unsigned long tcm_copy_atcm_text(void) +{ + /* The linker aligns both ends of the section to 8, so the whole extent is a + whole number of 64-bit units and there is no tail to handle narrowly. + That matters here rather than being tidiness: a 32-bit store to ATCM does + not establish the ECC check bits for its location, so a tail copied 32 + bits at a time would leave words that fault when read. */ + + volatile unsigned long long *dst; + const volatile unsigned long long *src; + unsigned long bytes; + unsigned long i; + + dst = (volatile unsigned long long *) (void *) &__atcm_text_start__; + src = (const volatile unsigned long long *) (void *) &__atcm_text_load__; + bytes = (unsigned long) (&__atcm_text_end__ - &__atcm_text_start__); + + for (i = 0UL; i < (bytes / 8UL); i++) + { + dst[i] = src[i]; + } + + /* Complete the writes, then discard any stale instruction-side copy of the + destination before it is executed. */ + + __asm__ volatile("dsb sy" ::: "memory"); + __asm__ volatile("mcr p15, 0, r0, c7, c5, 0" : : : "memory"); /* ICIALLU */ + __asm__ volatile("dsb sy" ::: "memory"); + __asm__ volatile("isb" ::: "memory"); + + return bytes; +} diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/tcm.h b/ports/cortex_r52/gnu/example_build/s32z280_evb/tcm.h index b47358f26..b80f226d3 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/tcm.h +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/tcm.h @@ -148,4 +148,14 @@ unsigned int tcm_enable(unsigned int index, unsigned long base); void tcm_preload(unsigned int index, unsigned long base, unsigned long bytes); +/* Copy the .atcm_text section from its load address in CODE to its run address + in ATCM. Must run before anything in that section is called, and after the + bank is enabled. Returns the number of bytes copied, which is zero when the + section is empty -- the normal case for an image that places nothing there. + + Uses 64-bit stores because ECC is enabled on this part and ATCM requires + them; see tcm_preload and Cortex-R52 TRM 6.2.2. */ + +unsigned long tcm_copy_atcm_text(void); + #endif diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/timer.c b/ports/cortex_r52/gnu/example_build/s32z280_evb/timer.c index 544102083..9fc5c0a17 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/timer.c +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/timer.c @@ -146,3 +146,41 @@ void timer_stop(void) __asm volatile ("mcr p15, 0, %0, c14, c2, 1" :: "r" (control)); __asm volatile ("isb"); } + + +/**************************************************************************/ +/* PMU cycle counter. */ +/* */ +/* PMCR.E gates all counters including the dedicated cycle counter, and */ +/* PMCNTENSET bit 31 enables that counter specifically. Both are needed. */ +/* PMCR.D is left clear so the counter advances every cycle rather than */ +/* every 64th, which is the resolution these measurements want. */ +/**************************************************************************/ + +#define PMCR_E (1UL << 0) /* enable all counters */ +#define PMCR_P (1UL << 1) /* reset event counters */ +#define PMCR_C (1UL << 2) /* reset cycle counter */ +#define PMCNTENSET_C (1UL << 31) /* cycle counter enable */ + +void timer_cycles_enable(void) +{ + unsigned long pmcr; + + /* Allow EL0/EL1 access and enable, resetting the counter as we go. */ + + __asm__ volatile("mrc p15, 0, %0, c9, c12, 0" : "=r"(pmcr)); + pmcr |= (PMCR_E | PMCR_C); + __asm__ volatile("mcr p15, 0, %0, c9, c12, 0" : : "r"(pmcr) : "memory"); + + __asm__ volatile("mcr p15, 0, %0, c9, c12, 1" + : : "r"((unsigned long) PMCNTENSET_C) : "memory"); + + __asm__ volatile("isb" ::: "memory"); +} + +unsigned int timer_read_cycles(void) +{ + unsigned long value; + __asm__ volatile("mrc p15, 0, %0, c9, c13, 0" : "=r"(value)); + return (unsigned int) value; +} diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/timer.h b/ports/cortex_r52/gnu/example_build/s32z280_evb/timer.h index 7cd411efc..0a0866b8f 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/timer.h +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/timer.h @@ -61,4 +61,12 @@ void timer_start_oneshot_irq(unsigned int ticks); unsigned int timer_fired(void); void timer_stop(void); +/* PMU cycle counter. CNTPCT runs at 8 MHz on this part, so its 125 ns + granularity is too coarse to resolve interrupt latency, let alone the jitter + in it. The cycle counter runs at the core clock and is what those + measurements use. timer_cycles_enable must be called before any read. */ + +void timer_cycles_enable(void); +unsigned int timer_read_cycles(void); + #endif /* TIMER_H */ From 1d3f3f8e4c82a1a716f892a4442bb659cc505f6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 17 Aug 2026 13:14:16 -0400 Subject: [PATCH 058/181] Measured the cache benchmark at four alignments, because one is not enough (#631) This benchmark was bimodal and reported a single number, which made it worse than no benchmark. The same workload on the same silicon reports either 24% cache benefit or none at all, decided only by where the loop falls inside a 64-byte line -- and therefore by any unrelated change that shifts code ahead of it. Two nop instructions added to entry.S were enough to flip it. That is not a hypothetical. A run of conclusions drawn from this probe turned out to be measuring code layout: an interrupt-handler comparison, a claim that enabling a second TCM bank costs all cache benefit, and a follow-up claim that what mattered was when the TCM region register was written rather than what it contained. The last of those was reported to NXP as a defect and has had to be withdrawn. Enabling CTCM and adding two nops produce identical results, to the digit, because the only measurable consequence of the enable was the eight bytes of instructions it added. Four copies of the loop are now generated at different offsets within a cache line, all four are measured, and the low and high gains are both reported. Pinning a single alignment was tried first and is not a fix: it silently picks one of the two modes -- aligned to 64 the loop sits permanently in the low one. Measured on the S32Z280-594EVB, reproducing exactly across runs: loop offset in line cold warm gain 0 890,302 890,035 0% 16 890,208 889,976 0% 32 857,439 651,390 24.0% 48 857,631 651,571 24.0% The cold pass differs between the modes as well, 890k against 857k, so the loop is slower even with both caches off. The cold pass is instruction-fetch bound out of code RAM at half the core frequency (S32Z2 RM 6.3.6), and how the loop straddles lines decides how much of the data cache's contribution is visible at all. This probe therefore measures both caches together and always did; the sweep at least makes the variation visible instead of letting one arbitrary placement stand in for the part. C4 now passes if any alignment shows a 10% speedup, and says so explicitly when the low mode does not, so the sensitivity appears in the log rather than being discovered later. Verified: with the sweep in place, adding 0, 8, 12 or 20 bytes of nops to entry.S leaves the reported low and high gains unchanged. Before it, the same shifts read 24.0%, 0%, 0% and 0%. Also adds cache_disable_all, which the sweep needs: cache_enable was one-way, so a second cold reading in one run was impossible. Assisted-by: Claude Code (Opus 5) --- .../gnu/example_build/s32z280_evb/bsp_boot.c | 215 ++++++++++++------ .../gnu/example_build/s32z280_evb/cache.c | 26 +++ .../gnu/example_build/s32z280_evb/cache.h | 6 + .../example_build/s32z280_evb/irq_dispatch.c | 6 + 4 files changed, 188 insertions(+), 65 deletions(-) diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/bsp_boot.c b/ports/cortex_r52/gnu/example_build/s32z280_evb/bsp_boot.c index 50d22a2b2..6a63947a5 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/bsp_boot.c +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/bsp_boot.c @@ -193,21 +193,102 @@ static void enable_irq_at_el1(void) * believed. */ -static unsigned long cache_bench_words; +/* Decimal, because a measurement read by a person should not need converting. + report() stays hex for register values, where hex is the right form. */ -static void cache_workload(void) +static void report_dec(unsigned long value) { - volatile unsigned int *buffer = (volatile unsigned int *) S32Z_DRAM2_BASE; - unsigned long pass; - unsigned long i; + char digits[12]; + unsigned int n = 0U; + + if (value == 0UL) { linflexd_putc('0'); return; } - for (pass = 0UL; pass < 32UL; pass++) + while ((value > 0UL) && (n < 12U)) { - for (i = 0UL; i < cache_bench_words; i++) - { - buffer[i] = buffer[i] + i + pass; - } + digits[n] = (char) ('0' + (value % 10UL)); + value /= 10UL; + n++; } + while (n > 0U) { n--; linflexd_putc(digits[n]); } +} + +static void report_dec_small(unsigned int value) +{ + report_dec((unsigned long) value); +} + +#define BUFFER_BASE S32Z_DRAM2_BASE + +static unsigned long cache_bench_words; + +/* Aligned to a cache line, and that alignment is load-bearing rather than + cosmetic. Without it this measurement is bimodal: it reports either about + 24% cache benefit or none at all, decided purely by where the loop happens + to fall relative to a 64-byte line, and therefore by any unrelated change + that shifts code ahead of it. Adding two nop instructions to the startup + file was enough to flip it, which is how a run of conclusions drawn from + this probe -- including a defect report to NXP -- turned out to be measuring + code layout rather than the part. + + Pinning the entry point does not make the workload fast or slow, it makes it + the same across builds, which is the only property that lets two numbers be + compared. */ + +/* Four copies of the same loop, each 64-byte aligned and then displaced by a + different offset within the line. The measurement runs all four and reports + the spread. + + One copy is not enough, and a single number from this workload is actively + misleading. Unpinned, it reported either about 24% cache benefit or none at + all depending on where the loop fell relative to a 64-byte line -- two nop + instructions added to the startup file flipped it. Pinning the entry to a + line does not fix that, it just picks one of the two modes and hides the + other: aligned to 64 the loop sits permanently in the low mode. + + The variation is real behaviour, not noise. Both modes reproduce exactly + across runs. The cold pass runs with both caches off, so it is heavily + instruction-fetch bound out of code RAM at half the core frequency, and how + the loop straddles lines decides how much of the data cache's contribution + is visible at all. Reporting min and max across alignments says that out + loud instead of letting one arbitrary placement stand in for the part. */ + +#define CACHE_WORKLOAD_COPIES 4U + +#define MAKE_CACHE_WORKLOAD(name, pad_words) \ +__attribute__((aligned(64), noinline)) \ +static void name(void) \ +{ \ + volatile unsigned int *buffer = (volatile unsigned int *) BUFFER_BASE; \ + unsigned long pass; \ + unsigned long i; \ + \ + __asm__ volatile(".rept " #pad_words "\n\tnop\n\t.endr"); \ + \ + for (pass = 0UL; pass < 32UL; pass++) \ + { \ + for (i = 0UL; i < cache_bench_words; i++) \ + { \ + buffer[i] = buffer[i] + i + pass; \ + } \ + } \ +} + +MAKE_CACHE_WORKLOAD(cache_workload_a, 0) +MAKE_CACHE_WORKLOAD(cache_workload_b, 4) +MAKE_CACHE_WORKLOAD(cache_workload_c, 8) +MAKE_CACHE_WORKLOAD(cache_workload_d, 12) + +static void (*const cache_workloads[CACHE_WORKLOAD_COPIES])(void) = +{ + cache_workload_a, /* loop at line offset 0 */ + cache_workload_b, /* loop at line offset 16 */ + cache_workload_c, /* loop at line offset 32 */ + cache_workload_d /* loop at line offset 48 */ +}; + +static void cache_workload(void) +{ + cache_workloads[0](); } @@ -728,46 +809,57 @@ void bsp_main(void) cache_bench_words = cache_dcache_bytes() / (2UL * sizeof(unsigned int)); report("bench wds", (unsigned int) cache_bench_words); - linflexd_puts("C1 timing over DRAM2, the half-speed bank, caches OFF\n"); + /* Measured at four loop alignments, not one, and the spread is reported + because it is large and real. See the comment on the workload copies. */ + + linflexd_puts("C1 timing DRAM2 at four loop alignments\n"); { - unsigned long long before; - unsigned long long after; - unsigned long cold; - unsigned long warm; + unsigned long gains[CACHE_WORKLOAD_COPIES]; + unsigned long lo = 0xFFFFFFFFUL; + unsigned long hi = 0UL; + unsigned int k; - before = timer_read_cntpct(); - cache_workload(); - after = timer_read_cntpct(); - cold = (unsigned long) (after - before); + for (k = 0U; k < CACHE_WORKLOAD_COPIES; k++) + { + unsigned long long before; + unsigned long long after; + unsigned long cold; + unsigned long warm; + + /* Cold: both caches off. cache_disable_all also invalidates, so + each alignment starts from the same state as the first. */ + + cache_disable_all(); + + before = timer_read_cntpct(); + cache_workloads[k](); + after = timer_read_cntpct(); + cold = (unsigned long) (after - before); + + cache_enable(); + + before = timer_read_cntpct(); + cache_workloads[k](); + after = timer_read_cntpct(); + warm = (unsigned long) (after - before); + + gains[k] = (cold > warm) ? (((cold - warm) * 1000UL) / cold) : 0UL; + + if (gains[k] < lo) { lo = gains[k]; } + if (gains[k] > hi) { hi = gains[k]; } + + linflexd_puts(" offset "); + report_dec_small(k * 16U); + linflexd_puts(": cold "); + report_dec(cold); + linflexd_puts(" warm "); + report_dec(warm); + linflexd_puts(" gain/1000 "); + report_dec(gains[k]); + linflexd_puts("\n"); + } - MARK(0x71); - linflexd_puts("C2 enabling caches\n"); - cache_enable(); MARK(0x72); - report("SCTLR ", read_sctlr_after_mpu()); - report("cachesOn ", cache_enabled()); - - before = timer_read_cntpct(); - cache_workload(); - after = timer_read_cntpct(); - warm = (unsigned long) (after - before); - - MARK(0x73); - report("counts off", cold); - report("counts on ", warm); - - /* Report the two claims separately, because they are separate. - "Enabled" is what SCTLR says and is checkable. "Effective" needs a - measurable speedup, and a criterion of merely warm < cold is - worthless: the first run of this test showed 609904 against 609686, - a 0.036% difference that is noise, and printed PASS on it. - - A cache having little to offer here is plausible rather than - broken. Both the code and the data this workload touches live in - full-speed RTU banks, which the core reaches at its own - clock; the only slower memory on this board is DRAM2 at - half speed, and DDR, which is not initialised. */ - if (cache_enabled() == 1U) { linflexd_puts("C3 PASS caches enabled (SCTLR.C and SCTLR.I set)\n"); @@ -777,33 +869,26 @@ void bsp_main(void) linflexd_puts("C3 FAIL caches did not enable\n"); } - if (cold > warm) - { - unsigned long gain = ((cold - warm) * 1000UL) / cold; + report("gain lo ", (unsigned int) lo); + report("gain hi ", (unsigned int) hi); - report("gain/1000", gain); + /* The claim is that the caches can help this workload, which needs one + alignment to show it. A criterion applied to a single arbitrary + alignment would report either 24% or nothing at all, and both would + be true of the same silicon. */ - if (gain >= 100UL) - { - linflexd_puts("C4 PASS caches measurably faster (>=10%)\n"); - } - else + if (hi >= 100UL) + { + linflexd_puts("C4 PASS caches measurably faster at some alignment\n"); + if (lo < 100UL) { - linflexd_puts("C4 speedup below 10% -- see gain/1000 above\n"); + linflexd_puts(" note: alignment-dependent, low mode under 10%\n"); } } else { - linflexd_puts("C4 no speedup measured\n"); + linflexd_puts("C4 no alignment showed a 10% speedup\n"); } - - /* Push the markers and counters out of the write-back cache so a - debugger reading SRAM sees them. Without this a post-mortem read - could report stale values from before the cache was enabled. */ - - cache_clean_all(); - MARK(0x74); - cache_clean_all(); } /* --- protection test --------------------------------------------------- diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/cache.c b/ports/cortex_r52/gnu/example_build/s32z280_evb/cache.c index 29b7cc396..a7b0d6a19 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/cache.c +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/cache.c @@ -318,3 +318,29 @@ unsigned int cache_enabled(void) return (((sctlr & SCTLR_C) != 0UL) && ((sctlr & SCTLR_I) != 0UL)) ? 1U : 0U; } + + +void cache_disable_all(void) +{ + unsigned long sctlr; + + /* Clean before disabling, so dirty lines reach memory while the cache is + still on to write them back. Invalidate afterwards, so nothing stale is + left to be hit if the caches are enabled again. */ + + cache_clean_all(); + __asm__ volatile("dsb sy" ::: "memory"); + + __asm__ volatile("mrc p15, 0, %0, c1, c0, 0" : "=r"(sctlr)); + sctlr &= ~((1UL << 2) | (1UL << 12)); /* SCTLR.C, SCTLR.I */ + __asm__ volatile("mcr p15, 0, %0, c1, c0, 0" : : "r"(sctlr) : "memory"); + + __asm__ volatile("dsb sy" ::: "memory"); + __asm__ volatile("isb" ::: "memory"); + + cache_invalidate_dcache_all(); + cache_invalidate_icache_all(); + + __asm__ volatile("dsb sy" ::: "memory"); + __asm__ volatile("isb" ::: "memory"); +} diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/cache.h b/ports/cortex_r52/gnu/example_build/s32z280_evb/cache.h index 0ded69370..3202c97e3 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/cache.h +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/cache.h @@ -50,6 +50,12 @@ void cache_clean_all(void); void cache_enable(void); +/* Clean, then disable both caches, then invalidate. Needed by any measurement + that wants more than one cold pass in a single run: cache_enable is + one-way, and a second cold reading is otherwise impossible. */ + +void cache_disable_all(void); + unsigned int cache_enabled(void); /* Decoded L1 data-cache geometry, from CCSIDR. Sizing a cache benchmark diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/irq_dispatch.c b/ports/cortex_r52/gnu/example_build/s32z280_evb/irq_dispatch.c index 0ef90b7b4..2d9876611 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/irq_dispatch.c +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/irq_dispatch.c @@ -193,6 +193,7 @@ unsigned int board_service_count; #define BOARD_ISR_SECTION #endif +__attribute__((aligned(64))) static BOARD_ISR_SECTION void board_irq_service_body(unsigned long intid); void board_irq_service(unsigned long intid) @@ -212,6 +213,11 @@ void board_irq_service(unsigned long intid) } +/* Aligned for the same reason as cache_workload: this body is timed, and + without a fixed alignment the figure moves with unrelated code changes + elsewhere in the image. */ + +__attribute__((aligned(64))) static BOARD_ISR_SECTION void board_irq_service_body(unsigned long intid) { if (intid == GICV3_SPURIOUS_INTID) From 3aaaa6700d51ddb4279ad1a5b9899afaca513354 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 17 Aug 2026 13:33:43 -0400 Subject: [PATCH 059/181] Revalidated the ATCM handler result across four placements, and it holds (#632) The handler comparison in #630 measured one alignment, which is the mistake that made the cache benchmark in this example report 24% or 0% for identical silicon. The handler body is now generated at four offsets within a cache line, all four are measured, and the figures are reported per placement. The claim survives. Mean cycles for the handler body: loop offset code RAM ATCM 0 523 383 16 534 377 32 539 375 48 521 383 ATCM is faster at every placement, by about 28%, and the two sets of means do not overlap. Worst case improves as well, 510 against 694. Two things worth recording beyond the headline. The handler measurement is only mildly alignment sensitive, 3.5% across placements in code RAM and 2% in ATCM, quite unlike the cache loop's two modes. So this comparison was less fragile than the cache one, and #630's direction was right even though its method was not defensible. The absolute numbers differ from #630 because the body now sits behind a placement wrapper that adds a call; the comparison is internally consistent either way. Both variants also report identical cache sweeps, 0 and 0 and 240 and 240, which settles the regression this branch's predecessor appeared to show. That apparent regression was the single-alignment probe moving between its two modes, not anything about ATCM. One copy of the logic is kept: the wrappers inline a single always_inline implementation, so the four placements cannot drift apart. Assisted-by: Claude Code (Opus 5) --- .../gnu/example_build/s32z280_evb/bsp_boot.c | 55 ++++++++++-- .../example_build/s32z280_evb/irq_dispatch.c | 88 +++++++++++++++---- 2 files changed, 117 insertions(+), 26 deletions(-) diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/bsp_boot.c b/ports/cortex_r52/gnu/example_build/s32z280_evb/bsp_boot.c index 6a63947a5..ce6d03480 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/bsp_boot.c +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/bsp_boot.c @@ -750,19 +750,58 @@ void bsp_main(void) sum += (unsigned long) v; } - linflexd_puts("I5 handler body cycles "); + linflexd_puts("I5 handler body cycles, four placements "); #ifdef TX_R52_ATCM_ISR - linflexd_puts("(body in ATCM)\n"); + linflexd_puts("(bodies in ATCM)\n"); #else - linflexd_puts("(body in code RAM)\n"); + linflexd_puts("(bodies in code RAM)\n"); #endif report("samples ", n); - if (n > 0U) + + /* Per placement, because the aggregate hides exactly the thing that + invalidated the previous version of this comparison. 16 samples + each, in the order the wrapper rotated through them. */ + { - report("min ", lo); - report("max ", hi); - report("mean ", (unsigned int) (sum / n)); - report("spread ", hi - lo); + unsigned int slot; + unsigned int each = 64U / 4U; + + for (slot = 0U; slot < 4U; slot++) + { + unsigned int s_lo = 0xFFFFFFFFU; + unsigned int s_hi = 0U; + unsigned long s_sum = 0UL; + unsigned int c = 0U; + unsigned int m; + + for (m = slot * each; (m < ((slot + 1U) * each)) && (m < n); m++) + { + unsigned int v = board_service_cycles[m]; + + if (v < s_lo) { s_lo = v; } + if (v > s_hi) { s_hi = v; } + s_sum += (unsigned long) v; + c++; + } + + linflexd_puts(" offset "); + report_dec((unsigned long) (slot * 16U)); + linflexd_puts(": "); + if (c == 0U) + { + linflexd_puts("no samples\n"); + } + else + { + linflexd_puts("min "); + report_dec((unsigned long) s_lo); + linflexd_puts(" max "); + report_dec((unsigned long) s_hi); + linflexd_puts(" mean "); + report_dec(s_sum / c); + linflexd_puts("\n"); + } + } } } report("first INTID", (unsigned int) board_first_intid); diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/irq_dispatch.c b/ports/cortex_r52/gnu/example_build/s32z280_evb/irq_dispatch.c index 2d9876611..92fbe97b4 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/irq_dispatch.c +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/irq_dispatch.c @@ -193,32 +193,28 @@ unsigned int board_service_count; #define BOARD_ISR_SECTION #endif -__attribute__((aligned(64))) -static BOARD_ISR_SECTION void board_irq_service_body(unsigned long intid); +static inline __attribute__((always_inline)) +void board_irq_service_impl(unsigned long intid); -void board_irq_service(unsigned long intid) -{ - unsigned int before; - unsigned int after; - - before = timer_read_cycles(); - board_irq_service_body(intid); - after = timer_read_cycles(); - if (board_service_count < BOARD_LATENCY_SAMPLES) - { - board_service_cycles[board_service_count] = after - before; - board_service_count++; - } -} /* Aligned for the same reason as cache_workload: this body is timed, and without a fixed alignment the figure moves with unrelated code changes elsewhere in the image. */ -__attribute__((aligned(64))) -static BOARD_ISR_SECTION void board_irq_service_body(unsigned long intid) +/* Four placements of one implementation. The logic below is inlined into each + of the four wrappers further down, each 64-byte aligned and then displaced by + a different offset within the line, and the measurement rotates through them. + + A single placement is not measurable. The cache benchmark in this file's + sibling turned out to be bimodal with respect to exactly this, reporting 24% + or 0% for identical silicon depending on where a loop fell in a line, and it + invalidated a handler comparison and a defect report to NXP before anyone + noticed. Pinning one alignment does not fix that, it just chooses a mode. */ + +static inline __attribute__((always_inline)) +void board_irq_service_impl(unsigned long intid) { if (intid == GICV3_SPURIOUS_INTID) { @@ -303,6 +299,62 @@ static BOARD_ISR_SECTION void board_irq_service_body(unsigned long intid) } +/* The four placements. pad nops shift the inlined body within its line. */ + +#define MAKE_ISR_BODY(name, pad) \ +__attribute__((aligned(64), noinline)) \ +static BOARD_ISR_SECTION void name(unsigned long intid) \ +{ \ + __asm__ volatile(".rept " #pad "\n\tnop\n\t.endr"); \ + board_irq_service_impl(intid); \ +} + +MAKE_ISR_BODY(board_irq_body_a, 0) +MAKE_ISR_BODY(board_irq_body_b, 4) +MAKE_ISR_BODY(board_irq_body_c, 8) +MAKE_ISR_BODY(board_irq_body_d, 12) + +#define BOARD_ISR_PLACEMENTS 4U +#define BOARD_SAMPLES_EACH (BOARD_LATENCY_SAMPLES / BOARD_ISR_PLACEMENTS) + +static void (*const board_irq_bodies[BOARD_ISR_PLACEMENTS])(unsigned long) = +{ + board_irq_body_a, /* body at line offset 0 */ + board_irq_body_b, /* body at line offset 16 */ + board_irq_body_c, /* body at line offset 32 */ + board_irq_body_d /* body at line offset 48 */ +}; + + +void board_irq_service(unsigned long intid) +{ + unsigned int before; + unsigned int after; + + /* A block of samples per placement, so each alignment is measured under the + same conditions rather than interleaved with the others. */ + + { + unsigned int slot = board_service_count / BOARD_SAMPLES_EACH; + + if (slot >= BOARD_ISR_PLACEMENTS) + { + slot = BOARD_ISR_PLACEMENTS - 1U; + } + + before = timer_read_cycles(); + board_irq_bodies[slot](intid); + after = timer_read_cycles(); + } + + if (board_service_count < BOARD_LATENCY_SAMPLES) + { + board_service_cycles[board_service_count] = after - before; + board_service_count++; + } +} + + /**************************************************************************/ /* board_irq_handler -- the non-nesting entry point. */ /* */ From 35de56853c24fac04d15b7b99f5d3c1ec369d9f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 17 Aug 2026 13:46:33 -0400 Subject: [PATCH 060/181] Retracted the claim that a second TCM bank costs the data cache (#633) entry.S and readme_s32z280.txt both stated that enabling any second TCM bank removes all measurable data-cache benefit on this part, and gave five configurations as evidence: ATCM alone at a 24% cache gain, four combinations involving a second bank at none. Both concluded the cause was not a particular bank, not its address and not the ECC preload, but enabling a second bank at all. Both cited the Cortex-R52 and S32Z2 errata as not covering it and offered a shared RAM pool between the LLC and the TCMs as an explanation. A defect report went to NXP on that basis. It was an artifact of the benchmark. That benchmark was bimodal with respect to where its timing loop fell inside a 64-byte cache line, reporting either 24% or nothing at all for identical silicon, and every one of those five configurations was an edit to entry.S, so every one shifted the code that followed and moved the loop between modes. Adding two nop instructions reproduces the "second bank" figure exactly, to the digit. The report to NXP has been withdrawn. Re-measured with the alignment sweep added in #631, one bank and two are indistinguishable: loop offset in line ATCM only ATCM + CTCM 0 gain 0 gain 0 16 gain 0 gain 0 32 gain 240/1000 gain 240/1000 48 gain 240/1000 gain 240/1000 So enabling a second bank costs nothing measurable. The banks stay disabled, but for the ordinary reason that nothing in this example uses them, and both texts now say that instead. Enabling one is a single line, with the ECC preload before any read (TRM 6.2.2) and an MPU region as the only prerequisites, both already handled for ATCM. The readme also now states the general point, which outlasts the TCM detail: a single-figure timing result from this example cannot be compared across builds unless the timed loop's alignment is controlled, because almost any change shifts code. Comments and documentation only; no generated code changes. Verified on the board regardless, since entry.S was touched: six of six probes pass and the sweep is unchanged. Assisted-by: Claude Code (Opus 5) --- .../gnu/example_build/s32z280_evb/entry.S | 55 ++++++++-------- .../s32z280_evb/readme_s32z280.txt | 62 +++++++++++-------- 2 files changed, 66 insertions(+), 51 deletions(-) diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/entry.S b/ports/cortex_r52/gnu/example_build/s32z280_evb/entry.S index 7b48ef459..1b5a73d44 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/entry.S +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/entry.S @@ -260,36 +260,41 @@ start_a32: ldr r0, =(0x30000000 | (0x07 << 2) | (1 << 8) | (1 << 1) | (1 << 0)) mcr p15, 0, r0, c9, c1, 0 /* IMP_ATCMREGIONR */ - /* BTCM and CTCM are deliberately NOT enabled, and this costs nothing that - * matters: the reference manual describes TCM_A as the bank "optimized for - * small, regularly executed code such as interrupt service routines or OS - * kernels", which is what a TCM is wanted for here. + /* BTCM and CTCM are not enabled, because nothing in this example uses them. + * That is the whole reason, and it is worth stating plainly because the + * reason given here previously was wrong. * - * Enabling a second bank on this part removes all measurable data-cache - * benefit. Measured, five configurations, one variable: + * This comment used to claim that enabling a second bank removed all + * measurable data-cache benefit, and it listed five configurations to prove + * it: ATCM alone showing a 24% cache gain, and four combinations involving a + * second bank showing none. It concluded that the trigger was not a + * particular bank, not the bank's address and not the ECC preload, but + * enabling a second bank at all. It cited the Cortex-R52 and S32Z2 errata as + * not covering it, and offered a shared RAM pool between the LLC and the TCMs + * as an explanation. A defect report went to NXP on that basis. * - * ATCM only cache gain 24% - * ATCM + BTCM cache gain 0% - * ATCM + BTCM + CTCM cache gain 0% - * ATCM + BTCM at another base cache gain 0% - * ATCM + CTCM, BTCM disabled cache gain 0% + * All of it was an artifact of the benchmark that produced the numbers. That + * benchmark was bimodal with respect to where its loop fell inside a 64-byte + * cache line, reporting either 24% or nothing at all for identical silicon, + * and every one of those five configurations was an edit to this file, so + * every one shifted the code that followed and flipped the mode. Adding two + * nop instructions here reproduces the "second bank" result exactly, to the + * digit. The report to NXP has been withdrawn. * - * So it is not a particular bank, not the bank's address, and not the ECC - * preload -- it is enabling a second bank at all. The benchmark buffer sits - * in non-RTU-local SRAM at 0x31800000, outside every TCM window, and the - * cache still reports 16KB with 4 ways and 64 sets throughout. + * Measured again with a benchmark that sweeps four loop alignments and + * reports the distribution, ATCM alone and ATCM plus CTCM are + * indistinguishable: * - * No erratum covers it. Checked the Cortex-R52 errata notice - * (SDEN-857344 issue 19, all 25 entries) and the S32Z2 mask set errata for - * 0P91J; the RTU and R52 entries there are ERR050509, ERR051107, ERR051153, - * ERR051441, ERR051613, ERR051614 and ERR052126, none of which describes - * this. A shared RAM pool between the LLC and the TCMs would explain it, - * since the RTU has a last-level cache that "allocates ways to specific - * domains", but that is a guess and it is NXP's to confirm. + * loop offset in line ATCM only ATCM + CTCM + * 0 gain 0 gain 0 + * 16 gain 0 gain 0 + * 32 gain 240/1000 gain 240/1000 + * 48 gain 240/1000 gain 240/1000 * - * Enabling them is one uncommented line each if that answer arrives. Until - * then, shipping them would trade a 24% cache regression for TCM this - * example does not use. + * So enabling a second bank costs nothing measurable. Enabling one is a + * single line, and the only prerequisites are the ECC preload before any read + * (TRM 6.2.2) and an MPU region, both of which tcm.c and mpu.c already + * handle for ATCM. They stay off until something needs them. */ isb diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/readme_s32z280.txt b/ports/cortex_r52/gnu/example_build/s32z280_evb/readme_s32z280.txt index 47723c165..30aef5dcc 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/readme_s32z280.txt +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/readme_s32z280.txt @@ -92,32 +92,42 @@ model and not an R52 at all. two banks. The boot image preloads it (ECC check bits are not initialised by the core) and proves it holds data both before and after the MPU is enabled. - BTCM and CTCM are left disabled on purpose, and that is a measurement rather - than caution. Enabling any second bank removes all measurable data-cache - benefit on this part: - - ATCM only cache gain 24% - ATCM + BTCM cache gain 0% - ATCM + BTCM + CTCM cache gain 0% - ATCM + BTCM at another base cache gain 0% - ATCM + CTCM, BTCM disabled cache gain 0% - - Five configurations, one variable. Not a particular bank, not its address, - not the ECC preload -- enabling a second bank at all. The benchmark buffer is - in non-RTU-local SRAM at 0x31800000, outside every TCM window, and CCSIDR - reports the same 16 KB four-way cache throughout. - - No erratum covers this. Checked SDEN-857344 issue 19 (all 25 Cortex-R52 - entries) and the S32Z2 0P91J mask set errata, whose RTU and R52 entries are - ERR050509, ERR051107, ERR051153, ERR051441, ERR051613, ERR051614 and - ERR052126. A RAM pool shared between the RTU's last-level cache and the TCMs - would explain it -- the LLC "allocates ways to specific domains" -- but that is - a guess for NXP to confirm, and worth raising with the other RTU questions. - - Losing nothing by this: the reference manual describes TCM_A as the bank - "optimized for small, regularly executed code such as interrupt service - routines or OS kernels", which is what a TCM is wanted for here. Enabling the - other two is one line each in entry.S when there is an answer. + BTCM and CTCM are left disabled because nothing in this example uses them. + + An earlier version of this file said something much stronger and it was + wrong. It claimed that enabling any second bank removes all measurable + data-cache benefit on this part, and gave five configurations as evidence: + ATCM alone at a 24% cache gain, and four combinations involving a second bank + at none. It concluded the cause was not a particular bank, not its address + and not the ECC preload, but enabling a second bank at all. A defect report + went to NXP on that basis and has since been withdrawn. + + The benchmark that produced those numbers was bimodal with respect to where + its timing loop fell inside a 64-byte cache line. The same workload on the + same silicon reported either 24% or nothing at all depending on that + placement, and each of the five configurations was an edit to entry.S, so + each shifted the code that followed and moved the loop between the two + modes. Adding two nop instructions to entry.S reproduces the "second bank" + figure exactly. + + Re-measured with a benchmark that sweeps four loop alignments and reports the + distribution, one bank and two are indistinguishable: + + loop offset in line ATCM only ATCM + CTCM + 0 gain 0 gain 0 + 16 gain 0 gain 0 + 32 gain 240/1000 gain 240/1000 + 48 gain 240/1000 gain 240/1000 + + Enabling a second bank costs nothing measurable. It is one line in entry.S, + and the prerequisites are the ECC preload before any read (TRM 6.2.2) and an + MPU region, both already handled for ATCM. + + The wider lesson is worth more than the TCM detail: a single-figure timing + result from this example cannot be compared across builds unless the timed + loop's alignment is controlled, because almost any change shifts code. The + cache and interrupt-handler measurements here now sweep alignments and report + the spread for that reason. The DDR window at 0x7A000000 is dark until DDR is initialised. TCM is still absent from link.lds: nothing is placed there yet. From 62e966f6bf0f4f56c7b8e40b672a0d7374aa56f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 17 Aug 2026 16:33:55 -0400 Subject: [PATCH 061/181] Enabled BTCM, measured it, and put a ThreadX thread stack in it (#634) * Enabled BTCM and measured what it offers as a data store BTCM was disabled because of a regression that turned out not to exist; the claim was retracted in the previous commit. It is enabled now, and this measures why that is worth doing: 16 KB at zero wait states, where ATCM has one, and no cache in the path at all. Enabling it needs three things, all of which existed for ATCM already: the region register write at EL2, an MPU region, and an ECC preload before any read (TRM 6.2.2). BTCM accepts 32-bit stores where ATCM needs 64-bit, which tcm_preload already handles. The cache benchmark now sweeps three memories rather than one, four loop alignments each. At the alignments where the loop is not instruction-fetch bound: memory cold (uncached) warm (cached) gain DRAM2 half-speed 857,540 651,436 24.0% DRAM0 full-speed 797,824 651,297 18.3% BTCM zero wait 694,689 651,369 6.2% Three things follow. Warm times are identical across all three memories, within 0.02%. Once the data cache is working the backing store barely matters, because the working set fits in it. Cold times rank as the reference manual predicts: BTCM fastest, then DRAM0, then DRAM2 at half the core frequency (S32Z2 RM 6.3.6). BTCM still shows a 6.2% gain when the caches are enabled, and that cannot be the data cache, because an enabled TCM is Non-cacheable Non-shareable Normal memory whatever the MPU says. It is the instruction cache on the timing loop. This probe has always measured both caches together; three memories side by side is what makes that visible. The number that matters for placing data in BTCM: uncached BTCM is within 6.6% of the best cached case, where uncached DRAM0 is 22% off it. Data in BTCM runs at close to cache-hit speed with no cache to miss, which is the determinism argument stated as a measurement rather than an assertion. DRAM2's sweep is unchanged with BTCM enabled, 0 and 0 and 240 and 240, which independently confirms the retraction. Assisted-by: Claude Code (Opus 5) * Put a ThreadX thread stack in BTCM The code side of TCM was done in #630; this is the data side. One of the demo's three thread stacks now lives in BTCM and the other two stay in DRAM0, so a run exercises both paths and a mistake in either shows up. link.lds gains a BTCM region and a .btcm_bss NOLOAD section, so a stack is an ordinary C array with a section attribute and the linker checks it fits, rather than a hardcoded address that silently overflows the bank. entry.S preloads the whole bank at EL2, and that is not optional. ECC is enabled on this part, so a TCM location must be written before it can be read (TRM 6.2.2), and a stack is read before the program writes it -- the first context restore pops what tx_thread_create built into it. The preload has to happen before any C runs, because the demo images do not run bsp_boot.c, which is where the ATCM preload lives. 32-bit stores suffice for BTCM where ATCM needs 64-bit. Why BTCM for a stack: 16 KB at zero wait states where ATCM has one, and never cached whatever the MPU says about it. Measured in the previous commit, uncached BTCM comes within 6.6% of the best cached case while uncached DRAM0 is 22% off it, so stack access runs at close to cache-hit speed without depending on a line being resident. That is the property a determinism argument needs. What this commit does not claim: no thread-level timing improvement has been measured. The case for BTCM here rests on the memory characterisation and on removing the cache from the path, not on a measured context-switch figure. That measurement is worth doing and has not been done. Verified on the S32Z280-594EVB. The demo reports its stack addresses so the placement is visible rather than implied -- sleeper at 0x30100000 in BTCM, spinner and judge in DRAM0 -- and passes with 100 ticks, 20 sleeper wakeups and 20 preemptions, so a real thread schedules, preempts and context-switches on a tightly-coupled-memory stack. The boot image still passes six of six probes. Assisted-by: Claude Code (Opus 5) --- .../gnu/example_build/s32z280_evb/bsp_boot.c | 144 +++++++++++------- .../example_build/s32z280_evb/demo_s32z280.c | 23 +++ .../gnu/example_build/s32z280_evb/entry.S | 27 ++++ .../gnu/example_build/s32z280_evb/link.lds | 17 +++ .../gnu/example_build/s32z280_evb/mpu.c | 16 +- 5 files changed, 169 insertions(+), 58 deletions(-) diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/bsp_boot.c b/ports/cortex_r52/gnu/example_build/s32z280_evb/bsp_boot.c index ce6d03480..13ea498b4 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/bsp_boot.c +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/bsp_boot.c @@ -256,9 +256,8 @@ static unsigned long cache_bench_words; #define MAKE_CACHE_WORKLOAD(name, pad_words) \ __attribute__((aligned(64), noinline)) \ -static void name(void) \ +static void name(volatile unsigned int *buffer) \ { \ - volatile unsigned int *buffer = (volatile unsigned int *) BUFFER_BASE; \ unsigned long pass; \ unsigned long i; \ \ @@ -278,7 +277,7 @@ MAKE_CACHE_WORKLOAD(cache_workload_b, 4) MAKE_CACHE_WORKLOAD(cache_workload_c, 8) MAKE_CACHE_WORKLOAD(cache_workload_d, 12) -static void (*const cache_workloads[CACHE_WORKLOAD_COPIES])(void) = +static void (*const cache_workloads[CACHE_WORKLOAD_COPIES])(volatile unsigned int *) = { cache_workload_a, /* loop at line offset 0 */ cache_workload_b, /* loop at line offset 16 */ @@ -288,7 +287,7 @@ static void (*const cache_workloads[CACHE_WORKLOAD_COPIES])(void) = static void cache_workload(void) { - cache_workloads[0](); + cache_workloads[0]((volatile unsigned int *) BUFFER_BASE); } @@ -530,6 +529,15 @@ void bsp_main(void) linflexd_puts("T3 preloading ATCM to establish ECC check bits\n"); tcm_preload(0U, S32Z_ATCM_BASE, S32Z_ATCM_SIZE); + /* BTCM too, now that entry.S enables it. Whole bank: nothing is + placed there at link time, and with ECC on, a location must be + written before it can be read. BTCM accepts 32-bit stores where + ATCM needs 64-bit (TRM 6.2.2); tcm_preload handles the + difference. */ + + linflexd_puts("T3b preloading BTCM\n"); + tcm_preload(1U, S32Z_BTCM_BASE, S32Z_BTCM_SIZE); + MARK(0x22); linflexd_puts("T4 write and read back ATCM\n"); { @@ -851,51 +859,79 @@ void bsp_main(void) /* Measured at four loop alignments, not one, and the spread is reported because it is large and real. See the comment on the workload copies. */ - linflexd_puts("C1 timing DRAM2 at four loop alignments\n"); - { - unsigned long gains[CACHE_WORKLOAD_COPIES]; - unsigned long lo = 0xFFFFFFFFUL; - unsigned long hi = 0UL; - unsigned int k; - - for (k = 0U; k < CACHE_WORKLOAD_COPIES; k++) - { - unsigned long long before; - unsigned long long after; - unsigned long cold; - unsigned long warm; + /* Three memories, four loop alignments each. The memories are the point: + DRAM2 runs at half the core frequency, DRAM0 at full, and BTCM at full + with zero wait states and no cache in the path at all -- an enabled TCM is + Non-cacheable Non-shareable Normal memory whatever the MPU says. - /* Cold: both caches off. cache_disable_all also invalidates, so - each alignment starts from the same state as the first. */ + The alignment sweep is what makes the three comparable. A single figure + per memory would be picking one of two modes per memory and calling it a + result, which is how this example previously produced a defect report that + had to be withdrawn. */ - cache_disable_all(); - - before = timer_read_cntpct(); - cache_workloads[k](); - after = timer_read_cntpct(); - cold = (unsigned long) (after - before); - - cache_enable(); - - before = timer_read_cntpct(); - cache_workloads[k](); - after = timer_read_cntpct(); - warm = (unsigned long) (after - before); + linflexd_puts("C1 timing three memories, four loop alignments each\n"); + { + static const struct + { + const char *name; + unsigned long base; + } memories[3] = + { + { "DRAM2 half-speed", S32Z_DRAM2_BASE }, + { "DRAM0 full-speed", S32Z_DRAM0_BASE + 0x10000UL }, + { "BTCM 0 wait ", S32Z_BTCM_BASE } + }; - gains[k] = (cold > warm) ? (((cold - warm) * 1000UL) / cold) : 0UL; + unsigned long overall_hi = 0UL; + unsigned int m; - if (gains[k] < lo) { lo = gains[k]; } - if (gains[k] > hi) { hi = gains[k]; } + for (m = 0U; m < 3U; m++) + { + unsigned int k; - linflexd_puts(" offset "); - report_dec_small(k * 16U); - linflexd_puts(": cold "); - report_dec(cold); - linflexd_puts(" warm "); - report_dec(warm); - linflexd_puts(" gain/1000 "); - report_dec(gains[k]); + linflexd_puts(" "); + linflexd_puts(memories[m].name); + linflexd_puts(" at 0x"); + linflexd_put_hex32((unsigned int) memories[m].base); linflexd_puts("\n"); + + for (k = 0U; k < CACHE_WORKLOAD_COPIES; k++) + { + volatile unsigned int *buf = + (volatile unsigned int *) memories[m].base; + unsigned long long before; + unsigned long long after; + unsigned long cold; + unsigned long warm; + unsigned long gain; + + cache_disable_all(); + + before = timer_read_cntpct(); + cache_workloads[k](buf); + after = timer_read_cntpct(); + cold = (unsigned long) (after - before); + + cache_enable(); + + before = timer_read_cntpct(); + cache_workloads[k](buf); + after = timer_read_cntpct(); + warm = (unsigned long) (after - before); + + gain = (cold > warm) ? (((cold - warm) * 1000UL) / cold) : 0UL; + if (gain > overall_hi) { overall_hi = gain; } + + linflexd_puts(" offset "); + report_dec((unsigned long) (k * 16U)); + linflexd_puts(": cold "); + report_dec(cold); + linflexd_puts(" warm "); + report_dec(warm); + linflexd_puts(" gain/1000 "); + report_dec(gain); + linflexd_puts("\n"); + } } MARK(0x72); @@ -908,25 +944,19 @@ void bsp_main(void) linflexd_puts("C3 FAIL caches did not enable\n"); } - report("gain lo ", (unsigned int) lo); - report("gain hi ", (unsigned int) hi); - - /* The claim is that the caches can help this workload, which needs one - alignment to show it. A criterion applied to a single arbitrary - alignment would report either 24% or nothing at all, and both would - be true of the same silicon. */ + /* The claim is that the caches can help somewhere, which needs one + memory at one alignment to show it. BTCM is expected to show nothing: + it is not cached, so there is nothing for enabling the cache to + improve, and a zero there is the correct answer rather than a + failure. */ - if (hi >= 100UL) + if (overall_hi >= 100UL) { - linflexd_puts("C4 PASS caches measurably faster at some alignment\n"); - if (lo < 100UL) - { - linflexd_puts(" note: alignment-dependent, low mode under 10%\n"); - } + linflexd_puts("C4 PASS caches measurably faster somewhere\n"); } else { - linflexd_puts("C4 no alignment showed a 10% speedup\n"); + linflexd_puts("C4 no memory and alignment showed a 10% speedup\n"); } } diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/demo_s32z280.c b/ports/cortex_r52/gnu/example_build/s32z280_evb/demo_s32z280.c index 9a3d3e389..04d31ef9e 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/demo_s32z280.c +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/demo_s32z280.c @@ -57,6 +57,21 @@ static TX_THREAD sleeper_thread; static TX_THREAD spinner_thread; static TX_THREAD judge_thread; +/* One stack in BTCM, the rest in DRAM0, so a run exercises both and the + difference is visible if one of them is wrong. + + BTCM is 16 KB at zero wait states and is never cached, whatever the MPU says + about it. That is the point for a stack: access cost does not depend on + whether a line happens to be resident, which is what a determinism argument + needs. Measured on this part, uncached BTCM comes within 6.6% of the best + cached case, where uncached DRAM0 is 22% off it. + + entry.S writes every location in the bank before any C runs, which is + required before a read because ECC is enabled (TRM 6.2.2). A stack is read + before it is written -- the first context restore pops what tx_thread_create + built -- so that preload is not optional here. */ + +__attribute__((section(".btcm_bss"), aligned(8))) static unsigned char sleeper_stack[DEMO_STACK_SIZE]; static unsigned char spinner_stack[DEMO_STACK_SIZE]; static unsigned char judge_stack[DEMO_STACK_SIZE]; @@ -191,6 +206,14 @@ void tx_application_define(void *first_unused_memory) { (void) first_unused_memory; + linflexd_puts("stacks: sleeper 0x"); + linflexd_put_hex32((unsigned int) (unsigned long) sleeper_stack); + linflexd_puts(" (BTCM) spinner 0x"); + linflexd_put_hex32((unsigned int) (unsigned long) spinner_stack); + linflexd_puts(" judge 0x"); + linflexd_put_hex32((unsigned int) (unsigned long) judge_stack); + linflexd_puts("\n"); + (void) tx_thread_create(&sleeper_thread, "sleeper", sleeper_entry, 0UL, sleeper_stack, DEMO_STACK_SIZE, 1U, 1U, TX_NO_TIME_SLICE, TX_AUTO_START); diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/entry.S b/ports/cortex_r52/gnu/example_build/s32z280_evb/entry.S index 1b5a73d44..6813251ae 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/entry.S +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/entry.S @@ -260,6 +260,33 @@ start_a32: ldr r0, =(0x30000000 | (0x07 << 2) | (1 << 8) | (1 << 1) | (1 << 0)) mcr p15, 0, r0, c9, c1, 0 /* IMP_ATCMREGIONR */ + + /* BTCM as well. 16 KB at zero wait states, where ATCM has one, so it is the + * faster bank for data -- which is what it is wanted for here. The claim + * that a second bank costs the data cache was withdrawn; see the note below. + * Preloaded by bsp_main before any read, as ECC requires, and BTCM accepts + * 32-bit stores where ATCM needs 64-bit (TRM 6.2.2). + */ + ldr r0, =(0x30100000 | (0x05 << 2) | (0 << 8) | (1 << 1) | (1 << 0)) + mcr p15, 0, r0, c9, c1, 1 /* IMP_BTCMREGIONR */ + isb + + /* Preload the whole bank. ECC is enabled on this part, so a TCM location + * must be written before it can be read (TRM 6.2.2), and this has to happen + * before any C runs: the demo images place thread stacks here and do not run + * bsp_boot.c, which is where the ATCM preload lives. 32-bit stores are + * sufficient for BTCM where ATCM needs 64-bit. + */ + + ldr r1, =0x30100000 + ldr r2, =0x00004000 + mov r3, #0 + +3: str r3, [r1], #4 + subs r2, r2, #4 + bgt 3b + + dsb sy /* BTCM and CTCM are not enabled, because nothing in this example uses them. * That is the whole reason, and it is worth stating plainly because the * reason given here previously was wrong. diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/link.lds b/ports/cortex_r52/gnu/example_build/s32z280_evb/link.lds index 1b39be82a..cb73bb35a 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/link.lds +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/link.lds @@ -49,6 +49,11 @@ MEMORY placed here runs at full core speed with one wait state, where CODE is RTU code RAM and runs at half the core frequency (S32Z2 RM 6.3.6). */ ATCM (rwx) : ORIGIN = 0x30000000, LENGTH = 0x00010000 /* 64 KB */ + /* BTCM. 16 KB at zero wait states, enabled by entry.S, and preloaded there + as well because ECC means a location must be written before it is read. + Used for data that wants deterministic access without depending on a + cache -- an enabled TCM is never cached. */ + BTCM (rw) : ORIGIN = 0x30100000, LENGTH = 0x00004000 /* 16 KB */ DATA (rwx) : ORIGIN = 0x31780000, LENGTH = 0x00080000 /* 512 KB: DRAM0 + DRAM1, both full core speed */ } @@ -130,6 +135,18 @@ SECTIONS __data_end__ = .; } > DATA + /* Data placed in BTCM. NOLOAD: nothing is copied in, and entry.S has + already written every location in the bank to establish ECC check bits, + so anything here is safe to read before it is written by the program. */ + + .btcm_bss (NOLOAD) : ALIGN(8) + { + __btcm_bss_start__ = .; + *(.btcm_bss*) + . = ALIGN(8); + __btcm_bss_end__ = .; + } > BTCM + .bss (NOLOAD) : { . = ALIGN(8); diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/mpu.c b/ports/cortex_r52/gnu/example_build/s32z280_evb/mpu.c index 42fe0f772..0af4ee94d 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/mpu.c +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/mpu.c @@ -388,7 +388,21 @@ static void build_table(void) AXIM provides there, which is not TCM and would read as success. See the measurement in entry.S. */ - mpu_regions_used = 7U; + /* BTCM. Data only, so execute-never, unlike the ATCM region above which + holds code. An enabled TCM behaves as Non-cacheable Non-shareable Normal + memory whatever the MPU says, so the attribute index below describes the + permissions and nothing else -- but a region is still required before the + bank can be touched at all. */ + + mpu_regions[7].mpu_region_base = S32Z_BTCM_BASE; + mpu_regions[7].mpu_region_limit = S32Z_BTCM_BASE + S32Z_BTCM_SIZE - 1UL; + mpu_regions[7].mpu_region_ap = MPU_AP_RW_EL1; + mpu_regions[7].mpu_region_execute_never = 1U; + mpu_regions[7].mpu_region_shareability = MPU_SH_NON; + mpu_regions[7].mpu_region_attr_index = MPU_ATTR_NORMAL_WB; + mpu_regions[7].mpu_region_name = "btcm RW NX tcm"; + + mpu_regions_used = 8U; } From 367d91880b928a250c46c5b28486b8d932bf1e50 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 17 Aug 2026 17:08:29 -0400 Subject: [PATCH 062/181] Measured context-switch cost against the memory holding the stack (#635) #634 placed a thread stack in BTCM and deliberately claimed no timing benefit, because none had been measured. This measures it. Two pairs of equal-priority threads hand control back and forth with tx_thread_relinquish. One pair has both stacks in BTCM, the other in DRAM0, and the measuring thread of each pair times the round trip in PMU cycles. Both pairs run in one image from one copy of the measuring code, which is what makes the comparison safe: the alignment trap that invalidated earlier work here bites when two builds with different layouts are compared, and a code shift moves both pairs equally. Reproducible to the cycle across runs: min mean max BTCM stacks 1370 1379 1402 DRAM0 stacks 1476 1480 1508 BTCM is about 7.4% faster, or 110 cycles on a round trip of two switches. Three findings that bound the claim, and the last one deflates it. The figure holds whether the cache is warm or cold. Cleaning and invalidating the data cache before every timed switch costs both configurations about 40 cycles and leaves the gap at 7.4%: warm it is 1334 against 1440, cold 1370 against 1476. So the advantage comes from BTCM's zero wait states, not from avoiding cache misses. That is because a context switch touches almost no stack -- sixteen registers, about one cache line -- so the stack's cache state has little to contribute either way. TCM should matter much more for threads with deep call chains or large locals, where the stack working set is big enough for cache state to dominate. That is not measured here and should not be assumed. There is no determinism benefit visible in this test. Excluding preempted samples, jitter is 32 cycles for BTCM and 28 to 34 for DRAM0 -- comparable, not better. A first version of this measurement appeared to show BTCM with 16 times less jitter, and that was wrong: max was reporting whichever pair a timer tick had landed on. Across three runs the outlier appeared in the BTCM pair once and the DRAM0 pair twice. Samples past 2000 cycles are now counted separately and excluded from min, mean and max alike, and the count is printed so the reader can see how many there were. Also tried and discarded: loading the partner thread with a cache walk to create pressure. The timed round trip includes the partner, so the walk dominated every sample and put all 256 past the outlier threshold. The per-sample flush replaced it and sits outside the timestamps. The demo also starts the PMU cycle counter, which bsp_boot.c does for the probe image and this image never ran. Without it every reading would have been zero, which reads as a free context switch rather than as a dead counter. Assisted-by: Claude Code (Opus 5) --- .../example_build/s32z280_evb/demo_s32z280.c | 210 ++++++++++++++++++ 1 file changed, 210 insertions(+) diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/demo_s32z280.c b/ports/cortex_r52/gnu/example_build/s32z280_evb/demo_s32z280.c index 04d31ef9e..91d459721 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/demo_s32z280.c +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/demo_s32z280.c @@ -49,6 +49,8 @@ #include "tx_api.h" #include "linflexd.h" +#include "timer.h" +#include "cache.h" #include "board.h" #define DEMO_STACK_SIZE 2048 @@ -103,6 +105,160 @@ static void report(const char *name, unsigned long value) /* Highest priority. Sleeps, so it can only run again if the tick advances and the scheduler resumes it. */ +/**************************************************************************/ +/* Context-switch cost, stack in BTCM against stack in DRAM0. */ +/* */ +/* Two pairs of equal-priority threads hand control back and forth with */ +/* tx_thread_relinquish, and the measuring thread of each pair times the */ +/* round trip. One pair has both stacks in BTCM, the other in DRAM0. */ +/* */ +/* A round trip is two context switches plus the partner's loop, and the */ +/* partner's code is the same for both pairs, so the difference between */ +/* the pairs is the memory holding the stacks and nothing else. */ +/* */ +/* Both pairs run in one image from one copy of the measuring code, which */ +/* is what makes this comparison safe. The alignment trap that invalid- */ +/* ated earlier work here bites when two builds with different layouts */ +/* are compared; a code shift moves both pairs equally and cancels. */ +/* */ +/* Cycles, from the PMU counter: CNTPCT at 8 MHz cannot resolve a context */ +/* switch. Priorities 2 and 3 put the BTCM pair first and keep both */ +/* above judge and spinner. The sleeper at priority 1 still preempts */ +/* occasionally, which can land in max; min and mean are the robust */ +/* figures and all three are reported. */ +/**************************************************************************/ + +static void demo_dec(unsigned long value) +{ + char digits[12]; + unsigned int n = 0U; + + if (value == 0UL) { linflexd_putc('0'); return; } + + while ((value > 0UL) && (n < 12U)) + { + digits[n] = (char) ('0' + (value % 10UL)); + value /= 10UL; + n++; + } + while (n > 0U) { n--; linflexd_putc(digits[n]); } +} + +#define CTX_SAMPLES 256U +#define CTX_PAIRS 2U + +static TX_THREAD ctx_btcm_a_thread; +static TX_THREAD ctx_btcm_b_thread; +static TX_THREAD ctx_dram_a_thread; +static TX_THREAD ctx_dram_b_thread; + +__attribute__((section(".btcm_bss"), aligned(8))) +static unsigned char ctx_btcm_a_stack[DEMO_STACK_SIZE]; +__attribute__((section(".btcm_bss"), aligned(8))) +static unsigned char ctx_btcm_b_stack[DEMO_STACK_SIZE]; + +static unsigned char ctx_dram_a_stack[DEMO_STACK_SIZE]; +static unsigned char ctx_dram_b_stack[DEMO_STACK_SIZE]; + +static volatile unsigned int ctx_done[CTX_PAIRS]; +static unsigned int ctx_lo[CTX_PAIRS]; +static unsigned int ctx_hi[CTX_PAIRS]; +static unsigned int ctx_mean[CTX_PAIRS]; +static unsigned int ctx_over[CTX_PAIRS]; + +/* A round trip costs about 1400 cycles. Anything past this is not a context + switch, it is a switch that got interrupted -- the sleeper at priority 1 + preempts either pair when a tick lands mid-measurement. Counted rather than + averaged in, because max is otherwise a report on which pair was unlucky: + across three runs the maximum appeared in the BTCM pair once and the DRAM0 + pair twice, while min and mean held to the cycle. */ + +#define CTX_OUTLIER_CYCLES 2000U + +/* Cache state, and why it is forced rather than left to chance. + + With the cache left alone this workload never evicts anything: the DRAM0 + stack stays resident in the 16 KB data cache, every access is a hit, and + DRAM0 measures beautifully. That is a true result for an idle system and a + misleading one for the argument TCM is usually made for, which is about worst + case when other work has pushed your stack out. + + Loading the partner thread with a cache walk does not work either: the timed + round trip includes the partner, so the walk dominates every sample. It was + tried and discarded, and it put every one of 256 samples past the outlier + threshold. + + Instead the cache is cleaned and invalidated immediately before each timed + switch, outside the timed region. Every switch then runs from a cold cache, + which is the state a stack in DRAM0 finds itself in after other work has run + and the state a stack in BTCM is immune to, because an enabled TCM is never + cached. Both pairs get the same treatment, so the difference is the memory. */ + + +/* One copy, used by both pairs. */ + +static void ctx_measure_entry(ULONG which) +{ + unsigned int lo = 0xFFFFFFFFU; + unsigned int hi = 0U; + unsigned long sum = 0UL; + unsigned int over = 0U; + unsigned int counted = 0U; + unsigned int i; + + for (i = 0U; i < CTX_SAMPLES; i++) + { + unsigned int before; + unsigned int after; + unsigned int delta; + + /* Cold cache for every sample, and clean before invalidate so dirty + stack lines reach memory rather than being discarded. Outside the + timestamps, so its own cost is not in the measurement. */ + + cache_clean_all(); + cache_invalidate_dcache_all(); + + before = timer_read_cycles(); + tx_thread_relinquish(); + after = timer_read_cycles(); + + delta = after - before; + + if (delta > CTX_OUTLIER_CYCLES) + { + /* Preempted mid-switch. Excluded from min, max and mean alike: a + maximum that reports whichever pair a tick landed on is not a + measurement of anything, and reporting it as jitter was wrong + once already. */ + + over++; + } + else + { + if (delta < lo) { lo = delta; } + if (delta > hi) { hi = delta; } + sum += (unsigned long) delta; + counted++; + } + } + + ctx_lo[which] = lo; + ctx_hi[which] = hi; + ctx_mean[which] = (counted > 0U) ? (unsigned int) (sum / counted) : 0U; + ctx_over[which] = over; + + ctx_done[which] = 1U; /* releases the partner */ +} + +static void ctx_partner_entry(ULONG which) +{ + while (ctx_done[which] == 0U) + { + tx_thread_relinquish(); + } +} + static void sleeper_entry(ULONG input) { unsigned long spinner_before; @@ -157,6 +313,37 @@ static void judge_entry(ULONG input) ticks_end = tx_time_get(); linflexd_puts("\n=== ThreadX on S32Z280: results ===\n"); + + linflexd_puts("context switch round trip, cycles\n"); + { + static const char *const where[CTX_PAIRS] = { "stacks in BTCM ", + "stacks in DRAM0" }; + unsigned int q; + + for (q = 0U; q < CTX_PAIRS; q++) + { + linflexd_puts(" "); + linflexd_puts(where[q]); + if (ctx_done[q] == 0U) + { + linflexd_puts(": did not finish\n"); + } + else + { + linflexd_puts(": min "); + demo_dec(ctx_lo[q]); + linflexd_puts(" mean "); + demo_dec(ctx_mean[q]); + linflexd_puts(" max "); + demo_dec(ctx_hi[q]); + linflexd_puts(" preempted "); + demo_dec(ctx_over[q]); + linflexd_puts(" of "); + demo_dec(CTX_SAMPLES); + linflexd_puts("\n"); + } + } + } report("ticks ", (unsigned long) (ticks_end - ticks_start)); report("sleeper ", sleeper_runs); report("spinner ", spinner_runs); @@ -222,6 +409,29 @@ void tx_application_define(void *first_unused_memory) judge_stack, DEMO_STACK_SIZE, 10U, 10U, TX_NO_TIME_SLICE, TX_AUTO_START); + /* The PMU cycle counter has to be started here. bsp_boot.c starts it for + the probe image, and this image does not run bsp_boot.c, so without this + every reading below would be zero -- which would read as a free context + switch rather than as a dead counter. */ + + timer_cycles_enable(); + + /* BTCM pair first at priority 2, DRAM0 pair after it at 3. */ + + (void) tx_thread_create(&ctx_btcm_b_thread, "ctxB btcm", ctx_partner_entry, 0UL, + ctx_btcm_b_stack, DEMO_STACK_SIZE, + 2U, 2U, TX_NO_TIME_SLICE, TX_AUTO_START); + (void) tx_thread_create(&ctx_btcm_a_thread, "ctxA btcm", ctx_measure_entry, 0UL, + ctx_btcm_a_stack, DEMO_STACK_SIZE, + 2U, 2U, TX_NO_TIME_SLICE, TX_AUTO_START); + + (void) tx_thread_create(&ctx_dram_b_thread, "ctxB dram", ctx_partner_entry, 1UL, + ctx_dram_b_stack, DEMO_STACK_SIZE, + 3U, 3U, TX_NO_TIME_SLICE, TX_AUTO_START); + (void) tx_thread_create(&ctx_dram_a_thread, "ctxA dram", ctx_measure_entry, 1UL, + ctx_dram_a_stack, DEMO_STACK_SIZE, + 3U, 3U, TX_NO_TIME_SLICE, TX_AUTO_START); + (void) tx_thread_create(&spinner_thread, "spinner", spinner_entry, 0UL, spinner_stack, DEMO_STACK_SIZE, 20U, 20U, TX_NO_TIME_SLICE, TX_AUTO_START); From f535a4ec67456b9ba0cd8ecda3dfbf08894c17b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 17 Aug 2026 17:26:08 -0400 Subject: [PATCH 063/181] Measured stack-heavy work against the memory holding the stack (#636) #635 found BTCM worth about 7.4% on a context switch with no determinism advantage, and said why: a switch saves sixteen registers, roughly one cache line, so the stack's cache state has almost nothing to contribute. It named the interesting case as work with a large stack working set, said it had not been measured, and said it should not be assumed. This measures it, and the answer inverts the earlier one. deep_touch recurses 24 frames, writing a frame on the way down and reading it on the way up, so the working set is the whole descent. The cache is cleaned and invalidated before each sample, so every descent starts cold. Two threads, one stack in BTCM and one in DRAM0, no partner threads and no relinquish: the timed region is entirely within one thread. Reproducible across runs: min mean max spread stack in BTCM 42868 43031 44890 2020 stack in DRAM0 42982 43291 49842 6860 The mean is the same to within 0.6%. The worst case is 10% lower for BTCM and the spread is 3.4 times tighter. No sample in either configuration exceeded twice the minimum, so these maxima are the workload rather than a timer tick -- which is the mistake that produced a false jitter result in #635 and is why the count of interrupted samples is printed. Put beside #635 the two measurements say opposite things and both are true. For a context switch, a small footprint touched every time, BTCM buys throughput and no determinism. For stack-heavy work, a large footprint touched once, it buys determinism and almost no throughput. The reason is that this workload is compute bound at the optimisation level this BSP builds at: 43000 cycles for 24 frames is dominated by call and loop overhead, so line fills are a few percent of the total and barely move the mean. What they do is vary, and that variance is what a bank with no cache in the path removes. So the determinism argument for TCM holds here, but it is worth 10% of worst case and a threefold narrowing of spread, not an order of magnitude. Anyone citing this in a safety argument should cite those numbers and not a larger claim. Assisted-by: Claude Code (Opus 5) --- .../example_build/s32z280_evb/demo_s32z280.c | 169 ++++++++++++++++++ 1 file changed, 169 insertions(+) diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/demo_s32z280.c b/ports/cortex_r52/gnu/example_build/s32z280_evb/demo_s32z280.c index 91d459721..474786e32 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/demo_s32z280.c +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/demo_s32z280.c @@ -259,6 +259,135 @@ static void ctx_partner_entry(ULONG which) } } +/**************************************************************************/ +/* Stack-heavy work, stack in BTCM against stack in DRAM0. */ +/* */ +/* #635 measured context switches and found BTCM worth about 7.4%, with */ +/* no determinism advantage, and said why: a switch saves sixteen */ +/* registers, roughly one cache line, so the stack's cache state has */ +/* almost nothing to contribute. It also said the interesting case was */ +/* work with a large stack working set, that it had not been measured, and */ +/* that it should not be assumed. This measures it. */ +/* */ +/* deep_touch recurses, writing a frame on the way down and reading it on */ +/* the way up, so the stack working set is the whole descent rather than */ +/* one frame. The cache is cleaned and invalidated before each sample, so */ +/* the descent starts cold: a stack in DRAM0 must fill a line per frame, */ +/* while a stack in BTCM has no cache in the path to miss. */ +/* */ +/* No partner threads and no relinquish here. The measurement is entirely */ +/* within one thread, which removes the confound that made the context */ +/* switch figure hard to read -- there, the timed region included the */ +/* partner's execution. */ +/* */ +/* Samples are kept and post-processed rather than filtered against a */ +/* fixed threshold, because the cost of this workload was not known in */ +/* advance and a guessed threshold discarded every sample once already. */ +/**************************************************************************/ + +#define DEEP_SAMPLES 64U +#define DEEP_DEPTH 24U +#define DEEP_FRAME 16U /* words: 64 bytes, one cache line per frame */ + +static TX_THREAD deep_btcm_thread; +static TX_THREAD deep_dram_thread; + +/* 4 KB: 24 frames of 64 bytes plus call overhead is about 2.1 KB, and ThreadX + needs its own room on top. */ + +__attribute__((section(".btcm_bss"), aligned(8))) +static unsigned char deep_btcm_stack[4096]; +static unsigned char deep_dram_stack[4096]; + +static unsigned int deep_samples[CTX_PAIRS][DEEP_SAMPLES]; +static unsigned int deep_lo[CTX_PAIRS]; +static unsigned int deep_hi[CTX_PAIRS]; +static unsigned int deep_mean[CTX_PAIRS]; +static unsigned int deep_over[CTX_PAIRS]; +static volatile unsigned int deep_done[CTX_PAIRS]; + +__attribute__((noinline)) +static unsigned int deep_touch(unsigned int depth) +{ + volatile unsigned int frame[DEEP_FRAME]; + unsigned int acc = 0U; + unsigned int i; + + for (i = 0U; i < DEEP_FRAME; i++) + { + frame[i] = depth + i; + } + + if (depth > 0U) + { + acc = deep_touch(depth - 1U); + } + + for (i = 0U; i < DEEP_FRAME; i++) + { + acc += frame[i]; + } + + return acc; +} + +static void deep_entry(ULONG which) +{ + unsigned int i; + unsigned int lo; + unsigned long sum; + unsigned int counted; + unsigned int over; + unsigned int hi; + + for (i = 0U; i < DEEP_SAMPLES; i++) + { + unsigned int before; + unsigned int after; + + cache_clean_all(); + cache_invalidate_dcache_all(); + + before = timer_read_cycles(); + (void) deep_touch(DEEP_DEPTH); + after = timer_read_cycles(); + + deep_samples[which][i] = after - before; + } + + /* Post-process: the minimum sets the scale, and anything past twice it was + interrupted rather than slow. */ + + lo = 0xFFFFFFFFU; + for (i = 0U; i < DEEP_SAMPLES; i++) + { + if (deep_samples[which][i] < lo) { lo = deep_samples[which][i]; } + } + + hi = 0U; sum = 0UL; counted = 0U; over = 0U; + for (i = 0U; i < DEEP_SAMPLES; i++) + { + unsigned int v = deep_samples[which][i]; + + if (v > (lo * 2U)) + { + over++; + } + else + { + if (v > hi) { hi = v; } + sum += (unsigned long) v; + counted++; + } + } + + deep_lo[which] = lo; + deep_hi[which] = hi; + deep_mean[which] = (counted > 0U) ? (unsigned int) (sum / counted) : 0U; + deep_over[which] = over; + deep_done[which] = 1U; +} + static void sleeper_entry(ULONG input) { unsigned long spinner_before; @@ -314,6 +443,37 @@ static void judge_entry(ULONG input) linflexd_puts("\n=== ThreadX on S32Z280: results ===\n"); + linflexd_puts("stack-heavy work, cycles (24 frames, cold cache)\n"); + { + static const char *const dwhere[CTX_PAIRS] = { "stack in BTCM ", + "stack in DRAM0" }; + unsigned int q; + + for (q = 0U; q < CTX_PAIRS; q++) + { + linflexd_puts(" "); + linflexd_puts(dwhere[q]); + if (deep_done[q] == 0U) + { + linflexd_puts(": did not finish\n"); + } + else + { + linflexd_puts(": min "); + demo_dec(deep_lo[q]); + linflexd_puts(" mean "); + demo_dec(deep_mean[q]); + linflexd_puts(" max "); + demo_dec(deep_hi[q]); + linflexd_puts(" interrupted "); + demo_dec(deep_over[q]); + linflexd_puts(" of "); + demo_dec(DEEP_SAMPLES); + linflexd_puts("\n"); + } + } + } + linflexd_puts("context switch round trip, cycles\n"); { static const char *const where[CTX_PAIRS] = { "stacks in BTCM ", @@ -432,6 +592,15 @@ void tx_application_define(void *first_unused_memory) ctx_dram_a_stack, DEMO_STACK_SIZE, 3U, 3U, TX_NO_TIME_SLICE, TX_AUTO_START); + /* Stack-heavy pair, after the context-switch pairs. */ + + (void) tx_thread_create(&deep_btcm_thread, "deep btcm", deep_entry, 0UL, + deep_btcm_stack, sizeof(deep_btcm_stack), + 4U, 4U, TX_NO_TIME_SLICE, TX_AUTO_START); + (void) tx_thread_create(&deep_dram_thread, "deep dram", deep_entry, 1UL, + deep_dram_stack, sizeof(deep_dram_stack), + 5U, 5U, TX_NO_TIME_SLICE, TX_AUTO_START); + (void) tx_thread_create(&spinner_thread, "spinner", spinner_entry, 0UL, spinner_stack, DEMO_STACK_SIZE, 20U, 20U, TX_NO_TIME_SLICE, TX_AUTO_START); From 1ef49338e93895e50ed4f5196a77eed9ca8a5103 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 17 Aug 2026 17:59:12 -0400 Subject: [PATCH 064/181] Gave each thread its own MPU window, and made a violation fault (#637) First step towards a ThreadX module port for this core: establish that PMSAv8-R regions can be switched per thread on this part, what that costs, and that a violation actually faults. Those are the questions worth answering before writing a module manager on top of them. Two threads each own a 4 KB window at the top of DRAM2. The windows are carved out of the broad data region in mpu.c, because isolation is only meaningful in memory no other region already covers -- every other region in that map is a wide RW window, so a private buffer inside one of them would be reachable by every thread whatever else was programmed. Each thread writes its own window, which must succeed, and then reaches for the other thread's, which must fault. The second half is the part that matters: a test that only shows a thread reaching its own memory would pass just as well with no protection at all. Measured on the S32Z280-594EVB, reproducible across three runs: thread 0 window 0x3187E000 own: reachable other: faulted thread 1 window 0x3187F000 own: reachable other: faulted region switch cost: 562 to 604 cycles The cost is worth noting for the module port to come. A context switch on this part is about 1400 cycles, so switching one region adds roughly 40% to it, and most of that is the dsb and isb rather than the register writes. A module switch programming several regions should therefore batch the barriers once at the end rather than per region. Scope, stated plainly. The window is applied by the thread calling thread_mpu_activate, not by the scheduler. The port's scheduler does call _tx_execution_thread_enter under TX_ENABLE_EXECUTION_CHANGE_NOTIFY, which would make it automatic, but that macro is read by port assembly compiled into the shared threadx library, so enabling it would oblige all nine example targets in this port to supply the four execution hooks. A ThreadX module port carries its own copies of the port assembly for exactly that reason, and that is where the switch belongs. There is no user mode, no syscall boundary and no loader here. The fault is survivable the same way the boot probes make it survivable: fault_expected tells the data abort handler to record the violation and resume after the faulting access. That works in thread context because the handler returns where it came from rather than to a fixed recovery point. Assisted-by: Claude Code (Opus 5) --- .../example_build/s32z280_evb/CMakeLists.txt | 1 + .../example_build/s32z280_evb/demo_s32z280.c | 124 +++++++++++ .../gnu/example_build/s32z280_evb/mpu.c | 7 +- .../gnu/example_build/s32z280_evb/platform.h | 12 ++ .../example_build/s32z280_evb/thread_mpu.c | 197 ++++++++++++++++++ .../example_build/s32z280_evb/thread_mpu.h | 79 +++++++ 6 files changed, 419 insertions(+), 1 deletion(-) create mode 100644 ports/cortex_r52/gnu/example_build/s32z280_evb/thread_mpu.c create mode 100644 ports/cortex_r52/gnu/example_build/s32z280_evb/thread_mpu.h diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/CMakeLists.txt b/ports/cortex_r52/gnu/example_build/s32z280_evb/CMakeLists.txt index 94fe43301..7f216700c 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/CMakeLists.txt +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/CMakeLists.txt @@ -106,6 +106,7 @@ add_executable(s32z280_demo.elf EXCLUDE_FROM_ALL ${EVB_DIR}/gic_probe.c ${EVB_DIR}/cache.c ${EVB_DIR}/tcm.c + ${EVB_DIR}/thread_mpu.c ${EVB_DIR}/demo_s32z280.c ) diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/demo_s32z280.c b/ports/cortex_r52/gnu/example_build/s32z280_evb/demo_s32z280.c index 474786e32..11637ad92 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/demo_s32z280.c +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/demo_s32z280.c @@ -51,6 +51,7 @@ #include "linflexd.h" #include "timer.h" #include "cache.h" +#include "thread_mpu.h" #include "board.h" #define DEMO_STACK_SIZE 2048 @@ -388,6 +389,73 @@ static void deep_entry(ULONG which) deep_done[which] = 1U; } +/**************************************************************************/ +/* Per-thread memory protection, demonstrated rather than asserted. */ +/* */ +/* Two threads each own a 4 KB window at the top of DRAM2, carved out of */ +/* the broad data region in mpu.c so that nothing else grants access to */ +/* them. Each thread writes its own window, which must succeed, and then */ +/* reaches for the other thread's, which must fault. */ +/* */ +/* The second half is the part that matters. A test that only shows a */ +/* thread reaching its own memory proves nothing about isolation: it */ +/* would pass just as well with no protection at all. */ +/* */ +/* The fault is made survivable the same way the boot probes do it -- */ +/* fault_expected tells the data abort handler to record the violation */ +/* and resume at the instruction after the faulting access, rather than */ +/* treating it as fatal. That works in thread context because the */ +/* handler returns to where it came from rather than to a fixed recovery */ +/* point. */ +/**************************************************************************/ + +#define ISO_THREADS 2U + +static TX_THREAD iso_thread[ISO_THREADS]; + +static unsigned char iso_stack[ISO_THREADS][DEMO_STACK_SIZE]; + +static volatile unsigned int iso_done[ISO_THREADS]; +static unsigned int iso_own_ok[ISO_THREADS]; +static unsigned int iso_other_faulted[ISO_THREADS]; +static unsigned long iso_own_base[ISO_THREADS]; + +static void iso_entry(ULONG which) +{ + extern unsigned int fault_expected; + extern unsigned int fault_taken; + + unsigned long own = thread_mpu_window_base((unsigned int) which); + unsigned long other = thread_mpu_window_base((unsigned int) (1UL - which)); + unsigned int before; + unsigned int pattern = 0xC0DE0000U + (unsigned int) which; + + iso_own_base[which] = own; + + /* Install this thread's window. */ + + thread_mpu_activate(tx_thread_identify()); + + /* Its own window: must be reachable. */ + + *((volatile unsigned int *) own) = pattern; + iso_own_ok[which] = + (*((volatile unsigned int *) own) == pattern) ? 1U : 0U; + + /* The other thread's window: must not be. Only the write is attempted -- + reading it back would fault a second time, and the point is already + made. */ + + before = fault_taken; + fault_expected = 1U; + *((volatile unsigned int *) other) = 0xBADU; + fault_expected = 0U; + + iso_other_faulted[which] = (fault_taken > before) ? 1U : 0U; + + iso_done[which] = 1U; +} + static void sleeper_entry(ULONG input) { unsigned long spinner_before; @@ -443,6 +511,46 @@ static void judge_entry(ULONG input) linflexd_puts("\n=== ThreadX on S32Z280: results ===\n"); + linflexd_puts("per-thread MPU isolation\n"); + { + unsigned int w; + unsigned int all_ok = 1U; + + for (w = 0U; w < ISO_THREADS; w++) + { + linflexd_puts(" thread "); + demo_dec(w); + linflexd_puts(" window 0x"); + linflexd_put_hex32((unsigned int) iso_own_base[w]); + if (iso_done[w] == 0U) + { + linflexd_puts(" did not finish\n"); + all_ok = 0U; + } + else + { + linflexd_puts(iso_own_ok[w] ? " own: reachable" : " own: UNREACHABLE"); + linflexd_puts(iso_other_faulted[w] ? " other: faulted\n" + : " other: REACHED\n"); + if ((iso_own_ok[w] == 0U) || (iso_other_faulted[w] == 0U)) + { + all_ok = 0U; + } + } + } + + linflexd_puts(all_ok ? " PASS each thread reached its own window and faulted on the other\n" + : " FAIL isolation not demonstrated\n"); + + linflexd_puts(" region switch cost, cycles: min "); + demo_dec(thread_mpu_min_cycles()); + linflexd_puts(" max "); + demo_dec(thread_mpu_max_cycles()); + linflexd_puts(" switches "); + demo_dec(thread_mpu_switch_count()); + linflexd_puts("\n"); + } + linflexd_puts("stack-heavy work, cycles (24 frames, cold cache)\n"); { static const char *const dwhere[CTX_PAIRS] = { "stack in BTCM ", @@ -592,6 +700,22 @@ void tx_application_define(void *first_unused_memory) ctx_dram_a_stack, DEMO_STACK_SIZE, 3U, 3U, TX_NO_TIME_SLICE, TX_AUTO_START); + /* Isolation pair. Priority 6 and 7, after the measurement threads. */ + + { + unsigned int w; + + for (w = 0U; w < ISO_THREADS; w++) + { + (void) tx_thread_create(&iso_thread[w], "iso", iso_entry, + (ULONG) w, + iso_stack[w], DEMO_STACK_SIZE, + 6U + w, 6U + w, + TX_NO_TIME_SLICE, TX_AUTO_START); + (void) thread_mpu_grant(&iso_thread[w], w); + } + } + /* Stack-heavy pair, after the context-switch pairs. */ (void) tx_thread_create(&deep_btcm_thread, "deep btcm", deep_entry, 0UL, diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/mpu.c b/ports/cortex_r52/gnu/example_build/s32z280_evb/mpu.c index 0af4ee94d..2073d0db5 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/mpu.c +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/mpu.c @@ -353,8 +353,13 @@ static void build_table(void) bottom of the region -- no fault, just two objects on one address. */ mpu_regions[5].mpu_region_base = S32Z_DRAM2_BASE; + /* Stops short of the per-thread windows at the top of the bank. Those are + mapped one at a time by the thread-entry hook; leaving them inside this + region would make them reachable from every thread and the isolation + below would prove nothing. */ + mpu_regions[5].mpu_region_limit = S32Z_DRAM2_BASE - + S32Z_DRAM2_SIZE - 1UL; + + S32Z_DRAM2_SHARED_SIZE - 1UL; mpu_regions[5].mpu_region_ap = MPU_AP_RW_EL1; mpu_regions[5].mpu_region_execute_never = 1U; mpu_regions[5].mpu_region_shareability = MPU_SH_NON; diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/platform.h b/ports/cortex_r52/gnu/example_build/s32z280_evb/platform.h index 37f2e9e4a..4adbe55ec 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/platform.h +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/platform.h @@ -130,6 +130,18 @@ #define S32Z_DRAM0_SIZE 0x00040000UL #define S32Z_DRAM1_BASE 0x317C0000UL #define S32Z_DRAM1_SIZE 0x00040000UL +/* The top 8 KB of DRAM2 is deliberately left out of the broad data region in + mpu.c and mapped one window at a time, per thread, instead. Isolation is only + meaningful in memory that no other region already grants access to, and every + other region in that map is a wide RW window -- a private buffer placed inside + one of them would be reachable by every thread no matter what else was + programmed. */ + +#define S32Z_THREAD_WINDOW_BASE 0x3187E000UL +#define S32Z_THREAD_WINDOW_SIZE 0x00001000UL /* 4 KB per thread */ +#define S32Z_THREAD_WINDOW_COUNT 2UL +#define S32Z_DRAM2_SHARED_SIZE (S32Z_THREAD_WINDOW_BASE - S32Z_DRAM2_BASE) + #define S32Z_DRAM2_BASE 0x31800000UL #define S32Z_DRAM2_SIZE 0x00080000UL diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/thread_mpu.c b/ports/cortex_r52/gnu/example_build/s32z280_evb/thread_mpu.c new file mode 100644 index 000000000..9042aeb98 --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/thread_mpu.c @@ -0,0 +1,197 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* BOARD SUPPORT RELEASE */ +/* */ +/* thread_mpu.c Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frédéric Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Per-thread memory protection. See thread_mpu.h for what this is */ +/* and is not. */ +/* */ +/* MISRA C:2012 deviations (justified) */ +/* */ +/* Directive 4.3 -- the MPU is only reachable through CP15; every */ +/* access is encapsulated in a one-line accessor below. */ +/* */ +/**************************************************************************/ + +#include "tx_api.h" +#include "platform.h" +#include "mpu.h" +#include "timer.h" +#include "thread_mpu.h" + +/* The region reprogrammed on every thread entry. mpu.c programs 0 to 7, and + MPUIR on this part reports 20, so 8 is free. Chosen high on purpose: the + shared regions keep their indices, so a thread that reaches this hook with no + window still has code, stacks, console and GIC exactly as before. */ + +#define THREAD_MPU_REGION 8UL + +typedef struct +{ + TX_THREAD *owner; + unsigned long base; +} thread_window_t; + +static thread_window_t windows[S32Z_THREAD_WINDOW_COUNT]; + +static unsigned long switch_count; +static unsigned int last_cycles; +static unsigned int min_cycles = 0xFFFFFFFFU; +static unsigned int max_cycles; + + +/**************************************************************************/ +/* CP15 accessors. */ +/**************************************************************************/ + +static void write_prselr(unsigned long value) +{ + __asm__ volatile("mcr p15, 0, %0, c6, c2, 1" : : "r"(value) : "memory"); +} + +static void write_prbar(unsigned long value) +{ + __asm__ volatile("mcr p15, 0, %0, c6, c3, 0" : : "r"(value) : "memory"); +} + +static void write_prlar(unsigned long value) +{ + __asm__ volatile("mcr p15, 0, %0, c6, c3, 1" : : "r"(value) : "memory"); +} + + +/**************************************************************************/ +/* Registration. */ +/**************************************************************************/ + +unsigned long thread_mpu_window_base(unsigned int window) +{ + if ((unsigned long) window >= S32Z_THREAD_WINDOW_COUNT) + { + return 0UL; + } + + return S32Z_THREAD_WINDOW_BASE + + ((unsigned long) window * S32Z_THREAD_WINDOW_SIZE); +} + +unsigned long thread_mpu_grant(TX_THREAD *thread_ptr, unsigned int window) +{ + unsigned long base = thread_mpu_window_base(window); + + if ((base == 0UL) || (thread_ptr == TX_NULL)) + { + return 0UL; + } + + windows[window].owner = thread_ptr; + windows[window].base = base; + + return base; +} + + +/**************************************************************************/ +/* Activation. */ +/* */ +/* Called explicitly by a thread rather than from the scheduler, and that */ +/* is a deliberate limitation of this step rather than the intended */ +/* design. */ +/* */ +/* The port's scheduler does call _tx_execution_thread_enter under */ +/* TX_ENABLE_EXECUTION_CHANGE_NOTIFY, which would make this automatic on */ +/* every switch. That macro is read by the port assembly compiled into */ +/* the shared threadx library, so enabling it would oblige all nine */ +/* example targets in this port -- including the FVP ones -- to supply */ +/* the four execution hooks. A ThreadX module port carries its own */ +/* copies of the port assembly for exactly this reason, and that is where */ +/* the switch belongs. */ +/* */ +/* What this step establishes without that machinery: that a PMSAv8-R */ +/* region can be reprogrammed per thread on this part, what it costs, and */ +/* that a violation faults. Those are the questions worth answering */ +/* before writing a module manager on top of them. */ +/**************************************************************************/ + +void thread_mpu_activate(TX_THREAD *thread_ptr) +{ + unsigned int before; + unsigned int after; + unsigned int delta; + unsigned int i; + unsigned long base = 0UL; + + before = timer_read_cycles(); + + for (i = 0U; (unsigned long) i < S32Z_THREAD_WINDOW_COUNT; i++) + { + if (windows[i].owner == thread_ptr) + { + base = windows[i].base; + break; + } + } + + write_prselr(THREAD_MPU_REGION); + __asm__ volatile("isb" ::: "memory"); + + if (base == 0UL) + { + /* No window for this thread: disable the region rather than leaving the + previous thread's window in place. Forgetting this is how per-thread + protection silently becomes no protection -- the last thread to run + would leave its window open to whatever ran next. */ + + write_prlar(0UL); + } + else + { + write_prbar((base & ~0x3FUL) + | ((unsigned long) MPU_SH_NON << 3) + | ((unsigned long) MPU_AP_RW_EL1 << 1) + | 1UL); /* XN: data only */ + + write_prlar(((base + S32Z_THREAD_WINDOW_SIZE - 1UL) & ~0x3FUL) + | ((unsigned long) MPU_ATTR_NORMAL_WB << 1) + | 1UL); /* EN */ + } + + __asm__ volatile("dsb sy" ::: "memory"); + __asm__ volatile("isb" ::: "memory"); + + after = timer_read_cycles(); + delta = after - before; + + switch_count++; + last_cycles = delta; + if (delta < min_cycles) { min_cycles = delta; } + if (delta > max_cycles) { max_cycles = delta; } +} + + +unsigned long thread_mpu_switch_count(void) { return switch_count; } +unsigned int thread_mpu_last_cycles(void) { return last_cycles; } +unsigned int thread_mpu_min_cycles(void) { return min_cycles; } +unsigned int thread_mpu_max_cycles(void) { return max_cycles; } diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/thread_mpu.h b/ports/cortex_r52/gnu/example_build/s32z280_evb/thread_mpu.h new file mode 100644 index 000000000..cba6226e5 --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/thread_mpu.h @@ -0,0 +1,79 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* BOARD SUPPORT RELEASE */ +/* */ +/* thread_mpu.h Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frédéric Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Per-thread memory protection for the NXP S32Z280-594EVB. */ +/* */ +/* One MPU region is reprogrammed on every thread entry to grant the */ +/* incoming thread access to its own window and nothing else. A thread */ +/* with no window registered runs with that region disabled, so it */ +/* reaches none of them. */ +/* */ +/* This is a step towards a ThreadX module port for this core, not a */ +/* substitute for one. It demonstrates that PMSAv8-R regions can be */ +/* switched per thread on this part, at a measured cost, and that a */ +/* violation faults -- which are the questions worth answering before */ +/* building a module manager on top of them. There is no user mode, no */ +/* syscall boundary and no loader here. */ +/* */ +/* The hook is _tx_execution_thread_enter, which the port's scheduler */ +/* already calls under TX_ENABLE_EXECUTION_CHANGE_NOTIFY, after the */ +/* stack pointer has been switched. No port assembly is modified. */ +/* */ +/**************************************************************************/ + +#ifndef THREAD_MPU_H +#define THREAD_MPU_H + +#include "tx_api.h" + +/* Apply a thread's window, or disable the region if it has none. Called by the + thread itself in this step; see the comment in thread_mpu.c for why it is not + yet driven from the scheduler. */ + +void thread_mpu_activate(TX_THREAD *thread_ptr); + +/* Give a thread exclusive access to one of the per-thread windows. The index + selects the window, 0 to S32Z_THREAD_WINDOW_COUNT - 1. Returns the window's + base address, or 0 if the index is out of range or the table is full. */ + +unsigned long thread_mpu_grant(TX_THREAD *thread_ptr, unsigned int window); + +/* Base address of a window, whether or not it is granted to anyone. Lets a + test reach for a window it does not own. */ + +unsigned long thread_mpu_window_base(unsigned int window); + +/* How many thread entries have reprogrammed the region, and what the last one + cost in cycles. The cost is the price of per-thread protection on this core + and is the reason the hook records it. */ + +unsigned long thread_mpu_switch_count(void); +unsigned int thread_mpu_last_cycles(void); +unsigned int thread_mpu_min_cycles(void); +unsigned int thread_mpu_max_cycles(void); + +#endif From ca62edd27ddf708f207d05a9478ca1f68203a13b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Tue, 18 Aug 2026 08:51:49 -0400 Subject: [PATCH 065/181] Swept the stack-heavy measurement across placements, and qualified its result (#638) #636 reported that a stack in BTCM gave a threefold tighter spread than DRAM0 for stack-heavy work. That measurement used a single code placement, which is the methodology #631 and #633 exist to correct: the cache benchmark got an alignment sweep and the interrupt handler got one, and this measurement never did. It was noticed when #637 added two threads to the same image and the figure moved -- both spreads came out near 6500 and the minima rose 15%. The recursive body is now generated at four placements and all four are measured, per placement, in one image. placement BTCM min / spread DRAM0 min / spread offset 0 41854 / 6850 42036 / 6880 offset 16 48670 / 1946 48792 / 1978 offset 32 42388 / 6914 42752 / 7018 offset 48 48914 / 1860 49198 / 6786 Reproducible across runs to within a few hundred cycles. Spread is dominated by code placement rather than by the memory holding the stack. It ranges from 1860 to 6914 depending on where the body falls in a cache line, and placement also moves the minimum by 17%, from 41854 to 49214. Against that, the memory contributes a consistent but small advantage: BTCM's minimum is lower at all four placements, by 0.4% to 0.9%. BTCM's spread beats DRAM0's decisively at one placement of the four, offset 48, at 1860 against 6786. At the other three the two are within 2% of each other. So the effect #636 reported is real where it occurs and is not a property of the part: quoting it as one invited the reader to expect it everywhere. #636's claim should be read as qualified by this. A stack in BTCM buys a small consistent improvement in the best case and a large improvement in spread at some code placements and not others. Anyone building a determinism argument on it needs the placement sweep in the loop, not a single figure. The pad nops that displace each placement execute on every recursion level rather than once, so each placement carries a slightly different constant cost, about 0.6% at the widest. That cancels in the BTCM against DRAM0 comparison, which is made at the same placement, and does not affect spread within one. Assisted-by: Claude Code (Opus 5) --- .../example_build/s32z280_evb/demo_s32z280.c | 182 ++++++++++++------ 1 file changed, 119 insertions(+), 63 deletions(-) diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/demo_s32z280.c b/ports/cortex_r52/gnu/example_build/s32z280_evb/demo_s32z280.c index 11637ad92..9f09d8d3d 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/demo_s32z280.c +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/demo_s32z280.c @@ -289,6 +289,7 @@ static void ctx_partner_entry(ULONG which) #define DEEP_SAMPLES 64U #define DEEP_DEPTH 24U #define DEEP_FRAME 16U /* words: 64 bytes, one cache line per frame */ +#define DEEP_PLACEMENTS 4U static TX_THREAD deep_btcm_thread; static TX_THREAD deep_dram_thread; @@ -301,36 +302,65 @@ static unsigned char deep_btcm_stack[4096]; static unsigned char deep_dram_stack[4096]; static unsigned int deep_samples[CTX_PAIRS][DEEP_SAMPLES]; -static unsigned int deep_lo[CTX_PAIRS]; -static unsigned int deep_hi[CTX_PAIRS]; -static unsigned int deep_mean[CTX_PAIRS]; -static unsigned int deep_over[CTX_PAIRS]; +static unsigned int deep_lo[CTX_PAIRS][DEEP_PLACEMENTS]; +static unsigned int deep_hi[CTX_PAIRS][DEEP_PLACEMENTS]; +static unsigned int deep_mean[CTX_PAIRS][DEEP_PLACEMENTS]; +static unsigned int deep_over[CTX_PAIRS][DEEP_PLACEMENTS]; static volatile unsigned int deep_done[CTX_PAIRS]; -__attribute__((noinline)) -static unsigned int deep_touch(unsigned int depth) -{ - volatile unsigned int frame[DEEP_FRAME]; - unsigned int acc = 0U; - unsigned int i; - - for (i = 0U; i < DEEP_FRAME; i++) - { - frame[i] = depth + i; - } - - if (depth > 0U) - { - acc = deep_touch(depth - 1U); - } +/* Four placements of the recursive body, each 64-byte aligned and then + displaced within its line, and the measurement sweeps all four. + + The first version of this measurement had one placement, which is the + methodology this example spent two changes correcting elsewhere. It showed + BTCM with a threefold tighter spread than DRAM0; that did not survive an + image with two more threads in it, where both spreads came out near 6500 and + the minima moved 15%. A single placement was reporting where the linker had + put the code. + + The pad nops execute on every recursion level rather than once, so each + placement carries a slightly different constant cost -- about 0.6% at the + widest pad. That cancels in the comparison that matters, because BTCM and + DRAM0 are measured at the same placement, and it does not affect the spread + within a placement. */ + +#define MAKE_DEEP_TOUCH(name, pad_words) \ +__attribute__((aligned(64), noinline)) \ +static unsigned int name(unsigned int depth) \ +{ \ + volatile unsigned int frame[DEEP_FRAME]; \ + unsigned int acc = 0U; \ + unsigned int i; \ + \ + __asm__ volatile(".rept " #pad_words "\n\tnop\n\t.endr"); \ + \ + for (i = 0U; i < DEEP_FRAME; i++) \ + { \ + frame[i] = depth + i; \ + } \ + \ + if (depth > 0U) \ + { \ + acc = name(depth - 1U); \ + } \ + \ + for (i = 0U; i < DEEP_FRAME; i++) \ + { \ + acc += frame[i]; \ + } \ + \ + return acc; \ +} - for (i = 0U; i < DEEP_FRAME; i++) - { - acc += frame[i]; - } +MAKE_DEEP_TOUCH(deep_touch_a, 0) +MAKE_DEEP_TOUCH(deep_touch_b, 4) +MAKE_DEEP_TOUCH(deep_touch_c, 8) +MAKE_DEEP_TOUCH(deep_touch_d, 12) - return acc; -} +static unsigned int (*const deep_touches[DEEP_PLACEMENTS])(unsigned int) = +{ + deep_touch_a, deep_touch_b, deep_touch_c, deep_touch_d +}; static void deep_entry(ULONG which) { @@ -345,47 +375,67 @@ static void deep_entry(ULONG which) { unsigned int before; unsigned int after; + unsigned int slot = i / (DEEP_SAMPLES / DEEP_PLACEMENTS); + + if (slot >= DEEP_PLACEMENTS) + { + slot = DEEP_PLACEMENTS - 1U; + } cache_clean_all(); cache_invalidate_dcache_all(); before = timer_read_cycles(); - (void) deep_touch(DEEP_DEPTH); + (void) deep_touches[slot](DEEP_DEPTH); after = timer_read_cycles(); deep_samples[which][i] = after - before; } - /* Post-process: the minimum sets the scale, and anything past twice it was - interrupted rather than slow. */ + /* Post-processed per placement. A figure spanning placements would mix the + four constant costs and hide exactly what this sweep exists to show. */ - lo = 0xFFFFFFFFU; - for (i = 0U; i < DEEP_SAMPLES; i++) - { - if (deep_samples[which][i] < lo) { lo = deep_samples[which][i]; } - } - - hi = 0U; sum = 0UL; counted = 0U; over = 0U; - for (i = 0U; i < DEEP_SAMPLES; i++) { - unsigned int v = deep_samples[which][i]; + unsigned int slot; + unsigned int each = DEEP_SAMPLES / DEEP_PLACEMENTS; - if (v > (lo * 2U)) + for (slot = 0U; slot < DEEP_PLACEMENTS; slot++) { - over++; - } - else - { - if (v > hi) { hi = v; } - sum += (unsigned long) v; - counted++; + unsigned int s; + unsigned int lo = 0xFFFFFFFFU; + unsigned int hi = 0U; + unsigned long sum = 0UL; + unsigned int counted = 0U; + unsigned int over = 0U; + + for (s = slot * each; s < ((slot + 1U) * each); s++) + { + if (deep_samples[which][s] < lo) { lo = deep_samples[which][s]; } + } + + for (s = slot * each; s < ((slot + 1U) * each); s++) + { + unsigned int v = deep_samples[which][s]; + + if (v > (lo * 2U)) + { + over++; + } + else + { + if (v > hi) { hi = v; } + sum += (unsigned long) v; + counted++; + } + } + + deep_lo[which][slot] = lo; + deep_hi[which][slot] = hi; + deep_mean[which][slot] = (counted > 0U) ? (unsigned int) (sum / counted) : 0U; + deep_over[which][slot] = over; } } - deep_lo[which] = lo; - deep_hi[which] = hi; - deep_mean[which] = (counted > 0U) ? (unsigned int) (sum / counted) : 0U; - deep_over[which] = over; deep_done[which] = 1U; } @@ -551,32 +601,38 @@ static void judge_entry(ULONG input) linflexd_puts("\n"); } - linflexd_puts("stack-heavy work, cycles (24 frames, cold cache)\n"); + linflexd_puts("stack-heavy work, cycles (24 frames, cold cache, 4 placements)\n"); { - static const char *const dwhere[CTX_PAIRS] = { "stack in BTCM ", - "stack in DRAM0" }; + static const char *const dwhere[CTX_PAIRS] = { "BTCM ", "DRAM0" }; unsigned int q; + unsigned int slot; for (q = 0U; q < CTX_PAIRS; q++) { - linflexd_puts(" "); - linflexd_puts(dwhere[q]); if (deep_done[q] == 0U) { + linflexd_puts(" "); + linflexd_puts(dwhere[q]); linflexd_puts(": did not finish\n"); + continue; } - else + + for (slot = 0U; slot < DEEP_PLACEMENTS; slot++) { + linflexd_puts(" "); + linflexd_puts(dwhere[q]); + linflexd_puts(" offset "); + demo_dec((unsigned long) (slot * 16U)); linflexd_puts(": min "); - demo_dec(deep_lo[q]); + demo_dec(deep_lo[q][slot]); linflexd_puts(" mean "); - demo_dec(deep_mean[q]); + demo_dec(deep_mean[q][slot]); linflexd_puts(" max "); - demo_dec(deep_hi[q]); - linflexd_puts(" interrupted "); - demo_dec(deep_over[q]); - linflexd_puts(" of "); - demo_dec(DEEP_SAMPLES); + demo_dec(deep_hi[q][slot]); + linflexd_puts(" spread "); + demo_dec(deep_hi[q][slot] - deep_lo[q][slot]); + linflexd_puts(" cut "); + demo_dec(deep_over[q][slot]); linflexd_puts("\n"); } } From b3486f9b4683a0434143fdc7b0ce90ec3b2bfcd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Tue, 18 Aug 2026 17:01:26 -0400 Subject: [PATCH 066/181] Bounded the wait in the thread priority change regression tests (#640) Both copies of this test, the SMP one and the non-SMP one, install an interrupt handler and then spin until it clears a flag: test_isr_dispatch = test_isr; do { ... } while (test_isr_dispatch); The handler clears that flag only on a narrow window: thread 3 at priority 6, ready, and not yet at the head of its priority list, which exists only part way through a priority change. If an interrupt never lands inside that window, the loop never ends. That is what has been failing in CI. The SMP suite has been red since 30 June, and this test times out in three of the last four failing runs, always in a stack-checking configuration. The evidence that it is a hang rather than slow work: the test carries no per-test timeout property, so ctest's --timeout 1000 applies, and locally the test finishes in 0.12 seconds with a worst case of 0.29 over thirty runs. Nothing turns that into more than a thousand seconds. It also survived --repeat until-pass:2, so it hung twice in succession. The TX_NOT_INTERRUPTABLE path in the same handler already stops after a fixed amount of work. Only the interruptable path, which is the one the failing configuration uses, had no protection. Cap the loop and clear the handler on the way out. When the window is not reached the test says so and still passes: not reaching it is a gap in what this run covered, not a fault in the code under test, and failing would report a defect that does not exist. The counters are left alone so the checks that follow keep their previous meaning. The cap is 100000 attempts. An exhausted cap takes about 60 seconds, measured, and a successful run takes 0.12 seconds, which puts the usual cost around two hundred attempts and leaves the cap roughly two orders of magnitude clear of it. That is wide enough not to lose coverage on a slower machine, while replacing a timeout that says nothing with a message that says what happened. Not reproducible here, which fits the diagnosis rather than contradicting it: on sixteen cores the window is hit almost at once. Thirty sequential runs, two hundred at parallelism thirty-two, sixty pinned to two CPUs, forty pinned to one, and three full-suite passes at the parallelism CI uses all came back clean. The defect is the reliance on the window, not any particular machine. Verified with the window deliberately made unreachable: before this change the test runs until it is killed, and after it exits in about a minute reporting that the window was not reached. The full SMP suite passes 110 of 110 at CI's parallelism. --- .../threadx_thread_priority_change.c | 27 ++++++++++++++++++- .../threadx_thread_priority_change.c | 27 ++++++++++++++++++- 2 files changed, 52 insertions(+), 2 deletions(-) diff --git a/test/smp/regression/threadx_thread_priority_change.c b/test/smp/regression/threadx_thread_priority_change.c index e68eadf51..763201c45 100644 --- a/test/smp/regression/threadx_thread_priority_change.c +++ b/test/smp/regression/threadx_thread_priority_change.c @@ -513,6 +513,15 @@ static void thread_3_entry(ULONG thread_input) UINT old_priority; UINT loop; +/* The interrupt below only fires on a narrow window: thread 3 at priority 6, + ready, and not yet at the head of its priority list. Waiting for it without a + bound made this test hang indefinitely when the window was never hit, which + showed up in CI as a timeout carrying no information about what went wrong. + The TX_NOT_INTERRUPTABLE path already stopped after a fixed amount of work; + this gives the interruptable path the same protection. */ +UINT attempts = 0; +#define MAX_PRIORITY_CHANGE_ATTEMPTS 100000 + /* Resume threads 4. */ tx_thread_resume(&thread_4); @@ -537,7 +546,23 @@ UINT loop; if (thread_4_counter) thread_1_counter++; - } while (test_isr_dispatch); + attempts++; + + } while (test_isr_dispatch && (attempts < MAX_PRIORITY_CHANGE_ATTEMPTS)); + + /* Stop the interrupt regardless, so a window that was never hit does not + leave the handler installed for the rest of the test. */ + test_isr_dispatch = TX_NULL; + + if (attempts >= MAX_PRIORITY_CHANGE_ATTEMPTS) + { + + /* The window was not reached. That is a gap in what this test covered on + this run rather than a fault in the code under test, so say so instead + of failing, and leave the counters alone so the checks that follow + still mean what they did before. */ + printf("(priority change window not reached in %u attempts) ", attempts); + } } diff --git a/test/tx/regression/threadx_thread_priority_change.c b/test/tx/regression/threadx_thread_priority_change.c index 1cb52ff99..ac750a5fc 100644 --- a/test/tx/regression/threadx_thread_priority_change.c +++ b/test/tx/regression/threadx_thread_priority_change.c @@ -354,6 +354,15 @@ static void thread_3_entry(ULONG thread_input) UINT old_priority; UINT loop; +/* The interrupt below only fires on a narrow window: thread 3 at priority 6, + ready, and not yet at the head of its priority list. Waiting for it without a + bound made this test hang indefinitely when the window was never hit, which + showed up in CI as a timeout carrying no information about what went wrong. + The TX_NOT_INTERRUPTABLE path already stopped after a fixed amount of work; + this gives the interruptable path the same protection. */ +UINT attempts = 0; +#define MAX_PRIORITY_CHANGE_ATTEMPTS 100000 + /* Resume threads 4. */ tx_thread_resume(&thread_4); @@ -378,7 +387,23 @@ UINT loop; if (thread_4_counter) thread_1_counter++; - } while (test_isr_dispatch); + attempts++; + + } while (test_isr_dispatch && (attempts < MAX_PRIORITY_CHANGE_ATTEMPTS)); + + /* Stop the interrupt regardless, so a window that was never hit does not + leave the handler installed for the rest of the test. */ + test_isr_dispatch = TX_NULL; + + if (attempts >= MAX_PRIORITY_CHANGE_ATTEMPTS) + { + + /* The window was not reached. That is a gap in what this test covered on + this run rather than a fault in the code under test, so say so instead + of failing, and leave the counters alone so the checks that follow + still mean what they did before. */ + printf("(priority change window not reached in %u attempts) ", attempts); + } } From dafb7d70ccae2f7256387de108956cd32ed228e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Thu, 20 Aug 2026 08:44:49 -0400 Subject: [PATCH 067/181] Stopped a stalled install from costing a whole regression run (#641) The Install softwares step runs apt-get update, an apt-get install and a pip install, and it has stalled twice: 55 minutes on the SMP job of one run, and more than two hours on the ThreadX job of the next, against a normal 27 to 152 seconds across every other run measured. In the second case the tests never started at all. No step in this template had a timeout, so a stall runs until the six hour job limit. That turns a transient apt or PyPI problem into a lost run, and it hides what happened: the job simply sits there, and the failure that eventually gets reported says nothing about which step was stuck. Bound the three steps that do real work. Ten minutes for the install, against a normal worst case of 152 seconds. Fifteen for the build, which has run between 4 and 54 seconds. Sixty for the test step, which is the only one whose length depends on the suites themselves; the longest observed is 37 minutes, and that was with a wait in one test that has since been bounded. A step that trips its timeout fails and names itself, which is the point. None of these numbers is tight enough to trip on work that is merely slow. Co-authored-by: Claude Opus 5 (1M context) --- .github/workflows/regression_template.yml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/.github/workflows/regression_template.yml b/.github/workflows/regression_template.yml index fad4d2f15..4f73cdd01 100644 --- a/.github/workflows/regression_template.yml +++ b/.github/workflows/regression_template.yml @@ -67,13 +67,20 @@ jobs: with: submodules: true + # apt and PyPI have stalled this step twice, for 55 minutes and for over two + # hours, against a normal 27 to 152 seconds. Nothing here had a timeout, so a + # stall ran until the six hour job limit and cost a whole run rather than + # failing and being retried. - name: Install softwares + timeout-minutes: 10 run: ${{ inputs.install_script }} - name: Build + timeout-minutes: 15 run: ${{ inputs.build_script }} - name: Test + timeout-minutes: 60 run: ${{ inputs.test_script }} - name: Publish Test Results From f2d27de25eb27b93fed30eab77d5bf7f9b6a46ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Thu, 20 Aug 2026 08:46:19 -0400 Subject: [PATCH 068/181] Stopped a dead apt mirror from taking the whole install down with it (#642) install.sh reaches the network four times, and on this runner pool that is not dependable. apt-get update stalled seven times in a single day: once for 55 minutes, once for more than two hours, and five times against the ten minute step timeout added alongside this. The log says the same thing every time. Every fetch from azure.archive.ubuntu.com comes back Ign, apt falls back to archive.ubuntu.com, and then the step produces no further output at all until something kills it. Nothing here bounded a fetch and nothing retried one, so a mirror being down cost a whole run instead of a few seconds. There is a second problem in the same lines. This script has no set -e, so a failed apt-get update did not stop the apt-get install that follows. The install went ahead against whatever package index the image happened to have, and the run failed later, somewhere with much less to say about why. Bound each attempt from outside and retry it. apt's own Acquire timeouts were tried first and are not enough: with them in place a run still sat inside a single apt-get update for nine and a half minutes without printing a line, having got as far as fetching noble-security InRelease. The retry loop never got a turn, because the first attempt never returned, and the step timeout was what eventually killed it. Whatever apt waits on there is not what Acquire::http::Timeout covers, so the bound has to come from outside the process. timeout does not care where the wait is. The Acquire options are kept anyway, since they make a slow mirror give up sooner, and pip gets its own retry and timeout flags for the same reason. timeout goes under sudo rather than over it, so that it signals apt itself. Signalling sudo risks the kill landing on sudo while apt carries on holding the dpkg lock, which would leave every retry failing for a different reason than the one being retried. The explicit exits stop a failed fetch being carried forward into a build. set -e is deliberately not used. rm -rf /opt/hostedtoolcache runs without sudo against a root owned directory and its exit status is not something this script should start depending on. The bounds fit inside the ten minute step timeout. Two minutes per attempt, three attempts, with 10 and 20 second backoffs, caps a command at about six and a half minutes, and a command that exhausts its attempts exits rather than letting the next one start. Co-authored-by: Claude Opus 5 (1M context) --- scripts/install.sh | 59 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 53 insertions(+), 6 deletions(-) diff --git a/scripts/install.sh b/scripts/install.sh index bc868477e..e37fd33a9 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -16,8 +16,55 @@ # Remove large folder to save space rm -rf /opt/hostedtoolcache -sudo apt-get update -sudo apt-get install -y \ +# Everything below reaches the network, and on this runner pool that is not +# dependable. apt-get update stalled seven times in a single day, once for more +# than two hours, each time with the Azure mirror returning nothing and the +# fallback to archive.ubuntu.com then going silent. Nothing here bounded a fetch +# and nothing retried one, so a mirror being down cost a whole run rather than a +# few seconds. Worse, this script has no set -e, so a failed update did not stop +# the install that follows: it went on to install from whatever index it already +# had, and the run failed later somewhere less obvious. +# +# Each command is wrapped in timeout rather than left to bound itself. apt's own +# Acquire timeouts were tried first and did not help: a run still sat inside a +# single apt-get update for nine and a half minutes without producing a line, +# having got as far as fetching noble-security InRelease, so the retry loop never +# got a turn and the step timeout was what eventually killed it. Whatever apt is +# waiting on there, it is not something Acquire::http::Timeout covers. timeout +# does not care where the wait is. +# +# The Acquire options are kept anyway, since they make a slow mirror give up +# sooner. The loop covers a mirror that is down rather than merely slow. The +# explicit exits stop a failed fetch from being carried forward into a build. +APT_OPTIONS=(-o Acquire::Retries=3 + -o Acquire::http::Timeout=20 + -o Acquire::https::Timeout=20) + +# Two minutes per attempt, killed outright if it ignores the first signal. Three +# attempts plus backoff bounds a command at about six and a half minutes, and a +# command that exhausts its attempts exits rather than letting the next one run. +# +# timeout goes under sudo, not over it, so that it signals apt itself. Signalling +# sudo instead risks the kill landing on sudo while apt carries on holding the +# dpkg lock, which would leave every retry failing for a different reason than +# the one being retried. +TIMEOUT=(timeout --kill-after=10 120) + +retry() { + local attempt + for attempt in 1 2 3; do + if "$@"; then + return 0 + fi + echo "install.sh: '$*' failed or timed out on attempt ${attempt}" + sleep $((attempt * 10)) + done + echo "install.sh: '$*' failed after 3 attempts" + return 1 +} + +retry sudo "${TIMEOUT[@]}" apt-get "${APT_OPTIONS[@]}" update || exit 1 +retry sudo "${TIMEOUT[@]}" apt-get "${APT_OPTIONS[@]}" install -y \ gcc-multilib \ git \ g++ \ @@ -28,10 +75,10 @@ sudo apt-get install -y \ tofrodos \ gawk \ cmake \ - software-properties-common + software-properties-common || exit 1 -python3 -m pip install --upgrade pip -pip3 install gcovr==4.1 +retry "${TIMEOUT[@]}" python3 -m pip install --retries 3 --timeout 30 --upgrade pip || exit 1 +retry "${TIMEOUT[@]}" pip3 install --retries 3 --timeout 30 gcovr==4.1 || exit 1 # Upgrade cmake to the latest version. -pip install --upgrade cmake +retry "${TIMEOUT[@]}" pip install --retries 3 --timeout 30 --upgrade cmake || exit 1 From 7928dc4268028961eeedfc3751c637ed232428d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Thu, 20 Aug 2026 08:49:01 -0400 Subject: [PATCH 069/181] Ran the ThreadX and SMP regression suites one test at a time (#643) A large part of both suites sleeps and then asserts on the tick counter, either exactly or within a tick: tx_thread_sleep(18); now = tx_time_get(); if ((now == 18) || (now == 19)) The Linux port drives ticks from a thread running under SCHED_FIFO, so ticks keep arriving whether or not the thread waiting on them can get a core. Starve that thread and further ticks land between the sleep expiring and the read, the value is past the one asked for, and a kernel that behaved correctly is reported as broken. Thirty-five tests here and forty-one on the SMP side sleep and then consult the clock or a counter driven by it, so this is most of the suite rather than a corner of it. The starvation is self-inflicted. Four tests are run at once on a four vCPU runner, and each one is a process carrying a scheduler thread, a SCHED_FIFO timer thread and a thread of its own, so the machine is oversubscribed two or three times over by design. That is why three of these failed in the run of 18 August, and why the retry hid two of them. Naming the sensitive tests and keeping them apart was tried first and does not converge. A list covering the tests comparing tx_time_get() for equality missed threadx_timer_multiple_accuracy_test, which compares timer-driven counters, and CI failed on it. Widening the list to cover those missed threadx_thread_sleep_for_100ticks_test, which asserts a range rather than an equality, and CI failed on that. A list that is quietly incomplete is worse than no list, because it reads as protection. So stop overlapping the tests. Serial execution removes the contention for every test at once, needs nothing to be enumerated, and makes a run reproducible: a test either passes on its own machine or has a real defect. The cost, measured in a four CPU cpuset, is close to a factor of four: the ThreadX suite goes from 12.2 to 47.6 seconds for a configuration and the SMP suite from 15.2 to 60.0 seconds. The suites parallelise almost perfectly, so that factor is what parallelism was buying. It is worth giving up. The run this replaces spent 36 minutes and reported a timeout carrying no information, and 2000 of those seconds went on retrying a test that had already hung twice. Serial also makes the tick budget in threadx_thread_wait_abort_and_isr_test mean what it says. Under contention that test took 255 seconds while its 20000 tick budget never engaged, because the ticks themselves stretch when the process cannot get a core. With nothing else running, ticks track wall clock and a budget in ticks bounds elapsed time. The FreeRTOS suite is left alone. It covers the creation paths of the compatibility layer and has no tick accuracy tests, so it has nothing to gain here. Co-authored-by: Claude Opus 5 (1M context) --- scripts/test_smp.sh | 2 +- scripts/test_tx.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/test_smp.sh b/scripts/test_smp.sh index 72be13c0b..51f1f8679 100755 --- a/scripts/test_smp.sh +++ b/scripts/test_smp.sh @@ -11,4 +11,4 @@ ############################################################################## -CTEST_PARALLEL_LEVEL=4 $(dirname `realpath $0`)/../test/smp/cmake/run.sh test all +CTEST_PARALLEL_LEVEL=1 $(dirname `realpath $0`)/../test/smp/cmake/run.sh test all diff --git a/scripts/test_tx.sh b/scripts/test_tx.sh index 3a2194319..1434995b7 100755 --- a/scripts/test_tx.sh +++ b/scripts/test_tx.sh @@ -11,4 +11,4 @@ ############################################################################## -CTEST_PARALLEL_LEVEL=4 $(dirname `realpath $0`)/../test/tx/cmake/run.sh test all +CTEST_PARALLEL_LEVEL=1 $(dirname `realpath $0`)/../test/tx/cmake/run.sh test all From 4d9ce418451cca88851c8e255a3bbb3703ad47ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Thu, 20 Aug 2026 08:49:43 -0400 Subject: [PATCH 070/181] Gave the wait abort ISR test a budget instead of an open-ended wait (#644) threadx_thread_wait_abort_and_isr_test waits for an interrupt to land while the preempt disable flag is set, and waits for it ten times, twenty in the SMP copy, with no bound on how long that takes. The handler in the same file already says what can go wrong: It is possible for this test to get into a resonance condition in which the ISR never occurs while preemption is disabled and perturbs its own duration to break out of it. That helps but guarantees nothing, and if the resonance holds, the loop does not end. It is also, by a wide margin, the most expensive thing in either suite. Run one test at a time in CI it took between 148 and 726 seconds per configuration: 1936 seconds of the ThreadX suite's 2209, against 273 seconds for the other ninety five tests together. Nothing else in the suite is within two orders of magnitude of it. The budget is in wall clock seconds, not ticks. That distinction turned out to matter. A tick is delivered only when the port's timer thread gets to run, so the simulated clock falls behind real time under load or under coverage instrumentation, and never makes the loss up. A first attempt bounded the wait at 20000 ticks, nominally 200 seconds, and failed to stop a run that took 726 seconds, because fewer than 20000 ticks had gone by. tx_time_get() cannot bound elapsed time here; time() can. A run that falls short says how many windows it reached rather than going quiet, and the check after the loop is untouched. That check compares semaphore bookkeeping which holds whatever number of windows were hit, so it still means exactly what it did before. Hitting the race a few times rather than ten is a smaller loss than it looks: the value is in reaching the window at all, and the later hits repeat what the first ones established. Verified by forcing the budget to 3 seconds, where the test stops after 3.14 seconds of wall clock and reports reaching 0 of 10 windows, with the following check intact. At 120 seconds both suites pass every configuration run serially. Co-authored-by: Claude Opus 5 (1M context) --- .../threadx_thread_wait_abort_and_isr_test.c | 37 ++++++++++++++++++- .../threadx_thread_wait_abort_and_isr_test.c | 37 ++++++++++++++++++- 2 files changed, 72 insertions(+), 2 deletions(-) diff --git a/test/smp/regression/threadx_thread_wait_abort_and_isr_test.c b/test/smp/regression/threadx_thread_wait_abort_and_isr_test.c index 75faf050f..1078e8e1a 100644 --- a/test/smp/regression/threadx_thread_wait_abort_and_isr_test.c +++ b/test/smp/regression/threadx_thread_wait_abort_and_isr_test.c @@ -12,6 +12,7 @@ /* This test is designed to test for simultaneous thread suspension lifting AND thread wait abort calls. */ #include +#include #include "tx_api.h" #include "tx_timer.h" @@ -178,6 +179,24 @@ static void thread_0_entry(ULONG thread_input) UINT status; +/* The window this test waits for is probabilistic, and the handler above says + as much: it can settle into a resonance in which the condition is never met. + Waiting for it without a bound means such a run never ends, and this test has + been the most expensive thing in the suite: run one at a time in CI it took + between 148 and 726 seconds per configuration, 88 percent of the whole + ThreadX suite, against 273 seconds for the other ninety five tests together. + + The budget is in wall clock seconds rather than ticks on purpose. The + simulated tick clock is not a proxy for elapsed time here: a tick arrives only + when the port's timer thread gets to run, so under load, or under coverage + instrumentation, ticks fall behind and never catch up. A budget of 20000 + ticks, nominally 200 seconds, failed to stop a run that took 726 seconds, + because fewer than 20000 ticks had passed. time() does not drift that way. */ +#define WAIT_ABORT_WINDOWS_WANTED ((ULONG) 20) +#define WAIT_ABORT_SECOND_BUDGET ((ULONG) 120) + +time_t start_wall; + /* Setup ISR for this test. */ test_isr_dispatch = isr_entry; @@ -186,7 +205,8 @@ UINT status; printf("Running Thread Wait Abort and ISR Resume Test....................... "); /* Loop to exploit the probability window inside tx_thread_wait_abort. */ - while (condition_count < 20) + start_wall = time(TX_NULL); + while (condition_count < WAIT_ABORT_WINDOWS_WANTED) { /* Suspend on the semaphore that is going to be set via the ISR. */ @@ -227,11 +247,26 @@ UINT status; #endif } + + /* Out of budget? */ + if (((ULONG) (time(TX_NULL) - start_wall)) > WAIT_ABORT_SECOND_BUDGET) + break; } /* Clear ISR dispatch. */ test_isr_dispatch = TX_NULL; + if (condition_count < WAIT_ABORT_WINDOWS_WANTED) + { + + /* Say what this run reached. Falling short is a gap in what was + exercised rather than a fault in the code under test, so the check + below still runs and still means what it did. */ + printf("(reached %lu of %lu windows in %lu seconds) ", + (ULONG) condition_count, WAIT_ABORT_WINDOWS_WANTED, + (ULONG) (time(TX_NULL) - start_wall)); + } + #ifdef TX_NOT_INTERRUPTABLE /* At this point, check to see if we got all the semaphores! */ if ((thread_0_counter != (semaphore_put_counter - semaphore_0.tx_semaphore_count)) || diff --git a/test/tx/regression/threadx_thread_wait_abort_and_isr_test.c b/test/tx/regression/threadx_thread_wait_abort_and_isr_test.c index e15b410fa..53c74cbb9 100644 --- a/test/tx/regression/threadx_thread_wait_abort_and_isr_test.c +++ b/test/tx/regression/threadx_thread_wait_abort_and_isr_test.c @@ -12,6 +12,7 @@ /* This test is designed to test for simultaneous thread suspension lifting AND thread wait abort calls. */ #include +#include #include "tx_api.h" static unsigned long thread_0_counter = 0; @@ -177,6 +178,24 @@ static void thread_0_entry(ULONG thread_input) UINT status; +/* The window this test waits for is probabilistic, and the handler above says + as much: it can settle into a resonance in which the condition is never met. + Waiting for it without a bound means such a run never ends, and this test has + been the most expensive thing in the suite: run one at a time in CI it took + between 148 and 726 seconds per configuration, 88 percent of the whole + ThreadX suite, against 273 seconds for the other ninety five tests together. + + The budget is in wall clock seconds rather than ticks on purpose. The + simulated tick clock is not a proxy for elapsed time here: a tick arrives only + when the port's timer thread gets to run, so under load, or under coverage + instrumentation, ticks fall behind and never catch up. A budget of 20000 + ticks, nominally 200 seconds, failed to stop a run that took 726 seconds, + because fewer than 20000 ticks had passed. time() does not drift that way. */ +#define WAIT_ABORT_WINDOWS_WANTED ((ULONG) 10) +#define WAIT_ABORT_SECOND_BUDGET ((ULONG) 120) + +time_t start_wall; + /* Setup ISR for this test. */ test_isr_dispatch = isr_entry; @@ -185,7 +204,8 @@ UINT status; printf("Running Thread Wait Abort and ISR Resume Test....................... "); /* Loop to exploit the probability window inside tx_thread_wait_abort. */ - while (condition_count < 10) + start_wall = time(TX_NULL); + while (condition_count < WAIT_ABORT_WINDOWS_WANTED) { /* Suspend on the semaphore that is going to be set via the ISR. */ @@ -226,11 +246,26 @@ UINT status; #endif } + + /* Out of budget? */ + if (((ULONG) (time(TX_NULL) - start_wall)) > WAIT_ABORT_SECOND_BUDGET) + break; } /* Clear ISR dispatch. */ test_isr_dispatch = TX_NULL; + if (condition_count < WAIT_ABORT_WINDOWS_WANTED) + { + + /* Say what this run reached. Falling short is a gap in what was + exercised rather than a fault in the code under test, so the check + below still runs and still means what it did. */ + printf("(reached %lu of %lu windows in %lu seconds) ", + (ULONG) condition_count, WAIT_ABORT_WINDOWS_WANTED, + (ULONG) (time(TX_NULL) - start_wall)); + } + #ifdef TX_NOT_INTERRUPTABLE /* At this point, check to see if we got all the semaphores! */ if ((thread_0_counter != (semaphore_put_counter - semaphore_0.tx_semaphore_count)) || From a5483f0773d5b2a15b5247b4f0fbd72a0c7a8750 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Thu, 20 Aug 2026 08:50:15 -0400 Subject: [PATCH 071/181] Bounded the wait for the delayed suspension window (#645) threadx_thread_delayed_suspension_test waits for an interrupt to land while thread 2 is part way through suspending, and waits for it with no bound: while(delayed_suspend_set == 0) { tx_thread_wait_abort(&thread_2); tx_thread_relinquish(); } How long that takes depends on the build to a degree that is easy to miss. The loop finishes in between a tenth of a second and three seconds in four of the five ThreadX configurations. In trace_build it took 490 seconds, which was 40 percent of the whole ThreadX suite and more than every other test in that configuration put together. This is the third test in these suites built the same way, after threadx_thread_priority_change and threadx_thread_wait_abort_and_isr_test: spin until an interrupt happens to land in a narrow window, with nothing to stop the spin if it does not. The other two have been given bounds already. Give this one a wall clock budget too, for the same reason as the last: a tick is delivered only when the port's timer thread runs, so the tick clock falls behind real time under load or instrumentation, and instrumentation is exactly what trace_build turns on. The check after the loop needs care that the other two did not. It compares thread_2_counter against thread_2_counter_capture, and the capture is taken inside the interrupt handler at the moment the window is hit. Leaving that check in place after a run that never reached the window would compare a live counter against the zero it was initialised to and report a defect that is not there. So the check is skipped when the window was not reached, and the run says so. Reaching the window still exercises it exactly as before. Verified both ways in trace_build, which is the configuration that was slow: the window is reached in 8 seconds here and the test passes as it always did, and with the budget forced to zero the test reports that the window was not reached and passes without the dependent check firing. Co-authored-by: Claude Opus 5 (1M context) --- .../threadx_thread_delayed_suspension_test.c | 39 +++++++++++++++++-- .../threadx_thread_delayed_suspension_test.c | 39 +++++++++++++++++-- 2 files changed, 72 insertions(+), 6 deletions(-) diff --git a/test/smp/regression/threadx_thread_delayed_suspension_test.c b/test/smp/regression/threadx_thread_delayed_suspension_test.c index fe0a82f89..17a89d038 100644 --- a/test/smp/regression/threadx_thread_delayed_suspension_test.c +++ b/test/smp/regression/threadx_thread_delayed_suspension_test.c @@ -12,6 +12,7 @@ /* This test checks out the delayed suspension clear from tx_thread_resume. */ #include +#include #include "tx_api.h" #include "tx_thread.h" #include "tx_timer.h" @@ -235,6 +236,12 @@ static void thread_0_entry(ULONG thread_input) UINT status; +#ifndef TX_NOT_INTERRUPTABLE +#define DELAYED_SUSPENSION_SECOND_BUDGET ((ULONG) 120) + +time_t start_wall; +#endif + /* Inform user. */ printf("Running Thread Delayed Suspension Clearing Test..................... "); @@ -277,8 +284,23 @@ UINT status; /* Resume the test thread. */ tx_thread_resume(&thread_2); - /* Wait until we see the delayed suspension set flag. */ - while(delayed_suspend_set == 0) + /* Wait until we see the delayed suspension set flag. + + The flag is set by the interrupt above, and only when that interrupt lands + while thread 2 is part way through suspending. That is a narrow window, + and waiting for it without a bound leaves the test no way out when it is + not reached. How narrow it is depends on the build: in the ThreadX suite + the same loop finishes in between a tenth of a second and three seconds in + four configurations, and took 490 seconds in trace_build, where it was the + most expensive thing in the suite by a wide margin. + + The budget is in wall clock seconds rather than ticks. A tick arrives only + when the port's timer thread runs, so the tick clock falls behind real + time under load or instrumentation, which is exactly the configuration + that needs bounding here. */ + start_wall = time(TX_NULL); + while ((delayed_suspend_set == 0) && + (((ULONG) (time(TX_NULL) - start_wall)) <= DELAYED_SUSPENSION_SECOND_BUDGET)) { /* Abort the suspension for thread 2. */ tx_thread_wait_abort(&thread_2); @@ -291,7 +313,18 @@ UINT status; tx_thread_relinquish(); /* At this point, check for an error. */ - if (thread_2_counter != thread_2_counter_capture) + if (delayed_suspend_set == 0) + { + + /* The window was never reached, so thread_2_counter_capture was never + taken and the comparison below would be against a value that means + nothing. Not reaching the window is a gap in what this run covered + rather than a fault in the code under test, so say so and skip the + check that depends on it. */ + printf("(delayed suspension window not reached in %lu seconds) ", + (ULONG) (time(TX_NULL) - start_wall)); + } + else if (thread_2_counter != thread_2_counter_capture) { /* Delayed suspension error... thread kept running! */ diff --git a/test/tx/regression/threadx_thread_delayed_suspension_test.c b/test/tx/regression/threadx_thread_delayed_suspension_test.c index 2bf264219..1841458a6 100644 --- a/test/tx/regression/threadx_thread_delayed_suspension_test.c +++ b/test/tx/regression/threadx_thread_delayed_suspension_test.c @@ -12,6 +12,7 @@ /* This test checks out the delayed suspension clear from tx_thread_resume. */ #include +#include #include "tx_api.h" #include "tx_thread.h" #include "tx_timer.h" @@ -235,6 +236,12 @@ static void thread_0_entry(ULONG thread_input) UINT status; +#ifndef TX_NOT_INTERRUPTABLE +#define DELAYED_SUSPENSION_SECOND_BUDGET ((ULONG) 120) + +time_t start_wall; +#endif + /* Inform user. */ printf("Running Thread Delayed Suspension Clearing Test..................... "); @@ -278,8 +285,23 @@ UINT status; /* Resume the test thread. */ tx_thread_resume(&thread_2); - /* Wait until we see the delayed suspension set flag. */ - while(delayed_suspend_set == 0) + /* Wait until we see the delayed suspension set flag. + + The flag is set by the interrupt above, and only when that interrupt lands + while thread 2 is part way through suspending. That is a narrow window, + and waiting for it without a bound leaves the test no way out when it is + not reached. How narrow it is depends on the build: this loop finishes in + between a tenth of a second and three seconds in four of the five ThreadX + configurations, and took 490 seconds in trace_build, where it was the most + expensive thing in the suite by a wide margin. + + The budget is in wall clock seconds rather than ticks. A tick arrives only + when the port's timer thread runs, so the tick clock falls behind real + time under load or instrumentation, which is exactly the configuration + that needs bounding here. */ + start_wall = time(TX_NULL); + while ((delayed_suspend_set == 0) && + (((ULONG) (time(TX_NULL) - start_wall)) <= DELAYED_SUSPENSION_SECOND_BUDGET)) { /* Abort the suspension for thread 2. */ @@ -293,7 +315,18 @@ UINT status; tx_thread_relinquish(); /* At this point, check for an error. */ - if (thread_2_counter != thread_2_counter_capture) + if (delayed_suspend_set == 0) + { + + /* The window was never reached, so thread_2_counter_capture was never + taken and the comparison below would be against a value that means + nothing. Not reaching the window is a gap in what this run covered + rather than a fault in the code under test, so say so and skip the + check that depends on it. */ + printf("(delayed suspension window not reached in %lu seconds) ", + (ULONG) (time(TX_NULL) - start_wall)); + } + else if (thread_2_counter != thread_2_counter_capture) { /* Delayed suspension error... thread kept running! */ From 83dfbc3534e352dfd5a78cb35c4d156597a5b6ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Thu, 20 Aug 2026 08:51:05 -0400 Subject: [PATCH 072/181] Made a teardown hang in the SMP suite say where it stopped (#646) The SMP regression suite times out in CI on threadx_thread_priority_change and the log carries nothing that says why. The reason the log is empty is mechanical: test_control_return() opens with fflush(stdout), and that is the last flush before either the test finishes or it wedges. Everything printed after it sits in stdout's block buffer, and ctest discards that buffer when it kills the process at the timeout. So the log ends at the test's own result line no matter where the process actually stopped. That is enough to place the hang, if not to explain it. The failing runs print "SUCCESS!" and then stop, which means every check in the test body ran and passed, and the wedge is somewhere between that flush and exit(). The run of 30 June shows the same signature before any of this test's waits were bounded, so the hang is not the unbounded wait removed earlier, and the message added then for an exhausted cap never appears. Retrying tells us nothing new either: the suite spends 1000 seconds per attempt, twice, to reproduce the same silent timeout. Record how far teardown gets, and bound it. A stage variable is updated at each step from test_control_return() through test_control_cleanup() to exit(), and a watchdog thread armed on entry to test_control_return() reports the last stage reached, the per-core scheduler state, and every thread on the created list, then exits 99. The watchdog covers teardown and not the test body, because the test body has no bounded runtime to hold it to. Several tests here wait on a probabilistic interrupt window: threadx_thread_wait_abort_and_isr_test has been measured between 0.34 and 439 seconds while passing. Teardown is a fixed amount of work that takes milliseconds, so a bound on it cannot turn a slow pass into a failure. The default is 60 seconds, which also means a wedged run now reports in one minute rather than burning the 2000 seconds two 1000-second attempts cost today. The report is written with write() rather than printf() because a wedged thread may be holding the stdio lock, and a watchdog that blocked on that lock would reproduce the silent timeout it exists to replace. For the same reason it reads the ThreadX globals directly and takes no kernel lock; the values may be torn, which is acceptable for a post-mortem and cannot deadlock. One walk in test_control_cleanup() is bounded as well. The loop that steps past the timer thread and the control thread has no terminating condition of its own and spins for good if _tx_thread_created_count and the created list ever disagree, which is one of the shapes the timeout could be taking. It now reports and stops instead. Off by default in the sense that matters: stderr stays empty and stdout keeps its buffering, so output is unchanged on a passing run. TX_TEST_TEARDOWN_TIMEOUT overrides the bound in seconds and zero disables the watchdog; TX_TEST_TEARDOWN_TRACE echoes each stage as it is reached and line-buffers stdout so the surrounding output survives a kill too. Verified against an injected hang at the point the failing runs stop: the watchdog fires, names the stage, and exits 99. The dump is already informative, showing thread 0 left at priority 0 with threshold 0 and inherit 0, the same priority as the control thread, with core 0's execute pointer still on it. All five SMP configurations pass 110 of 110 at the parallelism CI uses, in both quiet and trace modes, and the suite runtime is unchanged. Only the SMP harness is instrumented. The non-SMP suite has not shown this hang. Co-authored-by: Claude Opus 5 (1M context) --- test/smp/regression/testcontrol.c | 286 ++++++++++++++++++++++++++++++ 1 file changed, 286 insertions(+) diff --git a/test/smp/regression/testcontrol.c b/test/smp/regression/testcontrol.c index 1c3b2ccfd..c0ba34636 100644 --- a/test/smp/regression/testcontrol.c +++ b/test/smp/regression/testcontrol.c @@ -25,6 +25,13 @@ #include "tx_block_pool.h" #include "tx_byte_pool.h" #include "tx_event_flags.h" +#include +#include +#include +#include +#include +#include +#include #define TEST_STACK_SIZE 6144 @@ -1335,6 +1342,241 @@ TX_THREAD *thread_ptr; } +/* --------------------------------------------------------------------------- + Teardown diagnostics. + + When this suite hangs, CI reports nothing but a ctest timeout. The last + flush of stdout happens on entry to test_control_return(), so a test that + wedges after that point leaves the rest of its output sitting in stdout's + block buffer, which is discarded when ctest kills the process. The log + stops at the test's own result line and says nothing about where the + process stopped. + + Two things close that gap. A stage variable records how far teardown has + progressed, and a watchdog thread, armed on entry to test_control_return() + and stood down once the next test is about to be dispatched, reports the + last stage reached along with the scheduler state, then exits non-zero. + + The watchdog covers teardown only, never the test body. Several tests here + wait on a probabilistic interrupt window and have no bounded runtime: + threadx_thread_wait_abort_and_isr_test has been observed taking anywhere + from 0.34 to 439 seconds while passing. Teardown is a fixed amount of work + that takes milliseconds, so bounding it cannot turn a slow pass into a + failure. + + The report is written with write() rather than printf() deliberately. A + wedged thread may hold the stdio lock, and a watchdog that blocked on that + lock would reproduce the silent timeout it exists to replace. + + TX_TEST_TEARDOWN_TIMEOUT overrides the bound, in seconds; zero disables the + watchdog. TX_TEST_TEARDOWN_TRACE echoes every stage as it is reached and + puts stdout in line-buffered mode so the surrounding output survives too. + --------------------------------------------------------------------------- */ + +#define TEST_TEARDOWN_TIMEOUT_DEFAULT 60 /* Seconds allowed for teardown. */ +#define TEST_TEARDOWN_POLL_MS 250 /* Watchdog poll interval. */ +#define TEST_TEARDOWN_WALK_LIMIT 100000 /* Cap on the unbounded walk in cleanup. */ + +static const char * volatile test_teardown_stage_name = "test body"; +static volatile UINT test_teardown_armed = TX_FALSE; +static UINT test_teardown_timeout = TEST_TEARDOWN_TIMEOUT_DEFAULT; +static UINT test_teardown_trace = TX_FALSE; + + +/* Record how far teardown has progressed, and echo it when tracing is on. */ +static void test_teardown_stage(const char *stage) +{ + + test_teardown_stage_name = stage; + + if (test_teardown_trace != TX_FALSE) + { + (void) write(2, "[teardown] ", 11); + (void) write(2, stage, strlen(stage)); + (void) write(2, "\n", 1); + } +} + + +/* Name a thread for the report, without dereferencing a null pointer. */ +static const char *test_teardown_thread_name(TX_THREAD *thread_ptr) +{ + + if (thread_ptr == TX_NULL) + return "(none)"; + + if (thread_ptr -> tx_thread_name == TX_NULL) + return "(unnamed)"; + + return thread_ptr -> tx_thread_name; +} + + +/* Write out the state that matters for a teardown hang. */ +static void test_teardown_report(const char *reason) +{ + +char buffer[512]; +int length; +UINT core; +UINT count; +TX_THREAD *thread_ptr; + + + length = snprintf(buffer, sizeof(buffer), + "\n**** TEARDOWN WATCHDOG: %s ****\n" + " last stage reached: %s\n" + " _tx_thread_preempt_disable: %u\n" + " _tx_thread_created_count: %lu\n", + reason, test_teardown_stage_name, + (UINT) _tx_thread_preempt_disable, + (ULONG) _tx_thread_created_count); + if (length > 0) + (void) write(2, buffer, (size_t) length); + + for (core = 0; core < ((UINT) TX_THREAD_SMP_MAX_CORES); core++) + { + + length = snprintf(buffer, sizeof(buffer), + " core %u: system_state=%lu time_slice=%lu current=%s execute=%s\n", + core, (ULONG) _tx_thread_system_state[core], + (ULONG) _tx_timer_time_slice[core], + test_teardown_thread_name(_tx_thread_current_ptr[core]), + test_teardown_thread_name(_tx_thread_execute_ptr[core])); + if (length > 0) + (void) write(2, buffer, (size_t) length); + } + + /* Walk the created list, stopping at the head, and after a fixed number of + entries, so a corrupt list cannot trap us in here. */ + thread_ptr = _tx_thread_created_ptr; + for (count = 0; (thread_ptr != TX_NULL) && (count < ((UINT) 64)); count++) + { + + length = snprintf(buffer, sizeof(buffer), + " thread %-24s state=%u priority=%u threshold=%u inherit=%u " + "core_mapped=%u core_control=%lu deferred_preempt=%u suspension=%u\n", + test_teardown_thread_name(thread_ptr), + thread_ptr -> tx_thread_state, + thread_ptr -> tx_thread_priority, + thread_ptr -> tx_thread_preempt_threshold, + thread_ptr -> tx_thread_inherit_priority, + thread_ptr -> tx_thread_smp_core_mapped, + (ULONG) thread_ptr -> tx_thread_smp_core_control, + thread_ptr -> tx_thread_linux_deferred_preempt, + thread_ptr -> tx_thread_linux_suspension_type); + if (length > 0) + (void) write(2, buffer, (size_t) length); + + thread_ptr = thread_ptr -> tx_thread_created_next; + if (thread_ptr == _tx_thread_created_ptr) + break; + } +} + + +/* Report and leave. Used by the watchdog and by the bounded walk in cleanup. */ +static void test_teardown_abort(const char *reason) +{ + + test_teardown_report(reason); + _exit(99); +} + + +/* Watch an armed teardown, and only an armed one. */ +static void *test_teardown_watchdog(void *input) +{ + +sigset_t mask; +struct timespec interval; +ULONG waited_ms; +ULONG limit_ms; + + + /* The port drives thread suspend and resume with SIGUSR1 and SIGUSR2. + Block both here so this thread never takes one. */ + sigemptyset(&mask); + sigaddset(&mask, SIGUSR1); + sigaddset(&mask, SIGUSR2); + pthread_sigmask(SIG_BLOCK, &mask, TX_NULL); + + limit_ms = ((ULONG) test_teardown_timeout) * ((ULONG) 1000); + waited_ms = ((ULONG) 0); + + while (1) + { + + interval.tv_sec = 0; + interval.tv_nsec = ((long) TEST_TEARDOWN_POLL_MS) * 1000000L; + while (nanosleep(&interval, &interval) != 0) + { + if (errno != EINTR) + break; + } + + /* Nothing to watch while teardown is stood down. */ + if (test_teardown_armed == TX_FALSE) + { + waited_ms = ((ULONG) 0); + continue; + } + + waited_ms = waited_ms + ((ULONG) TEST_TEARDOWN_POLL_MS); + if (waited_ms >= limit_ms) + test_teardown_abort("teardown did not complete"); + } + + return input; +} + + +/* Start the watchdog, stood down. Called before any test runs, so that no + thread is created inside the window under investigation. */ +static void test_teardown_watchdog_start(void) +{ + +pthread_t watchdog_id; +char *value; + + + value = getenv("TX_TEST_TEARDOWN_TIMEOUT"); + if (value != TX_NULL) + test_teardown_timeout = (UINT) atoi(value); + + if (getenv("TX_TEST_TEARDOWN_TRACE") != TX_NULL) + { + + /* Tracing wants the stages in the log next to the output around them, + which block buffering would otherwise discard on a kill. */ + test_teardown_trace = TX_TRUE; + setvbuf(stdout, TX_NULL, _IOLBF, 0); + } + + /* A timeout of zero turns the watchdog off. */ + if (test_teardown_timeout == ((UINT) 0)) + return; + + if (pthread_create(&watchdog_id, TX_NULL, test_teardown_watchdog, TX_NULL) == 0) + pthread_detach(watchdog_id); +} + + +static void test_teardown_arm(const char *stage) +{ + + test_teardown_stage(stage); + test_teardown_armed = TX_TRUE; +} + + +static void test_teardown_stand_down(void) +{ + + test_teardown_armed = TX_FALSE; + test_teardown_stage("test body"); +} + /* Define the test control thread. This thread is responsible for dispatching all of the tests in the ThreadX test suite. */ @@ -1346,6 +1588,9 @@ UINT i; /* Raise the priority of the control thread to 0. */ tx_thread_priority_change(&test_control_thread, 0, &i); + + /* Bring up the teardown watchdog, stood down for now. */ + test_teardown_watchdog_start(); #ifdef CTEST test_control_cleanup(); #endif @@ -1364,6 +1609,10 @@ UINT i; while (test_control_tests[i].test_entry != TX_NULL) { + /* Teardown of the previous test is done. The watchdog covers teardown + only, so stand it down before dispatching the next test. */ + test_teardown_stand_down(); + /* Clear the ISR dispatch. */ test_isr_dispatch = TX_NULL; @@ -1381,12 +1630,15 @@ UINT i; tx_thread_suspend(&test_control_thread); /* Test finished, cleanup in preparation for the next test. */ + test_teardown_stage("control thread resumed after test"); test_control_cleanup(); } /* Finished with all tests, print results and return! */ + test_teardown_stage("all tests dispatched, printing summary"); printf("**** Testing Complete ****\n"); printf("**** Test Summary: Tests Passed: %lu Tests Failed: %lu System Errors: %lu\n", test_control_successful_tests, test_control_failed_tests, test_control_system_errors); + test_teardown_stage("calling exit()"); #ifndef EXTERNAL_EXIT exit(test_control_failed_tests + test_control_system_errors); #else @@ -1404,6 +1656,10 @@ UINT old_posture = TX_INT_ENABLE; fflush(stdout); + /* This is the last flush before the test either finishes or wedges, so + everything from here on is invisible in the log. Arm the watchdog. */ + test_teardown_arm("test_control_return entered"); + /* Save the status in a global. */ test_control_return_status = status; @@ -1456,7 +1712,9 @@ UINT old_posture = TX_INT_ENABLE; #endif /* Resume the control thread to fully exit the test. */ + test_teardown_stage("test_control_return: resuming control thread"); tx_thread_resume(&test_control_thread); + test_teardown_stage("test_control_return: control thread resume returned"); } @@ -1465,7 +1723,10 @@ void test_control_cleanup(void) TX_MUTEX *mutex_ptr; TX_THREAD *thread_ptr; +UINT walk_guard; + + test_teardown_stage("cleanup: deleting threads"); /* Delete all threads, except for timer thread, and test control thread. This ensures application-owned objects are no longer referenced before @@ -1497,9 +1758,18 @@ TX_THREAD *thread_ptr; break; /* Move to the thread not protected. */ + walk_guard = ((UINT) 0); while ((thread_ptr == &_tx_timer_thread) || (thread_ptr == &test_control_thread)) { + /* This walk has no natural bound. Should the created count and the + created list ever disagree, it spins here for good, which is one + of the shapes the CI timeout could be taking. Say so and stop + instead of hanging. */ + walk_guard = walk_guard + ((UINT) 1); + if (walk_guard > ((UINT) TEST_TEARDOWN_WALK_LIMIT)) + test_teardown_abort("cleanup thread walk did not terminate"); + /* Yes, move to the next thread. */ thread_ptr = thread_ptr -> tx_thread_created_next; } @@ -1512,6 +1782,8 @@ TX_THREAD *thread_ptr; tx_thread_delete(thread_ptr); } + test_teardown_stage("cleanup: deleting queues"); + /* Delete all queues. */ while(_tx_queue_created_ptr) { @@ -1520,6 +1792,8 @@ TX_THREAD *thread_ptr; tx_queue_delete(_tx_queue_created_ptr); } + test_teardown_stage("cleanup: deleting semaphores"); + /* Delete all semaphores. */ while(_tx_semaphore_created_ptr) { @@ -1528,6 +1802,8 @@ TX_THREAD *thread_ptr; tx_semaphore_delete(_tx_semaphore_created_ptr); } + test_teardown_stage("cleanup: deleting event flag groups"); + /* Delete all event flag groups. */ while(_tx_event_flags_created_ptr) { @@ -1536,6 +1812,8 @@ TX_THREAD *thread_ptr; tx_event_flags_delete(_tx_event_flags_created_ptr); } + test_teardown_stage("cleanup: deleting byte pools"); + /* Delete all byte pools. */ while(_tx_byte_pool_created_ptr) { @@ -1544,6 +1822,8 @@ TX_THREAD *thread_ptr; tx_byte_pool_delete(_tx_byte_pool_created_ptr); } + test_teardown_stage("cleanup: deleting block pools"); + /* Delete all block pools. */ while(_tx_block_pool_created_ptr) { @@ -1552,6 +1832,8 @@ TX_THREAD *thread_ptr; tx_block_pool_delete(_tx_block_pool_created_ptr); } + test_teardown_stage("cleanup: deleting timers"); + /* Delete all timers. */ while(_tx_timer_created_ptr) { @@ -1563,6 +1845,8 @@ TX_THREAD *thread_ptr; tx_timer_delete(_tx_timer_created_ptr); } + test_teardown_stage("cleanup: deleting mutexes"); + /* Delete all mutexes (except for system mutex). */ while(_tx_mutex_created_ptr) { @@ -1589,6 +1873,8 @@ TX_THREAD *thread_ptr; tx_mutex_delete(mutex_ptr); } + test_teardown_stage("cleanup: complete"); + /* At this point, only the test control thread and the system timer thread and/or mutex should still be in the system. */ } From fe40079353ab2de43035257973a3a8eacffb2d0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Thu, 20 Aug 2026 08:52:06 -0400 Subject: [PATCH 073/181] Stopped the thread priority change test leaving core 0 to a finished thread (#647) The SMP suite has been failing on threadx_thread_priority_change since 30 June. The test reports SUCCESS and the process then never exits, so ctest kills it at the thousand second timeout, twice, and the log carries nothing past the result line. Instrumenting the harness teardown produced the state at the hang: last stage reached: test_control_return: control thread resume returned _tx_thread_preempt_disable: 0 core 0: current=thread 0 execute=thread 0 thread test control thread state=0 priority=0 threshold=0 core_control=1 thread thread 0 state=1 priority=0 threshold=0 inherit=0 Core 0 is held by a thread in state 1, TX_COMPLETED, while the control thread sits in state 0, TX_READY, at priority 0. The Linux SMP scheduler fills a core only when _tx_thread_current_ptr for it is null, and clears that pointer only for a thread carrying a deferred preemption, which thread 0 is not. So core 0 can never be handed on, and with TX_THREAD_SMP_ONLY_CORE_0_DEFAULT and TX_SMP_NOT_POSSIBLE the control thread has nowhere else to go. The scheduler re-reads the same state every two milliseconds for as long as it is allowed to. What put thread 0 at priority 0 is the last thing this test does: thread_0.tx_thread_inherit_priority = 0; _tx_thread_smp_simple_priority_change(&thread_0, 16); with the stated intent of reaching the branch where the new priority is below the inheritance priority. Zero cannot reach that branch, because 16 is not less than 0. The other branch runs instead, and that branch assigns the inheritance priority as the thread's priority while the code after it links the thread into the list for the new priority regardless. Thread 0 therefore came away claiming priority 0 while living in the priority 16 list. Both halves of that hurt. Priority 0 ties with the control thread, so resuming the control thread raised no preemption and left the execute pointer alone. The mismatch between the recorded priority and the list the thread is linked into then means that completing thread 0 removes it from a list it was never in, leaving core 0 pointing at it for good. Give the inheritance priority a value above the new one, which is what the branch the comment names actually requires, and put it back to TX_MAX_PRIORITIES afterwards so nothing downstream reasons about an inheritance that is not there. Hold protection across the call as well: this is an internal routine that expects it, and it was being called in the open. Measured before and after by printing the thread's state at the point the test reports success. With the inheritance priority at 0 it is priority 0 threshold 0, matching the hang above, on every run. With it above the new priority it is priority 16 threshold 16, which agrees with the list the thread is linked into, and resuming the control thread preempts core 0 the ordinary way. All five SMP configurations pass 110 of 110 at the parallelism CI uses. The comparison in _tx_thread_smp_simple_priority_change deserves a second look on its own account. When its else branch runs, the thread's recorded priority and the list it is linked into disagree by construction. Only this test is known to reach that branch, by supplying an inheritance priority that cannot arise in ordinary operation, so nothing here claims a defect in shipped paths. Co-authored-by: Claude Opus 5 (1M context) --- .../threadx_thread_priority_change.c | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/test/smp/regression/threadx_thread_priority_change.c b/test/smp/regression/threadx_thread_priority_change.c index 763201c45..d22f3d721 100644 --- a/test/smp/regression/threadx_thread_priority_change.c +++ b/test/smp/regression/threadx_thread_priority_change.c @@ -465,11 +465,28 @@ TX_THREAD *temp_thread; /* Restore interrupts. */ TX_RESTORE - /* Hit branch in _tx_thread_smp_simple_priority_change such that the - new priority is less than the inheritance priority. */ - thread_0.tx_thread_inherit_priority = 0; + /* Hit the branch in _tx_thread_smp_simple_priority_change where the new + priority is below the inheritance priority. That needs an inheritance + priority above the new one, so 0 does not reach it: with 0 the other + branch runs, and that branch records the inheritance priority as the + thread's priority while still linking the thread at the new priority. + Thread 0 came out of here claiming priority 0 while living in the + priority 16 list, which is what has been hanging this test in CI. + Priority 0 ties with the control thread, so resuming the control thread + raised no preemption, and once thread 0 completed, core 0 was left owned + by a completed thread with the control thread ready and unscheduled. + + This routine is internal and expects protection to be in force, so hold + it here rather than calling in the open. */ + TX_DISABLE + thread_0.tx_thread_inherit_priority = 20; _tx_thread_smp_simple_priority_change(&thread_0, 16); + /* Put the inheritance priority back to the value that means this thread is + not inheriting one, so nothing downstream reasons about a phantom. */ + thread_0.tx_thread_inherit_priority = TX_MAX_PRIORITIES; + TX_RESTORE + /* Successful test. */ printf("SUCCESS!\n"); test_control_return(0); From c8d27c4e252a4a2f56100f086ccd985e85a57485 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Thu, 20 Aug 2026 08:52:44 -0400 Subject: [PATCH 074/181] Stopped the SMP stack check analyzing a stack it just found broken (#648) TX_THREAD_STACK_CHECK detects a broken stack, calls the error handler, and then tests whether the word below the high-water mark still holds the fill pattern. On the SMP side that second test is a plain if, so a thread whose stack has just been reported as corrupt goes straight on into _tx_thread_stack_analyze(). Analyzing a stack that is known to be broken is what that function is least able to do. It binary searches between stack_lowest and stack_highest for the fill pattern and then scans forward with while (*stack_ptr == TX_STACK_FILL) which has no bound of its own and no reason to terminate once the pattern it is looking for is no longer where the pointers say it should be. The non-SMP copy was given an else for exactly this reason. The SMP copy never was, and the two macros are otherwise identical, line for line, so this single keyword was the whole of the divergence. The path is live in CI rather than theoretical. Instrumenting the internal handler and running all 110 binaries of stack_checking_build shows threadx_thread_stack_checking_test reaching it four times per run, on a thread whose stack the test corrupts on purpose. Every one of those four currently falls through into the analyze it should be skipping. This is not the timeout the SMP suite has been failing on. threadx_thread_priority_change never reaches the error handler at all, so whatever wedges it in teardown is something else. Worth closing regardless: a runaway scan inside stack analysis would present as a test that stops producing output and is eventually killed, which is the shape that has been costing this suite whole runs, and it would be indistinguishable in the log from the hang already being chased. Verified on both configurations that define TX_ENABLE_STACK_CHECKING. threadx_thread_stack_checking_test, the one test that exercises the changed branch, passes 60 consecutive runs, and stack_checking_build and stack_checking_rand_fill_build both pass 110 of 110, repeated at the parallelism CI uses. Co-authored-by: Claude Opus 5 (1M context) --- common_smp/inc/tx_thread.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common_smp/inc/tx_thread.h b/common_smp/inc/tx_thread.h index 7dc7801be..b92ce50e6 100644 --- a/common_smp/inc/tx_thread.h +++ b/common_smp/inc/tx_thread.h @@ -82,7 +82,7 @@ _tx_thread_stack_error_handler((thread_ptr)); \ TX_DISABLE \ } \ - if (*(((ULONG *) (thread_ptr) -> tx_thread_stack_highest_ptr) - 1) != TX_STACK_FILL) \ + else if (*(((ULONG *) (thread_ptr) -> tx_thread_stack_highest_ptr) - 1) != TX_STACK_FILL) \ { \ TX_RESTORE \ _tx_thread_stack_analyze((thread_ptr)); \ From e46b1b07872aa7872d08dd8c5edbd456ec5f5ff8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Thu, 20 Aug 2026 11:11:31 -0400 Subject: [PATCH 075/181] Asked the wait abort test for three windows, and failed a run that reached none (#649) Four CI runs of the same tree, twenty configuration-runs in total, show this test's budget being reached far more often than the first green run suggested, and a pass being reported every time it was: trace_build 3 of 10 windows in 121 seconds disable_notify 3 of 10 windows in 121 seconds default_coverage 4 of 10 windows in 121 seconds stack_checking 7 of 10 windows in 121 seconds trace_build 0 of 10 windows in 121 seconds disable_notify 7 of 10 windows in 121 seconds stack_checking 3 of 10 windows in 121 seconds Seven of twenty, and the shortfall message only ever reaches an artifact: ctest is run with --output-on-failure, so a passing test's output is not in the job log at all. The suite has been quietly losing most of this test's coverage in whole configurations and reporting green. The loop runs in two modes, not one. A window arrives in milliseconds in the fast mode, and costs between 17 and 40 seconds in the slow one, with nothing in between across those twenty runs. Ten windows are therefore unreachable inside any budget worth having: at 40 seconds each that is 400 seconds, and the unbounded runs measured before any of this took up to 726. Raising the budget to cover the slow mode would trade a quiet loss of coverage for five configurations approaching the sixty minute step timeout. So ask for what a run can reach. Three windows cost 51 to 120 seconds in the slow mode and under a second in the fast one, and the later hits repeat what the first ones establish, so what is given up is small. The budget goes to 180 seconds because three windows at the worst rate measured is exactly the 120 it was, which would have truncated at two. The count is printed on every run rather than only on a short one. A number that appears only on shortfall cannot be told apart from a number nobody recorded. Reaching the window no times at all is a different matter, and was the worst of the seven. The check after the loop compares semaphore bookkeeping that a window has to have touched to mean anything, so a run that reached none of them compares a counter against the value it was initialised to and reports a pass having verified nothing. That run now keeps trying to a 300 second ceiling, and fails if it still has not reached the window. A genuine resonance that holds for five minutes is worth a failure; the old behaviour was worth nothing. The SMP copy keeps its count of twenty. It reaches them in under half a second in all five of its configurations, in all four runs, so the slow mode has never been observed there and the coverage is free. Both copies get the ceiling and the unconditional report, so the logic stays identical between them. Verified locally on all five configurations: the test reaches 3 of 3 in 5 to 14 seconds, and the full suites pass 96 of 96 and 110 of 110 run one test at a time. With the handler's window made unreachable and the ceiling lowered to 5 seconds, the test stops after 6 seconds, prints the count it reached, and reports ERROR #8 with the harness recording a failure rather than a pass. With the count raised past what the budget allows, a run that reaches two windows still passes, so falling short and reaching nothing stay distinct. The TX_NOT_INTERRUPTABLE branch, which no configuration in either suite builds, was compile-checked in both copies with the configurations' own compile commands. Co-authored-by: Claude Opus 5 (1M context) --- .../threadx_thread_wait_abort_and_isr_test.c | 72 +++++++++++++++--- .../threadx_thread_wait_abort_and_isr_test.c | 73 ++++++++++++++++--- 2 files changed, 124 insertions(+), 21 deletions(-) diff --git a/test/smp/regression/threadx_thread_wait_abort_and_isr_test.c b/test/smp/regression/threadx_thread_wait_abort_and_isr_test.c index 1078e8e1a..c66abff2d 100644 --- a/test/smp/regression/threadx_thread_wait_abort_and_isr_test.c +++ b/test/smp/regression/threadx_thread_wait_abort_and_isr_test.c @@ -191,9 +191,39 @@ UINT status; when the port's timer thread gets to run, so under load, or under coverage instrumentation, ticks fall behind and never catch up. A budget of 20000 ticks, nominally 200 seconds, failed to stop a run that took 726 seconds, - because fewer than 20000 ticks had passed. time() does not drift that way. */ + because fewer than 20000 ticks had passed. time() does not drift that way. + + How many windows to ask for is set by what a run can actually reach. Four CI + runs of the same tree measured this loop in two modes: one where a window + arrives in milliseconds and every window asked for costs under a second in + total, and one where a single window costs around forty seconds. Seven of + twenty configuration-runs landed in the slow mode and ran out of budget, + reaching 0, 3, 3, 3, 4, 7 and 7 of the ten then asked for, every one of them + still reporting a pass. Asking for three keeps the count reachable in both + modes. The later hits repeat what the first ones establish, so the coverage + given up is small, and what is recorded is honest. This copy reaches its + twenty windows in under half a second in all five of its configurations, so + it keeps that count; the non-SMP copy, where the slow mode was measured, asks + for three. + + Reaching the window no times at all is different in kind, which is what the + ceiling below is for. The check after the loop compares semaphore bookkeeping + that a window has to have touched to mean anything, so a pass with a count of + zero claims coverage the run did not have. One of those twenty runs did + exactly that, and said so only in an artifact nobody reads. A run that has not + reached the window once keeps trying up to the ceiling, and fails if it still + has not. + + The budget is 180 seconds rather than 120 because of what the slow mode costs + per window. The seven truncated runs reached their windows at between 17 and + 40 seconds each, so three of them can need 120 seconds, which is exactly what + the old budget allowed and would have truncated at two. 180 leaves margin at + the worst rate measured, and bounds five configurations at 15 minutes against + a 60 minute step timeout. Locally, where a window costs 2 to 5 seconds, three + of them take 5 to 14 seconds and the budget is never approached. */ #define WAIT_ABORT_WINDOWS_WANTED ((ULONG) 20) -#define WAIT_ABORT_SECOND_BUDGET ((ULONG) 120) +#define WAIT_ABORT_SECOND_BUDGET ((ULONG) 180) +#define WAIT_ABORT_ZERO_WINDOW_CEILING ((ULONG) 300) time_t start_wall; @@ -248,24 +278,46 @@ time_t start_wall; } - /* Out of budget? */ + /* Out of budget? A run that has not reached the window even once has + verified nothing yet, so it gets the higher ceiling before giving up. */ +#ifdef TX_NOT_INTERRUPTABLE if (((ULONG) (time(TX_NULL) - start_wall)) > WAIT_ABORT_SECOND_BUDGET) break; +#else + if (condition_count == 0) + { + if (((ULONG) (time(TX_NULL) - start_wall)) > WAIT_ABORT_ZERO_WINDOW_CEILING) + break; + } + else if (((ULONG) (time(TX_NULL) - start_wall)) > WAIT_ABORT_SECOND_BUDGET) + break; +#endif } /* Clear ISR dispatch. */ test_isr_dispatch = TX_NULL; - if (condition_count < WAIT_ABORT_WINDOWS_WANTED) + /* Say what this run reached, on every run and not only a short one. A count + printed only on shortfall cannot be told apart from a count nobody + recorded, and this line is what the CI artifacts carry. Falling short is a + gap in what was exercised rather than a fault in the code under test, so + the check below still runs and still means what it did. */ + printf("(reached %lu of %lu windows in %lu seconds) ", + (ULONG) condition_count, WAIT_ABORT_WINDOWS_WANTED, + (ULONG) (time(TX_NULL) - start_wall)); + +#ifndef TX_NOT_INTERRUPTABLE + + /* Reached it no times? Then the check below compares bookkeeping no window + ever touched, and a pass would report coverage this run did not have. */ + if (condition_count == 0) { - /* Say what this run reached. Falling short is a gap in what was - exercised rather than a fault in the code under test, so the check - below still runs and still means what it did. */ - printf("(reached %lu of %lu windows in %lu seconds) ", - (ULONG) condition_count, WAIT_ABORT_WINDOWS_WANTED, - (ULONG) (time(TX_NULL) - start_wall)); + /* Test error! */ + printf("ERROR #8\n"); + test_control_return(4); } +#endif #ifdef TX_NOT_INTERRUPTABLE /* At this point, check to see if we got all the semaphores! */ diff --git a/test/tx/regression/threadx_thread_wait_abort_and_isr_test.c b/test/tx/regression/threadx_thread_wait_abort_and_isr_test.c index 53c74cbb9..0b1585080 100644 --- a/test/tx/regression/threadx_thread_wait_abort_and_isr_test.c +++ b/test/tx/regression/threadx_thread_wait_abort_and_isr_test.c @@ -190,9 +190,38 @@ UINT status; when the port's timer thread gets to run, so under load, or under coverage instrumentation, ticks fall behind and never catch up. A budget of 20000 ticks, nominally 200 seconds, failed to stop a run that took 726 seconds, - because fewer than 20000 ticks had passed. time() does not drift that way. */ -#define WAIT_ABORT_WINDOWS_WANTED ((ULONG) 10) -#define WAIT_ABORT_SECOND_BUDGET ((ULONG) 120) + because fewer than 20000 ticks had passed. time() does not drift that way. + + How many windows to ask for is set by what a run can actually reach. Four CI + runs of the same tree measured this loop in two modes: one where a window + arrives in milliseconds and every window asked for costs under a second in + total, and one where a single window costs around forty seconds. Seven of + twenty configuration-runs landed in the slow mode and ran out of budget, + reaching 0, 3, 3, 3, 4, 7 and 7 of the ten then asked for, every one of them + still reporting a pass. Asking for three keeps the count reachable in both + modes. The later hits repeat what the first ones establish, so the coverage + given up is small, and what is recorded is honest. The SMP copy asks for + twenty and reaches them in under half a second in all five of its + configurations, so it keeps its count. + + Reaching the window no times at all is different in kind, which is what the + ceiling below is for. The check after the loop compares semaphore bookkeeping + that a window has to have touched to mean anything, so a pass with a count of + zero claims coverage the run did not have. One of those twenty runs did + exactly that, and said so only in an artifact nobody reads. A run that has not + reached the window once keeps trying up to the ceiling, and fails if it still + has not. + + The budget is 180 seconds rather than 120 because of what the slow mode costs + per window. The seven truncated runs reached their windows at between 17 and + 40 seconds each, so three of them can need 120 seconds, which is exactly what + the old budget allowed and would have truncated at two. 180 leaves margin at + the worst rate measured, and bounds five configurations at 15 minutes against + a 60 minute step timeout. Locally, where a window costs 2 to 5 seconds, three + of them take 5 to 14 seconds and the budget is never approached. */ +#define WAIT_ABORT_WINDOWS_WANTED ((ULONG) 3) +#define WAIT_ABORT_SECOND_BUDGET ((ULONG) 180) +#define WAIT_ABORT_ZERO_WINDOW_CEILING ((ULONG) 300) time_t start_wall; @@ -247,24 +276,46 @@ time_t start_wall; } - /* Out of budget? */ + /* Out of budget? A run that has not reached the window even once has + verified nothing yet, so it gets the higher ceiling before giving up. */ +#ifdef TX_NOT_INTERRUPTABLE if (((ULONG) (time(TX_NULL) - start_wall)) > WAIT_ABORT_SECOND_BUDGET) break; +#else + if (condition_count == 0) + { + if (((ULONG) (time(TX_NULL) - start_wall)) > WAIT_ABORT_ZERO_WINDOW_CEILING) + break; + } + else if (((ULONG) (time(TX_NULL) - start_wall)) > WAIT_ABORT_SECOND_BUDGET) + break; +#endif } /* Clear ISR dispatch. */ test_isr_dispatch = TX_NULL; - if (condition_count < WAIT_ABORT_WINDOWS_WANTED) + /* Say what this run reached, on every run and not only a short one. A count + printed only on shortfall cannot be told apart from a count nobody + recorded, and this line is what the CI artifacts carry. Falling short is a + gap in what was exercised rather than a fault in the code under test, so + the check below still runs and still means what it did. */ + printf("(reached %lu of %lu windows in %lu seconds) ", + (ULONG) condition_count, WAIT_ABORT_WINDOWS_WANTED, + (ULONG) (time(TX_NULL) - start_wall)); + +#ifndef TX_NOT_INTERRUPTABLE + + /* Reached it no times? Then the check below compares bookkeeping no window + ever touched, and a pass would report coverage this run did not have. */ + if (condition_count == 0) { - /* Say what this run reached. Falling short is a gap in what was - exercised rather than a fault in the code under test, so the check - below still runs and still means what it did. */ - printf("(reached %lu of %lu windows in %lu seconds) ", - (ULONG) condition_count, WAIT_ABORT_WINDOWS_WANTED, - (ULONG) (time(TX_NULL) - start_wall)); + /* Test error! */ + printf("ERROR #8\n"); + test_control_return(4); } +#endif #ifdef TX_NOT_INTERRUPTABLE /* At this point, check to see if we got all the semaphores! */ From 977e14e776aed933446835c825b18aa4ca521577 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 24 Aug 2026 11:30:19 -0400 Subject: [PATCH 076/181] Ran the regression suites on dev, where the pull requests actually are (#652) The ThreadX, SMP and FreeRTOS-compatibility suites triggered on master only, for both push and pull_request. dev is the integration branch, so these suites gated no pull request that anybody opened: the last dev run of any kind was a manual workflow_dispatch on 2026-08-18. This is the same defect ports_arch_check.yml already carries a comment about, where it cost eight months of ports drifting from ports_arch unnoticed. ci_cortex_m.yml has it too and is handled separately. That 2026-08-18 run failed, which is the reason to check before switching this on rather than after. Two tests failed: threadx_timer_simple_test in the ThreadX suite, with ERROR #28, and threadx_thread_priority_change in the SMP suite, with a timeout. Both were fixed two days later -- the first by running the suites one test at a time (#643), which is what a timer test failing only under parallel load wants, and the second by #647 by name. Verified before this commit rather than assumed: both suites were re-run on this tree, and all 1030 tests pass across all ten build configurations, the ThreadX suite in 34 to 64 seconds per configuration and the SMP suite in 61 to 63. The 2026-08-18 run took 36m19s, of which a single test that has since been given a budget accounted for 439 seconds. No paths filter is added deliberately. The suites build the linux port, so a filter would have to enumerate what cannot affect them, and the failure mode of getting that list wrong is a regression that merges because the filter excluded the file that caused it. The deploy job needs no guard: regression_template.yml already restricts deploy_code_coverage to push and workflow_dispatch, and restricts the coverage PR comment to pull requests from the repository itself, so neither fires for a pull request from a fork. Assisted-by: Claude Opus 5 --- .github/workflows/regression_test.yml | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/.github/workflows/regression_test.yml b/.github/workflows/regression_test.yml index 8fa974743..329f448c5 100644 --- a/.github/workflows/regression_test.yml +++ b/.github/workflows/regression_test.yml @@ -1,13 +1,24 @@ name: regression_test -# Controls when the action will run. Triggers the workflow on push or pull request -# events but only for the master branch +# Runs the ThreadX, SMP and FreeRTOS-compatibility regression suites. +# +# dev is included as well as master, for the same reason ports_arch_check.yml +# names it: dev is the integration branch, so a check that runs only against +# master gates nothing that anybody opens. Until now these suites ran on no +# pull request that anybody actually raised, and the last dev run of any kind +# was a manual workflow_dispatch. +# +# That run, on 2026-08-18, failed two tests: threadx_timer_simple_test in the +# ThreadX suite and threadx_thread_priority_change in the SMP one. Both are +# fixed -- the first by running the suites one test at a time (#643), the +# second by #647 -- and both suites now pass all 1030 tests across all ten +# build configurations. The suites were never the problem; the trigger was. on: workflow_dispatch: push: - branches: [ master ] + branches: [ master, dev ] pull_request: - branches: [ master ] + branches: [ master, dev ] # A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: From 9218bad4bc292a030ce8f4df5c82db2362a6b6c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 24 Aug 2026 13:07:38 -0400 Subject: [PATCH 077/181] Kept the coverage publish on master, where the environment allows it (#654) Running the regression suites on dev (#652) was meant to test the branch the pull requests target. It changed what gets published as well, which was not intended and does not work: the first push to dev after that merge failed with Branch "dev" is not allowed to deploy to github-pages due to environment protection rules. All three suites passed in that run -- tx, smp and freertos. The only failure was deploy / deploy_code_coverage, rejected before it ran, because the github-pages environment restricts deployments to master. The guard goes here rather than in the environment settings, because the environment rule is doing its job. Which branch the published coverage report describes is a deliberate decision, and moving it from master to dev is a change worth making on purpose rather than as a side effect of a trigger fix. Doing so needs the environment setting relaxed as well as this line removed. The per-suite deploy_code_coverage jobs need no guard: tx, smp and freertos all pass skip_deploy: true, and regression_template.yml already restricts that job to push and workflow_dispatch. Only the deploy job, which is the one that publishes, was reaching the environment. Assisted-by: Claude Opus 5 --- .github/workflows/regression_test.yml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/.github/workflows/regression_test.yml b/.github/workflows/regression_test.yml index 329f448c5..2aebd7b41 100644 --- a/.github/workflows/regression_test.yml +++ b/.github/workflows/regression_test.yml @@ -89,6 +89,20 @@ jobs: # skip_deploy: true # skip_coverage: true deploy: + # Publishing the coverage report stays on master. Adding dev to this + # workflow's triggers was meant to run the suites on the branch the pull + # requests target, not to change what gets published -- and the first + # push to dev after that change failed here with 'Branch "dev" is not + # allowed to deploy to github-pages due to environment protection rules', + # while all three suites passed. The github-pages environment restricts + # deployments to master, so the job was rejected before it ran. + # + # Guarding here rather than relaxing the environment rule, because the + # rule is doing its job: it is a deliberate answer to the question of + # which branch the published report describes. Moving that answer to dev + # is a separate decision, and it needs the environment setting changed + # as well as this line removed. + if: github.ref == 'refs/heads/master' permissions: contents: read issues: read From 5a68c9da4b9f8ac726ef93349ab43f6a7a76e4d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 24 Aug 2026 13:42:31 -0400 Subject: [PATCH 078/181] Allowed the Linux toolchain file to accept a compiler override (#656) cmake/linux.cmake set CMAKE_C_COMPILER and CMAKE_CXX_COMPILER unconditionally. CMake reads a toolchain file before it consults CC and CXX, and a plain set() in a toolchain file also takes precedence over -DCMAKE_C_COMPILER, so neither of the two usual ways to pick a compiler had any effect: the tree could only ever be built with whatever /usr/bin/gcc happened to point at. That matters because AGENTS.md names GCC 14 as the project's default compiler on Linux, while distributions still ship an older gcc as the default for some time. Selecting GCC 14 previously meant either editing this file or changing the machine's system-wide default. Both variables now fall back to gcc and g++ only when nothing else has been specified, so the default build is byte-for-byte what it was, while -DCMAKE_C_COMPILER=gcc-14 or CC=gcc-14 now work as expected. The binutils variables in this file are left alone: they are unused on the Linux target, so guarding them would be unrelated churn. Assisted-by: Claude Code (Opus 5) --- cmake/linux.cmake | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/cmake/linux.cmake b/cmake/linux.cmake index 192425c6b..55cd5e003 100644 --- a/cmake/linux.cmake +++ b/cmake/linux.cmake @@ -1,8 +1,25 @@ set(CMAKE_SYSTEM_NAME Linux) set(CMAKE_SYSTEM_PROCESSOR x86_64) -set(CMAKE_C_COMPILER gcc) -set(CMAKE_CXX_COMPILER g++) +# Let the compiler be chosen on the command line or from the environment, for example +# -DCMAKE_C_COMPILER=gcc-14 or CC=gcc-14. CMake reads a toolchain file before it consults +# CC and CXX, so setting these unconditionally would quietly override both and leave no +# way to build with anything but the distribution's default gcc. +if(NOT DEFINED CMAKE_C_COMPILER) + if(DEFINED ENV{CC}) + set(CMAKE_C_COMPILER $ENV{CC}) + else() + set(CMAKE_C_COMPILER gcc) + endif() +endif() + +if(NOT DEFINED CMAKE_CXX_COMPILER) + if(DEFINED ENV{CXX}) + set(CMAKE_CXX_COMPILER $ENV{CXX}) + else() + set(CMAKE_CXX_COMPILER g++) + endif() +endif() set(AS as) set(AR ar) set(OBJCOPY objcopy) From a4397e133a907b2ce0cabe8d7fda4314056f3c8b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 24 Aug 2026 14:47:26 -0400 Subject: [PATCH 079/181] Reconfigured the build when the requested compiler changes (#657) CMake records the compiler it detected inside the build directory and keeps using it on every later configure. Since cmake/linux.cmake began honouring CC, that made a compiler switch silently ineffective: CC=gcc-14 ./run.sh build against an existing build directory printed "ninja: no work to do", exited 0, and left the previous compiler in place. Anyone verifying a change against a second compiler would have been reading stale results while being told the build had succeeded. generate() now compares the compiler recorded in the build directory with the one currently requested, and reconfigures from scratch when they differ. The comparison uses the path as CMake records it, which is the unresolved path as given, so /usr/bin/gcc matches command -v gcc rather than the versioned target its symlink points at. build_libs() gets the same treatment. Only the C compiler is consulted: both trees that use this script declare LANGUAGES C, so no CXX compiler is ever detected. Nothing is reconfigured unless the compiler actually changed, so repeat builds stay incremental and the default path is unchanged. Assisted-by: Claude Code (Opus 5) --- scripts/cmake_bootstrap.sh | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/scripts/cmake_bootstrap.sh b/scripts/cmake_bootstrap.sh index d66d668de..014f44234 100755 --- a/scripts/cmake_bootstrap.sh +++ b/scripts/cmake_bootstrap.sh @@ -31,8 +31,32 @@ function validate() { help } +# CMake records the compiler it detected inside the build directory and keeps using it on +# every later configure. Changing CC would otherwise be ignored without a word: the build +# reports success while still using the compiler the directory was first configured with, +# so anyone verifying a change against a second compiler would be reading stale results. +# Only the C compiler is consulted, because these test trees declare LANGUAGES C. +function compiler_changed() { + local build=$1 + local recorded requested + + [ -d "build/$build" ] || return 1 + + recorded=$(sed -n 's/^set(CMAKE_C_COMPILER "\(.*\)")$/\1/p' build/$build/CMakeFiles/*/CMakeCCompiler.cmake 2>/dev/null | head -1) + [ -n "$recorded" ] || return 1 + + requested=$(command -v "${CC:-gcc}" 2>/dev/null) + [ -n "$requested" ] || return 1 + + [ "$recorded" != "$requested" ] +} + function generate() { build=$1 + if compiler_changed $build; then + echo "Compiler changed since build/$build was configured. Reconfiguring from scratch." + rm -rf build/$build + fi cmake -Bbuild/$build -GNinja -DBUILD_SHARED_LIBS=ON -DCMAKE_TOOLCHAIN_FILE=$(dirname $(realpath $0))/../cmake/linux.cmake -DCMAKE_BUILD_TYPE=$build . } @@ -41,6 +65,10 @@ function build() { } function build_libs() { + if compiler_changed libs; then + echo "Compiler changed since build/libs was configured. Reconfiguring from scratch." + rm -rf build/libs + fi cmake -Bbuild/libs -GNinja -DBUILD_SHARED_LIBS=ON -DCMAKE_TOOLCHAIN_FILE=$(dirname $(realpath $0))/../cmake/linux.cmake libs cmake --build build/libs } From eabdb86409f43d50c6ae823566a83ab41c039050 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 24 Aug 2026 15:55:18 -0400 Subject: [PATCH 080/181] Matched gcov to the compiler that produced the coverage data (#658) gcov reads a data format tied to the compiler that produced it. coverage.sh took whatever gcov was first on PATH, which was fine while the compiler was also whatever was first on PATH. #656 made cmake/linux.cmake honour CC and #657 made a compiler switch actually reconfigure the build, so that assumption no longer holds, and the first person to use the new capability would have hit this. Measured on dev with both of those merged: CC=gcc-14 ./run.sh build default_build_coverage # succeeds ./coverage.sh default_build_coverage # exit 64 gcov says why, if asked directly: tx_block_allocate.c.gcno:version 'B42*', prefer 'B33*' gcovr turns that into "GCOV returncode was 3" and exits 64 through a Python traceback, after the tests have already passed. It reads like a coverage bug rather than a toolchain mismatch, which is the part that would have cost someone an afternoon. gcov is now derived from CC rather than found on PATH, so the caller sets one variable instead of remembering two. GCOV still overrides, for a toolchain that does not follow the gcc/gcov naming, and a derived gcov that does not exist is reported as such instead of surfacing as a traceback. Verified, tx and smp, before and after: CC=gcc-14 was exit 64, now exit 0, 177 files and 1527/3827 lines CC unset exit 0, 177 files and 1527/3827 lines, unchanged CC=gcc-99 exit 1 naming gcov-99 and CC, rather than a traceback GCOV=gcov-14 with CC=gcc-99, exit 0, so the override still wins A mismatched pairing still fails, deliberately: reading a gcc-14 tree with the default gcc-13 gcov is exit 64 as before. Producing a number from mismatched data would be worse than refusing. Assisted-by: Claude Opus 5 --- test/smp/cmake/coverage.sh | 30 ++++++++++++++++++++++++++++-- test/tx/cmake/coverage.sh | 30 ++++++++++++++++++++++++++++-- 2 files changed, 56 insertions(+), 4 deletions(-) diff --git a/test/smp/cmake/coverage.sh b/test/smp/cmake/coverage.sh index d35284f57..a7312e1f4 100755 --- a/test/smp/cmake/coverage.sh +++ b/test/smp/cmake/coverage.sh @@ -16,5 +16,31 @@ set -e cd $(dirname $0) threadx_smp=$(realpath ../../../common_smp/src) mkdir -p coverage_report/$1 -gcovr --object-directory=build/$1/threadx_smp/CMakeFiles/threadx_smp.dir/$threadx_smp -r build/$1 -f ../../../common_smp/src --xml-pretty --output coverage_report/$1.xml -gcovr --object-directory=build/$1/threadx_smp/CMakeFiles/threadx_smp.dir/$threadx_smp -r build/$1 -f ../../../common_smp/src --html --html-details --output coverage_report/$1/index.html + +# gcov reads a data format tied to the compiler that produced it, so gcov has to match +# the gcc that built the objects. Since cmake/linux.cmake began honouring CC, taking +# whatever gcov happens to be first on PATH is no longer safe: building with gcc-14 and +# reading with gcov-13 gives "version 'B42*', prefer 'B33*'" from gcov, and gcovr turns +# that into "GCOV returncode was 3" and exits 64. The tests pass and then the coverage +# step fails with a Python traceback, which reads like a coverage bug rather than a +# toolchain mismatch. +# +# So derive gcov from CC rather than asking the caller to remember both. GCOV still +# overrides, for a toolchain that does not follow the gcc/gcov naming. +: "${CC:=gcc}" +if [ -z "${GCOV:-}" ]; then + cc_base=$(basename "$CC") + case "$cc_base" in + gcc*) GCOV="gcov${cc_base#gcc}" ;; + *) GCOV="gcov" ;; + esac +fi + +if ! command -v "$GCOV" >/dev/null 2>&1; then + echo "coverage.sh: '$GCOV' not found, derived from CC='$CC'." >&2 + echo "Install it, or set GCOV to the gcov matching that compiler." >&2 + exit 1 +fi + +gcovr --gcov-executable "$GCOV" --object-directory=build/$1/threadx_smp/CMakeFiles/threadx_smp.dir/$threadx_smp -r build/$1 -f ../../../common_smp/src --xml-pretty --output coverage_report/$1.xml +gcovr --gcov-executable "$GCOV" --object-directory=build/$1/threadx_smp/CMakeFiles/threadx_smp.dir/$threadx_smp -r build/$1 -f ../../../common_smp/src --html --html-details --output coverage_report/$1/index.html diff --git a/test/tx/cmake/coverage.sh b/test/tx/cmake/coverage.sh index 6dda78b38..9b47339e8 100755 --- a/test/tx/cmake/coverage.sh +++ b/test/tx/cmake/coverage.sh @@ -15,5 +15,31 @@ set -e cd $(dirname $0) mkdir -p coverage_report/$1 -gcovr --object-directory=build/$1/threadx/CMakeFiles/threadx.dir/common/src -r build/$1 -f ../../../common/src --xml-pretty --output coverage_report/$1.xml -gcovr --object-directory=build/$1/threadx/CMakeFiles/threadx.dir/common/src -r build/$1 -f ../../../common/src --html --html-details --output coverage_report/$1/index.html + +# gcov reads a data format tied to the compiler that produced it, so gcov has to match +# the gcc that built the objects. Since cmake/linux.cmake began honouring CC, taking +# whatever gcov happens to be first on PATH is no longer safe: building with gcc-14 and +# reading with gcov-13 gives "version 'B42*', prefer 'B33*'" from gcov, and gcovr turns +# that into "GCOV returncode was 3" and exits 64. The tests pass and then the coverage +# step fails with a Python traceback, which reads like a coverage bug rather than a +# toolchain mismatch. +# +# So derive gcov from CC rather than asking the caller to remember both. GCOV still +# overrides, for a toolchain that does not follow the gcc/gcov naming. +: "${CC:=gcc}" +if [ -z "${GCOV:-}" ]; then + cc_base=$(basename "$CC") + case "$cc_base" in + gcc*) GCOV="gcov${cc_base#gcc}" ;; + *) GCOV="gcov" ;; + esac +fi + +if ! command -v "$GCOV" >/dev/null 2>&1; then + echo "coverage.sh: '$GCOV' not found, derived from CC='$CC'." >&2 + echo "Install it, or set GCOV to the gcov matching that compiler." >&2 + exit 1 +fi + +gcovr --gcov-executable "$GCOV" --object-directory=build/$1/threadx/CMakeFiles/threadx.dir/common/src -r build/$1 -f ../../../common/src --xml-pretty --output coverage_report/$1.xml +gcovr --gcov-executable "$GCOV" --object-directory=build/$1/threadx/CMakeFiles/threadx.dir/common/src -r build/$1 -f ../../../common/src --html --html-details --output coverage_report/$1/index.html From adc6469b91f36892288a61ff9e46bf483ce486bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 24 Aug 2026 16:31:21 -0400 Subject: [PATCH 081/181] Published the coverage report instead of everything the run produced (#655) The download step in deploy_code_coverage asked for the artifact named ${{ steps.artifact.outputs.coverage_report }}. That output is set by the "Coverage Report name" step of run_tests, which is a different job, and the steps context does not cross jobs. So the expression evaluated to the empty string and the action took its documented path for an unspecified name: No input name, artifact-ids or pattern filtered specified, downloading all artifacts Total of 4 artifact(s) downloaded The four are the two coverage reports and the two test_reports bundles of JUnit XML, each extracted into a directory named after the artifact. The next step uploads the lot to Pages, so the published site has carried the test reports alongside the coverage, one directory deeper than intended, under a path containing a run timestamp that changed on every publish. Any link to a coverage report broke the next time one was published. Selecting by pattern with merge-multiple fixes both halves: the pattern excludes the test_reports bundles, and merging puts the contents of the two coverage artifacts directly into coverage_report rather than under a directory named for each. Each artifact holds one directory named for its suite, renamed from default_build_coverage by "Prepare Coverage GitHub Pages", so the result is the two suite directories the deploy expects and the timestamped artifact name no longer appears in the published path. Verified on a runner rather than reasoned about, with an isolated workflow that uploads artifacts shaped like the real ones and downloads them both ways: OLD coverage_report/coverage_report--ThreadX/ThreadX/index.html coverage_report/coverage_report--ThreadX/default_build_coverage.xml coverage_report/coverage_report--SMP/SMP/index.html coverage_report/coverage_report--SMP/default_build_coverage.xml coverage_report/test_reports SMP/results.xml coverage_report/test_reports ThreadX/results.xml NEW coverage_report/ThreadX/index.html coverage_report/SMP/index.html coverage_report/default_build_coverage.xml Both artifacts carry a default_build_coverage.xml and the merge means one overwrites the other, which the run above also shows. That file is consumed by CodeCoverageSummary back in run_tests and is not read here, so it is untidy rather than wrong, and it is called out in a comment. The delete step is fixed in the same place and for a related reason. The artifacts are named coverage_report-, useGlob defaults to true in this action, and as a glob "coverage_report" matches only the literal string. It has been deleting nothing, without failing, and retention-days: 1 on the upload is what has actually been clearing these up. Assisted-by: Claude Opus 5 --- .github/workflows/regression_template.yml | 37 +++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/.github/workflows/regression_template.yml b/.github/workflows/regression_template.yml index 4f73cdd01..7f9f496f1 100644 --- a/.github/workflows/regression_template.yml +++ b/.github/workflows/regression_template.yml @@ -178,10 +178,37 @@ jobs: id-token: write steps: + # Selects the coverage artifacts by pattern rather than by name. + # + # This used to ask for ${{ steps.artifact.outputs.coverage_report }}, + # which is set by the "Coverage Report name" step of run_tests -- a + # different job. The steps context does not cross jobs, so that + # expression evaluated to the empty string and the action fell back to + # its documented behaviour for an unspecified name: "No input name, + # artifact-ids or pattern filtered specified, downloading all + # artifacts". It pulled down four, the two coverage reports and the two + # test_reports bundles of JUnit XML, each into a directory named after + # the artifact -- so the published site carried the test reports as well + # as the coverage, under paths containing a run timestamp that changed + # on every publish. + # + # merge-multiple puts the contents of both coverage artifacts directly + # into coverage_report rather than under a directory named for each + # artifact. Each one holds a single directory named for its suite, + # ThreadX or SMP, renamed from default_build_coverage by the "Prepare + # Coverage GitHub Pages" step, so the merge yields exactly the two + # suite directories the deploy expects, and the artifact name -- with + # its timestamp -- stops appearing in the published path at all. + # + # The two artifacts also each carry a default_build_coverage.xml, and + # the merge means one overwrites the other. That file is consumed by + # CodeCoverageSummary back in run_tests and is not read here, so this is + # untidy rather than wrong. - uses: actions/download-artifact@v4.3.0 if: ${{ inputs.skip_test }} with: - name: ${{ steps.artifact.outputs.coverage_report }} + pattern: coverage_report-* + merge-multiple: true path: ${{ inputs.cmake_path }}/coverage_report - name: Upload Code Coverage Pages @@ -190,10 +217,16 @@ jobs: with: path: . + # The artifacts are named coverage_report- by run_tests, so the + # bare name matched nothing: useGlob defaults to true in this action, and + # as a glob "coverage_report" matches only the literal string. The step + # has therefore been deleting nothing. It does not fail on a miss, which + # is why that went unnoticed; retention-days: 1 on the upload is what has + # actually been clearing these up. - name: Delete Duplicate Code Coverage Artifact uses: geekyeggo/delete-artifact@v5.1.0 with: - name: coverage_report + name: coverage_report-* - name: Deploy GitHub Pages site id: deployment From 7959aef3bc39c7ffc49fa47e00575aa6c697c273 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 24 Aug 2026 16:36:18 -0400 Subject: [PATCH 082/181] Kept the coverage report from the runs that most need one (#659) A failing test threw away coverage that had already been collected, and the run whose behaviour changed is exactly the run whose coverage is worth reading. Measured on the failing run of 2026-08-18: it uploaded test_reports for all three suites and no coverage_report artifact at all. Two causes, and the workflow one is the smaller of them. cmake_bootstrap.sh runs under set -e, so a failing ctest aborted test() before ./coverage.sh was reached. The gcda files exist by that point, so nothing was missing except the step that reads them. ctest's status is now captured and returned at the end, and the summary grep is allowed to fail rather than being the thing that stops the coverage behind it. The serial branch of the test dispatch collected no status either, so under set -e the first failing configuration stopped the remaining four from being tested at all -- and their coverage from being collected. That was cheap while the suites ran in parallel, because the parallel branch already collects exit codes from its background jobs. Moving to serial execution in #643 quietly made one failure cost the other four configurations. The serial branch now collects status the same way the parallel branch does. With those fixed the report exists, so the workflow steps that publish it no longer skip on failure. They are guarded with !cancelled() rather than always(), so a cancelled run still stops promptly, which is the idiom deploy_code_coverage already uses. The ${{ }} wrapping is required and not decoration: a bare ! opens a YAML tag, and the file will not parse without it. Verified locally by replacing one test binary with a stub that exits 1: before the failing run of 2026-08-18 produced no coverage_report artifact after run.sh test default_build_coverage exits 8, and produces coverage_report/default_build_coverage.xml with 177 files and 3804 of 3827 lines after run.sh test all exits 8, and all five configurations run rather than stopping at the first The failure still fails. Only the reporting around it changed. Assisted-by: Claude Opus 5 --- .github/workflows/regression_template.yml | 23 +++++++++++++------- scripts/cmake_bootstrap.sh | 26 +++++++++++++++++++---- 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/.github/workflows/regression_template.yml b/.github/workflows/regression_template.yml index 7f9f496f1..27666ae7d 100644 --- a/.github/workflows/regression_template.yml +++ b/.github/workflows/regression_template.yml @@ -104,8 +104,15 @@ jobs: - name: Configure GitHub Pages uses: actions/configure-pages@v5.0.0 + # The coverage steps below run even when a test failed. cmake_bootstrap.sh + # now produces the report in that case, and the run whose behaviour changed + # is the one whose coverage is worth reading; previously a single flaky test + # suppressed the report for the whole run. !cancelled() rather than always(), + # so a cancelled run still stops promptly -- the same idiom the + # deploy_code_coverage job below already uses. The ${{ }} is required: a bare + # ! opens a YAML tag, and the expression will not parse without it. - name: Generate Code Coverage Results Summary - if: (!inputs.skip_coverage) + if: ${{ !cancelled() && (!inputs.skip_coverage) }} uses: irongut/CodeCoverageSummary@v1.3.0 with: filename: ${{ inputs.cmake_path }}/coverage_report/${{ inputs.coverage_name }}.xml @@ -115,13 +122,13 @@ jobs: output: file - name: Write Code Coverage Summary - if: (!inputs.skip_coverage) + if: ${{ !cancelled() && (!inputs.skip_coverage) }} run: | echo "## Coverage Report ${{ inputs.result_affix }}" >> $GITHUB_STEP_SUMMARY cat code-coverage-results.md >> $GITHUB_STEP_SUMMARY - name: Create CheckRun for Code Coverage - if: ((github.event_name == 'push') || (github.event_name == 'workflow_dispatch') || (github.event.pull_request.head.repo.full_name == github.repository)) && (!inputs.skip_coverage) + if: ${{ !cancelled() && ((github.event_name == 'push') || (github.event_name == 'workflow_dispatch') || (github.event.pull_request.head.repo.full_name == github.repository)) && (!inputs.skip_coverage) }} uses: LouisBrunner/checks-action@v2.0.0 with: token: ${{ secrets.GITHUB_TOKEN }} @@ -132,7 +139,7 @@ jobs: output_text_description_file: code-coverage-results.md - name: Add Code Coverage PR Comment - if: ((github.event_name == 'push') || (github.event.pull_request.head.repo.full_name == github.repository)) && (!inputs.skip_coverage) + if: ${{ !cancelled() && ((github.event_name == 'push') || (github.event.pull_request.head.repo.full_name == github.repository)) && (!inputs.skip_coverage) }} uses: marocchino/sticky-pull-request-comment@v2.9.4 with: header: Code Coverage ${{ inputs.result_affix }} @@ -140,7 +147,7 @@ jobs: # Add sudo to move coverage folder created by root user - name: Prepare Coverage GitHub Pages - if: (!inputs.skip_coverage) + if: ${{ !cancelled() && (!inputs.skip_coverage) }} run: >- if [ "${{ inputs.result_affix }}" != "" ] && ${{ inputs.skip_deploy }}; then sudo mv ${{ inputs.cmake_path }}/coverage_report/${{ inputs.coverage_name }} \ @@ -149,12 +156,12 @@ jobs: - name: Coverage Report name id: artifact - if: (!inputs.skip_coverage) + if: ${{ !cancelled() && (!inputs.skip_coverage) }} run: echo "coverage_report=coverage_report-$(date +%s)" >> $GITHUB_OUTPUT - name: Upload Code Coverage Artifacts uses: actions/upload-artifact@v4.6.2 - if: (inputs.skip_deploy && !inputs.skip_coverage) + if: ${{ !cancelled() && (inputs.skip_deploy && !inputs.skip_coverage) }} with: name: ${{ steps.artifact.outputs.coverage_report }} path: ${{ inputs.cmake_path }}/coverage_report @@ -162,7 +169,7 @@ jobs: - name: Upload Code Coverage Pages uses: actions/upload-pages-artifact@v3.0.1 - if: (!inputs.skip_deploy && !inputs.skip_coverage) + if: ${{ !cancelled() && (!inputs.skip_deploy && !inputs.skip_coverage) }} with: path: ${{ inputs.cmake_path }}/coverage_report/${{ inputs.coverage_name }} diff --git a/scripts/cmake_bootstrap.sh b/scripts/cmake_bootstrap.sh index 014f44234..faa43133f 100755 --- a/scripts/cmake_bootstrap.sh +++ b/scripts/cmake_bootstrap.sh @@ -82,13 +82,24 @@ function test() { else repeat_fail=${CTEST_REPEAT_FAIL} fi - ctest $parallel --timeout 1000 -O $1.txt -T test --no-compress-output --test-output-size-passed 4194304 --test-output-size-failed 4194304 --output-on-failure --repeat until-pass:${repeat_fail} --output-junit $1.xml + # ctest's status is captured rather than allowed to abort the function, and + # returned at the end. set -e would otherwise stop here on the first failing + # test, and everything below would be skipped -- including coverage.sh. The + # gcda files exist by that point, so a failing run threw away coverage it had + # already collected, and the run whose behaviour changed is exactly the one + # whose coverage is worth reading. Measured: the failing run of 2026-08-18 + # produced test_reports artifacts and no coverage_report artifact at all. + local status=0 + ctest $parallel --timeout 1000 -O $1.txt -T test --no-compress-output --test-output-size-passed 4194304 --test-output-size-failed 4194304 --output-on-failure --repeat until-pass:${repeat_fail} --output-junit $1.xml || status=$? popd - grep -E "^(\s*[0-9]+|Total)" build/$1/$1.txt >build/$1.txt + # Tolerated because this is a summary for humans, and a ctest that died early + # enough to leave no matching line must not be what stops the coverage below. + grep -E "^(\s*[0-9]+|Total)" build/$1/$1.txt >build/$1.txt || true sed -i "s/\x1B\[[0-9;]*[JKmsu]//g" build/$1.txt if [[ $1 = *"_coverage" ]]; then ./coverage.sh $1 fi + return $status } cd $(dirname $0) @@ -146,11 +157,18 @@ elif [ "$command" == "test" ]; then done exit $exit_code else - # Run builds in serial + # Run builds in serial. The status is collected the same way the parallel + # branch above collects it, so one failing configuration no longer stops + # the remaining ones from being tested. That mattered more after the + # suites moved to serial execution: a failure in the first configuration + # meant the other four never ran, and their coverage was never collected + # either. + exit_code=0 for item in $builds; do echo "Testing $item" - test $item $parallel_jobs + test $item $parallel_jobs || exit_code=$? done + exit $exit_code fi elif [ "$command" == "build_libs" ]; then build_libs From 042049a7b2d514b11027bc3c5714c4952966cb00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 24 Aug 2026 16:38:24 -0400 Subject: [PATCH 083/181] Revived the Cortex-M build, which had compiled nothing since June (#653) Two defects, and the second hid the first. This workflow triggered on master only, for both push and pull_request, while dev is the integration branch. So it gated no pull request that anybody opened. That is the same defect ports_arch_check.yml carries a comment about, where it cost eight months of ports drifting from ports_arch unnoticed, and regression_test.yml has it too. And it had not compiled anything since at least 2026-06-08. Every run since then failed in six to eight seconds at "Prepare all required actions", before checkout, because GitHub automatically fails any request that uses actions/cache@v1. The last run of any kind was 2026-06-30. A workflow that fails in seven seconds is normally noticed within the day; this one was not, because of the first defect. The two together meant the project's only job that cross-compiles a port with GCC had been reporting nothing at all. The toolchain now follows clang_check.yml rather than third party actions: a pinned release fetched directly from Arm, verified against the published sha256asc, and cached with actions/cache@v4. That also moves the compiler off 9-2019-q4, a 2019 release, onto a version matching the GCC 14 default this project states. The ninja install is guarded on ninja being absent rather than run unconditionally, because scripts/install.sh already carries a long comment about apt-get update stalling for over two hours and taking a whole regression run with it. fail-fast is off so that one port failing still reports the other three. Verified before committing, with the pinned 14.3.rel1 toolchain: the download and sha256sum -c sequence in the install step was run as written, the archive extracts to the directory the PATH step expects, and all four ports configure and build clean with zero warnings. This covers four ports of the forty under ports/ that have a gnu directory. Widening it to every Arm gnu port is separate work. Assisted-by: Claude Opus 5 --- .github/workflows/ci_cortex_m.yml | 102 ++++++++++++++++++++---------- 1 file changed, 67 insertions(+), 35 deletions(-) diff --git a/.github/workflows/ci_cortex_m.yml b/.github/workflows/ci_cortex_m.yml index a207ab1be..ab7cc7923 100644 --- a/.github/workflows/ci_cortex_m.yml +++ b/.github/workflows/ci_cortex_m.yml @@ -1,14 +1,31 @@ -# This is a basic workflow to help you get started with Actions - name: cortex_m -# Controls when the action will run. Triggers the workflow on push or pull request -# events but only for the master branch +# Cross-compiles the Cortex-M ports with GCC. +# +# Two things were wrong with this workflow and both are fixed here. +# +# It ran on master only, for both push and pull_request, while dev is the +# integration branch -- the same defect ports_arch_check.yml carries a comment +# about, where it cost eight months of ports drifting unnoticed. So this +# gated no pull request that anybody opened. +# +# And it had not compiled anything since at least 2026-06-08. Every run since +# then failed in six to eight seconds, at "Prepare all required actions", +# before checkout: GitHub automatically fails any request using +# actions/cache@v1. Nobody noticed, because of the first defect. +# +# The toolchain setup now follows clang_check.yml rather than third party +# actions: a pinned release fetched directly, verified against Arm's published +# checksum, and cached with actions/cache@v4. That also moves the compiler +# from 9-2019-q4 to a version matching the project's stated GCC 14 default. +# +# This covers four ports of the forty under ports/ that have a gnu directory. +# Widening that to every Arm gnu port is separate work. on: push: - branches: [ master ] + branches: [ master, dev ] pull_request: - branches: [ master ] + branches: [ master, dev ] paths: - ".github/workflows/ci_cortex_m.yml" - 'common/**' @@ -18,60 +35,75 @@ on: - 'ports/cortex_m4/gnu/**' - 'ports/cortex_m7/gnu/**' -# A workflow run is made up of one or more jobs that can run sequentially or in parallel jobs: - # This workflow contains a single job called "build" build: - # The type of runner that the job will run on runs-on: ubuntu-24.04 strategy: + fail-fast: false matrix: port: [0, 3, 4, 7] name: Cortex M${{ matrix.port }} build - # Steps represent a sequence of tasks that will be executed as part of the job + env: + # Pinned deliberately, as the runner image is: a toolchain upgrade should + # be a reviewable commit rather than something that changes underneath the + # ports. Releases: https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads + GCC_VERSION: 14.3.rel1 + GCC_TARGET: arm-none-eabi + steps: - # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it - name: Check out the repository uses: actions/checkout@v4 with: submodules: true - # Store the arm compilers in the cache to speed up builds - - name: Cache arm-none-eabi-gcc tools + - name: Cache the Arm GNU toolchain id: cache-arm-gcc - uses: actions/cache@v1 + uses: actions/cache@v4 with: - path: $HOME/arm-none-eabi-gcc-9-2019-q4 - key: ${{ runner.os }}-arm-gcc-9-2019-q4 + path: toolchain + key: arm-gnu-toolchain-${{ env.GCC_VERSION }}-x86_64-${{ env.GCC_TARGET }} - # Get the arm-non-eabi-gcc toolchain - - name: Install arm-none-eabi-gcc - uses: fiam/arm-none-eabi-gcc@v1 + - name: Install the Arm GNU toolchain if: steps.cache-arm-gcc.outputs.cache-hit != 'true' - with: - release: '9-2019-q4' # The arm-none-eabi-gcc release to use. - directory: $HOME/arm-none-eabi-gcc-9-2019-q4 + run: | + set -eu + base="https://developer.arm.com/-/media/Files/downloads/gnu/${GCC_VERSION}/binrel" + archive="arm-gnu-toolchain-${GCC_VERSION}-x86_64-${GCC_TARGET}.tar.xz" + mkdir -p toolchain && cd toolchain + curl -fsSLO "$base/$archive" + curl -fsSLO "$base/$archive.sha256asc" + sha256sum -c "$archive.sha256asc" + tar xf "$archive" + rm -f "$archive" - # Get CMake into the environment - - name: Install cmake 3.19.1 - uses: lukka/get-cmake@v3.19.1 + - name: Put the toolchain on PATH + run: | + set -eu + echo "$GITHUB_WORKSPACE/toolchain/arm-gnu-toolchain-${GCC_VERSION}-x86_64-${GCC_TARGET}/bin" >> "$GITHUB_PATH" - # Get Ninja into the environment - - name: Install ninja-build - uses: seanmiddleditch/gha-setup-ninja@v3 + # Only reaches apt if the runner image has stopped shipping ninja. This + # repository has already paid for unguarded apt calls: scripts/install.sh + # carries a long comment about apt-get update stalling for over two hours + # and taking whole regression runs with it. Do not turn this into an + # unconditional install. + - name: Ensure ninja is available + run: | + set -eu + if command -v ninja >/dev/null 2>&1; then + ninja --version + else + sudo apt-get update + sudo apt-get install -y --no-install-recommends ninja-build + fi + + - name: Report the toolchain version + run: ${{ env.GCC_TARGET }}-gcc --version - # Prepare the build system - name: Prepare build system run: cmake -Bbuild -DCMAKE_TOOLCHAIN_FILE=./cmake/cortex_m${{ matrix.port }}.cmake -GNinja . - env: - PATH: "$HOME/arm-none-eabi-gcc-9-2019-q4/bin:$PATH" - name: Compile and link run: cmake --build ./build - env: - PATH: "$HOME/arm-none-eabi-gcc-9-2019-q4/bin:$PATH" - - From 3d852eb4514733ecee026fa836ee72a621ad9e87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Tue, 25 Aug 2026 15:52:49 -0400 Subject: [PATCH 084/181] Pinned every action to a commit SHA, and moved them off Node 20 (#660) Node 20 is removed from the GitHub runners on 16 September 2026. Every run in this repository currently emits the deprecation warning for it, naming actions/checkout, actions/configure-pages, actions/upload-artifact, LouisBrunner/checks-action and marocchino/sticky-pull-request-comment among others. After that date those actions stop working rather than warning, so this is a deadline and not housekeeping. Every action is now referenced by a 40-character commit SHA with the version in a trailing comment. A tag can be repointed at any commit; a SHA cannot, so this is what makes "which code ran in our CI" answerable from the repository rather than from whatever the tag meant at the time. The versions were behind by as much as four majors -- download-artifact was on v4.3.0 against v8.0.1 -- because nothing in this repository has ever reported that an action moved. Compatibility was checked against each new action.yml rather than assumed, for every input this repository actually passes: checkout submodules is unchanged cache path and key are unchanged upload-artifact name, path and retention-days are unchanged download-artifact pattern, merge-multiple and path are unchanged configure-pages takes no input here, and none became required deploy-pages still exposes page_url, which the job reads upload-pages-art. path is unchanged checks-action token, name, conclusion, output and output_text_description_file all survive v2 to v3 sticky-comment header and path survive v2 to v3, and the new GITHUB_TOKEN input defaults to github.token, which is what v2 used implicitly delete-artifact name survives v5 to v6, and useGlob still defaults to true, so the coverage_report-* glob from #655 still matches CodeCoverageSummary already current at v1.3.0; pinned, not moved The artifact pair moves together, as it must. The round trip was verified on a runner before this commit: upload-artifact v7 to download-artifact v8, through the pattern and merge-multiple selection #655 introduced, filtered 4 artifacts to 2 and produced exactly the tree the deploy expects. Two behaviour changes worth knowing. download-artifact v8 adds a digest-mismatch input defaulting to error, so a corrupted artifact now fails the job instead of passing through -- the right default, but a change. upload-artifact v6 and above require a runner of at least 2.327.1, which the hosted runners satisfy and a self-hosted runner would need checking for. Assisted-by: Claude Opus 5 --- .github/workflows/ci_cortex_m.yml | 8 ++++-- .github/workflows/clang_check.yml | 8 ++++-- .github/workflows/ports_arch_check.yml | 8 ++++-- .github/workflows/regression_template.yml | 30 +++++++++++++---------- 4 files changed, 35 insertions(+), 19 deletions(-) diff --git a/.github/workflows/ci_cortex_m.yml b/.github/workflows/ci_cortex_m.yml index ab7cc7923..933c950fb 100644 --- a/.github/workflows/ci_cortex_m.yml +++ b/.github/workflows/ci_cortex_m.yml @@ -54,14 +54,18 @@ jobs: GCC_TARGET: arm-none-eabi steps: + # Actions are pinned to a commit SHA, with the version in the trailing + # comment. A tag can be moved; a SHA cannot, so this is what makes "which + # code ran in CI" answerable from the repository. Dependabot moves these + # pins and rewrites the comment with them -- see .github/dependabot.yml. - name: Check out the repository - uses: actions/checkout@v4 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: submodules: true - name: Cache the Arm GNU toolchain id: cache-arm-gcc - uses: actions/cache@v4 + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: path: toolchain key: arm-gnu-toolchain-${{ env.GCC_VERSION }}-x86_64-${{ env.GCC_TARGET }} diff --git a/.github/workflows/clang_check.yml b/.github/workflows/clang_check.yml index e791f82e9..405033f0b 100644 --- a/.github/workflows/clang_check.yml +++ b/.github/workflows/clang_check.yml @@ -27,12 +27,16 @@ jobs: ATFE_VERSION: 22.1.0 steps: + # Actions are pinned to a commit SHA, with the version in the trailing + # comment. A tag can be moved; a SHA cannot, so this is what makes "which + # code ran in CI" answerable from the repository. Dependabot moves these + # pins and rewrites the comment with them -- see .github/dependabot.yml. - name: Checkout sources - uses: actions/checkout@v4 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Cache Arm Toolchain for Embedded id: cache-atfe - uses: actions/cache@v4 + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 with: path: atfe key: atfe-${{ env.ATFE_VERSION }}-linux-x86_64 diff --git a/.github/workflows/ports_arch_check.yml b/.github/workflows/ports_arch_check.yml index 589ef372c..334a53864 100644 --- a/.github/workflows/ports_arch_check.yml +++ b/.github/workflows/ports_arch_check.yml @@ -35,8 +35,12 @@ jobs: # supplied: token" and the check never evaluated anything. The default # GITHUB_TOKEN is enough to check out a public repository, and the # repository has no submodules. + # Actions are pinned to a commit SHA, with the version in the trailing + # comment. A tag can be moved; a SHA cannot, so this is what makes "which + # code ran in CI" answerable from the repository. Dependabot moves these + # pins and rewrites the comment with them -- see .github/dependabot.yml. - name: Checkout sources - uses: actions/checkout@v4 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 # Check the port trees: the generated ports must be reproducible from # ports_arch, and no port header may be left unbalanced or carrying code @@ -60,7 +64,7 @@ jobs: # GITHUB_TOKEN is enough to check out a public repository, and the # repository has no submodules. - name: Checkout sources - uses: actions/checkout@v4 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 # Regenerate the A profile ports and fail if anything changed, which means # a generated port was edited directly instead of ports_arch. diff --git a/.github/workflows/regression_template.yml b/.github/workflows/regression_template.yml index 27666ae7d..62a28e937 100644 --- a/.github/workflows/regression_template.yml +++ b/.github/workflows/regression_template.yml @@ -62,8 +62,12 @@ jobs: # Steps represent a sequence of tasks that will be executed as part of the job steps: + # Actions are pinned to a commit SHA, with the version in the trailing + # comment. A tag can be moved; a SHA cannot, so this is what makes "which + # code ran in CI" answerable from the repository. Dependabot moves these + # pins and rewrites the comment with them -- see .github/dependabot.yml. - name: Check out the repository - uses: actions/checkout@v4.2.2 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: submodules: true @@ -84,7 +88,7 @@ jobs: run: ${{ inputs.test_script }} - name: Publish Test Results - uses: EnricoMi/publish-unit-test-result-action@v2.11.0 + uses: EnricoMi/publish-unit-test-result-action@d0a4676d0e0b938bc201470d88276b7c74c712b3 # v2.24.0 if: always() with: check_name: Test Results ${{ inputs.result_affix }} @@ -93,7 +97,7 @@ jobs: - name: Upload Test Results if: success() || failure() - uses: actions/upload-artifact@v4.6.2 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 with: name: test_reports ${{ inputs.result_affix }} path: | @@ -102,7 +106,7 @@ jobs: ${{ inputs.cmake_path }}/build/**/regression/output_files/*.bin - name: Configure GitHub Pages - uses: actions/configure-pages@v5.0.0 + uses: actions/configure-pages@45bfe0192ca1faeb007ade9deae92b16b8254a0d # v6.0.0 # The coverage steps below run even when a test failed. cmake_bootstrap.sh # now produces the report in that case, and the run whose behaviour changed @@ -113,7 +117,7 @@ jobs: # ! opens a YAML tag, and the expression will not parse without it. - name: Generate Code Coverage Results Summary if: ${{ !cancelled() && (!inputs.skip_coverage) }} - uses: irongut/CodeCoverageSummary@v1.3.0 + uses: irongut/CodeCoverageSummary@51cc3a756ddcd398d447c044c02cb6aa83fdae95 # v1.3.0 with: filename: ${{ inputs.cmake_path }}/coverage_report/${{ inputs.coverage_name }}.xml format: markdown @@ -129,7 +133,7 @@ jobs: - name: Create CheckRun for Code Coverage if: ${{ !cancelled() && ((github.event_name == 'push') || (github.event_name == 'workflow_dispatch') || (github.event.pull_request.head.repo.full_name == github.repository)) && (!inputs.skip_coverage) }} - uses: LouisBrunner/checks-action@v2.0.0 + uses: LouisBrunner/checks-action@937cbbcde3259005b50746dc91cde29098aac2ff # v3.1.0 with: token: ${{ secrets.GITHUB_TOKEN }} name: Code Coverage ${{ inputs.result_affix }} @@ -140,7 +144,7 @@ jobs: - name: Add Code Coverage PR Comment if: ${{ !cancelled() && ((github.event_name == 'push') || (github.event.pull_request.head.repo.full_name == github.repository)) && (!inputs.skip_coverage) }} - uses: marocchino/sticky-pull-request-comment@v2.9.4 + uses: marocchino/sticky-pull-request-comment@5770ad5eb8f42dd2c4f34da00c94c5381e49af88 # v3.0.5 with: header: Code Coverage ${{ inputs.result_affix }} path: code-coverage-results.md @@ -160,7 +164,7 @@ jobs: run: echo "coverage_report=coverage_report-$(date +%s)" >> $GITHUB_OUTPUT - name: Upload Code Coverage Artifacts - uses: actions/upload-artifact@v4.6.2 + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 if: ${{ !cancelled() && (inputs.skip_deploy && !inputs.skip_coverage) }} with: name: ${{ steps.artifact.outputs.coverage_report }} @@ -168,7 +172,7 @@ jobs: retention-days: 1 - name: Upload Code Coverage Pages - uses: actions/upload-pages-artifact@v3.0.1 + uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0 if: ${{ !cancelled() && (!inputs.skip_deploy && !inputs.skip_coverage) }} with: path: ${{ inputs.cmake_path }}/coverage_report/${{ inputs.coverage_name }} @@ -211,7 +215,7 @@ jobs: # the merge means one overwrites the other. That file is consumed by # CodeCoverageSummary back in run_tests and is not read here, so this is # untidy rather than wrong. - - uses: actions/download-artifact@v4.3.0 + - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 if: ${{ inputs.skip_test }} with: pattern: coverage_report-* @@ -219,7 +223,7 @@ jobs: path: ${{ inputs.cmake_path }}/coverage_report - name: Upload Code Coverage Pages - uses: actions/upload-pages-artifact@v3.0.1 + uses: actions/upload-pages-artifact@fc324d3547104276b827a68afc52ff2a11cc49c9 # v5.0.0 if: ${{ inputs.skip_test }} with: path: . @@ -231,13 +235,13 @@ jobs: # is why that went unnoticed; retention-days: 1 on the upload is what has # actually been clearing these up. - name: Delete Duplicate Code Coverage Artifact - uses: geekyeggo/delete-artifact@v5.1.0 + uses: geekyeggo/delete-artifact@176a747ab7e287e3ff4787bf8a148716375ca118 # v6.0.0 with: name: coverage_report-* - name: Deploy GitHub Pages site id: deployment - uses: actions/deploy-pages@v4.0.5 + uses: actions/deploy-pages@cd2ce8fcbc39b97be8ca5fce6e763baed58fa128 # v5.0.0 - name: Write Code Coverage Report URL run: >- From b6a00a2014009145b4f19e66a7f80e34887ea987 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Tue, 25 Aug 2026 16:05:04 -0400 Subject: [PATCH 085/181] Added the Dependabot configuration the pinned actions need (#662) The action references were pinned to commit SHAs in #660, and a SHA pin with nothing moving it is worse than a floating tag -- it holds CI on whatever was current the day it was written. That is exactly how actions/cache@v1 stayed in ci_cortex_m.yml until GitHub began auto-failing every request that used it. The drift measured before that catch-up: download-artifact four majors behind, checkout and upload-artifact three each, cache and upload-pages-artifact two, with nothing ever reporting it. This closes the loop, and the reference to .github/dependabot.yml that #660 left in each workflow's pinning comment. Weekly, github-actions only. Patch and minor are grouped into one pull request because they are the routine traffic and a queue reviewed one item at a time is a queue that gets ignored. Majors stay ungrouped, one each, because every breaking change this repository has met in an action has been a major. Two choices worth stating rather than leaving to be rediscovered. target-branch is dev. Dependabot reads this file from the default branch, which is master, but master is deliberately kept behind dev and pull requests belong where the regression suites gate them. The consequence is that landing this on dev arms it without firing it: nothing happens until a release merge carries the file to master. Setting target-branch also opts out of Dependabot security updates, which only run against the default branch -- a small cost for this ecosystem, since an action advisory arrives as an ordinary bump on the weekly run, but a real one. The pull-request limit is raised from the default five to ten. Nine actions are in use, and five would hold majors back with nothing saying that it had. No other ecosystem is configured, deliberately: external dependencies are forbidden, there are no submodules, and the one pinned tool -- gcovr in scripts/install.sh -- lives in a shell script no ecosystem can parse, so that pin keeps moving by hand. No sibling eclipse-threadx repository has a Dependabot configuration, so this sets the pattern rather than following one. The dependencies label it uses already exists here. Assisted-by: Claude Opus 5 --- .github/dependabot.yml | 91 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 000000000..1091a2d6b --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,91 @@ +version: 2 + +# Keeps the pinned action SHAs moving. +# +# Every action reference under .github/workflows is a 40-character commit SHA +# with the version in a trailing comment. A SHA pin *without* this file is worse +# than a floating tag: it freezes CI on whatever was current the day it was +# written, which is how actions/cache@v1 came to sit in ci_cortex_m.yml until +# GitHub started auto-failing every request that used it. Measured on +# 2026-08-24, before the catch-up: download-artifact was four majors behind, +# checkout and upload-artifact three each, cache and upload-pages-artifact two. +# Nothing had ever reported that, because there was no configuration here -- nor +# in netxduo, filex, guix or rtos-docs-asciidoc, so this file sets the pattern +# rather than following one. +# +# Dependabot understands the SHA form and rewrites the trailing version comment +# together with the pin, so the comment cannot drift away from the SHA it +# describes. That is what keeps "which exact code ran in our CI" answerable from +# the repository, which the SBOM and certification work needs on its own. +# +# Two things this does not fix. It reports drift, not silence: a workflow that +# never triggers rots unnoticed no matter what is pinned in it, and the trigger +# fixes in ci_cortex_m.yml and regression_test.yml are the cure for that. And it +# does nothing at all until this file reaches the default branch -- see the note +# on target-branch below. +# +# There is no entry for any other ecosystem, and that is a decision rather than +# an oversight: the project forbids external dependencies, there are no +# submodules, and the one pinned tool -- gcovr in scripts/install.sh -- lives in +# a shell script that no Dependabot ecosystem can parse. That pin moves by hand. +updates: + - package-ecosystem: "github-actions" + # "/" is the only accepted value for this ecosystem; it covers + # .github/workflows and .github/actions. The five reusable-workflow + # references in regression_test.yml are local paths + # (./.github/workflows/regression_template.yml) and are correctly left + # alone -- they carry no version to move. + directory: "/" + + schedule: + interval: "weekly" + day: "monday" + time: "06:00" + timezone: "Etc/UTC" + + # Dependabot reads this file from the repository's DEFAULT branch, which is + # master. But master is deliberately kept behind dev, and pull requests + # belong on dev, where the regression suites gate them. target-branch sends + # the pull requests to dev and makes Dependabot read the workflows it is + # updating from dev as well. + # + # The consequence to plan for: landing this file on dev arms it, it does not + # fire it. Nothing happens until a release merge carries it to master. + # + # Setting target-branch also opts out of Dependabot *security* updates, + # which only ever run against the default branch. For this ecosystem the + # cost is small -- an action advisory arrives as an ordinary version bump on + # the weekly run -- but it is a real trade and not a detail to rediscover + # later. + target-branch: "dev" + + groups: + # Patch and minor arrive together in one pull request: they are the + # routine traffic, and reviewing them one at a time is how an update queue + # starts being ignored, which is the failure mode this file exists to + # prevent. Majors stay ungrouped, one pull request each, because every + # breaking change this repository has met in an action set has been a + # major -- download-artifact v8 defaulting digest-mismatch to error, and + # upload-artifact v6 requiring runner 2.327.1 or newer, are both from the + # last catch-up. + actions-minor-and-patch: + patterns: + - "*" + update-types: + - "minor" + - "patch" + + # Nine distinct third-party and first-party actions are in use. Dependabot's + # default limit of five would hold majors back with nothing saying that it + # had; ten leaves room for a wave without becoming a silent cap. + open-pull-requests-limit: 10 + + labels: + - "dependencies" + + # Reviewers are not listed here. .github/CODEOWNERS already routes every + # path to @eclipse-threadx/admins and Dependabot honours it. + # + # Commit subjects are left at Dependabot's own "Bump x from a to b" wording. + # The project asks for a past-tense subject and still gets one: these pull + # requests are squash-merged, and the subject is set at that point. From 2d9b9f74171234c0b5e0982042dd24c7e24e1387 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Tue, 25 Aug 2026 16:35:16 -0400 Subject: [PATCH 086/181] Bumped gcovr off the 4.1 pin it had been held on since 2018 (#663) The coverage tooling was pinned to gcovr 4.1, released in 2018, and that version is missing the two options the coverage work needs next: --json and --add-tracefile, which is how the five build configurations get merged into one report. This moves the pin to 8.6, the current release. The pin stays exact, and it stays hand-moved: it lives in a shell script, and no Dependabot ecosystem can parse that. Isolated deliberately, so that a movement in the coverage number caused by the tool could not be confused with one caused by a later change. Measured on the default_build_coverage tree of test/tx, over the same gcda with the same gcov, varying only the gcovr version: gcovr lines-valid branches-valid files 4.1 3827 1994 177 7.0 3827 1994 177 8.3 3827 1994 177 8.6 3827 1994 177 So the denominator does not move with the tool at all, and this bump moves no number. The plan this came from expected 3822 to become 3827; that figure does not reproduce, under gcc-13 or gcc-14, with or without --object-directory. The only variant that changes the count is dropping the -f filter, which collapses the report to nothing. Two things found while measuring, both recorded because they matter to what comes next. The coverage numerator is not deterministic. On an identical tree with an identical compiler, three consecutive runs of the full suite -- all 96 tests passing every time -- reported 3826, 3827 and 3827 covered lines. The line that flickers is tx_thread_system_resume.c:529, the preemption path of _tx_thread_system_resume, and it takes its guarding branch with it. It has been described as never executed; it is executed on some runs and not others. A coverage floor has to be set with that in mind, and the honest fix is a test that takes the path deliberately. Reading gcc-13 output, the compiler the runners actually use, gcovr 8.6 runs the existing coverage.sh unchanged: Cobertura XML and 181 HTML files, same 177 classes. --xml-pretty and --object-directory still work on 8.6 but are now deprecated aliases for --cobertura-pretty and --gcov-object-directory, worth knowing for whoever removes --object-directory next. Assisted-by: Claude Opus 5 --- scripts/install.sh | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/scripts/install.sh b/scripts/install.sh index e37fd33a9..c142370de 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -78,7 +78,24 @@ retry sudo "${TIMEOUT[@]}" apt-get "${APT_OPTIONS[@]}" install -y \ software-properties-common || exit 1 retry "${TIMEOUT[@]}" python3 -m pip install --retries 3 --timeout 30 --upgrade pip || exit 1 -retry "${TIMEOUT[@]}" pip3 install --retries 3 --timeout 30 gcovr==4.1 || exit 1 +# gcovr was pinned to 4.1, released in 2018. That version cannot do what merging +# the coverage of several build configurations needs: it has no --json and no +# --add-tracefile, both of which arrived later. The pin is exact rather than +# floating so the coverage percentage stays comparable between runs -- the +# denominator is a property of the tool as much as of the tree -- and it is moved +# by hand, because it lives in a shell script that Dependabot cannot parse. +# +# Measured before bumping, on the default_build_coverage tree of test/tx, over +# the same gcda with the same gcov, varying only the gcovr version: 4.1, 7.0, +# 8.3 and 8.6 all report lines-valid 3827 across 177 files and branches-valid +# 1994. The denominator does not move with the tool, so this bump moves no +# number and any movement in a later run belongs to a later change. +# +# The numerator does move, but not because of gcovr: tx_thread_system_resume.c +# line 529 is executed on some runs of the suite and not others, so the same +# tree reports 3826 or 3827 covered lines with every test passing either way. +# That is a property of the suite, not of this pin. +retry "${TIMEOUT[@]}" pip3 install --retries 3 --timeout 30 gcovr==8.6 || exit 1 # Upgrade cmake to the latest version. retry "${TIMEOUT[@]}" pip install --retries 3 --timeout 30 --upgrade cmake || exit 1 From b756220c434f1ca49495020cb1c001c8910b2179 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Tue, 25 Aug 2026 17:16:51 -0400 Subject: [PATCH 087/181] Fixed the coverage report's paths and scoping (#664) The Cobertura XML embedded absolute machine paths, and the flag that looked like it scoped the report to one build configuration was doing nothing at all. Both coverage.sh scripts had the defect; both are fixed here, because the SMP report is published to the same Pages site as the ThreadX one. Paths. -r was the build directory and -f pointed outside it, so gcovr could not express the sources relative to the root and fell back to absolute paths. The result named files as /home/runner/work/threadx/threadx/common/src/... while the element beside them said build/default_build_coverage, so the two halves of the same file disagreed and nothing could map coverage back to the repository. -r is the repository root now and -f an absolute path beneath it, which gives filename="common/src/tx_block_allocate.c". Both must be absolute: -r ../../.. -f common/src produces a report of zero files and exits 0, which is the worst failure mode available here. Scoping. --object-directory does not restrict which gcda files are found -- it tells gcovr how to get from a gcda file back to the compiler's working directory. Pointed at an empty directory it still produced the full 177-file report. That was harmless only by accident, because -r build/$1 constrained the search instead; moving -r to the repository root removes that accident, so the two changes have to land together. Measured, with a second instrumented configuration deliberately made sparser than the first: scoped by the positional search path 3221 of 3827 lines -- the truth no search path, -r at the repo root 3827 of 3827 -- silently merged --object-directory at the sparse tree 3827 of 3827 -- scopes nothing So the search path is load-bearing, and it matters ahead of instrumenting all five configurations: without it each configuration would have reported the union as its own. An empty report is not an error to gcovr -- it warns and exits 0 -- and it carries line-rate="1.0" next to lines-valid="0", so a consumer reads no data at all as fully covered. No coverage threshold can catch that, since an empty report passes any threshold. Hence the explicit assertion that the report has content, which fires with exit 1 on an object directory that exists but is empty, where the old shape returned 177 files and exit 0. Also says out loud that ports/linux/gnu/src is deliberately outside the filter. gcno files exist for it and it is dropped without a word today. Number-neutral, and that was the test. Over the same frozen gcda, changing only the gcovr invocation: ThreadX 3827 of 3827 lines and 1993 of 1994 branches across 177 files, SMP 4739 of 4791 and 2417 of 2430 across 185, before and after alike. Same answers on gcovr 7.0, 8.3 and 8.6, so the change is not wedged to the current pin. End to end through run.sh, 96 of 96 and 110 of 110 pass with the reports written. Assisted-by: Claude Opus 5 --- test/smp/cmake/coverage.sh | 59 ++++++++++++++++++++++++++++++++++++-- test/tx/cmake/coverage.sh | 55 +++++++++++++++++++++++++++++++++-- 2 files changed, 109 insertions(+), 5 deletions(-) diff --git a/test/smp/cmake/coverage.sh b/test/smp/cmake/coverage.sh index a7312e1f4..abcf7cceb 100755 --- a/test/smp/cmake/coverage.sh +++ b/test/smp/cmake/coverage.sh @@ -14,7 +14,6 @@ set -e cd $(dirname $0) -threadx_smp=$(realpath ../../../common_smp/src) mkdir -p coverage_report/$1 # gcov reads a data format tied to the compiler that produced it, so gcov has to match @@ -42,5 +41,59 @@ if ! command -v "$GCOV" >/dev/null 2>&1; then exit 1 fi -gcovr --gcov-executable "$GCOV" --object-directory=build/$1/threadx_smp/CMakeFiles/threadx_smp.dir/$threadx_smp -r build/$1 -f ../../../common_smp/src --xml-pretty --output coverage_report/$1.xml -gcovr --gcov-executable "$GCOV" --object-directory=build/$1/threadx_smp/CMakeFiles/threadx_smp.dir/$threadx_smp -r build/$1 -f ../../../common_smp/src --html --html-details --output coverage_report/$1/index.html +# gcovr is given three paths below, and each of them has to be absolute, for a +# different reason. +# +# -r is the repository root rather than the build directory, so the report names +# files the way the repository does -- "common_smp/src/tx_block_allocate.c" +# instead of "/home/runner/work/threadx/threadx/common_smp/src/tx_block_allocate.c". +# With -r inside build/, gcovr cannot express the sources relative to it, because +# they are outside it, and falls back to absolute paths. Those paths then differ +# on every machine and disagree with the element written beside them in +# the same file, so anything that maps coverage back to the repository -- PR +# annotations, Codecov, SonarQube -- cannot follow them. +# +# Both -r and -f must be absolute. "-r ../../.. -f common_smp/src" produces a +# report containing zero files and exits 0, which is the worst failure mode +# available here: a green run carrying an empty report. Measured, not assumed. +repo_root=$(cd ../../.. && pwd) + +# This is what actually scopes the report to one build configuration, and it is +# the positional search path -- not --object-directory, which used to be here +# and was doing nothing at all. That flag tells gcovr how to get from a gcda +# file back to the compiler's working directory; it does not restrict which gcda +# files are found. Pointed at an empty directory it still produced the full +# report, because gcovr searches -r as well. +# +# That matters more now than it did before. While -r was build/$1 it happened to +# constrain the search to this configuration by accident. -r is the repository +# root now, and every configuration's gcda lies somewhere under it, so without +# an explicit search path the report would silently merge all five. +# +# The odd shape of this path is CMake's, not ours: common_smp/src sits outside +# this directory's source tree, so CMake mangles each source file's absolute +# path into the object path, minus the leading slash. Hence the concatenation +# rather than a join -- $repo_root already begins with one. +objdir=$PWD/build/$1/threadx_smp/CMakeFiles/threadx_smp.dir$repo_root/common_smp/src + +# The Linux port's own sources are deliberately outside -f. gcno files exist for +# two directories -- common_smp/src and ports_smp/linux/gnu/src -- and only the +# first is reported. The kernel is what this suite is here to cover; the +# architecture ports are validated functionally rather than structurally, and +# linux/gnu is a development host port that nothing ships on. Written down +# because a filter argument on its own is not a decision the next reader can see. +filter=$repo_root/common_smp/src + +gcovr --gcov-executable "$GCOV" -r "$repo_root" -f "$filter" "$objdir" --xml-pretty --output coverage_report/$1.xml +gcovr --gcov-executable "$GCOV" -r "$repo_root" -f "$filter" "$objdir" --html --html-details --output coverage_report/$1/index.html + +# An empty report is not an error as far as gcovr is concerned: it warns and +# exits 0. Worse, it advertises line-rate="1.0" alongside lines-valid="0", so +# every downstream consumer reads "no data at all" as "100% covered". A coverage +# threshold cannot catch that, because an empty report passes any threshold. So +# the assertion belongs here, next to the paths that would cause it. +if ! grep -q "&2 + echo "Expected gcda files under $objdir." >&2 + exit 1 +fi diff --git a/test/tx/cmake/coverage.sh b/test/tx/cmake/coverage.sh index 9b47339e8..aabf039f7 100755 --- a/test/tx/cmake/coverage.sh +++ b/test/tx/cmake/coverage.sh @@ -41,5 +41,56 @@ if ! command -v "$GCOV" >/dev/null 2>&1; then exit 1 fi -gcovr --gcov-executable "$GCOV" --object-directory=build/$1/threadx/CMakeFiles/threadx.dir/common/src -r build/$1 -f ../../../common/src --xml-pretty --output coverage_report/$1.xml -gcovr --gcov-executable "$GCOV" --object-directory=build/$1/threadx/CMakeFiles/threadx.dir/common/src -r build/$1 -f ../../../common/src --html --html-details --output coverage_report/$1/index.html +# gcovr is given three paths below, and each of them has to be absolute, for a +# different reason. +# +# -r is the repository root rather than the build directory, so the report names +# files the way the repository does -- "common/src/tx_block_allocate.c" instead +# of "/home/runner/work/threadx/threadx/common/src/tx_block_allocate.c". With -r +# inside build/, gcovr cannot express the sources relative to it, because they +# are outside it, and falls back to absolute paths. Those paths then differ on +# every machine and disagree with the element written beside them in +# the same file, so anything that maps coverage back to the repository -- PR +# annotations, Codecov, SonarQube -- cannot follow them. +# +# Both -r and -f must be absolute. "-r ../../.. -f common/src" produces a report +# containing zero files and exits 0, which is the worst failure mode available +# here: a green run carrying an empty report. Measured, not assumed. +repo_root=$(cd ../../.. && pwd) + +# This is what actually scopes the report to one build configuration, and it is +# the positional search path -- not --object-directory, which used to be here +# and was doing nothing at all. That flag tells gcovr how to get from a gcda +# file back to the compiler's working directory; it does not restrict which gcda +# files are found. Pointed at an empty directory it still produced the full +# 177-file report, because gcovr searches -r as well. +# +# That matters more now than it did before. While -r was build/$1 it happened to +# constrain the search to this configuration by accident. -r is the repository +# root now, and every configuration's gcda lies somewhere under it, so without +# an explicit search path the report would silently merge all five. Measured on +# gcovr 8.6: with this search path, an empty directory yields an empty report +# and the real one yields 177 files. +objdir=$PWD/build/$1/threadx/CMakeFiles/threadx.dir/common/src + +# The Linux port's own sources are deliberately outside -f. gcno files exist for +# two directories -- common/src and ports/linux/gnu/src -- and only the first is +# reported. The kernel is what this suite is here to cover; the architecture +# ports are validated functionally rather than structurally, and linux/gnu is a +# development host port that nothing ships on. Written down because a filter +# argument on its own is not a decision the next reader can see. +filter=$repo_root/common/src + +gcovr --gcov-executable "$GCOV" -r "$repo_root" -f "$filter" "$objdir" --xml-pretty --output coverage_report/$1.xml +gcovr --gcov-executable "$GCOV" -r "$repo_root" -f "$filter" "$objdir" --html --html-details --output coverage_report/$1/index.html + +# An empty report is not an error as far as gcovr is concerned: it warns and +# exits 0. Worse, it advertises line-rate="1.0" alongside lines-valid="0", so +# every downstream consumer reads "no data at all" as "100% covered". A coverage +# threshold cannot catch that, because an empty report passes any threshold. So +# the assertion belongs here, next to the paths that would cause it. +if ! grep -q "&2 + echo "Expected gcda files under $objdir." >&2 + exit 1 +fi From 3e85bbd431763139b0bf54eb949964ee74cb1682 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Wed, 26 Aug 2026 08:13:33 -0400 Subject: [PATCH 088/181] Instrumented every build configuration and merged their coverage (#665) Only default_build_coverage carried -fprofile-arcs, because the gate was the build type and it is the only one of five whose name ends in _coverage. The other four build and run all their tests and their coverage was discarded. That is not redundancy thrown away: each configuration selects a different set of TX_ feature macros, so the code the other four compile is absent from the denominator rather than uncovered in it. TX_COVERAGE instruments a build regardless of its name, defaulting to OFF so a single configuration built by hand behaves as before. coverage.sh gains a --merge mode that unions the per-configuration JSON tracefiles, and cmake_bootstrap.sh runs it after the test loop so a local run produces the same merged report CI reads. The template sets TX_COVERAGE for build and test, and coverage_name moves to the merged report. Measured on the ThreadX suite, all 480 tests passing: default_build_coverage 3827 valid 3827 covered disable_notify_callbacks_build 3767 3766 stack_checking_build 3857 3856 stack_checking_rand_fill_build 3862 3861 trace_build 4123 4108 merged 4503 4487 The denominator grows by 676 lines, 17.7%, and the figure moves from 99.97% to 99.64%. The second one is honest, and the drop is the point rather than a regression: the denominator now includes code the old report never counted. The union also contains a file the old report did not contain at all -- tx_thread_stack_error_handler.c compiles only under TX_ENABLE_STACK_CHECKING, so it was not listed at 0%, it was simply absent. 177 files becomes 178. Coverage collection moved out of test() and now runs after the test loop, one configuration at a time. gcov writes its intermediate gcov files into the directory gcovr is rooted at, and coverage.sh roots every configuration at the repository root so filenames come out repo-relative. Five concurrent gcovr processes therefore share one scratch directory and delete each other's output: the first full run of this change passed all 480 tests and produced no report for three of the five configurations. Measured both ways -- two gcovr rooted at the repository root fail concurrently and succeed in sequence. CI would not have caught it, because test_tx.sh sets CTEST_PARALLEL_LEVEL=1 and takes the serial branch. Per-configuration output moved under coverage_report/per_configuration/ and is excluded from the Pages artifact. The deploy job merges the ThreadX and SMP artifacts into one tree and every configuration directory has the same name in both, so left at the top level one suite's would overwrite the other's on the published site. On the SMP suite, an earlier run of this change saw trace_build fail threadx_smp_time_slice_test and then hang, which raised the question of whether -fprofile-arcs perturbs a timing-sensitive test. It does not. Sixteen runs settle it, and the decisive one is that threadx_smp_time_slice_test failed ERROR #31 -- twice in a row under --repeat until-pass:2 -- on an uninstrumented build, in the exact shape CI runs, while three instrumented runs of that shape passed 5 of 5. In the CI shape, CTEST_PARALLEL_LEVEL=1 run.sh test all: TX_COVERAGE=OFF 3 runs 2 green, one ERROR #31 310 s TX_COVERAGE=ON 3 runs 3 green, 5/5 each 325-329 s So the test is a pre-existing flake on dev and instrumenting all five costs about 5% of the suite's wall clock. Separately, and also in both instrumented and uninstrumented builds, run.sh's parallel branch -- what a developer gets typing run.sh test all with no CTEST_PARALLEL_LEVEL -- hangs under its own load, four times in twelve runs. Several SMP tests create 1024 ThreadX threads by construction and the Linux port backs each with a pthread, so five configurations at once put on the order of 5000 threads on the machine. CI sets CTEST_PARALLEL_LEVEL=1 and does not take that branch. Assisted-by: Claude Opus 5 --- .github/workflows/regression_template.yml | 37 +++++++++- scripts/cmake_bootstrap.sh | 90 +++++++++++++++++++++-- test/smp/cmake/CMakeLists.txt | 16 +++- test/smp/cmake/coverage.sh | 69 +++++++++++++++-- test/tx/cmake/CMakeLists.txt | 16 +++- test/tx/cmake/coverage.sh | 73 ++++++++++++++++-- 6 files changed, 278 insertions(+), 23 deletions(-) diff --git a/.github/workflows/regression_template.yml b/.github/workflows/regression_template.yml index 62a28e937..7eea8f432 100644 --- a/.github/workflows/regression_template.yml +++ b/.github/workflows/regression_template.yml @@ -29,8 +29,13 @@ on: default: false required: false type: boolean + # The merged report, not one configuration's. Every configuration is + # instrumented now (TX_COVERAGE below) and coverage.sh --merge unions + # them; default_build_coverage was one build of five, and the code the + # other four select was absent from its denominator rather than uncovered + # in it. coverage_name: - default: 'default_build_coverage' + default: 'merged' required: false type: string skip_deploy: @@ -79,12 +84,20 @@ jobs: timeout-minutes: 10 run: ${{ inputs.install_script }} + # TX_COVERAGE instruments every build configuration rather than only the one + # whose name ends in _coverage. It has to be set for the build as well as the + # test: the build is where -fprofile-arcs is decided, and the test run is + # where the reports are collected and merged. - name: Build timeout-minutes: 15 + env: + TX_COVERAGE: ${{ inputs.skip_coverage && 'OFF' || 'ON' }} run: ${{ inputs.build_script }} - name: Test timeout-minutes: 60 + env: + TX_COVERAGE: ${{ inputs.skip_coverage && 'OFF' || 'ON' }} run: ${{ inputs.test_script }} - name: Publish Test Results @@ -163,12 +176,32 @@ jobs: if: ${{ !cancelled() && (!inputs.skip_coverage) }} run: echo "coverage_report=coverage_report-$(date +%s)" >> $GITHUB_OUTPUT + # per_configuration is excluded deliberately. deploy_code_coverage downloads + # every coverage_report-* artifact with merge-multiple, so whatever is in + # here lands on the published site -- and each suite's per-configuration + # directories carry the same names, so ThreadX's would overwrite SMP's. + # The top level therefore holds only the suite directory and the merged XML, + # which is the shape the deploy already expects. - name: Upload Code Coverage Artifacts uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 if: ${{ !cancelled() && (inputs.skip_deploy && !inputs.skip_coverage) }} with: name: ${{ steps.artifact.outputs.coverage_report }} - path: ${{ inputs.cmake_path }}/coverage_report + path: | + ${{ inputs.cmake_path }}/coverage_report + !${{ inputs.cmake_path }}/coverage_report/per_configuration/** + retention-days: 1 + + # The per-configuration reports, kept separately so they are downloadable + # when the merged number moves and the question is which configuration moved + # it. The name deliberately does not match coverage_report-*, so the deploy + # job's pattern does not pick it up and it never reaches the published site. + - name: Upload Per-Configuration Coverage + uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 + if: ${{ !cancelled() && (!inputs.skip_coverage) }} + with: + name: coverage_detail ${{ inputs.result_affix }} + path: ${{ inputs.cmake_path }}/coverage_report/per_configuration retention-days: 1 - name: Upload Code Coverage Pages diff --git a/scripts/cmake_bootstrap.sh b/scripts/cmake_bootstrap.sh index faa43133f..eb9bee1b4 100755 --- a/scripts/cmake_bootstrap.sh +++ b/scripts/cmake_bootstrap.sh @@ -57,7 +57,7 @@ function generate() { echo "Compiler changed since build/$build was configured. Reconfiguring from scratch." rm -rf build/$build fi - cmake -Bbuild/$build -GNinja -DBUILD_SHARED_LIBS=ON -DCMAKE_TOOLCHAIN_FILE=$(dirname $(realpath $0))/../cmake/linux.cmake -DCMAKE_BUILD_TYPE=$build . + cmake -Bbuild/$build -GNinja -DBUILD_SHARED_LIBS=ON -DCMAKE_TOOLCHAIN_FILE=$(dirname $(realpath $0))/../cmake/linux.cmake -DCMAKE_BUILD_TYPE=$build -DTX_COVERAGE=${TX_COVERAGE:-OFF} . } function build() { @@ -84,11 +84,14 @@ function test() { fi # ctest's status is captured rather than allowed to abort the function, and # returned at the end. set -e would otherwise stop here on the first failing - # test, and everything below would be skipped -- including coverage.sh. The - # gcda files exist by that point, so a failing run threw away coverage it had - # already collected, and the run whose behaviour changed is exactly the one - # whose coverage is worth reading. Measured: the failing run of 2026-08-18 - # produced test_reports artifacts and no coverage_report artifact at all. + # test, and every configuration after it would go untested -- and, before + # collection moved out of this function, uncovered as well. The gcda files + # exist by that point, so a failing run threw away coverage it had already + # collected, and the run whose behaviour changed is exactly the one whose + # coverage is worth reading. Measured: the failing run of 2026-08-18 produced + # test_reports artifacts and no coverage_report artifact at all. Collection + # itself now happens in collect_all_coverage, after every configuration has + # been tested, and it does not stop at the first failure either. local status=0 ctest $parallel --timeout 1000 -O $1.txt -T test --no-compress-output --test-output-size-passed 4194304 --test-output-size-failed 4194304 --output-on-failure --repeat until-pass:${repeat_fail} --output-junit $1.xml || status=$? popd @@ -96,9 +99,72 @@ function test() { # enough to leave no matching line must not be what stops the coverage below. grep -E "^(\s*[0-9]+|Total)" build/$1/$1.txt >build/$1.txt || true sed -i "s/\x1B\[[0-9;]*[JKmsu]//g" build/$1.txt - if [[ $1 = *"_coverage" ]]; then + return $status +} + +# Coverage is collected for any configuration that was instrumented, which is +# what TX_COVERAGE decides. The build-type match is kept for the one +# configuration instrumented by its name, so building a single configuration by +# hand behaves exactly as it did before. +# +# Three of the test trees -- freertos, posix and tx/cmake/riscv -- have no +# coverage.sh at all, and this script serves them too. Say so rather than +# failing, so that TX_COVERAGE=ON is harmless anywhere it does not apply. +function collect_coverage() { + if [[ $1 = *"_coverage" ]] || [ "${TX_COVERAGE:-OFF}" = "ON" ]; then + if [ ! -x ./coverage.sh ]; then + echo "No coverage.sh in $(pwd); skipping coverage for $1." + return 0 + fi ./coverage.sh $1 fi +} + +# Collection runs after every configuration has been tested, and strictly one at +# a time. +# +# It used to sit inside test(), which was safe only while a single configuration +# was instrumented. gcov writes its intermediate .gcov files into the directory +# gcovr is rooted at, and coverage.sh roots every configuration at the repository +# root so that the report can name files the way the repository does. Five +# concurrent gcovr processes therefore share one scratch directory and delete +# each other's output. The symptom is a gcovr SanityCheckError naming a .gcov +# file that "doesn't exist but no error from GCOV detected", and it cost the +# report for three of the five configurations while all 480 tests still passed -- +# a green suite with most of its coverage missing. +# +# Measured both ways: two gcovr invocations rooted at the repository root fail +# when run concurrently and both succeed when run in sequence. CI happens to be +# safe already, because test_tx.sh sets CTEST_PARALLEL_LEVEL=1 and takes the +# serial branch below, but that is a coincidence of one caller rather than a +# property of this script. +# +# Collection deliberately does not stop at the first failure, for the reason +# given in test(): the configurations that did produce data should still report. +# +# The trade this makes, recorded rather than discovered later: a configuration +# that hangs long enough to hit the job's own timeout now costs the reports for +# the configurations that already finished, where collecting inside test() would +# have kept them. That is judged the smaller risk -- a per-test timeout is a +# ctest failure and the loop carries on, the job timeout sits at 60 minutes +# against a suite that takes 5 to 25, and the alternative loses most of the +# coverage on every parallel run instead of on a hang. +function collect_all_coverage() { + local item status=0 + for item in $builds; do + collect_coverage $item || status=$? + done + + # Union the per-configuration reports. Only the union is a coverage figure: + # each configuration compiles a different set of TX_ feature macros, so a + # line one of them compiles out is absent from its denominator rather than + # uncovered in it, and an average of five percentages means nothing. + # + # Done here rather than as a separate workflow step so a local run produces + # the same merged report CI reads. + if [ "${TX_COVERAGE:-OFF}" = "ON" ] && [ -x ./coverage.sh ]; then + ./coverage.sh --merge || status=$? + fi return $status } @@ -155,6 +221,11 @@ elif [ "$command" == "test" ]; then for p in $pids; do wait $p || exit_code=$? done + # A coverage failure turns the run red, but must not overwrite a test + # failure's status with its own. + coverage_status=0 + collect_all_coverage || coverage_status=$? + [ $exit_code -ne 0 ] || exit_code=$coverage_status exit $exit_code else # Run builds in serial. The status is collected the same way the parallel @@ -168,6 +239,11 @@ elif [ "$command" == "test" ]; then echo "Testing $item" test $item $parallel_jobs || exit_code=$? done + # A coverage failure turns the run red, but must not overwrite a test + # failure's status with its own. + coverage_status=0 + collect_all_coverage || coverage_status=$? + [ $exit_code -ne 0 ] || exit_code=$coverage_status exit $exit_code fi elif [ "$command" == "build_libs" ]; then diff --git a/test/smp/cmake/CMakeLists.txt b/test/smp/cmake/CMakeLists.txt index e2ca8627c..3a0d9638a 100644 --- a/test/smp/cmake/CMakeLists.txt +++ b/test/smp/cmake/CMakeLists.txt @@ -64,7 +64,21 @@ add_subdirectory(regression) add_subdirectory(samples) # Coverage -if(CMAKE_BUILD_TYPE MATCHES ".*_coverage") +# +# The gate here used to be the build type alone, and only one of the five +# configurations -- default_build_coverage -- has a name matching "*_coverage". +# So four configurations built and ran every test and their coverage was thrown +# away. That is not redundancy discarded: each configuration selects a different +# set of TX_ feature macros, so the code the other four compile is *absent from +# the denominator* rather than reported as uncovered. A figure taken from one of +# them is the executable-line count of one configuration, not of the kernel. +# +# TX_COVERAGE instruments a build regardless of its name. It defaults to OFF and +# the build-type match is kept, so configuring a single configuration by hand +# behaves exactly as it did before; the regression run turns it on for all five +# and merges the results. +option(TX_COVERAGE "Instrument this build for coverage regardless of build type" OFF) +if(TX_COVERAGE OR CMAKE_BUILD_TYPE MATCHES ".*_coverage") if(NOT MSVC) target_compile_options(threadx_smp PRIVATE -fprofile-arcs -ftest-coverage) target_link_options(threadx_smp PRIVATE -fprofile-arcs -ftest-coverage) diff --git a/test/smp/cmake/coverage.sh b/test/smp/cmake/coverage.sh index abcf7cceb..88de4f04a 100755 --- a/test/smp/cmake/coverage.sh +++ b/test/smp/cmake/coverage.sh @@ -14,7 +14,6 @@ set -e cd $(dirname $0) -mkdir -p coverage_report/$1 # gcov reads a data format tied to the compiler that produced it, so gcov has to match # the gcc that built the objects. Since cmake/linux.cmake began honouring CC, taking @@ -41,6 +40,57 @@ if ! command -v "$GCOV" >/dev/null 2>&1; then exit 1 fi +# The repository root, needed by every mode below. It has to be absolute: see the +# note on the per-configuration paths further down. +repo_root=$(cd ../../.. && pwd) +filter=$repo_root/common_smp/src + +# --merge unions the per-configuration reports into the one number that means +# something. Each configuration writes an intermediate JSON beside its XML, and +# this pass adds them all together. +# +# Reporting five separate percentages instead would invite a reader to average +# them, and an average is not a coverage figure -- a line covered only by +# trace_build is covered, and only the union says so. +# +# Do not be alarmed when the merged percentage is lower than the single +# configuration this used to report. That is the point: the denominator now +# includes code the old report never counted at all, because it was compiled out +# of the only instrumented build. +if [ "$1" = "--merge" ]; then + shopt -s nullglob + tracefiles=(coverage_report/per_configuration/*.json) + shopt -u nullglob + if [ ${#tracefiles[@]} -eq 0 ]; then + echo "coverage.sh --merge: no JSON in coverage_report/per_configuration/." >&2 + echo "Run the suites with TX_COVERAGE=ON first." >&2 + exit 1 + fi + + add_args=() + for t in "${tracefiles[@]}"; do + add_args+=(--add-tracefile "$t") + done + + mkdir -p coverage_report/merged + gcovr -r "$repo_root" "${add_args[@]}" --xml-pretty --output coverage_report/merged.xml + gcovr -r "$repo_root" "${add_args[@]}" --html --html-details --output coverage_report/merged/index.html + + if ! grep -q "&2 + exit 1 + fi + + # Named, not just counted. coverage_report/ is not cleaned between runs, so a + # tracefile left by an earlier run of a different set of configurations would + # otherwise be merged in without anything saying so. + echo "coverage.sh --merge: SMP, ${#tracefiles[@]} configuration(s):" + for t in "${tracefiles[@]}"; do + echo " $(basename "$t" .json)" + done + exit 0 +fi + # gcovr is given three paths below, and each of them has to be absolute, for a # different reason. # @@ -82,17 +132,26 @@ objdir=$PWD/build/$1/threadx_smp/CMakeFiles/threadx_smp.dir$repo_root/common_smp # architecture ports are validated functionally rather than structurally, and # linux/gnu is a development host port that nothing ships on. Written down # because a filter argument on its own is not a decision the next reader can see. -filter=$repo_root/common_smp/src -gcovr --gcov-executable "$GCOV" -r "$repo_root" -f "$filter" "$objdir" --xml-pretty --output coverage_report/$1.xml -gcovr --gcov-executable "$GCOV" -r "$repo_root" -f "$filter" "$objdir" --html --html-details --output coverage_report/$1/index.html +# Per-configuration output is kept in a subdirectory of its own, and the merged +# report sits alongside it at the top. That is not tidiness: the Pages deploy +# uploads coverage_report wholesale and merges the ThreadX and SMP artifacts +# into one tree, and every configuration directory has the same name in both +# suites. Left at the top level, default_build_coverage/ from one suite would +# overwrite the other's on the published site. Nested here, the top level still +# holds exactly the one suite directory the deploy expects. +mkdir -p coverage_report/per_configuration/$1 +gcovr --gcov-executable "$GCOV" -r "$repo_root" -f "$filter" "$objdir" \ + --json coverage_report/per_configuration/$1.json \ + --xml-pretty --output coverage_report/per_configuration/$1.xml +gcovr --gcov-executable "$GCOV" -r "$repo_root" -f "$filter" "$objdir" --html --html-details --output coverage_report/per_configuration/$1/index.html # An empty report is not an error as far as gcovr is concerned: it warns and # exits 0. Worse, it advertises line-rate="1.0" alongside lines-valid="0", so # every downstream consumer reads "no data at all" as "100% covered". A coverage # threshold cannot catch that, because an empty report passes any threshold. So # the assertion belongs here, next to the paths that would cause it. -if ! grep -q "&2 echo "Expected gcda files under $objdir." >&2 exit 1 diff --git a/test/tx/cmake/CMakeLists.txt b/test/tx/cmake/CMakeLists.txt index 97b3615bd..b2f0ab1fe 100644 --- a/test/tx/cmake/CMakeLists.txt +++ b/test/tx/cmake/CMakeLists.txt @@ -62,7 +62,21 @@ add_subdirectory(regression) add_subdirectory(samples) # Coverage -if(CMAKE_BUILD_TYPE MATCHES ".*_coverage") +# +# The gate here used to be the build type alone, and only one of the five +# configurations -- default_build_coverage -- has a name matching "*_coverage". +# So four configurations built and ran every test and their coverage was thrown +# away. That is not redundancy discarded: each configuration selects a different +# set of TX_ feature macros, so the code the other four compile is *absent from +# the denominator* rather than reported as uncovered. A figure taken from one of +# them is the executable-line count of one configuration, not of the kernel. +# +# TX_COVERAGE instruments a build regardless of its name. It defaults to OFF and +# the build-type match is kept, so configuring a single configuration by hand +# behaves exactly as it did before; the regression run turns it on for all five +# and merges the results. +option(TX_COVERAGE "Instrument this build for coverage regardless of build type" OFF) +if(TX_COVERAGE OR CMAKE_BUILD_TYPE MATCHES ".*_coverage") if(NOT MSVC) target_compile_options(threadx PRIVATE -fprofile-arcs -ftest-coverage) target_link_options(threadx PRIVATE -fprofile-arcs -ftest-coverage) diff --git a/test/tx/cmake/coverage.sh b/test/tx/cmake/coverage.sh index aabf039f7..32d466b73 100755 --- a/test/tx/cmake/coverage.sh +++ b/test/tx/cmake/coverage.sh @@ -14,7 +14,6 @@ set -e cd $(dirname $0) -mkdir -p coverage_report/$1 # gcov reads a data format tied to the compiler that produced it, so gcov has to match # the gcc that built the objects. Since cmake/linux.cmake began honouring CC, taking @@ -41,6 +40,57 @@ if ! command -v "$GCOV" >/dev/null 2>&1; then exit 1 fi +# The repository root, needed by every mode below. It has to be absolute: see the +# note on the per-configuration paths further down. +repo_root=$(cd ../../.. && pwd) +filter=$repo_root/common/src + +# --merge unions the per-configuration reports into the one number that means +# something. Each configuration writes an intermediate JSON beside its XML, and +# this pass adds them all together. +# +# Reporting five separate percentages instead would invite a reader to average +# them, and an average is not a coverage figure -- a line covered only by +# trace_build is covered, and only the union says so. +# +# Do not be alarmed when the merged percentage is lower than the single +# configuration this used to report. That is the point: the denominator now +# includes code the old report never counted at all, because it was compiled out +# of the only instrumented build. +if [ "$1" = "--merge" ]; then + shopt -s nullglob + tracefiles=(coverage_report/per_configuration/*.json) + shopt -u nullglob + if [ ${#tracefiles[@]} -eq 0 ]; then + echo "coverage.sh --merge: no JSON in coverage_report/per_configuration/." >&2 + echo "Run the suites with TX_COVERAGE=ON first." >&2 + exit 1 + fi + + add_args=() + for t in "${tracefiles[@]}"; do + add_args+=(--add-tracefile "$t") + done + + mkdir -p coverage_report/merged + gcovr -r "$repo_root" "${add_args[@]}" --xml-pretty --output coverage_report/merged.xml + gcovr -r "$repo_root" "${add_args[@]}" --html --html-details --output coverage_report/merged/index.html + + if ! grep -q "&2 + exit 1 + fi + + # Named, not just counted. coverage_report/ is not cleaned between runs, so a + # tracefile left by an earlier run of a different set of configurations would + # otherwise be merged in without anything saying so. + echo "coverage.sh --merge: ThreadX, ${#tracefiles[@]} configuration(s):" + for t in "${tracefiles[@]}"; do + echo " $(basename "$t" .json)" + done + exit 0 +fi + # gcovr is given three paths below, and each of them has to be absolute, for a # different reason. # @@ -55,8 +105,8 @@ fi # # Both -r and -f must be absolute. "-r ../../.. -f common/src" produces a report # containing zero files and exits 0, which is the worst failure mode available -# here: a green run carrying an empty report. Measured, not assumed. -repo_root=$(cd ../../.. && pwd) +# here: a green run carrying an empty report. Measured, not assumed. repo_root +# and filter are set above, before the merge mode, because it needs them too. # This is what actually scopes the report to one build configuration, and it is # the positional search path -- not --object-directory, which used to be here @@ -79,17 +129,26 @@ objdir=$PWD/build/$1/threadx/CMakeFiles/threadx.dir/common/src # ports are validated functionally rather than structurally, and linux/gnu is a # development host port that nothing ships on. Written down because a filter # argument on its own is not a decision the next reader can see. -filter=$repo_root/common/src -gcovr --gcov-executable "$GCOV" -r "$repo_root" -f "$filter" "$objdir" --xml-pretty --output coverage_report/$1.xml -gcovr --gcov-executable "$GCOV" -r "$repo_root" -f "$filter" "$objdir" --html --html-details --output coverage_report/$1/index.html +# Per-configuration output is kept in a subdirectory of its own, and the merged +# report sits alongside it at the top. That is not tidiness: the Pages deploy +# uploads coverage_report wholesale and merges the ThreadX and SMP artifacts +# into one tree, and every configuration directory has the same name in both +# suites. Left at the top level, default_build_coverage/ from one suite would +# overwrite the other's on the published site. Nested here, the top level still +# holds exactly the one suite directory the deploy expects. +mkdir -p coverage_report/per_configuration/$1 +gcovr --gcov-executable "$GCOV" -r "$repo_root" -f "$filter" "$objdir" \ + --json coverage_report/per_configuration/$1.json \ + --xml-pretty --output coverage_report/per_configuration/$1.xml +gcovr --gcov-executable "$GCOV" -r "$repo_root" -f "$filter" "$objdir" --html --html-details --output coverage_report/per_configuration/$1/index.html # An empty report is not an error as far as gcovr is concerned: it warns and # exits 0. Worse, it advertises line-rate="1.0" alongside lines-valid="0", so # every downstream consumer reads "no data at all" as "100% covered". A coverage # threshold cannot catch that, because an empty report passes any threshold. So # the assertion belongs here, next to the paths that would cause it. -if ! grep -q "&2 echo "Expected gcda files under $objdir." >&2 exit 1 From f89d65f04125be070b62fb089c20f7dd072f320d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Wed, 26 Aug 2026 08:14:38 -0400 Subject: [PATCH 089/181] Covered the trace entry update paths and the misaligned stack adjustment (#666) Against the merged coverage report -- every build configuration instrumented and unioned -- eighteen lines of common/src were uncovered. Seventeen of them were one missing scenario rather than eighteen separate gaps. tx_block_allocate, tx_byte_allocate, tx_thread_system_suspend and tx_thread_system_resume each carry blocks under TX_ENABLE_EVENT_TRACE that go back and patch a trace entry once the call has done its work, all of the shape: if (entry_ptr != TX_NULL) { if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp) entry_ptr comes from _tx_trace_buffer_current_ptr, which stays TX_NULL until tx_trace_enable is called at run time. Building with TX_ENABLE_EVENT_TRACE is not enough, and exactly one test in the suite enables tracing -- threadx_trace_basic_test -- which tests the enable API itself and never calls either allocator. So those blocks sat in the report's denominator and never in its covered set. threadx_trace_entry_update_test enables tracing and then drives both allocators twice each, once on the path that succeeds immediately and once through a suspension that a second thread satisfies, since each allocator carries one update block on either side. It then sleeps so that the last runnable thread suspends with nothing ready to take over: tx_thread_system_suspend lines 345 and 351 are on the branch that sets _tx_thread_execute_ptr to TX_NULL, and the two allocator suspensions never reach it because the other thread was always ready. The same test closes tx_trace_object_register's TX_NULL name break by creating a semaphore with no name. A semaphore and not a thread deliberately: for TX_TRACE_OBJECT_TYPE_THREAD the register function dereferences the pointer it is given to read the thread's priority, so that type needs a real TX_THREAD behind it. threadx_trace_basic_test makes the equivalent call only under ifndef TX_ENABLE_EVENT_TRACE, against the no-op stub. threadx_thread_misaligned_stack_test covers the remaining line, tx_thread_create.c:136, where a stack that does not begin on a ULONG boundary costs a ULONG of size so that rounding the start up cannot run past the end of the caller's buffer. Every other test hands tx_thread_create an aligned stack. That line is compiled only under TX_ENABLE_STACK_CHECKING, so it is absent from three of the five configurations' reports rather than uncovered in them, and it was verified under stack_checking_build. Measured on the merged report, all 480 tests passing and 5 of 5 configurations green: 4485 of 4503 covered before, 4502 of 4503 after, denominator unchanged. One line remains, tx_thread_system_resume.c:529, and it is the report's last flapping line rather than a standing gap -- two clean runs of the same tree gave 4503 of 4503 and 4502 of 4503. Reaching it by construction was tried twice and failed both times, so it is left alone here. It needs the preempt disable flag and the system state both clear, and tx_thread_resume raises the preempt disable flag before calling _tx_thread_system_resume, as do the put and send paths; creating a higher priority auto-start thread from thread context does not raise it but does not reach the check either, which a probe showed is executed only during initialisation, with the system state at TX_INITIALIZE_IN_PROGRESS. Assisted-by: Claude Opus 5 --- test/tx/cmake/regression/CMakeLists.txt | 2 + .../threadx_thread_misaligned_stack_test.c | 150 ++++++++ .../threadx_trace_entry_update_test.c | 331 ++++++++++++++++++ 3 files changed, 483 insertions(+) create mode 100644 test/tx/regression/threadx_thread_misaligned_stack_test.c create mode 100644 test/tx/regression/threadx_trace_entry_update_test.c diff --git a/test/tx/cmake/regression/CMakeLists.txt b/test/tx/cmake/regression/CMakeLists.txt index 34fba1b2c..7a0296dc1 100644 --- a/test/tx/cmake/regression/CMakeLists.txt +++ b/test/tx/cmake/regression/CMakeLists.txt @@ -80,6 +80,7 @@ set(regression_test_cases ${SOURCE_DIR}/threadx_thread_create_preemption_threshold_test.c ${SOURCE_DIR}/threadx_thread_delayed_suspension_test.c ${SOURCE_DIR}/threadx_thread_information_test.c + ${SOURCE_DIR}/threadx_thread_misaligned_stack_test.c ${SOURCE_DIR}/threadx_thread_multi_level_preemption_threshold_test.c ${SOURCE_DIR}/threadx_thread_multiple_non_current_test.c ${SOURCE_DIR}/threadx_thread_multiple_sleep_test.c @@ -109,6 +110,7 @@ set(regression_test_cases ${SOURCE_DIR}/threadx_timer_multiple_test.c ${SOURCE_DIR}/threadx_timer_simple_test.c ${SOURCE_DIR}/threadx_trace_basic_test.c + ${SOURCE_DIR}/threadx_trace_entry_update_test.c ${SOURCE_DIR}/threadx_initialize_kernel_setup_test.c) add_custom_command( diff --git a/test/tx/regression/threadx_thread_misaligned_stack_test.c b/test/tx/regression/threadx_thread_misaligned_stack_test.c new file mode 100644 index 000000000..63d64775a --- /dev/null +++ b/test/tx/regression/threadx_thread_misaligned_stack_test.c @@ -0,0 +1,150 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/* This test creates a thread whose stack does not begin on a ULONG boundary. + + tx_thread_create rounds the starting address up to the next ULONG and then + takes a ULONG off the size, so that the rounding cannot push the end of the + stack past the memory the caller supplied: + + if (new_stack_start != updated_stack_start) + { + stack_size = stack_size - (sizeof(ULONG)); + } + + Every other test in the suite hands tx_thread_create an aligned stack, so + that subtraction was never executed -- the only uncovered line in + tx_thread_create.c across all five build configurations. A misaligned stack + is legitimate: the API takes a VOID * and the alignment fix-up exists + precisely to accept one. + + The thread is then run to completion rather than merely created, because the + point of the adjustment is that the resulting stack is still usable and still + inside the caller's buffer. */ + +#include +#include "tx_api.h" + + +void test_control_return(UINT status); + + +static TX_THREAD thread_0; +static TX_THREAD thread_1; + +/* Thread 1's stack is carved out of this by hand so that its start can be put + deliberately off a ULONG boundary. The extra ULONG is what the misaligned + start is offset into, so that the stack still ends inside the array after + tx_thread_create has rounded the start up. */ + +static UCHAR misaligned_area[TEST_STACK_SIZE_PRINTF + sizeof(ULONG)]; + +static ULONG thread_1_counter = 0; + + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_thread_misaligned_stack_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; +CHAR *misaligned_stack; + + + /* Setup a pointer. */ + pointer = (CHAR *) first_unused_memory; + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + if (status != TX_SUCCESS) + { + + printf("Running Thread Misaligned Stack Test................................ ERROR #1\n"); + test_control_return(1); + } + + /* Push the start one byte past a ULONG boundary. The array itself is + aligned, so adding one is enough to guarantee the fix-up runs whatever + the alignment of the array turned out to be. */ + misaligned_stack = ((CHAR *) misaligned_area) + 1; + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 0, + misaligned_stack, TEST_STACK_SIZE_PRINTF, + 15, 15, TX_NO_TIME_SLICE, TX_AUTO_START); + + if (status != TX_SUCCESS) + { + + printf("Running Thread Misaligned Stack Test................................ ERROR #2\n"); + test_control_return(1); + } +} + + +static void thread_0_entry(ULONG thread_input) +{ + + /* Thread 1 is the higher priority of the two, so this thread first gets the + processor while thread 1 is sleeping. Sleep past that, so the check below + is made against a thread that has actually finished. */ + tx_thread_sleep(5); + + /* Both increments must have happened: one before thread 1 slept and one + after it woke, which is the half that needed the stack to survive a + context switch. */ + if (thread_1_counter != ((ULONG) 2)) + { + + printf("Running Thread Misaligned Stack Test................................ ERROR #3\n"); + test_control_return(1); + } + + /* The thread that ran on the misaligned stack must have run to completion, + which is what says the adjusted stack was usable. */ + if (thread_1.tx_thread_state != TX_COMPLETED) + { + + printf("Running Thread Misaligned Stack Test................................ ERROR #4\n"); + test_control_return(1); + } + + printf("Running Thread Misaligned Stack Test................................ SUCCESS!\n"); + test_control_return(0); +} + + +static void thread_1_entry(ULONG thread_input) +{ + + /* Use the stack either side of a context switch rather than returning + straight away. */ + thread_1_counter++; + + tx_thread_sleep(1); + + thread_1_counter++; +} diff --git a/test/tx/regression/threadx_trace_entry_update_test.c b/test/tx/regression/threadx_trace_entry_update_test.c new file mode 100644 index 000000000..d827497af --- /dev/null +++ b/test/tx/regression/threadx_trace_entry_update_test.c @@ -0,0 +1,331 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/* This test drives the trace entry update paths -- the blocks guarded by + TX_ENABLE_EVENT_TRACE that go back and patch a trace entry after the call + they belong to has finished its work. + + Those blocks all have the same shape: + + if (entry_ptr != TX_NULL) + { + if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp) + { + entry_ptr -> tx_trace_buffer_entry_information_field_N = ...; + } + } + + entry_ptr comes from _tx_trace_buffer_current_ptr, which stays TX_NULL until + tx_trace_enable() is called at run time. Compiling with TX_ENABLE_EVENT_TRACE + is therefore not enough to reach them, and the trace_build configuration on + its own never does: the only other test that enables tracing -- + threadx_trace_basic_test -- exercises the enable API itself and never calls + tx_block_allocate or tx_byte_allocate at all. So the update blocks in + tx_block_allocate.c, tx_byte_allocate.c, tx_thread_system_suspend.c and + tx_thread_system_resume.c were absent from the coverage report's covered set + while appearing in its denominator. + + Both allocators are driven twice, because they carry two of these blocks + each and only one is on the path that succeeds immediately: the second sits + after a suspension, where the allocation completes in the releasing thread's + context. Hence the second thread, which exists only to release what + thread 0 is waiting on. + + The test is built in all five configurations, and four of them do not define + TX_ENABLE_EVENT_TRACE. There tx_trace_enable reports TX_FEATURE_NOT_ENABLED, + the update blocks do not exist, and the allocation sequence below is still a + valid exercise of both allocators' suspension paths -- so the test is + meaningful in every configuration rather than skipped in four. */ + +#include +#include "tx_api.h" +#define TX_SOURCE_CODE +#include "tx_trace.h" + + +void test_control_return(UINT status); + + +static TX_THREAD thread_0; +static TX_THREAD thread_1; + +static TX_BLOCK_POOL block_pool_0; +static TX_BYTE_POOL byte_pool_0; +static TX_SEMAPHORE semaphore_0; + +/* The trace buffer is sized generously on purpose. The inner test of each + update block compares the saved time stamp against the one in the entry, and + a buffer small enough to wrap between the call and its completion would + overwrite the entry and take the false branch every time -- the block would + be reached and its body still never run. */ + +static UCHAR trace_buffer[16384]; + +/* Four blocks of 20 bytes: 100 / (20 + sizeof(void *)) on a 32-bit build. */ + +static UCHAR block_pool_area[100]; +static UCHAR byte_pool_area[512]; + +/* Allocated by thread 0 and released by thread 1, which is what lets thread 0's + suspended allocations complete. */ + +static void *held_block; +static void *held_bytes; + +static UINT error = 0; + + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_trace_entry_update_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Setup a pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Create the pools before tracing is enabled, so that the events this test + cares about are the allocations rather than the creates. */ + status = tx_block_pool_create(&block_pool_0, "trace entry update block pool", + 20, block_pool_area, sizeof(block_pool_area)); + + if (status != TX_SUCCESS) + { + + printf("Running Trace Entry Update Test..................................... ERROR #1\n"); + test_control_return(1); + } + + status = tx_byte_pool_create(&byte_pool_0, "trace entry update byte pool", + byte_pool_area, sizeof(byte_pool_area)); + + if (status != TX_SUCCESS) + { + + printf("Running Trace Entry Update Test..................................... ERROR #2\n"); + test_control_return(1); + } + + /* Turn tracing on. This is the whole point of the test: without it + _tx_trace_buffer_current_ptr stays TX_NULL and every update block below + takes its guarding false branch. */ + _tx_trace_initialize(); + status = tx_trace_enable(trace_buffer, sizeof(trace_buffer), 16); + +#ifdef TX_ENABLE_EVENT_TRACE + + if (status != TX_SUCCESS) + { + + printf("Running Trace Entry Update Test..................................... ERROR #3\n"); + test_control_return(1); + } +#else + + /* Four of the five build configurations reach this branch. The rest of the + test still runs; it just is not exercising any update block. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + printf("Running Trace Entry Update Test..................................... ERROR #4\n"); + test_control_return(1); + } +#endif + + /* Register an object with no name at all, now that tracing is on. The name + copy in _tx_trace_object_register guards against a TX_NULL name and + breaks out of the copy loop, and nothing else in the suite takes that + branch with tracing enabled -- threadx_trace_basic_test makes the + equivalent call only under #ifndef TX_ENABLE_EVENT_TRACE, against the + no-op stub. + + A semaphore rather than a thread, deliberately: for a thread object the + register function dereferences the pointer it is handed to read the + thread's priority, so that type needs a real TX_THREAD behind it. */ + status = tx_semaphore_create(&semaphore_0, TX_NULL, 1); + + if (status != TX_SUCCESS) + { + + printf("Running Trace Entry Update Test..................................... ERROR #5\n"); + test_control_return(1); + } + + /* Thread 0 drives the test and must run first, so it takes the higher + priority -- the lower number. */ + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0, + pointer, TEST_STACK_SIZE_PRINTF, + 15, 15, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + if (status != TX_SUCCESS) + { + + printf("Running Trace Entry Update Test..................................... ERROR #6\n"); + test_control_return(1); + } + + /* Thread 1 releases what thread 0 waits on. It runs only while thread 0 is + suspended, which is exactly when it is needed. */ + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 0, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + if (status != TX_SUCCESS) + { + + printf("Running Trace Entry Update Test..................................... ERROR #7\n"); + test_control_return(1); + } +} + + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; +void *block_ptr; +void *byte_ptr; +UINT i; + + + /* Empty the block pool. The first of these takes the immediate-success path + through tx_block_allocate, which carries the first update block. */ + held_block = TX_NULL; + for (i = 0; i < 4; i++) + { + + status = tx_block_allocate(&block_pool_0, &block_ptr, TX_NO_WAIT); + + if (status != TX_SUCCESS) + { + + error++; + break; + } + + /* Keep the first one for thread 1 to give back. */ + if (held_block == TX_NULL) + { + + held_block = block_ptr; + } + } + + /* The pool is empty now, so this suspends. It completes in thread 1's + context when the block comes back, which is the second update block in + tx_block_allocate -- and the suspend and resume it goes through carry the + update blocks in tx_thread_system_suspend and tx_thread_system_resume. */ + status = tx_block_allocate(&block_pool_0, &block_ptr, TX_WAIT_FOREVER); + + if (status != TX_SUCCESS) + { + + printf("Running Trace Entry Update Test..................................... ERROR #8\n"); + test_control_return(1); + } + + /* Now the same shape for the byte pool. Take most of it first, on the path + that succeeds immediately. */ + status = tx_byte_allocate(&byte_pool_0, &held_bytes, 300, TX_NO_WAIT); + + if (status != TX_SUCCESS) + { + + printf("Running Trace Entry Update Test..................................... ERROR #9\n"); + test_control_return(1); + } + + /* Not enough left, so this one suspends and is satisfied by thread 1's + release. */ + status = tx_byte_allocate(&byte_pool_0, &byte_ptr, 300, TX_WAIT_FOREVER); + + if (status != TX_SUCCESS) + { + + printf("Running Trace Entry Update Test..................................... ERROR #10\n"); + test_control_return(1); + } + + /* Sleep, so that thread 1 gets to run out its entry function and suspend + itself. That leaves nothing ready to execute, which is a third update + block in tx_thread_system_suspend -- the one on the path that sets + _tx_thread_execute_ptr to TX_NULL. The two suspensions above never reach + it, because the other thread was always ready to take over. */ + status = tx_thread_sleep(5); + + if (status != TX_SUCCESS) + { + + printf("Running Trace Entry Update Test..................................... ERROR #11\n"); + test_control_return(1); + } + + if (error) + { + + printf("Running Trace Entry Update Test..................................... ERROR #12\n"); + test_control_return(1); + } + else + { + + printf("Running Trace Entry Update Test..................................... SUCCESS!\n"); + test_control_return(0); + } +} + + +static void thread_1_entry(ULONG thread_input) +{ + +UINT status; + + + /* Reached only when thread 0 has suspended on the empty block pool. */ + status = tx_block_release(held_block); + + if (status != TX_SUCCESS) + { + + error++; + } + + /* And again when thread 0 has suspended on the byte pool. Thread 0 preempts + on the release above, runs until it suspends a second time, and control + comes back here. */ + status = tx_byte_release(held_bytes); + + if (status != TX_SUCCESS) + { + + error++; + } + + /* Thread 0 reports the result; this thread has nothing left to do. */ + tx_thread_suspend(&thread_1); +} From 147754cc869aaa73291b5ca8fd7b102dcd420660 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Wed, 26 Aug 2026 09:13:35 -0400 Subject: [PATCH 090/181] Enforced a coverage floor on the merged report (#667) The coverage summary reported a percentage and could not fail. Coverage could fall from 99.97% to anything at all and every check stayed green, against an AGENTS.md that asks for 100% test coverage -- a stated requirement measured with a gauge that had no failure mode. CodeCoverageSummary already takes thresholds and fail_below_min; neither was set. Both are now, through a new coverage_thresholds input on the template, because the two suites do not sit at the same figure: ThreadX 99, SMP 98. Three things were probed against the pinned action on a runner before picking those numbers, using the real merged.xml files from the dev push run of #666. The floor compares the line rate and nothing else. That mattered because branch coverage is around 78% in both suites while line coverage is 98.8-100%, so a floor aimed at the line figure would have been an immediate red wall had it tested branches or the lower of the two. The ThreadX report at 100.00% lines and 77.67% branches clears a floor of 99. The thresholds are whole numbers. '99.9 100' -- the value this was meant to be -- is rejected with 'System.ArgumentException - Threshold parameter set incorrectly.', and the step fails whether or not fail_below_min is set. So the choice is 99 or 100 with nothing between. 100 would fail on a race. tx_thread_system_resume.c:529 is reached by timing rather than by construction and flaps between runs of the same green tree, which is why #666 left it; 4502/4503 fails a floor of 100 and clears one of 99. A coverage gate that goes red on a coin toss is how coverage gates get switched off. SMP is 5114/5178 lines, 98.76%, with 64 uncovered lines across 11 files of common_smp/src -- #666 closed the equivalent gaps in common/src only. A shared floor of 99 would have failed that job on every run while ThreadX passed. One limit is recorded in the file rather than fixed: an empty report reads as 100%. gcovr writes line-rate="1.0" beside lines-valid="0" when it finds no data, and the action prints 'Line Rate = 100% (0 / 0)' and passes any floor. The check for that is the emptiness assertion #664 put in each suite's coverage.sh, not this one. Also corrected two stale filenames in the deploy job's comment: since #665 each coverage artifact carries merged.xml, not default_build_coverage.xml. Verified on the runner. Assisted-by: Claude Opus 5 --- .github/workflows/regression_template.yml | 55 ++++++++++++++++++++--- .github/workflows/regression_test.yml | 20 +++++++++ 2 files changed, 69 insertions(+), 6 deletions(-) diff --git a/.github/workflows/regression_template.yml b/.github/workflows/regression_template.yml index 7eea8f432..ad2d42aa7 100644 --- a/.github/workflows/regression_template.yml +++ b/.github/workflows/regression_template.yml @@ -38,6 +38,33 @@ on: default: 'merged' required: false type: string + # The lower and upper threshold percentages handed to + # CodeCoverageSummary, lower first. The lower one is a hard floor: the + # step below sets fail_below_min, so a run whose merged line rate falls + # under it turns the job red. + # + # Both must be whole numbers. Probed against the pinned action on a + # runner, 26 Aug 2026: '99.9 100' is rejected with + # 'System.ArgumentException - Threshold parameter set incorrectly.' and + # the step fails whether or not fail_below_min is set, because the action + # parses each half with an integer parse. So a floor can be 99 or 100 and + # nothing between, and the intended 99.9 is not expressible. + # + # The floor is compared against the LINE rate only -- not the branch + # rate, and not the lower of the two. Probed on the same run: the + # ThreadX report at 100.00% lines and 77.67% branches passes a floor of + # 99. Worth knowing, because branch coverage is around 78% in both + # suites while AGENTS.md asks for 100%, and a floor set from the + # headline line figure says nothing about it. + # + # Each suite sets its own in regression_test.yml, because they do not + # sit at the same figure. The default here is the action's own, low + # enough to be no floor at all in practice -- a caller that collects + # coverage is expected to name its number. + coverage_thresholds: + default: '50 75' + required: false + type: string skip_deploy: default: false required: false @@ -128,6 +155,18 @@ jobs: # so a cancelled run still stops promptly -- the same idiom the # deploy_code_coverage job below already uses. The ${{ }} is required: a bare # ! opens a YAML tag, and the expression will not parse without it. + # + # fail_below_min turns the summary into a gate. Until now coverage could + # fall from any figure to any other and no check went red, against an + # AGENTS.md that asks for 100% -- a stated requirement measured with a + # gauge that could not fail. + # + # One thing the floor does not defend, and it is the likeliest way for + # coverage to break: an empty report reads as 100%. gcovr writes + # line-rate="1.0" beside lines-valid="0" when it finds no data, and the + # action reports 'Line Rate = 100% (0 / 0)' and passes any floor -- + # probed on a runner, 26 Aug 2026. The check that catches that is the + # emptiness assertion in each suite's coverage.sh, not this one. - name: Generate Code Coverage Results Summary if: ${{ !cancelled() && (!inputs.skip_coverage) }} uses: irongut/CodeCoverageSummary@51cc3a756ddcd398d447c044c02cb6aa83fdae95 # v1.3.0 @@ -137,6 +176,8 @@ jobs: badge: true hide_complexity: true output: file + thresholds: ${{ inputs.coverage_thresholds }} + fail_below_min: true - name: Write Code Coverage Summary if: ${{ !cancelled() && (!inputs.skip_coverage) }} @@ -239,13 +280,15 @@ jobs: # merge-multiple puts the contents of both coverage artifacts directly # into coverage_report rather than under a directory named for each # artifact. Each one holds a single directory named for its suite, - # ThreadX or SMP, renamed from default_build_coverage by the "Prepare - # Coverage GitHub Pages" step, so the merge yields exactly the two - # suite directories the deploy expects, and the artifact name -- with - # its timestamp -- stops appearing in the published path at all. + # ThreadX or SMP, renamed from merged by the "Prepare Coverage GitHub + # Pages" step, so the merge yields exactly the two suite directories the + # deploy expects, and the artifact name -- with its timestamp -- stops + # appearing in the published path at all. # - # The two artifacts also each carry a default_build_coverage.xml, and - # the merge means one overwrites the other. That file is consumed by + # The two artifacts also each carry a merged.xml -- it was + # default_build_coverage.xml until #665 instrumented every configuration + # and unioned them -- and the merge means one overwrites the other. + # Verified on the runner: both hold merged.xml. That file is consumed by # CodeCoverageSummary back in run_tests and is not read here, so this is # untidy rather than wrong. - uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 diff --git a/.github/workflows/regression_test.yml b/.github/workflows/regression_test.yml index 2aebd7b41..a1e6f0c0a 100644 --- a/.github/workflows/regression_test.yml +++ b/.github/workflows/regression_test.yml @@ -37,6 +37,17 @@ jobs: cmake_path: ./test/tx/cmake result_affix: ThreadX skip_deploy: true + # 99 is the tightest floor available below this suite's figure. The + # merged report reads 4503/4503 lines -- 100.00% -- on the dev push run + # of #666, and two local runs of the same green tree came in at 100.00% + # and 99.98%: tx_thread_system_resume.c:529 is reached by timing rather + # than by construction and flaps between runs, and #666 could not reach + # it deliberately. So a floor of 100 is a check that fails on a race -- + # probed against the pinned action, 4502/4503 fails a floor of 100 and + # clears one of 99 -- and the thresholds are integers, so there is + # nothing between the two. Ratchet this to 100 if 529 is ever covered + # by construction. + coverage_thresholds: '99 100' smp: permissions: contents: read @@ -52,6 +63,15 @@ jobs: cmake_path: ./test/smp/cmake result_affix: SMP skip_deploy: true + # Lower than ThreadX's, because this suite is: the merged report reads + # 5114/5178 lines -- 98.76% -- on the same run, with 64 uncovered lines + # across 11 files of common_smp/src. #666 closed the equivalent gaps in + # common/src only, so common_smp still carries them, plus a family of + # its own in the *_delete.c teardown paths and tx_byte_pool_search.c. + # A shared floor of 99 would therefore red-wall this job on every run + # while ThreadX passed -- probed against the pinned action. Raise this + # towards 99 as those lines are covered. + coverage_thresholds: '98 100' freertos: permissions: contents: read From 9c32abb17d8facca0bc74dcd30bea0ed67635cc6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Fri, 28 Aug 2026 09:24:30 -0400 Subject: [PATCH 091/181] Assembled the module ports, which no check had ever compiled (#672) scripts/check_clang.sh globbed ports_module/*/gnu/src, which does not exist -- the module ports keep their assembly in module_manager/src. The [ -d ] guard skipped it in silence, so 116 assembly files across nine Arm module ports were assembled by no check, with either compiler, in the script whose own comments state three times that "a port that is simply absent from the count reads as covered". Stage 1 goes from 724 of 724 to 840 of 840; the feature-macro stage had the same gap and goes from 412 files to 469. Correcting the path exposed five defects, and only one of them was a build failure. The other four assembled cleanly and did the wrong thing, because GAS runs the C preprocessor on .S and not on .s: ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_unprotect.s, the only .s in a directory of twenty-one .S, ignored all four of its own feature macros. It wrote the caller's LR into the protection structure on every unprotect -- a store guarded by TX_MPCORE_DEBUG_ENABLE -- sent an unconditional SEV, and returned through both BX lr and MOV pc, lr. Its cortex_a5_smp and cortex_a9_smp siblings are .S. ports_module/cortex_m33/.../tx_thread_stack_build.s emitted both arms of an #ifdef TX_SINGLE_MODE_SECURE, so the non-secure LR value overwrote the secure one and the secure build got the wrong frame. ports_module/cortex_m23/.../tx_thread_context_{save,restore}.S carried the POP {r0, lr} that check_clang.sh's own comment describes as the reason the feature-macro stage exists. The 16-bit Thumb POP takes r0-r7 and pc only. The identical fix already sits in ports/cortex_m23/gnu/src; the module copy never got it because nothing scanned it. ports_module/cortex_m23/.../tx_thread_secure_stack_initialize.S used MOV rather than MOVS for an 8-bit immediate, latent behind TX_SINGLE_MODE_SECURE. Both siblings in the same directory already use MOVS. ports_module/cortex_a7/gnu/module_manager/src is the one that failed to assemble, on GCC 14.3 as well as on LLVM: #define SYS_MODE was never expanded, so #SYS_MODE reached the assembler as an undefined symbol. Twenty-nine .s files under gnu trees are renamed to .S. Every one of them is already named .S by the build scripts that compile it, so this repairs those scripts rather than churning them -- ports_module/cortex_a7's build_threadx.bat names all eighteen with a capital S, and works today only on a case-insensitive filesystem. Renaming rather than converting the #defines to GNU assignments is what fixes the #ifdef blocks as well as the constants; the assignments would have fixed two files and left twenty-seven silently ignoring their macros. Files with no preprocessor directives are left as .s: they are not broken, and check_ports.sh gains a check that keeps them that way. Only the gnu trees are checked there -- the IAR, Arm Compiler 5 and Keil assemblers preprocess .s themselves, and about three hundred files in this repository rely on that. Verified with both toolchains on the same tree: 840 of 840 assembled by ATfE 22.1.0 and by arm-gnu-toolchain 14.3.rel1, all five stages of check_clang.sh green, and check_ports.sh green including the reproducibility check. The new check was shown to fail by planting a copy of the file it was written for. No regression test accompanies this. The assembly it covers is executed by no host test, and the check itself going from 724 files to 840 is the coverage AGENTS.md asks for -- together with the new check_ports.sh section, which is what stops the class recurring. Assisted-by: Claude Code (Opus 5) --- ..._low_level.s => tx_initialize_low_level.S} | 0 ..._restore.s => tx_thread_context_restore.S} | 0 ...ontext_save.s => tx_thread_context_save.S} | 0 ...tore.s => tx_thread_fiq_context_restore.S} | 0 ...xt_save.s => tx_thread_fiq_context_save.S} | 0 ...ting_end.s => tx_thread_fiq_nesting_end.S} | 0 ..._start.s => tx_thread_fiq_nesting_start.S} | 0 ...ontrol.s => tx_thread_interrupt_control.S} | 0 ...isable.s => tx_thread_interrupt_disable.S} | 0 ...estore.s => tx_thread_interrupt_restore.S} | 0 ...ting_end.s => tx_thread_irq_nesting_end.S} | 0 ..._start.s => tx_thread_irq_nesting_start.S} | 0 ...thread_schedule.s => tx_thread_schedule.S} | 0 ..._stack_build.s => tx_thread_stack_build.S} | 0 ...tem_return.s => tx_thread_system_return.S} | 0 ...ve.s => tx_thread_vectored_context_save.S} | 0 ...timer_interrupt.s => tx_timer_interrupt.S} | 0 ...> txm_module_manager_thread_stack_build.S} | 0 ...s => txm_module_manager_user_mode_entry.S} | 0 .../src/tx_initialize_low_level.S | 4 +- .../src/tx_thread_context_restore.S | 11 +++- .../src/tx_thread_context_save.S | 11 +++- .../src/tx_thread_secure_stack_initialize.S | 4 +- ..._restore.s => tx_thread_context_restore.S} | 0 ...ontext_save.s => tx_thread_context_save.S} | 0 ...ontrol.s => tx_thread_interrupt_control.S} | 0 ...isable.s => tx_thread_interrupt_disable.S} | 0 ...estore.s => tx_thread_interrupt_restore.S} | 0 ..._stack_build.s => tx_thread_stack_build.S} | 0 ...tem_return.s => tx_thread_system_return.S} | 0 ...> txm_module_manager_thread_stack_build.S} | 0 ..._low_level.s => tx_initialize_low_level.S} | 0 ..._unprotect.s => tx_thread_smp_unprotect.S} | 0 scripts/check_clang.sh | 14 ++++- scripts/check_ports.sh | 56 ++++++++++++++++++- 35 files changed, 94 insertions(+), 6 deletions(-) rename ports_module/cortex_a7/gnu/example_build/{tx_initialize_low_level.s => tx_initialize_low_level.S} (100%) rename ports_module/cortex_a7/gnu/module_manager/src/{tx_thread_context_restore.s => tx_thread_context_restore.S} (100%) rename ports_module/cortex_a7/gnu/module_manager/src/{tx_thread_context_save.s => tx_thread_context_save.S} (100%) rename ports_module/cortex_a7/gnu/module_manager/src/{tx_thread_fiq_context_restore.s => tx_thread_fiq_context_restore.S} (100%) rename ports_module/cortex_a7/gnu/module_manager/src/{tx_thread_fiq_context_save.s => tx_thread_fiq_context_save.S} (100%) rename ports_module/cortex_a7/gnu/module_manager/src/{tx_thread_fiq_nesting_end.s => tx_thread_fiq_nesting_end.S} (100%) rename ports_module/cortex_a7/gnu/module_manager/src/{tx_thread_fiq_nesting_start.s => tx_thread_fiq_nesting_start.S} (100%) rename ports_module/cortex_a7/gnu/module_manager/src/{tx_thread_interrupt_control.s => tx_thread_interrupt_control.S} (100%) rename ports_module/cortex_a7/gnu/module_manager/src/{tx_thread_interrupt_disable.s => tx_thread_interrupt_disable.S} (100%) rename ports_module/cortex_a7/gnu/module_manager/src/{tx_thread_interrupt_restore.s => tx_thread_interrupt_restore.S} (100%) rename ports_module/cortex_a7/gnu/module_manager/src/{tx_thread_irq_nesting_end.s => tx_thread_irq_nesting_end.S} (100%) rename ports_module/cortex_a7/gnu/module_manager/src/{tx_thread_irq_nesting_start.s => tx_thread_irq_nesting_start.S} (100%) rename ports_module/cortex_a7/gnu/module_manager/src/{tx_thread_schedule.s => tx_thread_schedule.S} (100%) rename ports_module/cortex_a7/gnu/module_manager/src/{tx_thread_stack_build.s => tx_thread_stack_build.S} (100%) rename ports_module/cortex_a7/gnu/module_manager/src/{tx_thread_system_return.s => tx_thread_system_return.S} (100%) rename ports_module/cortex_a7/gnu/module_manager/src/{tx_thread_vectored_context_save.s => tx_thread_vectored_context_save.S} (100%) rename ports_module/cortex_a7/gnu/module_manager/src/{tx_timer_interrupt.s => tx_timer_interrupt.S} (100%) rename ports_module/cortex_a7/gnu/module_manager/src/{txm_module_manager_thread_stack_build.s => txm_module_manager_thread_stack_build.S} (100%) rename ports_module/cortex_a7/gnu/module_manager/src/{txm_module_manager_user_mode_entry.s => txm_module_manager_user_mode_entry.S} (100%) rename ports_module/cortex_m33/gnu/module_manager/src/{tx_thread_context_restore.s => tx_thread_context_restore.S} (100%) rename ports_module/cortex_m33/gnu/module_manager/src/{tx_thread_context_save.s => tx_thread_context_save.S} (100%) rename ports_module/cortex_m33/gnu/module_manager/src/{tx_thread_interrupt_control.s => tx_thread_interrupt_control.S} (100%) rename ports_module/cortex_m33/gnu/module_manager/src/{tx_thread_interrupt_disable.s => tx_thread_interrupt_disable.S} (100%) rename ports_module/cortex_m33/gnu/module_manager/src/{tx_thread_interrupt_restore.s => tx_thread_interrupt_restore.S} (100%) rename ports_module/cortex_m33/gnu/module_manager/src/{tx_thread_stack_build.s => tx_thread_stack_build.S} (100%) rename ports_module/cortex_m33/gnu/module_manager/src/{tx_thread_system_return.s => tx_thread_system_return.S} (100%) rename ports_module/cortex_m33/gnu/module_manager/src/{txm_module_manager_thread_stack_build.s => txm_module_manager_thread_stack_build.S} (100%) rename ports_smp/cortex_a5_smp/gnu/example_build/{tx_initialize_low_level.s => tx_initialize_low_level.S} (100%) rename ports_smp/cortex_a7_smp/gnu/src/{tx_thread_smp_unprotect.s => tx_thread_smp_unprotect.S} (100%) diff --git a/ports_module/cortex_a7/gnu/example_build/tx_initialize_low_level.s b/ports_module/cortex_a7/gnu/example_build/tx_initialize_low_level.S similarity index 100% rename from ports_module/cortex_a7/gnu/example_build/tx_initialize_low_level.s rename to ports_module/cortex_a7/gnu/example_build/tx_initialize_low_level.S diff --git a/ports_module/cortex_a7/gnu/module_manager/src/tx_thread_context_restore.s b/ports_module/cortex_a7/gnu/module_manager/src/tx_thread_context_restore.S similarity index 100% rename from ports_module/cortex_a7/gnu/module_manager/src/tx_thread_context_restore.s rename to ports_module/cortex_a7/gnu/module_manager/src/tx_thread_context_restore.S diff --git a/ports_module/cortex_a7/gnu/module_manager/src/tx_thread_context_save.s b/ports_module/cortex_a7/gnu/module_manager/src/tx_thread_context_save.S similarity index 100% rename from ports_module/cortex_a7/gnu/module_manager/src/tx_thread_context_save.s rename to ports_module/cortex_a7/gnu/module_manager/src/tx_thread_context_save.S diff --git a/ports_module/cortex_a7/gnu/module_manager/src/tx_thread_fiq_context_restore.s b/ports_module/cortex_a7/gnu/module_manager/src/tx_thread_fiq_context_restore.S similarity index 100% rename from ports_module/cortex_a7/gnu/module_manager/src/tx_thread_fiq_context_restore.s rename to ports_module/cortex_a7/gnu/module_manager/src/tx_thread_fiq_context_restore.S diff --git a/ports_module/cortex_a7/gnu/module_manager/src/tx_thread_fiq_context_save.s b/ports_module/cortex_a7/gnu/module_manager/src/tx_thread_fiq_context_save.S similarity index 100% rename from ports_module/cortex_a7/gnu/module_manager/src/tx_thread_fiq_context_save.s rename to ports_module/cortex_a7/gnu/module_manager/src/tx_thread_fiq_context_save.S diff --git a/ports_module/cortex_a7/gnu/module_manager/src/tx_thread_fiq_nesting_end.s b/ports_module/cortex_a7/gnu/module_manager/src/tx_thread_fiq_nesting_end.S similarity index 100% rename from ports_module/cortex_a7/gnu/module_manager/src/tx_thread_fiq_nesting_end.s rename to ports_module/cortex_a7/gnu/module_manager/src/tx_thread_fiq_nesting_end.S diff --git a/ports_module/cortex_a7/gnu/module_manager/src/tx_thread_fiq_nesting_start.s b/ports_module/cortex_a7/gnu/module_manager/src/tx_thread_fiq_nesting_start.S similarity index 100% rename from ports_module/cortex_a7/gnu/module_manager/src/tx_thread_fiq_nesting_start.s rename to ports_module/cortex_a7/gnu/module_manager/src/tx_thread_fiq_nesting_start.S diff --git a/ports_module/cortex_a7/gnu/module_manager/src/tx_thread_interrupt_control.s b/ports_module/cortex_a7/gnu/module_manager/src/tx_thread_interrupt_control.S similarity index 100% rename from ports_module/cortex_a7/gnu/module_manager/src/tx_thread_interrupt_control.s rename to ports_module/cortex_a7/gnu/module_manager/src/tx_thread_interrupt_control.S diff --git a/ports_module/cortex_a7/gnu/module_manager/src/tx_thread_interrupt_disable.s b/ports_module/cortex_a7/gnu/module_manager/src/tx_thread_interrupt_disable.S similarity index 100% rename from ports_module/cortex_a7/gnu/module_manager/src/tx_thread_interrupt_disable.s rename to ports_module/cortex_a7/gnu/module_manager/src/tx_thread_interrupt_disable.S diff --git a/ports_module/cortex_a7/gnu/module_manager/src/tx_thread_interrupt_restore.s b/ports_module/cortex_a7/gnu/module_manager/src/tx_thread_interrupt_restore.S similarity index 100% rename from ports_module/cortex_a7/gnu/module_manager/src/tx_thread_interrupt_restore.s rename to ports_module/cortex_a7/gnu/module_manager/src/tx_thread_interrupt_restore.S diff --git a/ports_module/cortex_a7/gnu/module_manager/src/tx_thread_irq_nesting_end.s b/ports_module/cortex_a7/gnu/module_manager/src/tx_thread_irq_nesting_end.S similarity index 100% rename from ports_module/cortex_a7/gnu/module_manager/src/tx_thread_irq_nesting_end.s rename to ports_module/cortex_a7/gnu/module_manager/src/tx_thread_irq_nesting_end.S diff --git a/ports_module/cortex_a7/gnu/module_manager/src/tx_thread_irq_nesting_start.s b/ports_module/cortex_a7/gnu/module_manager/src/tx_thread_irq_nesting_start.S similarity index 100% rename from ports_module/cortex_a7/gnu/module_manager/src/tx_thread_irq_nesting_start.s rename to ports_module/cortex_a7/gnu/module_manager/src/tx_thread_irq_nesting_start.S diff --git a/ports_module/cortex_a7/gnu/module_manager/src/tx_thread_schedule.s b/ports_module/cortex_a7/gnu/module_manager/src/tx_thread_schedule.S similarity index 100% rename from ports_module/cortex_a7/gnu/module_manager/src/tx_thread_schedule.s rename to ports_module/cortex_a7/gnu/module_manager/src/tx_thread_schedule.S diff --git a/ports_module/cortex_a7/gnu/module_manager/src/tx_thread_stack_build.s b/ports_module/cortex_a7/gnu/module_manager/src/tx_thread_stack_build.S similarity index 100% rename from ports_module/cortex_a7/gnu/module_manager/src/tx_thread_stack_build.s rename to ports_module/cortex_a7/gnu/module_manager/src/tx_thread_stack_build.S diff --git a/ports_module/cortex_a7/gnu/module_manager/src/tx_thread_system_return.s b/ports_module/cortex_a7/gnu/module_manager/src/tx_thread_system_return.S similarity index 100% rename from ports_module/cortex_a7/gnu/module_manager/src/tx_thread_system_return.s rename to ports_module/cortex_a7/gnu/module_manager/src/tx_thread_system_return.S diff --git a/ports_module/cortex_a7/gnu/module_manager/src/tx_thread_vectored_context_save.s b/ports_module/cortex_a7/gnu/module_manager/src/tx_thread_vectored_context_save.S similarity index 100% rename from ports_module/cortex_a7/gnu/module_manager/src/tx_thread_vectored_context_save.s rename to ports_module/cortex_a7/gnu/module_manager/src/tx_thread_vectored_context_save.S diff --git a/ports_module/cortex_a7/gnu/module_manager/src/tx_timer_interrupt.s b/ports_module/cortex_a7/gnu/module_manager/src/tx_timer_interrupt.S similarity index 100% rename from ports_module/cortex_a7/gnu/module_manager/src/tx_timer_interrupt.s rename to ports_module/cortex_a7/gnu/module_manager/src/tx_timer_interrupt.S diff --git a/ports_module/cortex_a7/gnu/module_manager/src/txm_module_manager_thread_stack_build.s b/ports_module/cortex_a7/gnu/module_manager/src/txm_module_manager_thread_stack_build.S similarity index 100% rename from ports_module/cortex_a7/gnu/module_manager/src/txm_module_manager_thread_stack_build.s rename to ports_module/cortex_a7/gnu/module_manager/src/txm_module_manager_thread_stack_build.S diff --git a/ports_module/cortex_a7/gnu/module_manager/src/txm_module_manager_user_mode_entry.s b/ports_module/cortex_a7/gnu/module_manager/src/txm_module_manager_user_mode_entry.S similarity index 100% rename from ports_module/cortex_a7/gnu/module_manager/src/txm_module_manager_user_mode_entry.s rename to ports_module/cortex_a7/gnu/module_manager/src/txm_module_manager_user_mode_entry.S diff --git a/ports_module/cortex_m23/gnu/module_manager/src/tx_initialize_low_level.S b/ports_module/cortex_m23/gnu/module_manager/src/tx_initialize_low_level.S index 28c37f367..5e356aeb9 100644 --- a/ports_module/cortex_m23/gnu/module_manager/src/tx_initialize_low_level.S +++ b/ports_module/cortex_m23/gnu/module_manager/src/tx_initialize_low_level.S @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Claude Code (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -105,7 +107,7 @@ _tx_initialize_low_level: /* Configure SysTick. */ LDR r0, =0xE000E000 // Build address of NVIC registers - MOV r1, #0 // Build value for SysTick reset + MOVS r1, #0 // Build value for SysTick reset STR r1, [r0, #0x10] // Reset SysTick Control STR r1, [r0, #0x18] // Reset SysTick Counter Value LDR r1, =SYSTICK_CYCLES diff --git a/ports_module/cortex_m23/gnu/module_manager/src/tx_thread_context_restore.S b/ports_module/cortex_m23/gnu/module_manager/src/tx_thread_context_restore.S index 2f9d7165b..f08f68fb0 100644 --- a/ports_module/cortex_m23/gnu/module_manager/src/tx_thread_context_restore.S +++ b/ports_module/cortex_m23/gnu/module_manager/src/tx_thread_context_restore.S @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Claude Code (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -69,7 +71,14 @@ _tx_thread_context_restore: /* Call the ISR exit function to indicate an ISR is complete. */ PUSH {r0, lr} // Save return address BL _tx_execution_isr_exit // Call the ISR exit function - POP {r0, lr} // Recover return address + POP {r0, r1} // Recover r0 and the return address + MOV lr, r1 // This core cannot POP into LR: the + // 16-bit Thumb POP takes r0-r7 and + // pc only. MOV to a high register + // is permitted, so restore LR from + // a scratch register. r1 is free -- + // the BL above may clobber r0-r3, + // which is why r0 is saved at all. #endif BX lr diff --git a/ports_module/cortex_m23/gnu/module_manager/src/tx_thread_context_save.S b/ports_module/cortex_m23/gnu/module_manager/src/tx_thread_context_save.S index f51cff714..b43467f7b 100644 --- a/ports_module/cortex_m23/gnu/module_manager/src/tx_thread_context_save.S +++ b/ports_module/cortex_m23/gnu/module_manager/src/tx_thread_context_save.S @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Claude Code (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -69,7 +71,14 @@ _tx_thread_context_save: /* Call the ISR enter function to indicate an ISR is starting. */ PUSH {r0, lr} // Save return address BL _tx_execution_isr_enter // Call the ISR enter function - POP {r0, lr} // Recover return address + POP {r0, r1} // Recover r0 and the return address + MOV lr, r1 // This core cannot POP into LR: the + // 16-bit Thumb POP takes r0-r7 and + // pc only. MOV to a high register + // is permitted, so restore LR from + // a scratch register. r1 is free -- + // the BL above may clobber r0-r3, + // which is why r0 is saved at all. #endif BX lr diff --git a/ports_module/cortex_m23/gnu/module_manager/src/tx_thread_secure_stack_initialize.S b/ports_module/cortex_m23/gnu/module_manager/src/tx_thread_secure_stack_initialize.S index ae66a5c58..44cc33962 100644 --- a/ports_module/cortex_m23/gnu/module_manager/src/tx_thread_secure_stack_initialize.S +++ b/ports_module/cortex_m23/gnu/module_manager/src/tx_thread_secure_stack_initialize.S @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Claude Code (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -67,7 +69,7 @@ _tx_thread_secure_stack_initialize: SVC 3 CPSID i // Disable interrupts #else - MOV r0, #0xFF // Feature not enabled + MOVS r0, #0xFF // Feature not enabled #endif BX lr .end diff --git a/ports_module/cortex_m33/gnu/module_manager/src/tx_thread_context_restore.s b/ports_module/cortex_m33/gnu/module_manager/src/tx_thread_context_restore.S similarity index 100% rename from ports_module/cortex_m33/gnu/module_manager/src/tx_thread_context_restore.s rename to ports_module/cortex_m33/gnu/module_manager/src/tx_thread_context_restore.S diff --git a/ports_module/cortex_m33/gnu/module_manager/src/tx_thread_context_save.s b/ports_module/cortex_m33/gnu/module_manager/src/tx_thread_context_save.S similarity index 100% rename from ports_module/cortex_m33/gnu/module_manager/src/tx_thread_context_save.s rename to ports_module/cortex_m33/gnu/module_manager/src/tx_thread_context_save.S diff --git a/ports_module/cortex_m33/gnu/module_manager/src/tx_thread_interrupt_control.s b/ports_module/cortex_m33/gnu/module_manager/src/tx_thread_interrupt_control.S similarity index 100% rename from ports_module/cortex_m33/gnu/module_manager/src/tx_thread_interrupt_control.s rename to ports_module/cortex_m33/gnu/module_manager/src/tx_thread_interrupt_control.S diff --git a/ports_module/cortex_m33/gnu/module_manager/src/tx_thread_interrupt_disable.s b/ports_module/cortex_m33/gnu/module_manager/src/tx_thread_interrupt_disable.S similarity index 100% rename from ports_module/cortex_m33/gnu/module_manager/src/tx_thread_interrupt_disable.s rename to ports_module/cortex_m33/gnu/module_manager/src/tx_thread_interrupt_disable.S diff --git a/ports_module/cortex_m33/gnu/module_manager/src/tx_thread_interrupt_restore.s b/ports_module/cortex_m33/gnu/module_manager/src/tx_thread_interrupt_restore.S similarity index 100% rename from ports_module/cortex_m33/gnu/module_manager/src/tx_thread_interrupt_restore.s rename to ports_module/cortex_m33/gnu/module_manager/src/tx_thread_interrupt_restore.S diff --git a/ports_module/cortex_m33/gnu/module_manager/src/tx_thread_stack_build.s b/ports_module/cortex_m33/gnu/module_manager/src/tx_thread_stack_build.S similarity index 100% rename from ports_module/cortex_m33/gnu/module_manager/src/tx_thread_stack_build.s rename to ports_module/cortex_m33/gnu/module_manager/src/tx_thread_stack_build.S diff --git a/ports_module/cortex_m33/gnu/module_manager/src/tx_thread_system_return.s b/ports_module/cortex_m33/gnu/module_manager/src/tx_thread_system_return.S similarity index 100% rename from ports_module/cortex_m33/gnu/module_manager/src/tx_thread_system_return.s rename to ports_module/cortex_m33/gnu/module_manager/src/tx_thread_system_return.S diff --git a/ports_module/cortex_m33/gnu/module_manager/src/txm_module_manager_thread_stack_build.s b/ports_module/cortex_m33/gnu/module_manager/src/txm_module_manager_thread_stack_build.S similarity index 100% rename from ports_module/cortex_m33/gnu/module_manager/src/txm_module_manager_thread_stack_build.s rename to ports_module/cortex_m33/gnu/module_manager/src/txm_module_manager_thread_stack_build.S diff --git a/ports_smp/cortex_a5_smp/gnu/example_build/tx_initialize_low_level.s b/ports_smp/cortex_a5_smp/gnu/example_build/tx_initialize_low_level.S similarity index 100% rename from ports_smp/cortex_a5_smp/gnu/example_build/tx_initialize_low_level.s rename to ports_smp/cortex_a5_smp/gnu/example_build/tx_initialize_low_level.S diff --git a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_unprotect.s b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_unprotect.S similarity index 100% rename from ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_unprotect.s rename to ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_unprotect.S diff --git a/scripts/check_clang.sh b/scripts/check_clang.sh index ca646f312..f8ced1dd0 100755 --- a/scripts/check_clang.sh +++ b/scripts/check_clang.sh @@ -211,7 +211,13 @@ say "" say "== Assembly sources of every Arm gnu port ==" total=0 -for dir in ports/*/gnu/src ports_smp/*/gnu/src ports_module/*/gnu/src; do +# The module ports keep their assembly in module_manager/src, not src. This +# glob read ports_module/*/gnu/src until 26 Aug 2026; that directory does not +# exist, the [ -d ] guard below skipped it in silence, and 116 files across +# nine Arm module ports were assembled by no check with either compiler. The +# count went from 724 to 840 when the path was corrected, and three of the new +# files did not assemble. +for dir in ports/*/gnu/src ports_smp/*/gnu/src ports_module/*/gnu/module_manager/src; do [ -d "$dir" ] || continue core="$(echo "$dir" | cut -d/ -f2)" spec="${PORT_TARGET[$core]:-}" @@ -246,7 +252,13 @@ say "== Assembly behind feature macros ==" for macro in $FEATURE_MACROS; do macro_total=0 macro_bad=0 + # The module ports are named here for the same reason as in the stage + # above: they were absent from this list until 26 Aug 2026 and so read as + # covered. Adding them found the Cortex-M23 module manager carrying the + # very POP {r0, lr} this comment describes, six months after the same fix + # landed in its non-module sibling. for src in $(grep -rl "$macro" ports/*/gnu/src/*.S ports_smp/*/gnu/src/*.S \ + ports_module/*/gnu/module_manager/src/*.S \ 2>/dev/null | sort); do core="$(echo "$src" | cut -d/ -f2)" spec="${PORT_TARGET[$core]:-}" diff --git a/scripts/check_ports.sh b/scripts/check_ports.sh index b177a7ef6..1ba13ca03 100755 --- a/scripts/check_ports.sh +++ b/scripts/check_ports.sh @@ -39,6 +39,11 @@ # body in ports/cortex_m4/ac6/inc/tx_port.h, which placed statements # outside any function. See issue 569. # +# 4. Lowercase .s under a gnu tree. GAS preprocesses .S and not .s, so a +# .s file's #ifdef blocks are assembled whichever way the macro is set. +# Twenty-nine files were in that state, including one non-module SMP +# kernel port, and only one of them failed to assemble. +# # The last section reports, without failing, on port families that have no copy # script and so cannot be checked for reproducibility. # @@ -197,7 +202,56 @@ done < <(find ports ports_arch ports_module ports_smp -name "*.h" -type f \ [ "$orphans" -eq 0 ] && say " ok: no port header carries code at file scope" # -------------------------------------------------------------------------- -# 4. Report only: families with no copy script. +# 4. GNU assembly that uses the preprocessor must be named .S, not .s. +# -------------------------------------------------------------------------- +# GAS runs the C preprocessor on .S and not on .s. In a .s file every line +# beginning with # is just a comment, so nothing fails and nothing is +# substituted: a #define constant reaches the assembler as an undefined +# symbol, an #ifdef block is assembled whatever the macro says, and an +# #if/#else pair emits *both* branches. The port silently ignores its own +# feature macros. +# +# Measured 26 Aug 2026, when a corrected glob in check_clang.sh first offered +# the module ports to a compiler. Twenty-nine files were affected, and the +# damage was not only cosmetic: +# +# ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_unprotect.s -- the only .s +# in a directory of twenty-one .S -- wrote the caller's LR into the +# protection structure on every unprotect, a store guarded by +# TX_MPCORE_DEBUG_ENABLE, and returned through both BX lr and MOV pc, lr. +# +# ports_module/cortex_m33/.../tx_thread_stack_build.s emitted both arms of +# an #ifdef TX_SINGLE_MODE_SECURE, so the second LR value overwrote the +# first and the secure build got the non-secure one. +# +# ports_module/cortex_a7/.../tx_thread_schedule.s did fail to assemble, on +# GCC 14.3 as well as on LLVM, because #define SYS_MODE was never expanded. +# That is the only one of the twenty-nine any compiler complained about. +# +# Only the gnu trees are checked. The IAR, Arm Compiler 5 and Keil assemblers +# preprocess .s themselves, so the same combination is correct there, and +# around three hundred files in this repository depend on it. +say "" +say "== GNU assembly using the preprocessor is named .S ==" + +lowercase=0 +while IFS= read -r f; do + first="$(grep -nE '^[ \t]*#[ \t]*(define|include|if|ifdef|ifndef|else|elif|endif|undef)\b' \ + "$f" | head -1)" + if [ -n "$first" ]; then + fail "$f: preprocessor directive in a .s file, which GAS does not preprocess" + echo " line $first" + echo " Rename the file to .S. Check the callers first: a build script" + echo " that already names it .S is the usual sign of how this happened." + lowercase=$((lowercase + 1)) + fi +done < <(find ports ports_arch ports_module ports_smp -name "*.s" -type f \ + -path "*/gnu/*" 2>/dev/null | sort) + +[ "$lowercase" -eq 0 ] && say " ok: no .s file under a gnu tree uses the preprocessor" + +# -------------------------------------------------------------------------- +# 5. Report only: families with no copy script. # -------------------------------------------------------------------------- # These are maintained by hand, so a fix applied to one toolchain can silently # miss the others. Nothing here fails the run; it is a prompt to look. From 5b94bad6a207ebb6d8135d719efff0de86e712e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Fri, 28 Aug 2026 09:26:12 -0400 Subject: [PATCH 092/181] Fixed the AArch64 samples, none of which had ever linked with GCC (#673) Every AArch64 gnu example build failed at the sample link, all 27 of them -- 13 under ports/ and 14 under ports_smp/: libg.a(libc_a-init.o): in function `__libc_init_array': undefined reference to `_init' relocation truncated to fit: R_AARCH64_CALL26 against undefined symbol `_init' libg.a(libc_a-fini.o): in function `__libc_fini_array': undefined reference to `_fini' build_threadx_sample.sh links with -nostartfiles, which is correct for a port carrying its own reset path, and that drops crti.o and crtn.o along with everything else. startup.S calls __libc_init_array by design, and newlib's implementation calls _init, which crti.o is what defines. The AArch32 scripts are unaffected: they use nosys.specs and never reach __libc_init_array. The fix links crti.o and crtn.o explicitly, bracketing the object list -- the first must precede every .init contribution and the second must follow all of them, so their position is load-bearing rather than stylistic. Both paths come from the compiler's own -print-file-name, so nothing here hard-codes a toolchain layout. The atfe branch sets both to empty, deliberately: picolibc's __libc_init_array does not call _init, those 27 images link today, and adding crti.o would change a working link for no reason. That is also why check_clang.sh is green on these and does not list them as expected to fail -- the LLVM path never reached the gap, so nothing has ever linked them and failed. Fixed in ports_arch/ARMv8-A/threadx/ports/gnu/example_build, which is the single source for both the ports/ and ports_smp/ copies, then regenerated with update.sh --port-sets tx,tx_smp. The 27 generated copies are in this commit because ports_arch_check compares them. Verified: all 27 link with arm-gnu-toolchain 14.3.rel1 aarch64-none-elf, where 0 of 27 did before; _init and _fini disassemble to the expected crti prologue and crtn epilogue over a ret; check_clang.sh with ATfE 22.1.0 is still green on all five stages, including the 42 script-driven example builds; check_ports.sh is green including the reproducibility check. No regression test: these are link-only example images that no host test executes. What guards them is check_clang.sh's example stage today, and check_gcc.sh's, which is the next change and is the reason this was found. Assisted-by: Claude Code (Opus 5) --- .../gnu/example_build/build_threadx_sample.sh | 24 ++++++++++++++++++- .../gnu/example_build/build_threadx_sample.sh | 24 ++++++++++++++++++- .../gnu/example_build/build_threadx_sample.sh | 24 ++++++++++++++++++- .../gnu/example_build/build_threadx_sample.sh | 24 ++++++++++++++++++- .../gnu/example_build/build_threadx_sample.sh | 24 ++++++++++++++++++- .../gnu/example_build/build_threadx_sample.sh | 24 ++++++++++++++++++- .../gnu/example_build/build_threadx_sample.sh | 24 ++++++++++++++++++- .../gnu/example_build/build_threadx_sample.sh | 24 ++++++++++++++++++- .../gnu/example_build/build_threadx_sample.sh | 24 ++++++++++++++++++- .../gnu/example_build/build_threadx_sample.sh | 24 ++++++++++++++++++- .../gnu/example_build/build_threadx_sample.sh | 24 ++++++++++++++++++- .../gnu/example_build/build_threadx_sample.sh | 24 ++++++++++++++++++- .../gnu/example_build/build_threadx_sample.sh | 24 ++++++++++++++++++- .../gnu/example_build/build_threadx_sample.sh | 24 ++++++++++++++++++- .../gnu/example_build/build_threadx_sample.sh | 24 ++++++++++++++++++- .../gnu/example_build/build_threadx_sample.sh | 24 ++++++++++++++++++- .../gnu/example_build/build_threadx_sample.sh | 24 ++++++++++++++++++- .../gnu/example_build/build_threadx_sample.sh | 24 ++++++++++++++++++- .../gnu/example_build/build_threadx_sample.sh | 24 ++++++++++++++++++- .../gnu/example_build/build_threadx_sample.sh | 24 ++++++++++++++++++- .../gnu/example_build/build_threadx_sample.sh | 24 ++++++++++++++++++- .../gnu/example_build/build_threadx_sample.sh | 24 ++++++++++++++++++- .../gnu/example_build/build_threadx_sample.sh | 24 ++++++++++++++++++- .../gnu/example_build/build_threadx_sample.sh | 24 ++++++++++++++++++- .../gnu/example_build/build_threadx_sample.sh | 24 ++++++++++++++++++- .../gnu/example_build/build_threadx_sample.sh | 24 ++++++++++++++++++- .../gnu/example_build/build_threadx_sample.sh | 24 ++++++++++++++++++- .../gnu/example_build/build_threadx_sample.sh | 24 ++++++++++++++++++- 28 files changed, 644 insertions(+), 28 deletions(-) diff --git a/ports/cortex_a34/gnu/example_build/build_threadx_sample.sh b/ports/cortex_a34/gnu/example_build/build_threadx_sample.sh index fa5b92ec3..94248a888 100755 --- a/ports/cortex_a34/gnu/example_build/build_threadx_sample.sh +++ b/ports/cortex_a34/gnu/example_build/build_threadx_sample.sh @@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in # initialise_monitor_handles that startup.S calls. SYSCALL_LIB="--specs=rdimon.specs" SEMIHOST_STUB="" + # crti.o defines _init and _fini; crtn.o closes them. The link below + # passes -nostartfiles, which is right for a port with its own reset + # path but also drops these two, and startup.S calls + # __libc_init_array, whose newlib implementation calls _init. Without + # them every AArch64 sample failed to link: + # + # libg.a(libc_a-init.o): in function `__libc_init_array': + # undefined reference to `_init' + # relocation truncated to fit: R_AARCH64_CALL26 against undefined + # symbol `_init' + # + # crti.o must precede every other .init contribution and crtn.o must + # follow all of them, which is why they bracket the object list rather + # than sitting with the other flags. The AArch32 scripts need none of + # this: they use nosys.specs and never reach __libc_init_array. + CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)" + CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)" ;; atfe) CC="${ATFE_CLANG:-clang}" @@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in # picolibc has no initialise_monitor_handles, and neither does the # toolchain's semihosting library, so the weak stub stands in for it. SEMIHOST_STUB="sample_threadx/semihost_stub.S" + # Deliberately empty. picolibc's __libc_init_array does not call _init, + # so these images link today and adding crti.o would change a working + # link for no reason. + CRT_BEGIN="" + CRT_END="" ;; *) echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 @@ -80,7 +102,7 @@ done "${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \ -T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \ -o sample_threadx.out -Wl,-Map=sample_threadx.map \ - ${objects} tx.a + ${CRT_BEGIN} ${objects} tx.a ${CRT_END} rm -f ${objects} diff --git a/ports/cortex_a35/gnu/example_build/build_threadx_sample.sh b/ports/cortex_a35/gnu/example_build/build_threadx_sample.sh index fa5b92ec3..94248a888 100755 --- a/ports/cortex_a35/gnu/example_build/build_threadx_sample.sh +++ b/ports/cortex_a35/gnu/example_build/build_threadx_sample.sh @@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in # initialise_monitor_handles that startup.S calls. SYSCALL_LIB="--specs=rdimon.specs" SEMIHOST_STUB="" + # crti.o defines _init and _fini; crtn.o closes them. The link below + # passes -nostartfiles, which is right for a port with its own reset + # path but also drops these two, and startup.S calls + # __libc_init_array, whose newlib implementation calls _init. Without + # them every AArch64 sample failed to link: + # + # libg.a(libc_a-init.o): in function `__libc_init_array': + # undefined reference to `_init' + # relocation truncated to fit: R_AARCH64_CALL26 against undefined + # symbol `_init' + # + # crti.o must precede every other .init contribution and crtn.o must + # follow all of them, which is why they bracket the object list rather + # than sitting with the other flags. The AArch32 scripts need none of + # this: they use nosys.specs and never reach __libc_init_array. + CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)" + CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)" ;; atfe) CC="${ATFE_CLANG:-clang}" @@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in # picolibc has no initialise_monitor_handles, and neither does the # toolchain's semihosting library, so the weak stub stands in for it. SEMIHOST_STUB="sample_threadx/semihost_stub.S" + # Deliberately empty. picolibc's __libc_init_array does not call _init, + # so these images link today and adding crti.o would change a working + # link for no reason. + CRT_BEGIN="" + CRT_END="" ;; *) echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 @@ -80,7 +102,7 @@ done "${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \ -T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \ -o sample_threadx.out -Wl,-Map=sample_threadx.map \ - ${objects} tx.a + ${CRT_BEGIN} ${objects} tx.a ${CRT_END} rm -f ${objects} diff --git a/ports/cortex_a53/gnu/example_build/build_threadx_sample.sh b/ports/cortex_a53/gnu/example_build/build_threadx_sample.sh index fa5b92ec3..94248a888 100755 --- a/ports/cortex_a53/gnu/example_build/build_threadx_sample.sh +++ b/ports/cortex_a53/gnu/example_build/build_threadx_sample.sh @@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in # initialise_monitor_handles that startup.S calls. SYSCALL_LIB="--specs=rdimon.specs" SEMIHOST_STUB="" + # crti.o defines _init and _fini; crtn.o closes them. The link below + # passes -nostartfiles, which is right for a port with its own reset + # path but also drops these two, and startup.S calls + # __libc_init_array, whose newlib implementation calls _init. Without + # them every AArch64 sample failed to link: + # + # libg.a(libc_a-init.o): in function `__libc_init_array': + # undefined reference to `_init' + # relocation truncated to fit: R_AARCH64_CALL26 against undefined + # symbol `_init' + # + # crti.o must precede every other .init contribution and crtn.o must + # follow all of them, which is why they bracket the object list rather + # than sitting with the other flags. The AArch32 scripts need none of + # this: they use nosys.specs and never reach __libc_init_array. + CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)" + CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)" ;; atfe) CC="${ATFE_CLANG:-clang}" @@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in # picolibc has no initialise_monitor_handles, and neither does the # toolchain's semihosting library, so the weak stub stands in for it. SEMIHOST_STUB="sample_threadx/semihost_stub.S" + # Deliberately empty. picolibc's __libc_init_array does not call _init, + # so these images link today and adding crti.o would change a working + # link for no reason. + CRT_BEGIN="" + CRT_END="" ;; *) echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 @@ -80,7 +102,7 @@ done "${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \ -T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \ -o sample_threadx.out -Wl,-Map=sample_threadx.map \ - ${objects} tx.a + ${CRT_BEGIN} ${objects} tx.a ${CRT_END} rm -f ${objects} diff --git a/ports/cortex_a55/gnu/example_build/build_threadx_sample.sh b/ports/cortex_a55/gnu/example_build/build_threadx_sample.sh index fa5b92ec3..94248a888 100755 --- a/ports/cortex_a55/gnu/example_build/build_threadx_sample.sh +++ b/ports/cortex_a55/gnu/example_build/build_threadx_sample.sh @@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in # initialise_monitor_handles that startup.S calls. SYSCALL_LIB="--specs=rdimon.specs" SEMIHOST_STUB="" + # crti.o defines _init and _fini; crtn.o closes them. The link below + # passes -nostartfiles, which is right for a port with its own reset + # path but also drops these two, and startup.S calls + # __libc_init_array, whose newlib implementation calls _init. Without + # them every AArch64 sample failed to link: + # + # libg.a(libc_a-init.o): in function `__libc_init_array': + # undefined reference to `_init' + # relocation truncated to fit: R_AARCH64_CALL26 against undefined + # symbol `_init' + # + # crti.o must precede every other .init contribution and crtn.o must + # follow all of them, which is why they bracket the object list rather + # than sitting with the other flags. The AArch32 scripts need none of + # this: they use nosys.specs and never reach __libc_init_array. + CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)" + CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)" ;; atfe) CC="${ATFE_CLANG:-clang}" @@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in # picolibc has no initialise_monitor_handles, and neither does the # toolchain's semihosting library, so the weak stub stands in for it. SEMIHOST_STUB="sample_threadx/semihost_stub.S" + # Deliberately empty. picolibc's __libc_init_array does not call _init, + # so these images link today and adding crti.o would change a working + # link for no reason. + CRT_BEGIN="" + CRT_END="" ;; *) echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 @@ -80,7 +102,7 @@ done "${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \ -T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \ -o sample_threadx.out -Wl,-Map=sample_threadx.map \ - ${objects} tx.a + ${CRT_BEGIN} ${objects} tx.a ${CRT_END} rm -f ${objects} diff --git a/ports/cortex_a57/gnu/example_build/build_threadx_sample.sh b/ports/cortex_a57/gnu/example_build/build_threadx_sample.sh index fa5b92ec3..94248a888 100755 --- a/ports/cortex_a57/gnu/example_build/build_threadx_sample.sh +++ b/ports/cortex_a57/gnu/example_build/build_threadx_sample.sh @@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in # initialise_monitor_handles that startup.S calls. SYSCALL_LIB="--specs=rdimon.specs" SEMIHOST_STUB="" + # crti.o defines _init and _fini; crtn.o closes them. The link below + # passes -nostartfiles, which is right for a port with its own reset + # path but also drops these two, and startup.S calls + # __libc_init_array, whose newlib implementation calls _init. Without + # them every AArch64 sample failed to link: + # + # libg.a(libc_a-init.o): in function `__libc_init_array': + # undefined reference to `_init' + # relocation truncated to fit: R_AARCH64_CALL26 against undefined + # symbol `_init' + # + # crti.o must precede every other .init contribution and crtn.o must + # follow all of them, which is why they bracket the object list rather + # than sitting with the other flags. The AArch32 scripts need none of + # this: they use nosys.specs and never reach __libc_init_array. + CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)" + CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)" ;; atfe) CC="${ATFE_CLANG:-clang}" @@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in # picolibc has no initialise_monitor_handles, and neither does the # toolchain's semihosting library, so the weak stub stands in for it. SEMIHOST_STUB="sample_threadx/semihost_stub.S" + # Deliberately empty. picolibc's __libc_init_array does not call _init, + # so these images link today and adding crti.o would change a working + # link for no reason. + CRT_BEGIN="" + CRT_END="" ;; *) echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 @@ -80,7 +102,7 @@ done "${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \ -T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \ -o sample_threadx.out -Wl,-Map=sample_threadx.map \ - ${objects} tx.a + ${CRT_BEGIN} ${objects} tx.a ${CRT_END} rm -f ${objects} diff --git a/ports/cortex_a65/gnu/example_build/build_threadx_sample.sh b/ports/cortex_a65/gnu/example_build/build_threadx_sample.sh index fa5b92ec3..94248a888 100755 --- a/ports/cortex_a65/gnu/example_build/build_threadx_sample.sh +++ b/ports/cortex_a65/gnu/example_build/build_threadx_sample.sh @@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in # initialise_monitor_handles that startup.S calls. SYSCALL_LIB="--specs=rdimon.specs" SEMIHOST_STUB="" + # crti.o defines _init and _fini; crtn.o closes them. The link below + # passes -nostartfiles, which is right for a port with its own reset + # path but also drops these two, and startup.S calls + # __libc_init_array, whose newlib implementation calls _init. Without + # them every AArch64 sample failed to link: + # + # libg.a(libc_a-init.o): in function `__libc_init_array': + # undefined reference to `_init' + # relocation truncated to fit: R_AARCH64_CALL26 against undefined + # symbol `_init' + # + # crti.o must precede every other .init contribution and crtn.o must + # follow all of them, which is why they bracket the object list rather + # than sitting with the other flags. The AArch32 scripts need none of + # this: they use nosys.specs and never reach __libc_init_array. + CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)" + CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)" ;; atfe) CC="${ATFE_CLANG:-clang}" @@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in # picolibc has no initialise_monitor_handles, and neither does the # toolchain's semihosting library, so the weak stub stands in for it. SEMIHOST_STUB="sample_threadx/semihost_stub.S" + # Deliberately empty. picolibc's __libc_init_array does not call _init, + # so these images link today and adding crti.o would change a working + # link for no reason. + CRT_BEGIN="" + CRT_END="" ;; *) echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 @@ -80,7 +102,7 @@ done "${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \ -T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \ -o sample_threadx.out -Wl,-Map=sample_threadx.map \ - ${objects} tx.a + ${CRT_BEGIN} ${objects} tx.a ${CRT_END} rm -f ${objects} diff --git a/ports/cortex_a65ae/gnu/example_build/build_threadx_sample.sh b/ports/cortex_a65ae/gnu/example_build/build_threadx_sample.sh index fa5b92ec3..94248a888 100755 --- a/ports/cortex_a65ae/gnu/example_build/build_threadx_sample.sh +++ b/ports/cortex_a65ae/gnu/example_build/build_threadx_sample.sh @@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in # initialise_monitor_handles that startup.S calls. SYSCALL_LIB="--specs=rdimon.specs" SEMIHOST_STUB="" + # crti.o defines _init and _fini; crtn.o closes them. The link below + # passes -nostartfiles, which is right for a port with its own reset + # path but also drops these two, and startup.S calls + # __libc_init_array, whose newlib implementation calls _init. Without + # them every AArch64 sample failed to link: + # + # libg.a(libc_a-init.o): in function `__libc_init_array': + # undefined reference to `_init' + # relocation truncated to fit: R_AARCH64_CALL26 against undefined + # symbol `_init' + # + # crti.o must precede every other .init contribution and crtn.o must + # follow all of them, which is why they bracket the object list rather + # than sitting with the other flags. The AArch32 scripts need none of + # this: they use nosys.specs and never reach __libc_init_array. + CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)" + CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)" ;; atfe) CC="${ATFE_CLANG:-clang}" @@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in # picolibc has no initialise_monitor_handles, and neither does the # toolchain's semihosting library, so the weak stub stands in for it. SEMIHOST_STUB="sample_threadx/semihost_stub.S" + # Deliberately empty. picolibc's __libc_init_array does not call _init, + # so these images link today and adding crti.o would change a working + # link for no reason. + CRT_BEGIN="" + CRT_END="" ;; *) echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 @@ -80,7 +102,7 @@ done "${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \ -T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \ -o sample_threadx.out -Wl,-Map=sample_threadx.map \ - ${objects} tx.a + ${CRT_BEGIN} ${objects} tx.a ${CRT_END} rm -f ${objects} diff --git a/ports/cortex_a72/gnu/example_build/build_threadx_sample.sh b/ports/cortex_a72/gnu/example_build/build_threadx_sample.sh index fa5b92ec3..94248a888 100755 --- a/ports/cortex_a72/gnu/example_build/build_threadx_sample.sh +++ b/ports/cortex_a72/gnu/example_build/build_threadx_sample.sh @@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in # initialise_monitor_handles that startup.S calls. SYSCALL_LIB="--specs=rdimon.specs" SEMIHOST_STUB="" + # crti.o defines _init and _fini; crtn.o closes them. The link below + # passes -nostartfiles, which is right for a port with its own reset + # path but also drops these two, and startup.S calls + # __libc_init_array, whose newlib implementation calls _init. Without + # them every AArch64 sample failed to link: + # + # libg.a(libc_a-init.o): in function `__libc_init_array': + # undefined reference to `_init' + # relocation truncated to fit: R_AARCH64_CALL26 against undefined + # symbol `_init' + # + # crti.o must precede every other .init contribution and crtn.o must + # follow all of them, which is why they bracket the object list rather + # than sitting with the other flags. The AArch32 scripts need none of + # this: they use nosys.specs and never reach __libc_init_array. + CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)" + CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)" ;; atfe) CC="${ATFE_CLANG:-clang}" @@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in # picolibc has no initialise_monitor_handles, and neither does the # toolchain's semihosting library, so the weak stub stands in for it. SEMIHOST_STUB="sample_threadx/semihost_stub.S" + # Deliberately empty. picolibc's __libc_init_array does not call _init, + # so these images link today and adding crti.o would change a working + # link for no reason. + CRT_BEGIN="" + CRT_END="" ;; *) echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 @@ -80,7 +102,7 @@ done "${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \ -T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \ -o sample_threadx.out -Wl,-Map=sample_threadx.map \ - ${objects} tx.a + ${CRT_BEGIN} ${objects} tx.a ${CRT_END} rm -f ${objects} diff --git a/ports/cortex_a73/gnu/example_build/build_threadx_sample.sh b/ports/cortex_a73/gnu/example_build/build_threadx_sample.sh index fa5b92ec3..94248a888 100755 --- a/ports/cortex_a73/gnu/example_build/build_threadx_sample.sh +++ b/ports/cortex_a73/gnu/example_build/build_threadx_sample.sh @@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in # initialise_monitor_handles that startup.S calls. SYSCALL_LIB="--specs=rdimon.specs" SEMIHOST_STUB="" + # crti.o defines _init and _fini; crtn.o closes them. The link below + # passes -nostartfiles, which is right for a port with its own reset + # path but also drops these two, and startup.S calls + # __libc_init_array, whose newlib implementation calls _init. Without + # them every AArch64 sample failed to link: + # + # libg.a(libc_a-init.o): in function `__libc_init_array': + # undefined reference to `_init' + # relocation truncated to fit: R_AARCH64_CALL26 against undefined + # symbol `_init' + # + # crti.o must precede every other .init contribution and crtn.o must + # follow all of them, which is why they bracket the object list rather + # than sitting with the other flags. The AArch32 scripts need none of + # this: they use nosys.specs and never reach __libc_init_array. + CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)" + CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)" ;; atfe) CC="${ATFE_CLANG:-clang}" @@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in # picolibc has no initialise_monitor_handles, and neither does the # toolchain's semihosting library, so the weak stub stands in for it. SEMIHOST_STUB="sample_threadx/semihost_stub.S" + # Deliberately empty. picolibc's __libc_init_array does not call _init, + # so these images link today and adding crti.o would change a working + # link for no reason. + CRT_BEGIN="" + CRT_END="" ;; *) echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 @@ -80,7 +102,7 @@ done "${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \ -T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \ -o sample_threadx.out -Wl,-Map=sample_threadx.map \ - ${objects} tx.a + ${CRT_BEGIN} ${objects} tx.a ${CRT_END} rm -f ${objects} diff --git a/ports/cortex_a75/gnu/example_build/build_threadx_sample.sh b/ports/cortex_a75/gnu/example_build/build_threadx_sample.sh index fa5b92ec3..94248a888 100755 --- a/ports/cortex_a75/gnu/example_build/build_threadx_sample.sh +++ b/ports/cortex_a75/gnu/example_build/build_threadx_sample.sh @@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in # initialise_monitor_handles that startup.S calls. SYSCALL_LIB="--specs=rdimon.specs" SEMIHOST_STUB="" + # crti.o defines _init and _fini; crtn.o closes them. The link below + # passes -nostartfiles, which is right for a port with its own reset + # path but also drops these two, and startup.S calls + # __libc_init_array, whose newlib implementation calls _init. Without + # them every AArch64 sample failed to link: + # + # libg.a(libc_a-init.o): in function `__libc_init_array': + # undefined reference to `_init' + # relocation truncated to fit: R_AARCH64_CALL26 against undefined + # symbol `_init' + # + # crti.o must precede every other .init contribution and crtn.o must + # follow all of them, which is why they bracket the object list rather + # than sitting with the other flags. The AArch32 scripts need none of + # this: they use nosys.specs and never reach __libc_init_array. + CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)" + CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)" ;; atfe) CC="${ATFE_CLANG:-clang}" @@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in # picolibc has no initialise_monitor_handles, and neither does the # toolchain's semihosting library, so the weak stub stands in for it. SEMIHOST_STUB="sample_threadx/semihost_stub.S" + # Deliberately empty. picolibc's __libc_init_array does not call _init, + # so these images link today and adding crti.o would change a working + # link for no reason. + CRT_BEGIN="" + CRT_END="" ;; *) echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 @@ -80,7 +102,7 @@ done "${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \ -T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \ -o sample_threadx.out -Wl,-Map=sample_threadx.map \ - ${objects} tx.a + ${CRT_BEGIN} ${objects} tx.a ${CRT_END} rm -f ${objects} diff --git a/ports/cortex_a76/gnu/example_build/build_threadx_sample.sh b/ports/cortex_a76/gnu/example_build/build_threadx_sample.sh index fa5b92ec3..94248a888 100755 --- a/ports/cortex_a76/gnu/example_build/build_threadx_sample.sh +++ b/ports/cortex_a76/gnu/example_build/build_threadx_sample.sh @@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in # initialise_monitor_handles that startup.S calls. SYSCALL_LIB="--specs=rdimon.specs" SEMIHOST_STUB="" + # crti.o defines _init and _fini; crtn.o closes them. The link below + # passes -nostartfiles, which is right for a port with its own reset + # path but also drops these two, and startup.S calls + # __libc_init_array, whose newlib implementation calls _init. Without + # them every AArch64 sample failed to link: + # + # libg.a(libc_a-init.o): in function `__libc_init_array': + # undefined reference to `_init' + # relocation truncated to fit: R_AARCH64_CALL26 against undefined + # symbol `_init' + # + # crti.o must precede every other .init contribution and crtn.o must + # follow all of them, which is why they bracket the object list rather + # than sitting with the other flags. The AArch32 scripts need none of + # this: they use nosys.specs and never reach __libc_init_array. + CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)" + CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)" ;; atfe) CC="${ATFE_CLANG:-clang}" @@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in # picolibc has no initialise_monitor_handles, and neither does the # toolchain's semihosting library, so the weak stub stands in for it. SEMIHOST_STUB="sample_threadx/semihost_stub.S" + # Deliberately empty. picolibc's __libc_init_array does not call _init, + # so these images link today and adding crti.o would change a working + # link for no reason. + CRT_BEGIN="" + CRT_END="" ;; *) echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 @@ -80,7 +102,7 @@ done "${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \ -T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \ -o sample_threadx.out -Wl,-Map=sample_threadx.map \ - ${objects} tx.a + ${CRT_BEGIN} ${objects} tx.a ${CRT_END} rm -f ${objects} diff --git a/ports/cortex_a76ae/gnu/example_build/build_threadx_sample.sh b/ports/cortex_a76ae/gnu/example_build/build_threadx_sample.sh index fa5b92ec3..94248a888 100755 --- a/ports/cortex_a76ae/gnu/example_build/build_threadx_sample.sh +++ b/ports/cortex_a76ae/gnu/example_build/build_threadx_sample.sh @@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in # initialise_monitor_handles that startup.S calls. SYSCALL_LIB="--specs=rdimon.specs" SEMIHOST_STUB="" + # crti.o defines _init and _fini; crtn.o closes them. The link below + # passes -nostartfiles, which is right for a port with its own reset + # path but also drops these two, and startup.S calls + # __libc_init_array, whose newlib implementation calls _init. Without + # them every AArch64 sample failed to link: + # + # libg.a(libc_a-init.o): in function `__libc_init_array': + # undefined reference to `_init' + # relocation truncated to fit: R_AARCH64_CALL26 against undefined + # symbol `_init' + # + # crti.o must precede every other .init contribution and crtn.o must + # follow all of them, which is why they bracket the object list rather + # than sitting with the other flags. The AArch32 scripts need none of + # this: they use nosys.specs and never reach __libc_init_array. + CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)" + CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)" ;; atfe) CC="${ATFE_CLANG:-clang}" @@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in # picolibc has no initialise_monitor_handles, and neither does the # toolchain's semihosting library, so the weak stub stands in for it. SEMIHOST_STUB="sample_threadx/semihost_stub.S" + # Deliberately empty. picolibc's __libc_init_array does not call _init, + # so these images link today and adding crti.o would change a working + # link for no reason. + CRT_BEGIN="" + CRT_END="" ;; *) echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 @@ -80,7 +102,7 @@ done "${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \ -T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \ -o sample_threadx.out -Wl,-Map=sample_threadx.map \ - ${objects} tx.a + ${CRT_BEGIN} ${objects} tx.a ${CRT_END} rm -f ${objects} diff --git a/ports/cortex_a77/gnu/example_build/build_threadx_sample.sh b/ports/cortex_a77/gnu/example_build/build_threadx_sample.sh index fa5b92ec3..94248a888 100755 --- a/ports/cortex_a77/gnu/example_build/build_threadx_sample.sh +++ b/ports/cortex_a77/gnu/example_build/build_threadx_sample.sh @@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in # initialise_monitor_handles that startup.S calls. SYSCALL_LIB="--specs=rdimon.specs" SEMIHOST_STUB="" + # crti.o defines _init and _fini; crtn.o closes them. The link below + # passes -nostartfiles, which is right for a port with its own reset + # path but also drops these two, and startup.S calls + # __libc_init_array, whose newlib implementation calls _init. Without + # them every AArch64 sample failed to link: + # + # libg.a(libc_a-init.o): in function `__libc_init_array': + # undefined reference to `_init' + # relocation truncated to fit: R_AARCH64_CALL26 against undefined + # symbol `_init' + # + # crti.o must precede every other .init contribution and crtn.o must + # follow all of them, which is why they bracket the object list rather + # than sitting with the other flags. The AArch32 scripts need none of + # this: they use nosys.specs and never reach __libc_init_array. + CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)" + CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)" ;; atfe) CC="${ATFE_CLANG:-clang}" @@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in # picolibc has no initialise_monitor_handles, and neither does the # toolchain's semihosting library, so the weak stub stands in for it. SEMIHOST_STUB="sample_threadx/semihost_stub.S" + # Deliberately empty. picolibc's __libc_init_array does not call _init, + # so these images link today and adding crti.o would change a working + # link for no reason. + CRT_BEGIN="" + CRT_END="" ;; *) echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 @@ -80,7 +102,7 @@ done "${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \ -T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \ -o sample_threadx.out -Wl,-Map=sample_threadx.map \ - ${objects} tx.a + ${CRT_BEGIN} ${objects} tx.a ${CRT_END} rm -f ${objects} diff --git a/ports_arch/ARMv8-A/threadx/ports/gnu/example_build/build_threadx_sample.sh b/ports_arch/ARMv8-A/threadx/ports/gnu/example_build/build_threadx_sample.sh index fa5b92ec3..94248a888 100755 --- a/ports_arch/ARMv8-A/threadx/ports/gnu/example_build/build_threadx_sample.sh +++ b/ports_arch/ARMv8-A/threadx/ports/gnu/example_build/build_threadx_sample.sh @@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in # initialise_monitor_handles that startup.S calls. SYSCALL_LIB="--specs=rdimon.specs" SEMIHOST_STUB="" + # crti.o defines _init and _fini; crtn.o closes them. The link below + # passes -nostartfiles, which is right for a port with its own reset + # path but also drops these two, and startup.S calls + # __libc_init_array, whose newlib implementation calls _init. Without + # them every AArch64 sample failed to link: + # + # libg.a(libc_a-init.o): in function `__libc_init_array': + # undefined reference to `_init' + # relocation truncated to fit: R_AARCH64_CALL26 against undefined + # symbol `_init' + # + # crti.o must precede every other .init contribution and crtn.o must + # follow all of them, which is why they bracket the object list rather + # than sitting with the other flags. The AArch32 scripts need none of + # this: they use nosys.specs and never reach __libc_init_array. + CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)" + CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)" ;; atfe) CC="${ATFE_CLANG:-clang}" @@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in # picolibc has no initialise_monitor_handles, and neither does the # toolchain's semihosting library, so the weak stub stands in for it. SEMIHOST_STUB="sample_threadx/semihost_stub.S" + # Deliberately empty. picolibc's __libc_init_array does not call _init, + # so these images link today and adding crti.o would change a working + # link for no reason. + CRT_BEGIN="" + CRT_END="" ;; *) echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 @@ -80,7 +102,7 @@ done "${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \ -T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \ -o sample_threadx.out -Wl,-Map=sample_threadx.map \ - ${objects} tx.a + ${CRT_BEGIN} ${objects} tx.a ${CRT_END} rm -f ${objects} diff --git a/ports_smp/cortex_a34_smp/gnu/example_build/build_threadx_sample.sh b/ports_smp/cortex_a34_smp/gnu/example_build/build_threadx_sample.sh index fa5b92ec3..94248a888 100755 --- a/ports_smp/cortex_a34_smp/gnu/example_build/build_threadx_sample.sh +++ b/ports_smp/cortex_a34_smp/gnu/example_build/build_threadx_sample.sh @@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in # initialise_monitor_handles that startup.S calls. SYSCALL_LIB="--specs=rdimon.specs" SEMIHOST_STUB="" + # crti.o defines _init and _fini; crtn.o closes them. The link below + # passes -nostartfiles, which is right for a port with its own reset + # path but also drops these two, and startup.S calls + # __libc_init_array, whose newlib implementation calls _init. Without + # them every AArch64 sample failed to link: + # + # libg.a(libc_a-init.o): in function `__libc_init_array': + # undefined reference to `_init' + # relocation truncated to fit: R_AARCH64_CALL26 against undefined + # symbol `_init' + # + # crti.o must precede every other .init contribution and crtn.o must + # follow all of them, which is why they bracket the object list rather + # than sitting with the other flags. The AArch32 scripts need none of + # this: they use nosys.specs and never reach __libc_init_array. + CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)" + CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)" ;; atfe) CC="${ATFE_CLANG:-clang}" @@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in # picolibc has no initialise_monitor_handles, and neither does the # toolchain's semihosting library, so the weak stub stands in for it. SEMIHOST_STUB="sample_threadx/semihost_stub.S" + # Deliberately empty. picolibc's __libc_init_array does not call _init, + # so these images link today and adding crti.o would change a working + # link for no reason. + CRT_BEGIN="" + CRT_END="" ;; *) echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 @@ -80,7 +102,7 @@ done "${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \ -T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \ -o sample_threadx.out -Wl,-Map=sample_threadx.map \ - ${objects} tx.a + ${CRT_BEGIN} ${objects} tx.a ${CRT_END} rm -f ${objects} diff --git a/ports_smp/cortex_a35_smp/gnu/example_build/build_threadx_sample.sh b/ports_smp/cortex_a35_smp/gnu/example_build/build_threadx_sample.sh index fa5b92ec3..94248a888 100755 --- a/ports_smp/cortex_a35_smp/gnu/example_build/build_threadx_sample.sh +++ b/ports_smp/cortex_a35_smp/gnu/example_build/build_threadx_sample.sh @@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in # initialise_monitor_handles that startup.S calls. SYSCALL_LIB="--specs=rdimon.specs" SEMIHOST_STUB="" + # crti.o defines _init and _fini; crtn.o closes them. The link below + # passes -nostartfiles, which is right for a port with its own reset + # path but also drops these two, and startup.S calls + # __libc_init_array, whose newlib implementation calls _init. Without + # them every AArch64 sample failed to link: + # + # libg.a(libc_a-init.o): in function `__libc_init_array': + # undefined reference to `_init' + # relocation truncated to fit: R_AARCH64_CALL26 against undefined + # symbol `_init' + # + # crti.o must precede every other .init contribution and crtn.o must + # follow all of them, which is why they bracket the object list rather + # than sitting with the other flags. The AArch32 scripts need none of + # this: they use nosys.specs and never reach __libc_init_array. + CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)" + CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)" ;; atfe) CC="${ATFE_CLANG:-clang}" @@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in # picolibc has no initialise_monitor_handles, and neither does the # toolchain's semihosting library, so the weak stub stands in for it. SEMIHOST_STUB="sample_threadx/semihost_stub.S" + # Deliberately empty. picolibc's __libc_init_array does not call _init, + # so these images link today and adding crti.o would change a working + # link for no reason. + CRT_BEGIN="" + CRT_END="" ;; *) echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 @@ -80,7 +102,7 @@ done "${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \ -T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \ -o sample_threadx.out -Wl,-Map=sample_threadx.map \ - ${objects} tx.a + ${CRT_BEGIN} ${objects} tx.a ${CRT_END} rm -f ${objects} diff --git a/ports_smp/cortex_a53_smp/gnu/example_build/build_threadx_sample.sh b/ports_smp/cortex_a53_smp/gnu/example_build/build_threadx_sample.sh index fa5b92ec3..94248a888 100755 --- a/ports_smp/cortex_a53_smp/gnu/example_build/build_threadx_sample.sh +++ b/ports_smp/cortex_a53_smp/gnu/example_build/build_threadx_sample.sh @@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in # initialise_monitor_handles that startup.S calls. SYSCALL_LIB="--specs=rdimon.specs" SEMIHOST_STUB="" + # crti.o defines _init and _fini; crtn.o closes them. The link below + # passes -nostartfiles, which is right for a port with its own reset + # path but also drops these two, and startup.S calls + # __libc_init_array, whose newlib implementation calls _init. Without + # them every AArch64 sample failed to link: + # + # libg.a(libc_a-init.o): in function `__libc_init_array': + # undefined reference to `_init' + # relocation truncated to fit: R_AARCH64_CALL26 against undefined + # symbol `_init' + # + # crti.o must precede every other .init contribution and crtn.o must + # follow all of them, which is why they bracket the object list rather + # than sitting with the other flags. The AArch32 scripts need none of + # this: they use nosys.specs and never reach __libc_init_array. + CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)" + CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)" ;; atfe) CC="${ATFE_CLANG:-clang}" @@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in # picolibc has no initialise_monitor_handles, and neither does the # toolchain's semihosting library, so the weak stub stands in for it. SEMIHOST_STUB="sample_threadx/semihost_stub.S" + # Deliberately empty. picolibc's __libc_init_array does not call _init, + # so these images link today and adding crti.o would change a working + # link for no reason. + CRT_BEGIN="" + CRT_END="" ;; *) echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 @@ -80,7 +102,7 @@ done "${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \ -T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \ -o sample_threadx.out -Wl,-Map=sample_threadx.map \ - ${objects} tx.a + ${CRT_BEGIN} ${objects} tx.a ${CRT_END} rm -f ${objects} diff --git a/ports_smp/cortex_a55_smp/gnu/example_build/build_threadx_sample.sh b/ports_smp/cortex_a55_smp/gnu/example_build/build_threadx_sample.sh index fa5b92ec3..94248a888 100755 --- a/ports_smp/cortex_a55_smp/gnu/example_build/build_threadx_sample.sh +++ b/ports_smp/cortex_a55_smp/gnu/example_build/build_threadx_sample.sh @@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in # initialise_monitor_handles that startup.S calls. SYSCALL_LIB="--specs=rdimon.specs" SEMIHOST_STUB="" + # crti.o defines _init and _fini; crtn.o closes them. The link below + # passes -nostartfiles, which is right for a port with its own reset + # path but also drops these two, and startup.S calls + # __libc_init_array, whose newlib implementation calls _init. Without + # them every AArch64 sample failed to link: + # + # libg.a(libc_a-init.o): in function `__libc_init_array': + # undefined reference to `_init' + # relocation truncated to fit: R_AARCH64_CALL26 against undefined + # symbol `_init' + # + # crti.o must precede every other .init contribution and crtn.o must + # follow all of them, which is why they bracket the object list rather + # than sitting with the other flags. The AArch32 scripts need none of + # this: they use nosys.specs and never reach __libc_init_array. + CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)" + CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)" ;; atfe) CC="${ATFE_CLANG:-clang}" @@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in # picolibc has no initialise_monitor_handles, and neither does the # toolchain's semihosting library, so the weak stub stands in for it. SEMIHOST_STUB="sample_threadx/semihost_stub.S" + # Deliberately empty. picolibc's __libc_init_array does not call _init, + # so these images link today and adding crti.o would change a working + # link for no reason. + CRT_BEGIN="" + CRT_END="" ;; *) echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 @@ -80,7 +102,7 @@ done "${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \ -T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \ -o sample_threadx.out -Wl,-Map=sample_threadx.map \ - ${objects} tx.a + ${CRT_BEGIN} ${objects} tx.a ${CRT_END} rm -f ${objects} diff --git a/ports_smp/cortex_a57_smp/gnu/example_build/build_threadx_sample.sh b/ports_smp/cortex_a57_smp/gnu/example_build/build_threadx_sample.sh index fa5b92ec3..94248a888 100755 --- a/ports_smp/cortex_a57_smp/gnu/example_build/build_threadx_sample.sh +++ b/ports_smp/cortex_a57_smp/gnu/example_build/build_threadx_sample.sh @@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in # initialise_monitor_handles that startup.S calls. SYSCALL_LIB="--specs=rdimon.specs" SEMIHOST_STUB="" + # crti.o defines _init and _fini; crtn.o closes them. The link below + # passes -nostartfiles, which is right for a port with its own reset + # path but also drops these two, and startup.S calls + # __libc_init_array, whose newlib implementation calls _init. Without + # them every AArch64 sample failed to link: + # + # libg.a(libc_a-init.o): in function `__libc_init_array': + # undefined reference to `_init' + # relocation truncated to fit: R_AARCH64_CALL26 against undefined + # symbol `_init' + # + # crti.o must precede every other .init contribution and crtn.o must + # follow all of them, which is why they bracket the object list rather + # than sitting with the other flags. The AArch32 scripts need none of + # this: they use nosys.specs and never reach __libc_init_array. + CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)" + CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)" ;; atfe) CC="${ATFE_CLANG:-clang}" @@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in # picolibc has no initialise_monitor_handles, and neither does the # toolchain's semihosting library, so the weak stub stands in for it. SEMIHOST_STUB="sample_threadx/semihost_stub.S" + # Deliberately empty. picolibc's __libc_init_array does not call _init, + # so these images link today and adding crti.o would change a working + # link for no reason. + CRT_BEGIN="" + CRT_END="" ;; *) echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 @@ -80,7 +102,7 @@ done "${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \ -T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \ -o sample_threadx.out -Wl,-Map=sample_threadx.map \ - ${objects} tx.a + ${CRT_BEGIN} ${objects} tx.a ${CRT_END} rm -f ${objects} diff --git a/ports_smp/cortex_a65_smp/gnu/example_build/build_threadx_sample.sh b/ports_smp/cortex_a65_smp/gnu/example_build/build_threadx_sample.sh index fa5b92ec3..94248a888 100755 --- a/ports_smp/cortex_a65_smp/gnu/example_build/build_threadx_sample.sh +++ b/ports_smp/cortex_a65_smp/gnu/example_build/build_threadx_sample.sh @@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in # initialise_monitor_handles that startup.S calls. SYSCALL_LIB="--specs=rdimon.specs" SEMIHOST_STUB="" + # crti.o defines _init and _fini; crtn.o closes them. The link below + # passes -nostartfiles, which is right for a port with its own reset + # path but also drops these two, and startup.S calls + # __libc_init_array, whose newlib implementation calls _init. Without + # them every AArch64 sample failed to link: + # + # libg.a(libc_a-init.o): in function `__libc_init_array': + # undefined reference to `_init' + # relocation truncated to fit: R_AARCH64_CALL26 against undefined + # symbol `_init' + # + # crti.o must precede every other .init contribution and crtn.o must + # follow all of them, which is why they bracket the object list rather + # than sitting with the other flags. The AArch32 scripts need none of + # this: they use nosys.specs and never reach __libc_init_array. + CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)" + CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)" ;; atfe) CC="${ATFE_CLANG:-clang}" @@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in # picolibc has no initialise_monitor_handles, and neither does the # toolchain's semihosting library, so the weak stub stands in for it. SEMIHOST_STUB="sample_threadx/semihost_stub.S" + # Deliberately empty. picolibc's __libc_init_array does not call _init, + # so these images link today and adding crti.o would change a working + # link for no reason. + CRT_BEGIN="" + CRT_END="" ;; *) echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 @@ -80,7 +102,7 @@ done "${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \ -T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \ -o sample_threadx.out -Wl,-Map=sample_threadx.map \ - ${objects} tx.a + ${CRT_BEGIN} ${objects} tx.a ${CRT_END} rm -f ${objects} diff --git a/ports_smp/cortex_a65ae_smp/gnu/example_build/build_threadx_sample.sh b/ports_smp/cortex_a65ae_smp/gnu/example_build/build_threadx_sample.sh index fa5b92ec3..94248a888 100755 --- a/ports_smp/cortex_a65ae_smp/gnu/example_build/build_threadx_sample.sh +++ b/ports_smp/cortex_a65ae_smp/gnu/example_build/build_threadx_sample.sh @@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in # initialise_monitor_handles that startup.S calls. SYSCALL_LIB="--specs=rdimon.specs" SEMIHOST_STUB="" + # crti.o defines _init and _fini; crtn.o closes them. The link below + # passes -nostartfiles, which is right for a port with its own reset + # path but also drops these two, and startup.S calls + # __libc_init_array, whose newlib implementation calls _init. Without + # them every AArch64 sample failed to link: + # + # libg.a(libc_a-init.o): in function `__libc_init_array': + # undefined reference to `_init' + # relocation truncated to fit: R_AARCH64_CALL26 against undefined + # symbol `_init' + # + # crti.o must precede every other .init contribution and crtn.o must + # follow all of them, which is why they bracket the object list rather + # than sitting with the other flags. The AArch32 scripts need none of + # this: they use nosys.specs and never reach __libc_init_array. + CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)" + CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)" ;; atfe) CC="${ATFE_CLANG:-clang}" @@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in # picolibc has no initialise_monitor_handles, and neither does the # toolchain's semihosting library, so the weak stub stands in for it. SEMIHOST_STUB="sample_threadx/semihost_stub.S" + # Deliberately empty. picolibc's __libc_init_array does not call _init, + # so these images link today and adding crti.o would change a working + # link for no reason. + CRT_BEGIN="" + CRT_END="" ;; *) echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 @@ -80,7 +102,7 @@ done "${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \ -T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \ -o sample_threadx.out -Wl,-Map=sample_threadx.map \ - ${objects} tx.a + ${CRT_BEGIN} ${objects} tx.a ${CRT_END} rm -f ${objects} diff --git a/ports_smp/cortex_a72_smp/gnu/example_build/build_threadx_sample.sh b/ports_smp/cortex_a72_smp/gnu/example_build/build_threadx_sample.sh index fa5b92ec3..94248a888 100755 --- a/ports_smp/cortex_a72_smp/gnu/example_build/build_threadx_sample.sh +++ b/ports_smp/cortex_a72_smp/gnu/example_build/build_threadx_sample.sh @@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in # initialise_monitor_handles that startup.S calls. SYSCALL_LIB="--specs=rdimon.specs" SEMIHOST_STUB="" + # crti.o defines _init and _fini; crtn.o closes them. The link below + # passes -nostartfiles, which is right for a port with its own reset + # path but also drops these two, and startup.S calls + # __libc_init_array, whose newlib implementation calls _init. Without + # them every AArch64 sample failed to link: + # + # libg.a(libc_a-init.o): in function `__libc_init_array': + # undefined reference to `_init' + # relocation truncated to fit: R_AARCH64_CALL26 against undefined + # symbol `_init' + # + # crti.o must precede every other .init contribution and crtn.o must + # follow all of them, which is why they bracket the object list rather + # than sitting with the other flags. The AArch32 scripts need none of + # this: they use nosys.specs and never reach __libc_init_array. + CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)" + CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)" ;; atfe) CC="${ATFE_CLANG:-clang}" @@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in # picolibc has no initialise_monitor_handles, and neither does the # toolchain's semihosting library, so the weak stub stands in for it. SEMIHOST_STUB="sample_threadx/semihost_stub.S" + # Deliberately empty. picolibc's __libc_init_array does not call _init, + # so these images link today and adding crti.o would change a working + # link for no reason. + CRT_BEGIN="" + CRT_END="" ;; *) echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 @@ -80,7 +102,7 @@ done "${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \ -T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \ -o sample_threadx.out -Wl,-Map=sample_threadx.map \ - ${objects} tx.a + ${CRT_BEGIN} ${objects} tx.a ${CRT_END} rm -f ${objects} diff --git a/ports_smp/cortex_a73_smp/gnu/example_build/build_threadx_sample.sh b/ports_smp/cortex_a73_smp/gnu/example_build/build_threadx_sample.sh index fa5b92ec3..94248a888 100755 --- a/ports_smp/cortex_a73_smp/gnu/example_build/build_threadx_sample.sh +++ b/ports_smp/cortex_a73_smp/gnu/example_build/build_threadx_sample.sh @@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in # initialise_monitor_handles that startup.S calls. SYSCALL_LIB="--specs=rdimon.specs" SEMIHOST_STUB="" + # crti.o defines _init and _fini; crtn.o closes them. The link below + # passes -nostartfiles, which is right for a port with its own reset + # path but also drops these two, and startup.S calls + # __libc_init_array, whose newlib implementation calls _init. Without + # them every AArch64 sample failed to link: + # + # libg.a(libc_a-init.o): in function `__libc_init_array': + # undefined reference to `_init' + # relocation truncated to fit: R_AARCH64_CALL26 against undefined + # symbol `_init' + # + # crti.o must precede every other .init contribution and crtn.o must + # follow all of them, which is why they bracket the object list rather + # than sitting with the other flags. The AArch32 scripts need none of + # this: they use nosys.specs and never reach __libc_init_array. + CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)" + CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)" ;; atfe) CC="${ATFE_CLANG:-clang}" @@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in # picolibc has no initialise_monitor_handles, and neither does the # toolchain's semihosting library, so the weak stub stands in for it. SEMIHOST_STUB="sample_threadx/semihost_stub.S" + # Deliberately empty. picolibc's __libc_init_array does not call _init, + # so these images link today and adding crti.o would change a working + # link for no reason. + CRT_BEGIN="" + CRT_END="" ;; *) echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 @@ -80,7 +102,7 @@ done "${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \ -T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \ -o sample_threadx.out -Wl,-Map=sample_threadx.map \ - ${objects} tx.a + ${CRT_BEGIN} ${objects} tx.a ${CRT_END} rm -f ${objects} diff --git a/ports_smp/cortex_a75_smp/gnu/example_build/build_threadx_sample.sh b/ports_smp/cortex_a75_smp/gnu/example_build/build_threadx_sample.sh index fa5b92ec3..94248a888 100755 --- a/ports_smp/cortex_a75_smp/gnu/example_build/build_threadx_sample.sh +++ b/ports_smp/cortex_a75_smp/gnu/example_build/build_threadx_sample.sh @@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in # initialise_monitor_handles that startup.S calls. SYSCALL_LIB="--specs=rdimon.specs" SEMIHOST_STUB="" + # crti.o defines _init and _fini; crtn.o closes them. The link below + # passes -nostartfiles, which is right for a port with its own reset + # path but also drops these two, and startup.S calls + # __libc_init_array, whose newlib implementation calls _init. Without + # them every AArch64 sample failed to link: + # + # libg.a(libc_a-init.o): in function `__libc_init_array': + # undefined reference to `_init' + # relocation truncated to fit: R_AARCH64_CALL26 against undefined + # symbol `_init' + # + # crti.o must precede every other .init contribution and crtn.o must + # follow all of them, which is why they bracket the object list rather + # than sitting with the other flags. The AArch32 scripts need none of + # this: they use nosys.specs and never reach __libc_init_array. + CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)" + CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)" ;; atfe) CC="${ATFE_CLANG:-clang}" @@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in # picolibc has no initialise_monitor_handles, and neither does the # toolchain's semihosting library, so the weak stub stands in for it. SEMIHOST_STUB="sample_threadx/semihost_stub.S" + # Deliberately empty. picolibc's __libc_init_array does not call _init, + # so these images link today and adding crti.o would change a working + # link for no reason. + CRT_BEGIN="" + CRT_END="" ;; *) echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 @@ -80,7 +102,7 @@ done "${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \ -T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \ -o sample_threadx.out -Wl,-Map=sample_threadx.map \ - ${objects} tx.a + ${CRT_BEGIN} ${objects} tx.a ${CRT_END} rm -f ${objects} diff --git a/ports_smp/cortex_a76_smp/gnu/example_build/build_threadx_sample.sh b/ports_smp/cortex_a76_smp/gnu/example_build/build_threadx_sample.sh index fa5b92ec3..94248a888 100755 --- a/ports_smp/cortex_a76_smp/gnu/example_build/build_threadx_sample.sh +++ b/ports_smp/cortex_a76_smp/gnu/example_build/build_threadx_sample.sh @@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in # initialise_monitor_handles that startup.S calls. SYSCALL_LIB="--specs=rdimon.specs" SEMIHOST_STUB="" + # crti.o defines _init and _fini; crtn.o closes them. The link below + # passes -nostartfiles, which is right for a port with its own reset + # path but also drops these two, and startup.S calls + # __libc_init_array, whose newlib implementation calls _init. Without + # them every AArch64 sample failed to link: + # + # libg.a(libc_a-init.o): in function `__libc_init_array': + # undefined reference to `_init' + # relocation truncated to fit: R_AARCH64_CALL26 against undefined + # symbol `_init' + # + # crti.o must precede every other .init contribution and crtn.o must + # follow all of them, which is why they bracket the object list rather + # than sitting with the other flags. The AArch32 scripts need none of + # this: they use nosys.specs and never reach __libc_init_array. + CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)" + CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)" ;; atfe) CC="${ATFE_CLANG:-clang}" @@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in # picolibc has no initialise_monitor_handles, and neither does the # toolchain's semihosting library, so the weak stub stands in for it. SEMIHOST_STUB="sample_threadx/semihost_stub.S" + # Deliberately empty. picolibc's __libc_init_array does not call _init, + # so these images link today and adding crti.o would change a working + # link for no reason. + CRT_BEGIN="" + CRT_END="" ;; *) echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 @@ -80,7 +102,7 @@ done "${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \ -T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \ -o sample_threadx.out -Wl,-Map=sample_threadx.map \ - ${objects} tx.a + ${CRT_BEGIN} ${objects} tx.a ${CRT_END} rm -f ${objects} diff --git a/ports_smp/cortex_a76ae_smp/gnu/example_build/build_threadx_sample.sh b/ports_smp/cortex_a76ae_smp/gnu/example_build/build_threadx_sample.sh index fa5b92ec3..94248a888 100755 --- a/ports_smp/cortex_a76ae_smp/gnu/example_build/build_threadx_sample.sh +++ b/ports_smp/cortex_a76ae_smp/gnu/example_build/build_threadx_sample.sh @@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in # initialise_monitor_handles that startup.S calls. SYSCALL_LIB="--specs=rdimon.specs" SEMIHOST_STUB="" + # crti.o defines _init and _fini; crtn.o closes them. The link below + # passes -nostartfiles, which is right for a port with its own reset + # path but also drops these two, and startup.S calls + # __libc_init_array, whose newlib implementation calls _init. Without + # them every AArch64 sample failed to link: + # + # libg.a(libc_a-init.o): in function `__libc_init_array': + # undefined reference to `_init' + # relocation truncated to fit: R_AARCH64_CALL26 against undefined + # symbol `_init' + # + # crti.o must precede every other .init contribution and crtn.o must + # follow all of them, which is why they bracket the object list rather + # than sitting with the other flags. The AArch32 scripts need none of + # this: they use nosys.specs and never reach __libc_init_array. + CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)" + CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)" ;; atfe) CC="${ATFE_CLANG:-clang}" @@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in # picolibc has no initialise_monitor_handles, and neither does the # toolchain's semihosting library, so the weak stub stands in for it. SEMIHOST_STUB="sample_threadx/semihost_stub.S" + # Deliberately empty. picolibc's __libc_init_array does not call _init, + # so these images link today and adding crti.o would change a working + # link for no reason. + CRT_BEGIN="" + CRT_END="" ;; *) echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 @@ -80,7 +102,7 @@ done "${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \ -T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \ -o sample_threadx.out -Wl,-Map=sample_threadx.map \ - ${objects} tx.a + ${CRT_BEGIN} ${objects} tx.a ${CRT_END} rm -f ${objects} diff --git a/ports_smp/cortex_a77_smp/gnu/example_build/build_threadx_sample.sh b/ports_smp/cortex_a77_smp/gnu/example_build/build_threadx_sample.sh index fa5b92ec3..94248a888 100755 --- a/ports_smp/cortex_a77_smp/gnu/example_build/build_threadx_sample.sh +++ b/ports_smp/cortex_a77_smp/gnu/example_build/build_threadx_sample.sh @@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in # initialise_monitor_handles that startup.S calls. SYSCALL_LIB="--specs=rdimon.specs" SEMIHOST_STUB="" + # crti.o defines _init and _fini; crtn.o closes them. The link below + # passes -nostartfiles, which is right for a port with its own reset + # path but also drops these two, and startup.S calls + # __libc_init_array, whose newlib implementation calls _init. Without + # them every AArch64 sample failed to link: + # + # libg.a(libc_a-init.o): in function `__libc_init_array': + # undefined reference to `_init' + # relocation truncated to fit: R_AARCH64_CALL26 against undefined + # symbol `_init' + # + # crti.o must precede every other .init contribution and crtn.o must + # follow all of them, which is why they bracket the object list rather + # than sitting with the other flags. The AArch32 scripts need none of + # this: they use nosys.specs and never reach __libc_init_array. + CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)" + CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)" ;; atfe) CC="${ATFE_CLANG:-clang}" @@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in # picolibc has no initialise_monitor_handles, and neither does the # toolchain's semihosting library, so the weak stub stands in for it. SEMIHOST_STUB="sample_threadx/semihost_stub.S" + # Deliberately empty. picolibc's __libc_init_array does not call _init, + # so these images link today and adding crti.o would change a working + # link for no reason. + CRT_BEGIN="" + CRT_END="" ;; *) echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 @@ -80,7 +102,7 @@ done "${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \ -T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \ -o sample_threadx.out -Wl,-Map=sample_threadx.map \ - ${objects} tx.a + ${CRT_BEGIN} ${objects} tx.a ${CRT_END} rm -f ${objects} diff --git a/ports_smp/cortex_a78_smp/gnu/example_build/build_threadx_sample.sh b/ports_smp/cortex_a78_smp/gnu/example_build/build_threadx_sample.sh index fa5b92ec3..94248a888 100755 --- a/ports_smp/cortex_a78_smp/gnu/example_build/build_threadx_sample.sh +++ b/ports_smp/cortex_a78_smp/gnu/example_build/build_threadx_sample.sh @@ -44,6 +44,23 @@ case "${TOOLCHAIN}" in # initialise_monitor_handles that startup.S calls. SYSCALL_LIB="--specs=rdimon.specs" SEMIHOST_STUB="" + # crti.o defines _init and _fini; crtn.o closes them. The link below + # passes -nostartfiles, which is right for a port with its own reset + # path but also drops these two, and startup.S calls + # __libc_init_array, whose newlib implementation calls _init. Without + # them every AArch64 sample failed to link: + # + # libg.a(libc_a-init.o): in function `__libc_init_array': + # undefined reference to `_init' + # relocation truncated to fit: R_AARCH64_CALL26 against undefined + # symbol `_init' + # + # crti.o must precede every other .init contribution and crtn.o must + # follow all of them, which is why they bracket the object list rather + # than sitting with the other flags. The AArch32 scripts need none of + # this: they use nosys.specs and never reach __libc_init_array. + CRT_BEGIN="$("${CC}" -mcpu="${cpu}" -print-file-name=crti.o)" + CRT_END="$("${CC}" -mcpu="${cpu}" -print-file-name=crtn.o)" ;; atfe) CC="${ATFE_CLANG:-clang}" @@ -52,6 +69,11 @@ case "${TOOLCHAIN}" in # picolibc has no initialise_monitor_handles, and neither does the # toolchain's semihosting library, so the weak stub stands in for it. SEMIHOST_STUB="sample_threadx/semihost_stub.S" + # Deliberately empty. picolibc's __libc_init_array does not call _init, + # so these images link today and adding crti.o would change a working + # link for no reason. + CRT_BEGIN="" + CRT_END="" ;; *) echo "Unknown TOOLCHAIN '${TOOLCHAIN}'; expected gnu or atfe" >&2 @@ -80,7 +102,7 @@ done "${CC}" ${TARGET_FLAGS} -g -mcpu="${cpu}" -nostartfiles \ -T sample_threadx/sample_threadx.ld ${SYSCALL_LIB} \ -o sample_threadx.out -Wl,-Map=sample_threadx.map \ - ${objects} tx.a + ${CRT_BEGIN} ${objects} tx.a ${CRT_END} rm -f ${objects} From ff7fbe02f873170d1bd32b7c2ba7eae8d5e59f96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Fri, 28 Aug 2026 10:40:37 -0400 Subject: [PATCH 093/181] Added a GCC check for the Arm ports and ran it in CI (#675) * Assembled the module ports, which no check had ever compiled scripts/check_clang.sh globbed ports_module/*/gnu/src, which does not exist -- the module ports keep their assembly in module_manager/src. The [ -d ] guard skipped it in silence, so 116 assembly files across nine Arm module ports were assembled by no check, with either compiler, in the script whose own comments state three times that "a port that is simply absent from the count reads as covered". Stage 1 goes from 724 of 724 to 840 of 840; the feature-macro stage had the same gap and goes from 412 files to 469. Correcting the path exposed five defects, and only one of them was a build failure. The other four assembled cleanly and did the wrong thing, because GAS runs the C preprocessor on .S and not on .s: ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_unprotect.s, the only .s in a directory of twenty-one .S, ignored all four of its own feature macros. It wrote the caller's LR into the protection structure on every unprotect -- a store guarded by TX_MPCORE_DEBUG_ENABLE -- sent an unconditional SEV, and returned through both BX lr and MOV pc, lr. Its cortex_a5_smp and cortex_a9_smp siblings are .S. ports_module/cortex_m33/.../tx_thread_stack_build.s emitted both arms of an #ifdef TX_SINGLE_MODE_SECURE, so the non-secure LR value overwrote the secure one and the secure build got the wrong frame. ports_module/cortex_m23/.../tx_thread_context_{save,restore}.S carried the POP {r0, lr} that check_clang.sh's own comment describes as the reason the feature-macro stage exists. The 16-bit Thumb POP takes r0-r7 and pc only. The identical fix already sits in ports/cortex_m23/gnu/src; the module copy never got it because nothing scanned it. ports_module/cortex_m23/.../tx_thread_secure_stack_initialize.S used MOV rather than MOVS for an 8-bit immediate, latent behind TX_SINGLE_MODE_SECURE. Both siblings in the same directory already use MOVS. ports_module/cortex_a7/gnu/module_manager/src is the one that failed to assemble, on GCC 14.3 as well as on LLVM: #define SYS_MODE was never expanded, so #SYS_MODE reached the assembler as an undefined symbol. Twenty-nine .s files under gnu trees are renamed to .S. Every one of them is already named .S by the build scripts that compile it, so this repairs those scripts rather than churning them -- ports_module/cortex_a7's build_threadx.bat names all eighteen with a capital S, and works today only on a case-insensitive filesystem. Renaming rather than converting the #defines to GNU assignments is what fixes the #ifdef blocks as well as the constants; the assignments would have fixed two files and left twenty-seven silently ignoring their macros. Files with no preprocessor directives are left as .s: they are not broken, and check_ports.sh gains a check that keeps them that way. Only the gnu trees are checked there -- the IAR, Arm Compiler 5 and Keil assemblers preprocess .s themselves, and about three hundred files in this repository rely on that. Verified with both toolchains on the same tree: 840 of 840 assembled by ATfE 22.1.0 and by arm-gnu-toolchain 14.3.rel1, all five stages of check_clang.sh green, and check_ports.sh green including the reproducibility check. The new check was shown to fail by planting a copy of the file it was written for. No regression test accompanies this. The assembly it covers is executed by no host test, and the check itself going from 724 files to 840 is the coverage AGENTS.md asks for -- together with the new check_ports.sh section, which is what stops the class recurring. Assisted-by: Claude Code (Opus 5) * Fixed the AArch64 samples, none of which had ever linked with GCC Every AArch64 gnu example build failed at the sample link, all 27 of them -- 13 under ports/ and 14 under ports_smp/: libg.a(libc_a-init.o): in function `__libc_init_array': undefined reference to `_init' relocation truncated to fit: R_AARCH64_CALL26 against undefined symbol `_init' libg.a(libc_a-fini.o): in function `__libc_fini_array': undefined reference to `_fini' build_threadx_sample.sh links with -nostartfiles, which is correct for a port carrying its own reset path, and that drops crti.o and crtn.o along with everything else. startup.S calls __libc_init_array by design, and newlib's implementation calls _init, which crti.o is what defines. The AArch32 scripts are unaffected: they use nosys.specs and never reach __libc_init_array. The fix links crti.o and crtn.o explicitly, bracketing the object list -- the first must precede every .init contribution and the second must follow all of them, so their position is load-bearing rather than stylistic. Both paths come from the compiler's own -print-file-name, so nothing here hard-codes a toolchain layout. The atfe branch sets both to empty, deliberately: picolibc's __libc_init_array does not call _init, those 27 images link today, and adding crti.o would change a working link for no reason. That is also why check_clang.sh is green on these and does not list them as expected to fail -- the LLVM path never reached the gap, so nothing has ever linked them and failed. Fixed in ports_arch/ARMv8-A/threadx/ports/gnu/example_build, which is the single source for both the ports/ and ports_smp/ copies, then regenerated with update.sh --port-sets tx,tx_smp. The 27 generated copies are in this commit because ports_arch_check compares them. Verified: all 27 link with arm-gnu-toolchain 14.3.rel1 aarch64-none-elf, where 0 of 27 did before; _init and _fini disassemble to the expected crti prologue and crtn epilogue over a ret; check_clang.sh with ATfE 22.1.0 is still green on all five stages, including the 42 script-driven example builds; check_ports.sh is green including the reproducibility check. No regression test: these are link-only example images that no host test executes. What guards them is check_clang.sh's example stage today, and check_gcc.sh's, which is the next change and is the reason this was found. Assisted-by: Claude Code (Opus 5) * Added a GCC check for the Arm ports, which nothing had ever compiled GCC is the project's declared default compiler (AGENTS.md, "The default compiler for the project is GCC 14 on Linux"), it is what the gnu ports exist for, and it is what nearly every downstream user builds with -- and nothing in CI compiled a line of any port with it. The only cross-compilation check that ran was the LLVM one, so the ATfE path was better guarded than the GNU one, on ports whose directory is literally named gnu. ci_cortex_m covers four port families; this covers forty. Five stages, mirroring scripts/check_clang.sh stage for stage: 1. assemble every .S and .s of every Arm gnu port -- 840 files 2. assemble again the parts behind TX_ENABLE_VFP_SUPPORT, TX_ENABLE_FIQ_SUPPORT, TX_LOW_POWER and TX_ENABLE_EXECUTION_CHANGE_NOTIFY -- 469 files 3. compile common/src for one core per architecture profile -- 185 x 9 4. link the script-driven example builds -- 42 5. link the CMake-driven Cortex-R52 images -- 5 Two scripts rather than one with a --toolchain flag: the flag surface differs (a prefixed driver against --target=), the C library differs, and the set of examples that can link differs. Folding them together makes it easy to weaken one check while working on the other. Two toolchains, both required. Arm ships arm-none-eabi and aarch64-none-elf as separate downloads and PORT_TARGET maps every port to one of exactly those two triples, so --arm-none-eabi and --aarch64-none-elf each take a driver or the directory holding it, defaulting to the environment and then to PATH. A missing one is a hard error rather than a soft skip: letting a run cover half the tree and still report "all checks passed" is the failure this script exists to end. PORT_TARGET is copied verbatim from check_clang.sh, including its warning not to prefix-match core names -- cortex_a5* also matches the AArch64 cortex_a53. VFP_EXTRA is the one map that is not a copy, and check_clang.sh's comment about it is false for GCC. That comment says the A-profile defaults are already correct; arm-none-eabi-gcc defaults to -mfloat-abi=soft, which disables the FPU outright, so every VFP file fails with "selected processor does not support 'vmrs r1,FPSCR' in ARM mode". -mfloat-abi=hard alone is the fix and is the right one, because it selects the core's own default FPU rather than naming a -d16 one -- which is the trap the clang script warns about, since the A-profile paths save D16-D31. Cortex-R4 is the exception in both scripts and for the same reason: its FPU is an option rather than part of the core, so an explicit -mfpu is required. Every value was measured against 14.3.rel1. Stage 4 *unsets* TOOLCHAIN rather than setting it. The example build scripts already default to GNU, and a stray TOOLCHAIN=atfe from a developer's shell would otherwise make this stage silently check the other compiler. It cleans the example directories on both sides, because the success test is the existence of sample_threadx.out rather than the driver's exit status, and a stale image from a previous toolchain would report success. Failure logs are printed unfiltered: a missing tool says "command not found", and GNU ld's undefined-symbol lines carry no "error:" at all. Every skip is printed by name with a reason, per the house rule check_clang.sh states three times -- a port simply absent from the count reads as covered. This script also says outright that arm9 and arm11 are Arm and are skipped for having no PORT_TARGET entry, which the clang script's "not Arm" wording glosses. Verified on this tree with arm-gnu-toolchain 14.3.rel1: all five stages green, every count identical to check_clang.sh's on the same tree -- 840, 469, 185x9, 42, 5 -- in 4m28s. The failure paths were tested, not assumed. A deliberately broken .S in a module port is reported by name and line in stages 1 and 2 and exits 1, in --quiet mode as well. Reverting the AArch64 _init/_fini fix on one port only gives "FAIL: cortex_a53: example build produced no image", 41 of 42, and exit 1 -- and the log tail it prints contains no "error:" anywhere, which is why it is not filtered. A missing or wrong toolchain path exits 1 naming which triple was not found. RISC-V is deliberately out of scope for this first version: both ports assemble 8 of 8 with the project's own cmake flags, but adding them widens the toolchain download and the review surface for a family that is not regressing. No regression test accompanies this. The script is the test, it exercises no runtime behaviour, and its own failure paths are exercised above. Assisted-by: Claude Code (Opus 5) * Ran the GCC port check in CI, on dev as well as master scripts/check_gcc.sh with nothing invoking it would be a script nobody runs. This adds the workflow, modelled on clang_check.yml, and fixes a trigger gap in that file at the same time. One job, two cache steps. Arm ships AArch32 and AArch64 as separate downloads and the script needs both, so two caches keep the checks list short and let a single invocation see both compilers. The AArch32 cache path and key match cortex_m's exactly, so the two workflows share one entry rather than each holding its own copy of the same archive -- noted in a comment, because the only symptom of breaking that is a slower run. Both triggers name dev. A workflow that triggers only on master gates no pull request anybody opens; that is the defect ports_arch_check.yml carries a comment about, and it cost cortex_m three months of failing in seven seconds unnoticed. push is included as well as pull_request so dev's own history has a baseline and a bad squash-merge is caught rather than waiting for the next PR. The checksum suffix is .sha256asc and it is not interchangeable with .sha256. Arm publishes both for this release, and verified 26 Aug 2026, the .sha256 file for arm-none-eabi contains a 32-character MD5 rather than a SHA-256, so sha256sum -c on it fails with "no properly formatted checksum lines found". .sha256asc is a plain sha256sum-format line for both triples. The plan warned that this suffix had changed between releases; the sharper truth is that both suffixes exist simultaneously and one of them is not a SHA-256 at all. Recorded in a comment beside the step. Verified before writing them in rather than copied: both archive URLs and both checksum URLs resolve, the archives are xz, the checksum files are sha256sum-format for .sha256asc, and the AArch64 archive extracts to arm-gnu-toolchain-14.3.rel1-x86_64-aarch64-none-elf/bin/aarch64-none-elf-gcc, which is the path the workflow builds. The paths: lists are duplicated between push and pull_request rather than shared through a YAML anchor, deliberately: GitHub Actions' parser does not dependably honour anchors and the failure mode is the workflow refusing to parse, which is the cortex_m failure again. Ten duplicated lines are cheaper. clang_check.yml's paths: list was missing CMakeLists.txt, cmake/ and common_smp/, so that check did not run when files it reads changed -- the ports_smp example builds compile common_smp/src and its CMake stage reads the toolchain file and the top-level project. Both lists are now identical apart from each file's own name, and both say so. cortex_m is kept rather than deleted, against the plan's recommendation. It builds four ports *through CMake*, and that is the only thing exercising cmake/cortex_m*.cmake and the top-level CMakeLists for the M profile; this script's CMake stage covers cortex_r52 only. The overlap is the assembly and the C sources, not the build system, so deleting it would lose coverage rather than remove a duplicate. Said so in the workflow header. The script is passed explicit toolchain paths rather than left to find the drivers on PATH, so nothing about the runner image can decide which compiler runs, and it prints both versions it resolved. Assisted-by: Claude Code (Opus 5) --- .github/workflows/clang_check.yml | 10 + .github/workflows/gcc_check.yml | 175 +++++++++ scripts/check_gcc.sh | 571 ++++++++++++++++++++++++++++++ 3 files changed, 756 insertions(+) create mode 100644 .github/workflows/gcc_check.yml create mode 100755 scripts/check_gcc.sh diff --git a/.github/workflows/clang_check.yml b/.github/workflows/clang_check.yml index 405033f0b..2c90c790b 100644 --- a/.github/workflows/clang_check.yml +++ b/.github/workflows/clang_check.yml @@ -10,7 +10,17 @@ on: paths: - ".github/workflows/clang_check.yml" - "scripts/check_clang.sh" + # CMakeLists.txt, cmake/ and common_smp/ were missing until 26 Aug 2026, + # so this check did not run when the files it reads changed. The + # ports_smp example builds compile common_smp/src and the CMake stage + # reads the toolchain file and the top-level project. utility/ is + # deliberately absent: the FreeRTOS and POSIX layers under it are not + # enabled by any target this workflow builds. Keep this list and + # gcc_check.yml's the same. + - "CMakeLists.txt" + - "cmake/**" - "common/**" + - "common_smp/**" - "ports/**" - "ports_arch/**" - "ports_module/**" diff --git a/.github/workflows/gcc_check.yml b/.github/workflows/gcc_check.yml new file mode 100644 index 000000000..31e1ec346 --- /dev/null +++ b/.github/workflows/gcc_check.yml @@ -0,0 +1,175 @@ +name: gcc_check + +# Builds the Arm ports with the Arm GNU toolchain, in five stages: assemble +# every assembly source of every Arm gnu port, assemble again the parts guarded +# by feature macros, compile the common C sources for one core per architecture +# profile, then link the example builds, both the script-driven ones and those +# driven by CMake. +# +# Why this exists: GCC is the project's declared default compiler (AGENTS.md, +# "The default compiler for the project is GCC 14 on Linux") and until this +# workflow landed, nothing in CI compiled a line of any port with it. The only +# cross-compilation check that ran was clang_check, so the LLVM path was better +# guarded than the GNU one, on ports whose directory is literally named gnu. +# +# What it covers: 840 assembly sources across 40 port families, 469 of them +# again behind feature macros, common/src for nine cores, 42 script-driven +# example links and the five Cortex-R52 CMake images. Every skip is printed by +# name with a reason -- run scripts/check_gcc.sh --help, or read its header. +# +# What it does not cover: it compiles and links and **executes nothing**. The +# Cortex-R52 FVP ctest suite is not part of it. RISC-V, MIPS, RX and ARC are +# outside it entirely -- RISC-V deliberately, as both its ports do assemble and +# adding them widens the toolchain download for a family that is not regressing. +# +# It does not supersede cortex_m. That workflow builds four ports *through +# CMake*, which is the only thing exercising cmake/cortex_m*.cmake and the +# top-level CMakeLists for the M profile; this script's CMake stage covers +# cortex_r52 only. The overlap is the assembly and the C sources, not the build +# system. +on: + # push as well as pull_request, so dev's own history has a baseline and a bad + # squash-merge is caught rather than waiting for the next PR to notice. dev is + # named because it is the integration branch: a workflow that triggers only on + # master does not gate any pull request anybody opens, which is the defect + # ports_arch_check.yml carries a comment about and which cost cortex_m three + # months of failing in seven seconds unnoticed. + push: + branches: [ master, dev ] + paths: + - ".github/workflows/gcc_check.yml" + - "scripts/check_gcc.sh" + - "CMakeLists.txt" + - "cmake/**" + - "common/**" + - "common_smp/**" + - "ports/**" + - "ports_arch/**" + - "ports_module/**" + - "ports_smp/**" + pull_request: + branches: [ master, dev ] + # The two lists are duplicated rather than shared through a YAML anchor. + # GitHub Actions' workflow parser does not dependably honour anchors, and + # the failure mode is the whole workflow refusing to parse -- which is the + # cortex_m failure again, a job that dies before it does anything. Ten + # duplicated lines are cheaper than that. **Edit both.** + # + # common_smp, CMakeLists.txt and cmake/ are here and are absent from + # clang_check.yml's otherwise identical list, which is a gap in that file + # and is fixed alongside this one: the ports_smp example builds compile + # common_smp/src, and the CMake stage reads the toolchain file and the + # top-level project. utility/ is deliberately absent -- the FreeRTOS and + # POSIX layers under it are not enabled by any target this workflow builds. + paths: + - ".github/workflows/gcc_check.yml" + - "scripts/check_gcc.sh" + - "CMakeLists.txt" + - "cmake/**" + - "common/**" + - "common_smp/**" + - "ports/**" + - "ports_arch/**" + - "ports_module/**" + - "ports_smp/**" + +jobs: + gnu: + runs-on: ubuntu-24.04 + + env: + # Pinned deliberately, as the runner image is: a toolchain upgrade should + # be a reviewable commit rather than something that changes underneath the + # ports. 14.3.rel1 matches AGENTS.md's GCC 14 default and the version + # cortex_m already pins. + # Releases: https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads + GCC_VERSION: 14.3.rel1 + + steps: + # Actions are pinned to a commit SHA, with the version in the trailing + # comment. A tag can be moved; a SHA cannot, so this is what makes "which + # code ran in CI" answerable from the repository. Dependabot moves these + # pins and rewrites the comment with them -- see .github/dependabot.yml. + - name: Check out the repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + # Two toolchains, because Arm ships AArch32 and AArch64 as separate + # downloads and scripts/check_gcc.sh needs both -- every port maps to one of + # exactly those two triples. One job with two cache steps rather than two + # jobs, so the checks list stays short and a single script invocation sees + # both compilers. + # + # The AArch32 path and key match cortex_m's exactly, so the two workflows + # share one cache entry rather than each holding its own copy of the same + # 500MB archive. Change them together or the sharing silently stops and the + # only symptom is a slower run. + - name: Cache the AArch32 Arm GNU toolchain + id: cache-arm32 + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: toolchain + key: arm-gnu-toolchain-${{ env.GCC_VERSION }}-x86_64-arm-none-eabi + + - name: Cache the AArch64 Arm GNU toolchain + id: cache-arm64 + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: toolchain64 + key: arm-gnu-toolchain-${{ env.GCC_VERSION }}-x86_64-aarch64-none-elf + + # The checksum suffix is .sha256asc and not .sha256, and that is not a + # stylistic choice. Arm publishes both for this release, and for + # arm-none-eabi the .sha256 file contains a 32-character MD5 rather than a + # SHA-256 -- verified 26 Aug 2026 -- so sha256sum -c on it fails with "no + # properly formatted checksum lines found". .sha256asc is a plain + # sha256sum-format line for both triples. Do not "simplify" the suffix. + - name: Install the AArch32 Arm GNU toolchain + if: steps.cache-arm32.outputs.cache-hit != 'true' + run: | + set -eu + base="https://developer.arm.com/-/media/Files/downloads/gnu/${GCC_VERSION}/binrel" + archive="arm-gnu-toolchain-${GCC_VERSION}-x86_64-arm-none-eabi.tar.xz" + mkdir -p toolchain && cd toolchain + curl -fsSLO "$base/$archive" + curl -fsSLO "$base/$archive.sha256asc" + sha256sum -c "$archive.sha256asc" + tar xf "$archive" + rm -f "$archive" + + - name: Install the AArch64 Arm GNU toolchain + if: steps.cache-arm64.outputs.cache-hit != 'true' + run: | + set -eu + base="https://developer.arm.com/-/media/Files/downloads/gnu/${GCC_VERSION}/binrel" + archive="arm-gnu-toolchain-${GCC_VERSION}-x86_64-aarch64-none-elf.tar.xz" + mkdir -p toolchain64 && cd toolchain64 + curl -fsSLO "$base/$archive" + curl -fsSLO "$base/$archive.sha256asc" + sha256sum -c "$archive.sha256asc" + tar xf "$archive" + rm -f "$archive" + + # Only reaches apt if the runner image has stopped shipping ninja, which + # the CMake stage needs. This repository has already paid for unguarded apt + # calls: scripts/install.sh carries a long comment about apt-get update + # stalling for over two hours and taking whole regression runs with it. Do + # not turn this into an unconditional install. + - name: Ensure ninja is available + run: | + set -eu + if command -v ninja >/dev/null 2>&1; then + ninja --version + else + sudo apt-get update + sudo apt-get install -y --no-install-recommends ninja-build + fi + + # The script is told where both toolchains are rather than being left to + # find them on PATH, so nothing about the runner image can decide which + # compiler is used. The script prints both versions it resolved, which is + # what makes "was this really 14.3.rel1?" answerable from the log. + - name: Build the Arm ports with GCC + run: | + scripts/check_gcc.sh \ + --arm-none-eabi "$GITHUB_WORKSPACE/toolchain/arm-gnu-toolchain-${GCC_VERSION}-x86_64-arm-none-eabi/bin" \ + --aarch64-none-elf "$GITHUB_WORKSPACE/toolchain64/arm-gnu-toolchain-${GCC_VERSION}-x86_64-aarch64-none-elf/bin" diff --git a/scripts/check_gcc.sh b/scripts/check_gcc.sh new file mode 100755 index 000000000..6b2cb8d5c --- /dev/null +++ b/scripts/check_gcc.sh @@ -0,0 +1,571 @@ +#!/bin/bash +############################################################################## +# 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. +# +# AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +# The AI-generated portions may be considered public domain (CC0-1.0) +# and not subject to the project's licence. The human contributor has +# reviewed and verified that the code is correct. +# +# SPDX-License-Identifier: MIT and CC0-1.0 +############################################################################## + +# Builds the Arm ports with the GNU toolchain, in five stages: assemble every +# assembly source of every Arm gnu port, assemble again the parts guarded by +# feature macros, compile the common C sources for one core per architecture +# profile, then link the example builds, both the script-driven ones and those +# driven by CMake. Only the linking stages need a target C library. +# +# scripts/check_gcc.sh # both drivers from PATH +# scripts/check_gcc.sh --arm-none-eabi /path/to/toolchain/bin \ +# --aarch64-none-elf /path/to/toolchain/bin +# +# Options: +# --arm-none-eabi arm-none-eabi-gcc, or the directory holding it. +# Defaults to $ARM_NONE_EABI_GCC then to PATH. +# --aarch64-none-elf aarch64-none-elf-gcc, or its directory. +# Defaults to $AARCH64_NONE_ELF_GCC then to PATH. +# --asm-only Skip the C sources and the example builds. +# --no-examples Skip the example builds. +# --quiet Print only failures and the summary. +# +# Exit status is 0 when everything builds and 1 otherwise. +# +# Why this exists: GCC is the project's declared default compiler (AGENTS.md, +# "The default compiler for the project is GCC 14 on Linux"), it is what the +# gnu ports exist for, and it is what nearly every downstream user builds with +# -- and until this script landed, nothing in CI compiled a line of any port +# with it. The only cross-compilation check that ran was the LLVM one, so the +# ATfE path was better guarded than the GNU one, on ports whose directory is +# literally named gnu. +# +# This is the companion to scripts/check_clang.sh and deliberately mirrors it +# stage for stage. They are two scripts rather than one with a --toolchain flag +# because the flag surface differs (a prefixed driver against --target=), the +# C library differs, and the set of examples that can link differs. Folding +# them together makes it easy to weaken one check while working on the other. +# +# It compiles and links; it executes nothing. The Cortex-R52 FVP ctest suite is +# a separate matter, and the RISC-V, MIPS, RX and ARC families are outside it +# entirely -- every skip is printed by name below. +# +# Arm GNU toolchain releases: +# https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads + +set -u + +cd "$(dirname "$(realpath "$0")")/.." + +# Two toolchains, not one. Arm ships arm-none-eabi (AArch32: every M and R +# profile core and the A32 A-profile ports) and aarch64-none-elf as separate +# downloads, and PORT_TARGET below maps every port to one of exactly those two +# triples. Both are required: making a missing one a soft skip would let a run +# cover half the tree and still say "all checks passed", which is the failure +# this script was written to end. +CC_ARM="${ARM_NONE_EABI_GCC:-}" +CC_AARCH64="${AARCH64_NONE_ELF_GCC:-}" +asm_only=0 +no_examples=0 +quiet=0 + +while [ "$#" -gt 0 ]; do + case "$1" in + --arm-none-eabi) + [ "$#" -ge 2 ] || { echo "Error: --arm-none-eabi needs a path" >&2; exit 2; } + CC_ARM="$2"; shift 2 ;; + --aarch64-none-elf) + [ "$#" -ge 2 ] || { echo "Error: --aarch64-none-elf needs a path" >&2; exit 2; } + CC_AARCH64="$2"; shift 2 ;; + --asm-only) asm_only=1; no_examples=1; shift ;; + --no-examples) no_examples=1; shift ;; + --quiet) quiet=1; shift ;; + -h|--help) sed -n '17,36p' "$0"; exit 0 ;; + *) echo "Error: unknown option '$1'" >&2; exit 2 ;; + esac +done + +say() { [ "$quiet" -eq 1 ] || echo "$@"; } +fail() { echo " FAIL: $*"; } + +# Accept either the driver itself or the directory holding it, since a +# toolchain is unpacked as a tree and naming its bin directory is the natural +# thing to reach for. Resolve to an absolute path: the example stages run the +# build scripts from inside their own directories, so a relative path would +# stop resolving there. +resolve_gcc() { + triple="$1" + given="$2" + + if [ -z "$given" ]; then + command -v "${triple}-gcc" >/dev/null 2>&1 || return 1 + command -v "${triple}-gcc" + return 0 + fi + if [ -d "$given" ]; then + for candidate in "$given/${triple}-gcc" "$given/bin/${triple}-gcc"; do + [ -x "$candidate" ] && { realpath "$candidate"; return 0; } + done + return 1 + fi + [ -x "$given" ] || return 1 + realpath "$given" +} + +missing="" +CC_ARM="$(resolve_gcc arm-none-eabi "$CC_ARM")" || missing="$missing arm-none-eabi" +CC_AARCH64="$(resolve_gcc aarch64-none-elf "$CC_AARCH64")" || missing="$missing aarch64-none-elf" + +if [ -n "$missing" ]; then + echo "Error: compiler(s) not found:$missing" + echo "Pass --arm-none-eabi and --aarch64-none-elf, set ARM_NONE_EABI_GCC and" + echo "AARCH64_NONE_ELF_GCC, or put both drivers on PATH. Downloads:" + echo " https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads" + exit 1 +fi + +say "" +say "Using: $CC_ARM" +say " $("$CC_ARM" --version | head -1)" +say " $CC_AARCH64" +say " $("$CC_AARCH64" --version | head -1)" + +# The example build scripts and the CMake toolchain file call the drivers by +# their bare prefixed names, so both bin directories go on PATH for the linking +# stages. Done once, here, rather than per stage: a second toolchain arriving +# on PATH halfway through a run is exactly the kind of difference that makes a +# failure irreproducible. +PATH="$(dirname "$CC_ARM"):$(dirname "$CC_AARCH64"):$PATH" +export PATH + +# Pick the driver for a port from its triple, so the map below stays the single +# place a port's architecture is decided. +cc_for() { + case "$1" in + aarch64-none-elf) echo "$CC_AARCH64" ;; + *) echo "$CC_ARM" ;; + esac +} + +# Each port directory is mapped explicitly to a target triple and CPU. Do not +# replace this with prefix matching: cortex_a5* also matches cortex_a53 and +# cortex_a55, which are AArch64, and assembling those as ARM32 produces a flood +# of misleading errors. +# +# Copied verbatim from scripts/check_clang.sh. Keep the two identical -- a port +# covered by one check and not the other is worse than one covered by neither, +# because the checks list implies parity that does not exist. +declare -A PORT_TARGET=( + [cortex_m0]="arm-none-eabi cortex-m0 -mthumb" + [cortex_m0+]="arm-none-eabi cortex-m0plus -mthumb" + [cortex_m3]="arm-none-eabi cortex-m3 -mthumb" + [cortex_m4]="arm-none-eabi cortex-m4 -mthumb" + [cortex_m7]="arm-none-eabi cortex-m7 -mthumb" + [cortex_m23]="arm-none-eabi cortex-m23 -mthumb" + [cortex_m33]="arm-none-eabi cortex-m33 -mthumb" + [cortex_m52]="arm-none-eabi cortex-m52 -mthumb -mfloat-abi=hard" + [cortex_m55]="arm-none-eabi cortex-m55 -mthumb -mfloat-abi=hard" + [cortex_m85]="arm-none-eabi cortex-m85 -mthumb -mfloat-abi=hard" + [cortex_a5]="arm-none-eabi cortex-a5" + [cortex_a7]="arm-none-eabi cortex-a7" + [cortex_a8]="arm-none-eabi cortex-a8" + [cortex_a9]="arm-none-eabi cortex-a9" + [cortex_a12]="arm-none-eabi cortex-a12" + [cortex_a15]="arm-none-eabi cortex-a15" + [cortex_a17]="arm-none-eabi cortex-a17" + [cortex_a5_smp]="arm-none-eabi cortex-a5" + [cortex_a7_smp]="arm-none-eabi cortex-a7" + [cortex_a9_smp]="arm-none-eabi cortex-a9" + [cortex_r4]="arm-none-eabi cortex-r4" + [cortex_r5]="arm-none-eabi cortex-r5" + [cortex_r52]="arm-none-eabi cortex-r52" + [cortex_a34]="aarch64-none-elf cortex-a34" + [cortex_a35]="aarch64-none-elf cortex-a35" + [cortex_a53]="aarch64-none-elf cortex-a53" + [cortex_a55]="aarch64-none-elf cortex-a55" + [cortex_a57]="aarch64-none-elf cortex-a57" + [cortex_a65]="aarch64-none-elf cortex-a65" + [cortex_a65ae]="aarch64-none-elf cortex-a65ae" + [cortex_a72]="aarch64-none-elf cortex-a72" + [cortex_a73]="aarch64-none-elf cortex-a73" + [cortex_a75]="aarch64-none-elf cortex-a75" + [cortex_a76]="aarch64-none-elf cortex-a76" + [cortex_a76ae]="aarch64-none-elf cortex-a76ae" + [cortex_a77]="aarch64-none-elf cortex-a77" + [cortex_a34_smp]="aarch64-none-elf cortex-a34" + [cortex_a35_smp]="aarch64-none-elf cortex-a35" + [cortex_a53_smp]="aarch64-none-elf cortex-a53" + [cortex_a55_smp]="aarch64-none-elf cortex-a55" + [cortex_a57_smp]="aarch64-none-elf cortex-a57" + [cortex_a65_smp]="aarch64-none-elf cortex-a65" + [cortex_a65ae_smp]="aarch64-none-elf cortex-a65ae" + [cortex_a72_smp]="aarch64-none-elf cortex-a72" + [cortex_a73_smp]="aarch64-none-elf cortex-a73" + [cortex_a75_smp]="aarch64-none-elf cortex-a75" + [cortex_a76_smp]="aarch64-none-elf cortex-a76" + [cortex_a76ae_smp]="aarch64-none-elf cortex-a76ae" + [cortex_a77_smp]="aarch64-none-elf cortex-a77" + [cortex_a78_smp]="aarch64-none-elf cortex-a78" +) + +# Assembly guarded by a feature macro is invisible to the stage above, which +# assembles with default flags and so lets the preprocessor discard every #ifdef +# block before the assembler sees it. These are the macros a user can turn on; +# each file carrying one is assembled again with it defined. +# +# This is not hypothetical, and it is not only clang's finding. The Cortex-M23 +# module manager carried "POP {r0, lr}" in exactly these paths -- invalid on +# Armv8-M Baseline, where the 16-bit POP takes r0-r7 and pc only -- for six +# months after the identical fix landed in its non-module sibling, because no +# glob in either script reached ports_module until #672. +FEATURE_MACROS="TX_ENABLE_VFP_SUPPORT TX_ENABLE_FIQ_SUPPORT TX_LOW_POWER + TX_ENABLE_EXECUTION_CHANGE_NOTIFY" + +# TX_ENABLE_IRQ_NESTING and TX_ENABLE_FIQ_NESTING are deliberately not here. +# They guard no assembly in the trees this script walks: the nesting start and +# end routines are separate files compiled unconditionally, and the macros only +# feed the TX_PORT_SPECIFIC_BUILD_OPTIONS bitfield in tx_port.h. Adding them +# would assemble nothing new and imply coverage that does not exist. + +# Extra flags for the VFP paths, per core. +# +# check_clang.sh's equivalent map has one entry and a comment saying "Do not +# extend this to the A profile ports ... their defaults are already correct." +# That is true of clang and false of GCC, so do not copy that comment here. +# arm-none-eabi-gcc defaults to -mfloat-abi=soft, which disables the FPU +# outright, and every VFP file then fails with +# +# selected processor does not support 'vmrs r1,FPSCR' in ARM mode +# +# -mfloat-abi=hard alone is the fix, and it is the right one: it selects the +# core's own default FPU rather than naming one. Naming a -d16 FPU is the trap +# the clang script warns about -- the A-profile paths save D16-D31, which exist +# only on a 32-register FPU, so a -d16 choice turns 28 working files into +# "register expected". +# +# Cortex-R4 is the exception, in both scripts and for the same reason: its FPU +# is an option rather than part of the core, so -mfloat-abi=hard alone gives +# "selected architecture lacks an FPU" and an explicit -mfpu is required. The +# value matches check_clang.sh's, so the two scripts say the same thing about +# the same port. +# +# Every entry below was measured against arm-gnu-toolchain 14.3.rel1. A core +# that acquires a VFP-guarded file without an entry here fails loudly rather +# than silently, which is the intended behaviour. +declare -A VFP_EXTRA=( + [cortex_a5]="-mfloat-abi=hard" + [cortex_a7]="-mfloat-abi=hard" + [cortex_a8]="-mfloat-abi=hard" + [cortex_a9]="-mfloat-abi=hard" + [cortex_a12]="-mfloat-abi=hard" + [cortex_a15]="-mfloat-abi=hard" + [cortex_a17]="-mfloat-abi=hard" + [cortex_a5_smp]="-mfloat-abi=hard" + [cortex_a7_smp]="-mfloat-abi=hard" + [cortex_a9_smp]="-mfloat-abi=hard" + [cortex_r4]="-mfpu=vfpv3-d16 -mfloat-abi=softfp" + [cortex_r5]="-mfloat-abi=hard" + [cortex_r52]="-mfloat-abi=hard" +) + +# One core per architecture profile for the C sources. Compiling all of them +# for every core would multiply the run time without adding coverage, since the +# port headers differ by profile rather than by core. +# +# cortex_r52 earns a slot of its own next to cortex_r5 because Armv8-R AArch32 +# is a separate profile rather than a variant of Armv7-R. That port is written +# by hand instead of generated from ports_arch, and its tx_port.h differs +# accordingly, so cortex_r5 does not stand in for it. +C_CORES="cortex_m0 cortex_m4 cortex_m23 cortex_m33 cortex_m55 cortex_a7 cortex_a53 cortex_r5 cortex_r52" + +# Example builds driven by CMake rather than by a build_threadx.sh pair. These +# are covered by their own stage below, so the script-driven loop passes over +# them without reporting them as a gap. +CMAKE_EXAMPLE_CORES="cortex_r52" + +# Example builds that are not expected to link, with the reason. Named by +# their port directory, which covers both ports/ and ports_smp/. Listed +# explicitly rather than silently skipped, so the gaps stay visible. +# +# The same four as check_clang.sh, and the reason there is stated in terms of +# GNU tooling because that is where it was reproduced: +# +# their linker scripts define the .init and .fini sections but not the _init +# and _fini symbols. Those come from crti.o and crtn.o, which -nostartfiles +# leaves out, so newlib's fini.c cannot resolve them and the link ends with +# "undefined reference to `_fini'". +# +# The 27 AArch64 examples failed the same way until #673, which links crti.o +# and crtn.o back. They are deliberately absent from this list: they link. +EXAMPLES_EXPECTED_TO_FAIL="arm9 arm11 cortex_r4 cortex_r5" + +failures=0 +skipped="" + +# -------------------------------------------------------------------------- +say "" +say "== Assembly sources of every Arm gnu port ==" + +total=0 +# The module ports keep their assembly in module_manager/src, not src. +# check_clang.sh read ports_module/*/gnu/src until #672; that directory does +# not exist, the [ -d ] guard skipped it in silence, and 116 files across nine +# Arm module ports were assembled by no check with either compiler. This script +# has never had that hole and must not acquire it. +for dir in ports/*/gnu/src ports_smp/*/gnu/src ports_module/*/gnu/module_manager/src; do + [ -d "$dir" ] || continue + core="$(echo "$dir" | cut -d/ -f2)" + spec="${PORT_TARGET[$core]:-}" + if [ -z "$spec" ]; then + skipped="$skipped $core" + continue + fi + # shellcheck disable=SC2086 + set -- $spec + target="$1"; cpu="$2"; shift 2; extra="$*" + CC="$(cc_for "$target")" + + for src in "$dir"/*.S "$dir"/*.s; do + [ -f "$src" ] || continue + total=$((total + 1)) + output="$("$CC" -mcpu="$cpu" $extra -c "$src" -o /dev/null 2>&1)" + if [ -n "$output" ]; then + fail "$src" + echo "$output" | sed 's/^/ /' + failures=$((failures + 1)) + fi + done +done +say " $((total - failures)) of $total assembled" +if [ -n "$skipped" ]; then + say " not Arm, skipped:$(echo $skipped | tr ' ' '\n' | sort -u | tr '\n' ' ')" + say " (arm9 and arm11 are Arm; they are skipped for having no PORT_TARGET entry)" +fi + +# -------------------------------------------------------------------------- +say "" +say "== Assembly behind feature macros ==" + +for macro in $FEATURE_MACROS; do + macro_total=0 + macro_bad=0 + for src in $(grep -rl "$macro" ports/*/gnu/src/*.S ports_smp/*/gnu/src/*.S \ + ports_module/*/gnu/module_manager/src/*.S \ + 2>/dev/null | sort); do + core="$(echo "$src" | cut -d/ -f2)" + spec="${PORT_TARGET[$core]:-}" + [ -n "$spec" ] || continue + # shellcheck disable=SC2086 + set -- $spec + target="$1"; cpu="$2"; shift 2; extra="$*" + CC="$(cc_for "$target")" + + # The FPU flags apply to the VFP paths only; the other macros guard no + # floating-point code and do not need them. + fpu="" + if [ "$macro" = "TX_ENABLE_VFP_SUPPORT" ]; then + fpu="${VFP_EXTRA[$core]:-}" + fi + + macro_total=$((macro_total + 1)) + output="$("$CC" -mcpu="$cpu" $extra $fpu \ + -D"$macro" -c "$src" -o /dev/null 2>&1)" + if [ -n "$output" ]; then + fail "$src with -D$macro" + # Not filtered on "error": GCC prefixes its diagnostics with an + # "Assembler messages:" line and a missing tool says nothing of the + # kind, so filtering would hide the case worth seeing. + echo "$output" | head -4 | sed 's/^/ /' + macro_bad=$((macro_bad + 1)) + failures=$((failures + 1)) + fi + done + if [ "$macro_total" -eq 0 ]; then + say " $macro: no assembly is guarded by it" + else + say " $macro: $((macro_total - macro_bad)) of $macro_total assembled" + fi +done + +# -------------------------------------------------------------------------- +if [ "$asm_only" -eq 0 ]; then + say "" + say "== Common C sources, one core per architecture profile ==" + + for core in $C_CORES; do + spec="${PORT_TARGET[$core]:-}" + [ -n "$spec" ] || continue + # shellcheck disable=SC2086 + set -- $spec + target="$1"; cpu="$2"; shift 2; extra="$*" + CC="$(cc_for "$target")" + + count=0; bad=0 + for src in common/src/*.c; do + count=$((count + 1)) + output="$("$CC" -mcpu="$cpu" $extra \ + -Iports/"$core"/gnu/inc -Icommon/inc -c "$src" -o /dev/null 2>&1)" + if [ -n "$output" ]; then + fail "$core: $src" + echo "$output" | head -4 | sed 's/^/ /' + bad=$((bad + 1)); failures=$((failures + 1)) + fi + done + say " $core: $((count - bad)) of $count compiled" + done +fi + +# -------------------------------------------------------------------------- +if [ "$no_examples" -eq 0 ]; then + say "" + say "== Example builds, linked with GNU ld ==" + + example_ok=0 + example_total=0 + example_known="" + example_nodriver="" + example_nosample="" + for dir in ports/*/gnu/example_build ports_smp/*/gnu/example_build; do + [ -d "$dir" ] || continue + core="$(echo "$dir" | cut -d/ -f2)" + + # Anything on the expected-to-fail list is reported before any other + # filter is applied, so a name placed there can never drop out of the + # output. arm9 and arm11 are the cases that matter: they are Arm ports + # with example drivers, but they carry no PORT_TARGET entry, so the + # Arm test below would discard them. + case " $EXAMPLES_EXPECTED_TO_FAIL " in + *" $core "*) example_known="$example_known $core"; continue ;; + esac + + # Arm ports only, the same rule the assembly stage applies. Naming + # linux or mips32 as a gap here would be noise, not information. + [ -n "${PORT_TARGET[$core]:-}" ] || continue + + # Covered by the CMake stage below rather than here. + case " $CMAKE_EXAMPLE_CORES " in + *" $core "*) continue ;; + esac + + # A driverless example is not covered by this stage, so say so rather + # than dropping out in silence. A port that is simply absent from the + # count reads as covered. + if [ ! -f "$dir/build_threadx.sh" ]; then + example_nodriver="$example_nodriver $core" + continue + fi + if [ ! -f "$dir/build_threadx_sample.sh" ]; then + example_nosample="$example_nosample $core" + continue + fi + example_total=$((example_total + 1)) + + # Clean on both sides. A stale sample_threadx.out from a previous + # toolchain makes a failed link report success, because the success + # test below is the existence of the output file rather than the exit + # status of the driver. + rm -f "$dir"/*.o "$dir"/*.a "$dir"/*.out "$dir"/*.map 2>/dev/null || true + + # TOOLCHAIN is *unset*, not set: the build scripts already default to + # GNU with `: "${TOOLCHAIN:=gnu}"`, and a stray TOOLCHAIN=atfe from a + # developer's shell or an earlier command would otherwise make this + # stage silently check the other compiler. + log="$(cd "$dir" && unset TOOLCHAIN && ./build_threadx.sh 2>&1 && \ + ./build_threadx_sample.sh 2>&1)" || true + + if [ -f "$dir/sample_threadx.out" ]; then + example_ok=$((example_ok + 1)) + else + fail "$core: example build produced no image" + # Not filtered on "error": a missing tool reports "command not + # found" or "Permission denied", and filtering hid exactly that. + echo "$log" | tail -6 | sed 's/^/ /' + failures=$((failures + 1)) + fi + rm -f "$dir"/*.o "$dir"/*.a "$dir"/*.out "$dir"/*.map 2>/dev/null || true + done + say " $example_ok of $example_total example builds linked" + if [ -n "$example_known" ]; then + say " known not to link, see the list at the top of this script:$example_known" + fi + if [ -n "$example_nosample" ]; then + say " has build_threadx.sh but no build_threadx_sample.sh, so not linked:$example_nosample" + fi + if [ -n "$example_nodriver" ]; then + say " no script driver, so outside this stage:$example_nodriver" + fi +fi + +# -------------------------------------------------------------------------- +# The Cortex-R52 examples are built by CMake, so they need a toolchain file +# rather than the build_threadx.sh pair. Same compiler, same purpose as the +# stage above. +if [ "$no_examples" -eq 0 ]; then + say "" + say "== CMake example builds, linked with GNU ld ==" + + if ! command -v cmake >/dev/null 2>&1 || ! command -v ninja >/dev/null 2>&1; then + say " skipped: cmake and ninja are both required" + else + for core in $CMAKE_EXAMPLE_CORES; do + build_dir="$(mktemp -d)" + # ARM_TOOLCHAIN_PATH follows --arm-none-eabi, so this stage uses + # the same compiler as every other stage rather than the absolute + # path cmake/cortex_r52.cmake pins by default. + if cmake -S . -B "$build_dir" -G Ninja \ + -DCMAKE_TOOLCHAIN_FILE="cmake/${core}.cmake" \ + -DARM_TOOLCHAIN_PATH="$(dirname "$CC_ARM")" \ + -DTX_R52_BUILD_FVP_EXAMPLE=ON \ + -DTX_R52_ENABLE_MPU=ON >"$build_dir/configure.log" 2>&1; then + # Read the image list from the generated graph instead of + # repeating it here, so adding a target cannot silently escape + # this check. The images are EXCLUDE_FROM_ALL, so "ninja" alone + # would build none of them. + # + # The cmake_object_order_depends_target_* entries are CMake's + # own ordering phonies, one per real image and named after it. + # Counting those doubled the total and reported ten images built + # where there are five. + images="$(ninja -C "$build_dir" -t targets all 2>/dev/null \ + | grep -oE '^[A-Za-z0-9_]+\.elf' \ + | grep -v '^cmake_' | sort -u)" + if [ -z "$images" ]; then + fail "$core: no .elf targets found in the CMake graph" + failures=$((failures + 1)) + else + built=0; total=0 + for image in $images; do + total=$((total + 1)) + if ninja -C "$build_dir" "$image" \ + >"$build_dir/$image.log" 2>&1; then + built=$((built + 1)) + else + fail "$core: $image did not build" + tail -6 "$build_dir/$image.log" | sed 's/^/ /' + failures=$((failures + 1)) + fi + done + say " $core: $built of $total images linked" + fi + else + fail "$core: CMake configure failed" + tail -6 "$build_dir/configure.log" | sed 's/^/ /' + failures=$((failures + 1)) + fi + rm -rf "$build_dir" + done + fi +fi + +# -------------------------------------------------------------------------- +say "" +if [ "$failures" -eq 0 ]; then + say "All GNU toolchain checks passed." + exit 0 +fi + +echo "$failures GNU toolchain check(s) failed." +exit 1 From a2800fef16c5e229b71ce45050bf5fcf19d84bb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Fri, 28 Aug 2026 10:41:39 -0400 Subject: [PATCH 094/181] Covered the SMP suspension teardown and the long byte pool search (#677) Against the merged SMP coverage report -- every build configuration instrumented and unioned -- sixty-four lines of common_smp/src were uncovered, 5114 of 5178. Fifty-three of them are closed here and the report reads 5167 of 5178. The SMP coverage floor goes from 98 to 99 with it. Thirty-six of the sixty-four were one loop repeated four times: the walk in tx_block_pool_delete, tx_byte_pool_delete, tx_event_flags_delete and tx_queue_delete that releases every thread suspended on the object with TX_DELETED. The suite deletes all four object types after every single test, and that is exactly why the loop never ran. test_control_cleanup in the ThreadX suite deletes the application's objects first and its threads last, so a test that ends with a thread parked on a queue has that thread walked out of it by tx_queue_delete. The SMP suite's cleanup deletes the threads first, deliberately -- it was changed so that no application-owned object is still referenced when the object loops run, which is what stopped a class of teardown hang. The side effect is that all four deletes now run against an empty suspension list. tx_semaphore_delete is the one member of the family that was already covered, because threadx_semaphore_delete_test deletes a busy semaphore on purpose. threadx_object_delete_suspension_test is the same idea for the other four. Two threads suspend on each of a block pool, a byte pool, an event flags group and a queue; the control thread waits on the object's own suspended count through tx_*_info_get rather than on an ordering it cannot guarantee across four cores, deletes the object, and checks both waiters came out with TX_DELETED. Two waiters rather than one so the loop takes its back edge as well as its body, and every wait is bounded in ticks so a suspension that never arrives fails the test instead of hanging it. threadx_trace_entry_update_test and threadx_thread_misaligned_stack_test are ports of the two tests that closed the equivalent gaps in common/src, and close fourteen more lines here: tx_block_allocate 123, 175, 182, 319 and 326, tx_byte_allocate 130, 210, 217, 359 and 366, tx_thread_system_suspend 504 and 560, tx_trace_object_register 221, and tx_thread_create 133. The one substantive change is core confinement. The trace test needs thread 0 to suspend and thread 1 to then release what it waits for; on four cores thread 1 gives the block back before thread 0 has suspended and the update block behind the suspension is never reached, so both threads are excluded from cores 1 to 3. The misaligned stack test needed no such change. threadx_byte_memory_long_search_test closes three of the eleven in tx_byte_pool_search. Lines 264, 267 and 270 are the TX_BYTE_POOL_MULTIPLE_BLOCK_SEARCH limit -- twenty on this port -- where a long search drops and retakes protection so that it cannot lock the other cores out for the whole walk. No byte pool in the suite ever had twenty fragments. This one is filled with small chunks until it refuses another and then has every second chunk released, so the free fragments are never adjacent and cannot be merged, and the request is larger than any of them but smaller than the pool's theoretical total, which is what makes _tx_byte_pool_search walk rather than refuse at the door. The layout is asserted rather than assumed: the test checks the fragment count and checks the probe request really does fail before the workers start, because either would otherwise turn it into a silent no-op. Eleven lines remain and they are not a to-do list. Eight are the delay loop in tx_byte_pool_search that fires when another thread claims the pool inside the window the search opens. The Linux SMP port serialises all four cores on one pthread mutex, so that window is an unlock immediately followed by a lock on that mutex, and glibc hands an uncontended mutex straight back to the thread that just released it: measured over 180,003 windows across three cores, with zero handovers. The shipped test therefore does 250 searches per worker rather than the sixty thousand that probe used, because the twenty-block threshold is crossed by the first search. The other three are in tx_thread_smp_utilities. Line 149 is a range guard placed after the shift it is meant to guard, so reaching it needs a shift by the width of the type; the fix is to move the check above the shift, matching the TX_MAX_PRIORITIES > 32 variant of the same function, and that belongs in its own change. Lines 1073 and 1074 need a mutex owner that is genuinely executing on another core when a waiter suspends, and three shapes were tried without producing one on this port. Measured twice before and twice after, every gcda deleted between runs and 570 of 570 tests passing each time: 5114 of 5178 both times before, 5167 of 5178 both times after. Branch coverage goes from 2768 to 2821 and 2823 of 3548. A floor of 99 needs 5127, so the ratchet lands with forty lines of headroom against a numerator that has been seen moving by two between runs. Assisted-by: Claude Opus 5 --- .github/workflows/regression_test.yml | 25 +- test/smp/cmake/regression/CMakeLists.txt | 4 + .../threadx_byte_memory_long_search_test.c | 337 ++++++++++++ .../threadx_object_delete_suspension_test.c | 481 ++++++++++++++++++ .../threadx_thread_misaligned_stack_test.c | 156 ++++++ .../threadx_trace_entry_update_test.c | 367 +++++++++++++ 6 files changed, 1361 insertions(+), 9 deletions(-) create mode 100644 test/smp/regression/threadx_byte_memory_long_search_test.c create mode 100644 test/smp/regression/threadx_object_delete_suspension_test.c create mode 100644 test/smp/regression/threadx_thread_misaligned_stack_test.c create mode 100644 test/smp/regression/threadx_trace_entry_update_test.c diff --git a/.github/workflows/regression_test.yml b/.github/workflows/regression_test.yml index a1e6f0c0a..014ceec9a 100644 --- a/.github/workflows/regression_test.yml +++ b/.github/workflows/regression_test.yml @@ -63,15 +63,22 @@ jobs: cmake_path: ./test/smp/cmake result_affix: SMP skip_deploy: true - # Lower than ThreadX's, because this suite is: the merged report reads - # 5114/5178 lines -- 98.76% -- on the same run, with 64 uncovered lines - # across 11 files of common_smp/src. #666 closed the equivalent gaps in - # common/src only, so common_smp still carries them, plus a family of - # its own in the *_delete.c teardown paths and tx_byte_pool_search.c. - # A shared floor of 99 would therefore red-wall this job on every run - # while ThreadX passed -- probed against the pinned action. Raise this - # towards 99 as those lines are covered. - coverage_thresholds: '98 100' + # Raised from 98 with the four tests that closed 53 of the 64 lines this + # comment used to list: the merged report goes from 5114/5178 -- 98.76% -- + # to 5167/5178, 99.79%. A floor of 99 needs 5127, so there are 40 lines of + # headroom against a numerator measured flickering by two between runs. + # + # Still not 100, and not because the last eleven lines were skipped. Eight + # are tx_byte_pool_search.c's ownership delay loop, which needs another + # core to take the pool inside the window the search opens when it drops + # protection every twenty blocks; this port serialises all four cores on + # one pthread mutex and the thread that releases it wins the re-acquire + # every time -- measured over 180,003 windows, zero handovers. The other + # three are in tx_thread_smp_utilities.c: one is a range guard placed + # after the shift it is meant to guard, so reaching it needs undefined + # behaviour, and two are a priority-inheritance branch that needs the + # mutex owner genuinely executing on another core. See T17. + coverage_thresholds: '99 100' freertos: permissions: contents: read diff --git a/test/smp/cmake/regression/CMakeLists.txt b/test/smp/cmake/regression/CMakeLists.txt index 908ac5c72..af33ca3f0 100644 --- a/test/smp/cmake/regression/CMakeLists.txt +++ b/test/smp/cmake/regression/CMakeLists.txt @@ -25,6 +25,7 @@ set(regression_test_cases ${SOURCE_DIR}/threadx_block_memory_thread_terminate_test.c ${SOURCE_DIR}/threadx_byte_memory_basic_test.c ${SOURCE_DIR}/threadx_byte_memory_information_test.c + ${SOURCE_DIR}/threadx_byte_memory_long_search_test.c ${SOURCE_DIR}/threadx_byte_memory_prioritize_test.c ${SOURCE_DIR}/threadx_byte_memory_suspension_test.c ${SOURCE_DIR}/threadx_byte_memory_suspension_timeout_test.c @@ -52,6 +53,7 @@ set(regression_test_cases ${SOURCE_DIR}/threadx_mutex_proritize_test.c ${SOURCE_DIR}/threadx_mutex_suspension_timeout_test.c ${SOURCE_DIR}/threadx_mutex_thread_terminate_test.c + ${SOURCE_DIR}/threadx_object_delete_suspension_test.c ${SOURCE_DIR}/threadx_queue_basic_eight_word_test.c ${SOURCE_DIR}/threadx_queue_basic_four_word_test.c ${SOURCE_DIR}/threadx_queue_basic_one_word_test.c @@ -95,6 +97,7 @@ set(regression_test_cases ${SOURCE_DIR}/threadx_thread_create_preemption_threshold_test.c ${SOURCE_DIR}/threadx_thread_delayed_suspension_test.c ${SOURCE_DIR}/threadx_thread_information_test.c + ${SOURCE_DIR}/threadx_thread_misaligned_stack_test.c ${SOURCE_DIR}/threadx_thread_multi_level_preemption_threshold_test.c ${SOURCE_DIR}/threadx_thread_multiple_non_current_test.c ${SOURCE_DIR}/threadx_thread_multiple_sleep_test.c @@ -124,6 +127,7 @@ set(regression_test_cases ${SOURCE_DIR}/threadx_timer_multiple_test.c ${SOURCE_DIR}/threadx_timer_simple_test.c ${SOURCE_DIR}/threadx_trace_basic_test.c + ${SOURCE_DIR}/threadx_trace_entry_update_test.c ${SOURCE_DIR}/threadx_initialize_kernel_setup_test.c) add_custom_command( diff --git a/test/smp/regression/threadx_byte_memory_long_search_test.c b/test/smp/regression/threadx_byte_memory_long_search_test.c new file mode 100644 index 000000000..86a99be05 --- /dev/null +++ b/test/smp/regression/threadx_byte_memory_long_search_test.c @@ -0,0 +1,337 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/* This test makes _tx_byte_pool_search walk a long chain of fragments, from + more than one core at a time. + + The SMP version of that function carries two things its ThreadX counterpart + does not, and neither was covered. + + The first is the block-search limit. Under TX_BYTE_POOL_MULTIPLE_BLOCK_SEARCH + -- which this port's tx_user.h sets to 20 -- the search holds protection + across at most twenty blocks and then deliberately drops and retakes it, so + that a long search cannot lock the other cores out for the whole walk. + Nothing in the suite ever made one search examine twenty blocks: every byte + pool it builds has a handful of fragments at most. That is what this test + fixes. + + Having dropped protection, the search then checks whether some other thread + claimed the pool while it was let go, and if so spins for + TX_BYTE_POOL_DELAY_VALUE iterations before taking ownership back and + restarting the walk. That path this test does not reach, and the reason is a + property of the port rather than of the test: the Linux SMP port serialises + every core on one pthread mutex, and the window here is an unlock + immediately followed by a lock on that mutex. A thread spinning for the + protection on another core has to win that handoff, and glibc hands an + uncontended mutex straight back to the thread that just released it. + Measured: 180,003 windows over three cores, and the pool changed hands in + none of them. So tx_byte_pool_search.c lines 283 to 301 stay uncovered on + this port, and no number of iterations here will change that -- 250 is used + below rather than the tens of thousands that were tried, because the twenty- + block threshold above is crossed by the very first search and the rest buys + nothing. + + The pool is therefore filled with small allocations until it refuses another + one, and every second allocation is then released. That leaves upwards of + twenty free fragments, each too small to satisfy the request and none of + them adjacent to another, so the search can neither stop early nor merge its + way out of the walk. Every request is expected to fail with TX_NO_MEMORY; + the failure is the point, because a search that fails is a search that + walked the whole pool. + + The layout is asserted rather than assumed. If a change to the pool + arithmetic ever made the request satisfiable, or left fewer fragments than + the twenty-block threshold needs, this test would still pass while quietly + covering nothing -- so it checks the fragment count and checks that the + request really does fail before the threads start. + + The three worker threads are deliberately not confined to a core, so that + the walk really is driven from more than one core at a time. */ + +#include +#include "tx_api.h" +#include "threadx_test_port.h" + + +void test_control_return(UINT status); + + +/* Small chunks, every second one given back. The pool is filled until it + refuses another chunk rather than a fixed number of times, so that the + layout does not depend on this test agreeing with the allocator about the + per-block overhead -- get that wrong by one word and the pool is left with a + free tail large enough to satisfy the request below, and the search stops at + the first fragment instead of walking. */ + +#define CHUNK_BYTES ((ULONG) 8) +#define CHUNK_LIMIT ((UINT) 96) +#define MINIMUM_CHUNKS ((UINT) 40) + +/* Larger than any one free fragment and smaller than the pool's theoretical + capacity, which is what makes the search walk rather than refuse at the + door: _tx_byte_pool_search returns immediately when the request is at least + the theoretical total, without examining a single block. */ + +#define REQUEST_BYTES ((ULONG) 64) + +/* TX_BYTE_POOL_MULTIPLE_BLOCK_SEARCH is 20 on this port. The walk has to be + longer than that for the protection to be dropped at all. */ + +#define MINIMUM_FRAGMENTS ((ULONG) 24) + +/* Each worker searches this many times. One search is enough for the coverage; + the repetition is here so that the pool is genuinely walked from several + cores at once rather than by one thread at a time, which is the condition + the code under test was written for. */ + +#define SEARCHES_PER_THREAD ((ULONG) 250) + +#define WORKERS ((UINT) 3) + + +static TX_THREAD thread_0; +static TX_THREAD worker[WORKERS]; + +static TX_BYTE_POOL pool_0; + +static UCHAR pool_area[TX_TEST_BYTE_POOL_CAPACITY_BYTES(CHUNK_BYTES, 48)]; + +static void *chunk[CHUNK_LIMIT]; +static UINT chunk_count; + +static volatile ULONG workers_done = 0; +static volatile ULONG search_count[WORKERS]; + +static UINT error = 0; + + +static void thread_0_entry(ULONG thread_input); +static void worker_entry(ULONG thread_input); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_byte_memory_long_search_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; +UINT i; +CHAR *name; +ULONG available; +ULONG fragments; +void *probe_ptr; + + + /* Setup a pointer. */ + pointer = (CHAR *) first_unused_memory; + + status = tx_byte_pool_create(&pool_0, "long search pool", pool_area, sizeof(pool_area)); + + if (status != TX_SUCCESS) + { + + printf("Running Byte Memory Long Search Test................................ ERROR #1\n"); + test_control_return(1); + return; + } + + /* Fill the pool completely with small chunks, so that no free tail is left + behind that could satisfy the request. */ + chunk_count = ((UINT) 0); + while (chunk_count < CHUNK_LIMIT) + { + + status = tx_byte_allocate(&pool_0, &chunk[chunk_count], CHUNK_BYTES, TX_NO_WAIT); + + if (status != TX_SUCCESS) + { + + break; + } + + chunk_count++; + } + + if ((chunk_count < MINIMUM_CHUNKS) || (chunk_count == CHUNK_LIMIT)) + { + + printf("Running Byte Memory Long Search Test................................ ERROR #2\n"); + test_control_return(1); + return; + } + + /* Give every second one back. Alternating rather than consecutive, so that + no free fragment has a free neighbour and the search cannot merge two of + them into a block big enough to satisfy the request. */ + for (i = 1; i < chunk_count; i = i + ((UINT) 2)) + { + + status = tx_byte_release(chunk[i]); + + if (status != TX_SUCCESS) + { + + printf("Running Byte Memory Long Search Test................................ ERROR #3\n"); + test_control_return(1); + return; + } + + chunk[i] = TX_NULL; + } + + /* The walk has to be long enough to cross the twenty-block threshold. */ + status = tx_byte_pool_info_get(&pool_0, &name, &available, &fragments, TX_NULL, TX_NULL, TX_NULL); + + if ((status != TX_SUCCESS) || (fragments < MINIMUM_FRAGMENTS)) + { + + printf("Running Byte Memory Long Search Test................................ ERROR #4\n"); + test_control_return(1); + return; + } + + /* And the request has to fail, or the search stops at the first fragment + that fits and the walk never happens. */ + status = tx_byte_allocate(&pool_0, &probe_ptr, REQUEST_BYTES, TX_NO_WAIT); + + if (status != TX_NO_MEMORY) + { + + printf("Running Byte Memory Long Search Test................................ ERROR #5\n"); + test_control_return(1); + return; + } + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0, + pointer, TEST_STACK_SIZE_PRINTF, + 15, 15, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + if (status != TX_SUCCESS) + { + + printf("Running Byte Memory Long Search Test................................ ERROR #6\n"); + test_control_return(1); + return; + } + + /* The workers share one priority so that the scheduler is free to put them + on different cores, which is the whole point. */ + for (i = 0; i < WORKERS; i++) + { + + search_count[i] = ((ULONG) 0); + + status = tx_thread_create(&worker[i], "worker", worker_entry, (ULONG) i, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + if (status != TX_SUCCESS) + { + + printf("Running Byte Memory Long Search Test................................ ERROR #7\n"); + test_control_return(1); + } + } +} + + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; +UINT i; +CHAR *name; +ULONG available; +ULONG fragments; + + + /* Inform user. */ + printf("Running Byte Memory Long Search Test................................ "); + + /* Wait for the workers. They do not sleep, so this thread has to. */ + while (workers_done != ((ULONG) WORKERS)) + { + + tx_thread_sleep(1); + } + + for (i = 0; i < WORKERS; i++) + { + + if (search_count[i] != SEARCHES_PER_THREAD) + { + + error++; + } + } + + /* Every search failed, so nothing was taken and nothing was merged: the + pool must look exactly as it did when the workers started. */ + status = tx_byte_pool_info_get(&pool_0, &name, &available, &fragments, TX_NULL, TX_NULL, TX_NULL); + + if ((status != TX_SUCCESS) || (fragments < MINIMUM_FRAGMENTS)) + { + + error++; + } + + if (error) + { + + printf("ERROR #8\n"); + test_control_return(1); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + +static void worker_entry(ULONG thread_input) +{ + +UINT status; +ULONG i; +void *memory_ptr; + + + for (i = 0; i < SEARCHES_PER_THREAD; i++) + { + + status = tx_byte_allocate(&pool_0, &memory_ptr, REQUEST_BYTES, TX_NO_WAIT); + + if (status != TX_NO_MEMORY) + { + + error++; + break; + } + + search_count[thread_input]++; + } + + workers_done++; +} diff --git a/test/smp/regression/threadx_object_delete_suspension_test.c b/test/smp/regression/threadx_object_delete_suspension_test.c new file mode 100644 index 000000000..20633f087 --- /dev/null +++ b/test/smp/regression/threadx_object_delete_suspension_test.c @@ -0,0 +1,481 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/* This test deletes a block pool, a byte pool, an event flags group and a + queue while two threads are suspended on each of them, and checks that every + suspended thread is released with TX_DELETED. + + Each of those four delete routines carries the same loop, and in this suite + the whole loop body was uncovered -- thirty-six lines across the four files, + the largest single gap in the SMP coverage report: + + while (suspended_count != TX_NO_SUSPENSIONS) + { + suspended_count--; + TX_DISABLE + thread_ptr -> tx_thread_suspend_cleanup = TX_NULL; + thread_ptr -> tx_thread_suspend_status = TX_DELETED; + next_thread = thread_ptr -> tx_thread_suspended_next; + ... + _tx_thread_system_resume(thread_ptr); + thread_ptr = next_thread; + } + + The reason it was uncovered is worth writing down, because it is not that + the suite never deletes these objects -- it deletes all four after every + single test. test_control_cleanup() in the ThreadX suite deletes the + application's objects first and its threads last, so a test that ends with a + thread parked on a queue has that thread walked out of the queue by + tx_queue_delete. The SMP suite's cleanup deletes the threads first, on + purpose: it was changed so that no application-owned object is still + referenced when the object loops run, which is what stopped a class of + teardown hang. Correct, and the side effect is that every one of those + deletes now runs against an empty suspension list. + + So the coverage has to come from a test that means to delete a busy object + rather than from teardown that happens to. threadx_semaphore_delete_test + already does exactly this for semaphores, which is why tx_semaphore_delete.c + is the one member of the family that was fully covered; this is the same + idea for the other four. + + Two waiters per object rather than one, so the loop runs twice and its back + edge is taken as well as its body. + + The threads are not confined to a core. On this port they start on separate + cores and suspend in whatever order they get scheduled, so the control + thread waits on the object's own suspended count through tx_*_info_get + rather than on an ordering it cannot guarantee. The wait is bounded: a + suspension that never arrives fails the test instead of hanging it. */ + +#include +#include "tx_api.h" +#include "threadx_test_port.h" + + +void test_control_return(UINT status); + + +/* The four objects, deleted in this order. */ + +#define STAGE_BLOCK_POOL ((UINT) 0) +#define STAGE_BYTE_POOL ((UINT) 1) +#define STAGE_EVENT_FLAGS ((UINT) 2) +#define STAGE_QUEUE ((UINT) 3) +#define STAGE_COUNT ((UINT) 4) + +/* Number of threads that suspend on each object. */ + +#define WAITERS ((ULONG) 2) + +/* How many ticks the control thread will wait for a suspension before giving + up. Generous, because it is only ever reached when the test is failing -- + and finite, because the alternative is a run that hangs instead of one that + reports. */ + +#define WAIT_LIMIT_TICKS ((UINT) 200) + + +static TX_THREAD thread_0; +static TX_THREAD thread_1; +static TX_THREAD thread_2; + +static TX_BLOCK_POOL block_pool_0; +static TX_BYTE_POOL byte_pool_0; +static TX_EVENT_FLAGS_GROUP group_0; +static TX_QUEUE queue_0; + +/* Eight blocks of 16 bytes, all of them taken before any waiter runs. */ + +static UCHAR block_pool_area[TX_TEST_BLOCK_POOL_BYTES(16, 8)]; +static UCHAR byte_pool_area[TX_TEST_BYTE_POOL_BYTES(256)]; +static ULONG queue_area[16]; + +/* Counts of waiters that saw TX_DELETED, one entry per stage. */ + +static volatile ULONG deleted_count[STAGE_COUNT]; + +static UINT error = 0; + + +static void thread_0_entry(ULONG thread_input); +static void waiter_entry(ULONG thread_input); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_object_delete_suspension_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; +void *block_ptr; +void *bytes_ptr; +UINT i; + + + /* Setup a pointer. */ + pointer = (CHAR *) first_unused_memory; + + for (i = 0; i < STAGE_COUNT; i++) + { + + deleted_count[i] = ((ULONG) 0); + } + + /* Create the block pool and take every block, so that a waiter has nothing + to be given and suspends instead. */ + status = tx_block_pool_create(&block_pool_0, "delete suspension block pool", + 16, block_pool_area, sizeof(block_pool_area)); + + if (status != TX_SUCCESS) + { + + printf("Running Object Delete Suspension Test............................... ERROR #1\n"); + test_control_return(1); + } + + while (tx_block_allocate(&block_pool_0, &block_ptr, TX_NO_WAIT) == TX_SUCCESS) + { + + /* Nothing to do with the block; the point is that the pool is empty. */ + } + + /* Same idea for the byte pool: take enough of it that the 128-byte requests + below cannot be met. */ + status = tx_byte_pool_create(&byte_pool_0, "delete suspension byte pool", + byte_pool_area, sizeof(byte_pool_area)); + + if (status != TX_SUCCESS) + { + + printf("Running Object Delete Suspension Test............................... ERROR #2\n"); + test_control_return(1); + } + + status = tx_byte_allocate(&byte_pool_0, &bytes_ptr, 200, TX_NO_WAIT); + + if (status != TX_SUCCESS) + { + + printf("Running Object Delete Suspension Test............................... ERROR #3\n"); + test_control_return(1); + } + + /* An event flags group with nothing set. The waiters ask for a flag that is + never set by anybody. */ + status = tx_event_flags_create(&group_0, "delete suspension group"); + + if (status != TX_SUCCESS) + { + + printf("Running Object Delete Suspension Test............................... ERROR #4\n"); + test_control_return(1); + } + + /* An empty queue. The waiters receive from it and nobody ever sends. */ + status = tx_queue_create(&queue_0, "delete suspension queue", TX_1_ULONG, + queue_area, sizeof(queue_area)); + + if (status != TX_SUCCESS) + { + + printf("Running Object Delete Suspension Test............................... ERROR #5\n"); + test_control_return(1); + } + + /* The control thread runs at a higher priority than the waiters, but that + decides nothing here -- it waits on the suspended counts. */ + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0, + pointer, TEST_STACK_SIZE_PRINTF, + 15, 15, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + if (status != TX_SUCCESS) + { + + printf("Running Object Delete Suspension Test............................... ERROR #6\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_1, "thread 1", waiter_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + if (status != TX_SUCCESS) + { + + printf("Running Object Delete Suspension Test............................... ERROR #7\n"); + test_control_return(1); + } + + status = tx_thread_create(&thread_2, "thread 2", waiter_entry, 2, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + if (status != TX_SUCCESS) + { + + printf("Running Object Delete Suspension Test............................... ERROR #8\n"); + test_control_return(1); + } +} + + +/* Read the number of threads suspended on the object belonging to a stage. + Returns TX_TRUE when the count could be read, so that a failing info_get is + reported rather than mistaken for "nobody has suspended yet". */ + +static UINT suspended_on(UINT stage, ULONG *count) +{ + +UINT status; + + + /* Every destination but the suspended count is TX_NULL: each info_get + tests its destinations individually and skips the ones it is not given, + so there is nothing to declare here to throw away. */ + switch (stage) + { + + case STAGE_BLOCK_POOL: + + status = tx_block_pool_info_get(&block_pool_0, TX_NULL, TX_NULL, TX_NULL, + TX_NULL, count, TX_NULL); + break; + + case STAGE_BYTE_POOL: + + status = tx_byte_pool_info_get(&byte_pool_0, TX_NULL, TX_NULL, TX_NULL, + TX_NULL, count, TX_NULL); + break; + + case STAGE_EVENT_FLAGS: + + status = tx_event_flags_info_get(&group_0, TX_NULL, TX_NULL, + TX_NULL, count, TX_NULL); + break; + + default: + + status = tx_queue_info_get(&queue_0, TX_NULL, TX_NULL, TX_NULL, + TX_NULL, count, TX_NULL); + break; + } + + return((status == TX_SUCCESS) ? ((UINT) TX_TRUE) : ((UINT) TX_FALSE)); +} + + +/* Sleep until every waiter has suspended on this stage's object, or until the + budget runs out. Returns TX_TRUE if the waiters arrived. */ + +static UINT wait_for_waiters(UINT stage) +{ + +UINT ticks; +ULONG count; + + + count = ((ULONG) 0); + for (ticks = 0; ticks < WAIT_LIMIT_TICKS; ticks++) + { + + if (suspended_on(stage, &count) == ((UINT) TX_FALSE)) + { + + return((UINT) TX_FALSE); + } + + if (count == WAITERS) + { + + return((UINT) TX_TRUE); + } + + tx_thread_sleep(1); + } + + return((UINT) TX_FALSE); +} + + +/* Sleep until every waiter has reported TX_DELETED for this stage, or until the + budget runs out. */ + +static UINT wait_for_reports(UINT stage) +{ + +UINT ticks; + + + for (ticks = 0; ticks < WAIT_LIMIT_TICKS; ticks++) + { + + if (deleted_count[stage] == WAITERS) + { + + return((UINT) TX_TRUE); + } + + tx_thread_sleep(1); + } + + return((UINT) TX_FALSE); +} + + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; +UINT stage; + + + /* Inform user. */ + printf("Running Object Delete Suspension Test............................... "); + + for (stage = 0; stage < STAGE_COUNT; stage++) + { + + /* Both waiters have to be on the list before the delete, or the loop + under test walks a shorter list than this test means it to. */ + if (wait_for_waiters(stage) == ((UINT) TX_FALSE)) + { + + printf("ERROR #9 (stage %u)\n", stage); + test_control_return(1); + } + + switch (stage) + { + + case STAGE_BLOCK_POOL: + + status = tx_block_pool_delete(&block_pool_0); + break; + + case STAGE_BYTE_POOL: + + status = tx_byte_pool_delete(&byte_pool_0); + break; + + case STAGE_EVENT_FLAGS: + + status = tx_event_flags_delete(&group_0); + break; + + default: + + status = tx_queue_delete(&queue_0); + break; + } + + if (status != TX_SUCCESS) + { + + printf("ERROR #10 (stage %u)\n", stage); + test_control_return(1); + } + + /* Every waiter must come out of the delete with TX_DELETED, which is + the status the loop under test writes into each suspended thread. */ + if (wait_for_reports(stage) == ((UINT) TX_FALSE)) + { + + printf("ERROR #11 (stage %u)\n", stage); + test_control_return(1); + } + } + + if (error) + { + + printf("ERROR #12\n"); + test_control_return(1); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + +static void waiter_entry(ULONG thread_input) +{ + +UINT status; +UINT stage; +void *block_ptr; +void *bytes_ptr; +ULONG actual_flags; +ULONG message; + + + for (stage = 0; stage < STAGE_COUNT; stage++) + { + + switch (stage) + { + + case STAGE_BLOCK_POOL: + + /* The pool was emptied before any thread ran, so this suspends. */ + status = tx_block_allocate(&block_pool_0, &block_ptr, TX_WAIT_FOREVER); + break; + + case STAGE_BYTE_POOL: + + /* More than is left after the allocation made at define time. */ + status = tx_byte_allocate(&byte_pool_0, &bytes_ptr, 128, TX_WAIT_FOREVER); + break; + + case STAGE_EVENT_FLAGS: + + /* Nobody ever sets this flag. */ + status = tx_event_flags_get(&group_0, ((ULONG) 0x1), TX_AND_CLEAR, + &actual_flags, TX_WAIT_FOREVER); + break; + + default: + + /* Nobody ever sends to this queue. */ + status = tx_queue_receive(&queue_0, &message, TX_WAIT_FOREVER); + break; + } + + if (status == TX_DELETED) + { + + deleted_count[stage]++; + } + else + { + + /* Anything else means the object was not deleted out from under + this thread, and the control thread will say so. */ + error++; + return; + } + } +} diff --git a/test/smp/regression/threadx_thread_misaligned_stack_test.c b/test/smp/regression/threadx_thread_misaligned_stack_test.c new file mode 100644 index 000000000..fa72aab5a --- /dev/null +++ b/test/smp/regression/threadx_thread_misaligned_stack_test.c @@ -0,0 +1,156 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/* This test creates a thread whose stack does not begin on a ULONG boundary. + It is the SMP counterpart of the ThreadX suite's test of the same name. + + tx_thread_create rounds the starting address up to the next ULONG and then + takes a ULONG off the size, so that the rounding cannot push the end of the + stack past the memory the caller supplied: + + if (new_stack_start != updated_stack_start) + { + stack_size = stack_size - (sizeof(ULONG)); + } + + Every other test in the suite hands tx_thread_create an aligned stack, so + that subtraction was never executed -- the only uncovered line in + tx_thread_create.c across all five build configurations. A misaligned stack + is legitimate: the API takes a VOID * and the alignment fix-up exists + precisely to accept one. + + The line is compiled only under TX_ENABLE_STACK_CHECKING, so it is absent + from three of the five configurations' reports rather than uncovered in + them. + + The thread is then run to completion rather than merely created, because the + point of the adjustment is that the resulting stack is still usable and still + inside the caller's buffer. */ + +#include +#include "tx_api.h" + + +void test_control_return(UINT status); + + +static TX_THREAD thread_0; +static TX_THREAD thread_1; + +/* Thread 1's stack is carved out of this by hand so that its start can be put + deliberately off a ULONG boundary. The extra ULONG is what the misaligned + start is offset into, so that the stack still ends inside the array after + tx_thread_create has rounded the start up. */ + +static UCHAR misaligned_area[TEST_STACK_SIZE_PRINTF + sizeof(ULONG)]; + +static ULONG thread_1_counter = 0; + + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_thread_misaligned_stack_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; +CHAR *misaligned_stack; + + + /* Setup a pointer. */ + pointer = (CHAR *) first_unused_memory; + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + if (status != TX_SUCCESS) + { + + printf("Running Thread Misaligned Stack Test................................ ERROR #1\n"); + test_control_return(1); + } + + /* Push the start one byte past a ULONG boundary. The array itself is + aligned, so adding one is enough to guarantee the fix-up runs whatever + the alignment of the array turned out to be. */ + misaligned_stack = ((CHAR *) misaligned_area) + 1; + + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 0, + misaligned_stack, TEST_STACK_SIZE_PRINTF, + 15, 15, TX_NO_TIME_SLICE, TX_AUTO_START); + + if (status != TX_SUCCESS) + { + + printf("Running Thread Misaligned Stack Test................................ ERROR #2\n"); + test_control_return(1); + } +} + + +static void thread_0_entry(ULONG thread_input) +{ + + /* On this port the two threads start on separate cores, so this one does + not have to wait for a relinquish to run. It sleeps well past the single + tick thread 1 sleeps for, so the checks below are made against a thread + that has actually finished either way. */ + tx_thread_sleep(5); + + /* Both increments must have happened: one before thread 1 slept and one + after it woke, which is the half that needed the stack to survive a + context switch. */ + if (thread_1_counter != ((ULONG) 2)) + { + + printf("Running Thread Misaligned Stack Test................................ ERROR #3\n"); + test_control_return(1); + } + + /* The thread that ran on the misaligned stack must have run to completion, + which is what says the adjusted stack was usable. */ + if (thread_1.tx_thread_state != TX_COMPLETED) + { + + printf("Running Thread Misaligned Stack Test................................ ERROR #4\n"); + test_control_return(1); + } + + printf("Running Thread Misaligned Stack Test................................ SUCCESS!\n"); + test_control_return(0); +} + + +static void thread_1_entry(ULONG thread_input) +{ + + /* Use the stack either side of a context switch rather than returning + straight away. */ + thread_1_counter++; + + tx_thread_sleep(1); + + thread_1_counter++; +} diff --git a/test/smp/regression/threadx_trace_entry_update_test.c b/test/smp/regression/threadx_trace_entry_update_test.c new file mode 100644 index 000000000..17c366004 --- /dev/null +++ b/test/smp/regression/threadx_trace_entry_update_test.c @@ -0,0 +1,367 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/* This is the SMP counterpart of the ThreadX suite's trace entry update test. + It drives the trace entry update paths -- the blocks guarded by + TX_ENABLE_EVENT_TRACE that go back and patch a trace entry after the call + they belong to has finished its work. + + Those blocks all have the same shape: + + if (entry_ptr != TX_NULL) + { + if (time_stamp == entry_ptr -> tx_trace_buffer_entry_time_stamp) + { + entry_ptr -> tx_trace_buffer_entry_information_field_N = ...; + } + } + + entry_ptr comes from _tx_trace_buffer_current_ptr, which stays TX_NULL until + tx_trace_enable() is called at run time. Compiling with TX_ENABLE_EVENT_TRACE + is therefore not enough to reach them, and the trace_build configuration on + its own never does: the only other test that enables tracing -- + threadx_trace_basic_test -- exercises the enable API itself and never calls + tx_block_allocate or tx_byte_allocate at all. So the update blocks in + tx_block_allocate.c, tx_byte_allocate.c and tx_thread_system_suspend.c were + absent from the coverage report's covered set while appearing in its + denominator. + + Both allocators are driven twice, because they carry two of these blocks + each and only one is on the path that succeeds immediately: the second sits + after a suspension, where the allocation completes in the releasing thread's + context. Hence the second thread, which exists only to release what + thread 0 is waiting on. + + The one thing this version has to do that the ThreadX version does not is + pin both threads to a single core. On four cores the two threads run at the + same time, and thread 1 would give the block back before thread 0 had + suspended waiting for it -- the suspension the second update block sits + behind would never happen. Excluding both from cores 1 to 3 restores the + strict alternation the ThreadX suite gets for free. + + The test is built in all five configurations, and four of them do not define + TX_ENABLE_EVENT_TRACE. There tx_trace_enable reports TX_FEATURE_NOT_ENABLED, + the update blocks do not exist, and the allocation sequence below is still a + valid exercise of both allocators' suspension paths -- so the test is + meaningful in every configuration rather than skipped in four. */ + +#include +#include "tx_api.h" +#include "threadx_test_port.h" +#define TX_SOURCE_CODE +#include "tx_trace.h" + + +void test_control_return(UINT status); + + +static TX_THREAD thread_0; +static TX_THREAD thread_1; + +static TX_BLOCK_POOL block_pool_0; +static TX_BYTE_POOL byte_pool_0; +static TX_SEMAPHORE semaphore_0; + +/* Every thread this test creates is confined to core 0, so that the two of + them take turns the way they would on a uniprocessor. Bits 1, 2 and 3 set + means cores 1, 2 and 3 are excluded. */ + +#define TRACE_ENTRY_UPDATE_CORE_0_ONLY ((ULONG) 0xE) + +/* The trace buffer is sized generously on purpose. The inner test of each + update block compares the saved time stamp against the one in the entry, and + a buffer small enough to wrap between the call and its completion would + overwrite the entry and take the false branch every time -- the block would + be reached and its body still never run. */ + +static UCHAR trace_buffer[16384]; + +/* Four blocks of 20 bytes. */ + +static UCHAR block_pool_area[TX_TEST_BLOCK_POOL_BYTES(20, 4)]; +static UCHAR byte_pool_area[TX_TEST_BYTE_POOL_BYTES(512)]; + +/* Allocated by thread 0 and released by thread 1, which is what lets thread 0's + suspended allocations complete. */ + +static void *held_block; +static void *held_bytes; + +static UINT error = 0; + + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_trace_entry_update_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Setup a pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Create the pools before tracing is enabled, so that the events this test + cares about are the allocations rather than the creates. */ + status = tx_block_pool_create(&block_pool_0, "trace entry update block pool", + 20, block_pool_area, sizeof(block_pool_area)); + + if (status != TX_SUCCESS) + { + + printf("Running Trace Entry Update Test..................................... ERROR #1\n"); + test_control_return(1); + } + + status = tx_byte_pool_create(&byte_pool_0, "trace entry update byte pool", + byte_pool_area, sizeof(byte_pool_area)); + + if (status != TX_SUCCESS) + { + + printf("Running Trace Entry Update Test..................................... ERROR #2\n"); + test_control_return(1); + } + + /* Turn tracing on. This is the whole point of the test: without it + _tx_trace_buffer_current_ptr stays TX_NULL and every update block below + takes its guarding false branch. */ + _tx_trace_initialize(); + status = tx_trace_enable(trace_buffer, sizeof(trace_buffer), 16); + +#ifdef TX_ENABLE_EVENT_TRACE + + if (status != TX_SUCCESS) + { + + printf("Running Trace Entry Update Test..................................... ERROR #3\n"); + test_control_return(1); + } +#else + + /* Four of the five build configurations reach this branch. The rest of the + test still runs; it just is not exercising any update block. */ + if (status != TX_FEATURE_NOT_ENABLED) + { + + printf("Running Trace Entry Update Test..................................... ERROR #4\n"); + test_control_return(1); + } +#endif + + /* Register an object with no name at all, now that tracing is on. The name + copy in _tx_trace_object_register guards against a TX_NULL name and + breaks out of the copy loop, and nothing else in the suite takes that + branch with tracing enabled -- threadx_trace_basic_test makes the + equivalent call only under #ifndef TX_ENABLE_EVENT_TRACE, against the + no-op stub. + + A semaphore rather than a thread, deliberately: for a thread object the + register function dereferences the pointer it is handed to read the + thread's priority, so that type needs a real TX_THREAD behind it. */ + status = tx_semaphore_create(&semaphore_0, TX_NULL, 1); + + if (status != TX_SUCCESS) + { + + printf("Running Trace Entry Update Test..................................... ERROR #5\n"); + test_control_return(1); + } + + /* Thread 0 drives the test and must run first, so it takes the higher + priority -- the lower number. Both threads are created stopped so that + the core exclusion is in place before either of them is schedulable. */ + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0, + pointer, TEST_STACK_SIZE_PRINTF, + 15, 15, TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + status += tx_thread_smp_core_exclude(&thread_0, TRACE_ENTRY_UPDATE_CORE_0_ONLY); + + if (status != TX_SUCCESS) + { + + printf("Running Trace Entry Update Test..................................... ERROR #6\n"); + test_control_return(1); + } + + /* Thread 1 releases what thread 0 waits on. It runs only while thread 0 is + suspended, which is exactly when it is needed -- and only because it + shares thread 0's single core. */ + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 0, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + status += tx_thread_smp_core_exclude(&thread_1, TRACE_ENTRY_UPDATE_CORE_0_ONLY); + + if (status != TX_SUCCESS) + { + + printf("Running Trace Entry Update Test..................................... ERROR #7\n"); + test_control_return(1); + } + + /* Start them now that both exclusions are set. Priority decides the order, + not this one. */ + status = tx_thread_resume(&thread_1); + status += tx_thread_resume(&thread_0); + + if (status != TX_SUCCESS) + { + + printf("Running Trace Entry Update Test..................................... ERROR #8\n"); + test_control_return(1); + } +} + + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; +void *block_ptr; +void *byte_ptr; +UINT i; + + + /* Inform user. */ + printf("Running Trace Entry Update Test..................................... "); + + /* Empty the block pool. The first of these takes the immediate-success path + through tx_block_allocate, which carries the first update block. */ + held_block = TX_NULL; + for (i = 0; i < 4; i++) + { + + status = tx_block_allocate(&block_pool_0, &block_ptr, TX_NO_WAIT); + + if (status != TX_SUCCESS) + { + + error++; + break; + } + + /* Keep the first one for thread 1 to give back. */ + if (held_block == TX_NULL) + { + + held_block = block_ptr; + } + } + + /* The pool is empty now, so this suspends. It completes in thread 1's + context when the block comes back, which is the second update block in + tx_block_allocate -- and the suspend it goes through carries the update + block in tx_thread_system_suspend that names the next thread to run on + this core. */ + status = tx_block_allocate(&block_pool_0, &block_ptr, TX_WAIT_FOREVER); + + if (status != TX_SUCCESS) + { + + printf("ERROR #9\n"); + test_control_return(1); + } + + /* Now the same shape for the byte pool. Take most of it first, on the path + that succeeds immediately. */ + status = tx_byte_allocate(&byte_pool_0, &held_bytes, 300, TX_NO_WAIT); + + if (status != TX_SUCCESS) + { + + printf("ERROR #10\n"); + test_control_return(1); + } + + /* Not enough left, so this one suspends and is satisfied by thread 1's + release. */ + status = tx_byte_allocate(&byte_pool_0, &byte_ptr, 300, TX_WAIT_FOREVER); + + if (status != TX_SUCCESS) + { + + printf("ERROR #11\n"); + test_control_return(1); + } + + /* Sleep, so that thread 1 gets to run out its entry function and suspend + itself. That leaves nothing ready to execute anywhere, which is a second + update block in tx_thread_system_suspend -- the one on the branch taken + when the priority map is empty. The two suspensions above never reach it, + because thread 1 was always ready to take over. */ + status = tx_thread_sleep(5); + + if (status != TX_SUCCESS) + { + + printf("ERROR #12\n"); + test_control_return(1); + } + + if (error) + { + + printf("ERROR #13\n"); + test_control_return(1); + } + else + { + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + +static void thread_1_entry(ULONG thread_input) +{ + +UINT status; + + + /* Reached only when thread 0 has suspended on the empty block pool. */ + status = tx_block_release(held_block); + + if (status != TX_SUCCESS) + { + + error++; + } + + /* And again when thread 0 has suspended on the byte pool. Thread 0 preempts + on the release above, runs until it suspends a second time, and control + comes back here. */ + status = tx_byte_release(held_bytes); + + if (status != TX_SUCCESS) + { + + error++; + } + + /* Thread 0 reports the result; this thread has nothing left to do. */ + tx_thread_suspend(&thread_1); +} From 57390fc0fea1cbef93f6d153cd14584cf71e7733 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Tue, 1 Sep 2026 08:48:20 -0400 Subject: [PATCH 095/181] Refused the Cortex-R52 VFP option without a hard float ABI (#686) TX_R52_ENABLE_VFP with the default soft float ABI cannot build. The option defines TX_ENABLE_VFP_SUPPORT, which enables the VMRS, VSTMDB and VLDMIA blocks in the port assembly, and -mfloat-abi=soft leaves the assembler with no FPU to accept them. The configuration fails with eight errors of the form tx_thread_system_return.S:118: Error: selected processor does not support `vmrs r4,FPSCR' in ARM mode none of which mentions the float ABI, so a user has to reason from VMRS back to the option that enabled it. The guard that exists said otherwise. It warned that "the compiler will not emit floating-point instructions, so the VFP context path will never be exercised", which describes a build that succeeds and is merely pointless -- and then let configure finish, so the warning scrolled past well before the assembler errors appeared. It is now a FATAL_ERROR that names the fix, which is what the same file already does six lines above for TX_R52_ENABLE_FIQ_NESTING without TX_R52_ENABLE_FIQ. That combination is rejected for being "meaningless", while this one, which cannot assemble at all, was only warned about. The severities were the wrong way round. The option's definition also moves below the check, so the block reads like the FIQ nesting one. The ABI is not promoted to hard automatically. TX_R52_FLOAT_ABI is a cache variable the user may have set deliberately, and silently overriding an explicit choice is worse than refusing a combination that cannot work. readme_threadx.txt carried the same claim, and its option list marked the FIQ nesting dependency inline but not this one. Both corrected. No regression test. Nothing in the tree asserts a configure-time failure -- there is no harness for it, and the sibling FIQ nesting guard has none either -- so a test for this would have to introduce that mechanism for one case. Verified by hand in both directions instead: the soft-ABI combination now stops at configure with the message above, and the hard-ABI feature build (VFP, FIQ, IRQ nesting, FIQ nesting) builds its eight images clean and passes ctest 8/8 on the Armv8-R AEM FVP. scripts/check_gcc.sh passes unchanged; it configures the Cortex-R52 CMake stage without TX_R52_ENABLE_VFP, so the new branch is not on its path. Assisted-by: Claude Code (Opus 5) --- ports/cortex_r52/gnu/CMakeLists.txt | 12 +++++++----- ports/cortex_r52/gnu/readme_threadx.txt | 9 ++++++--- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/ports/cortex_r52/gnu/CMakeLists.txt b/ports/cortex_r52/gnu/CMakeLists.txt index af4642f82..26ca3028f 100644 --- a/ports/cortex_r52/gnu/CMakeLists.txt +++ b/ports/cortex_r52/gnu/CMakeLists.txt @@ -60,13 +60,15 @@ if(TX_R52_ENABLE_FIQ_NESTING) target_compile_definitions(${PROJECT_NAME} PUBLIC TX_ENABLE_FIQ_NESTING) endif() if(TX_R52_ENABLE_VFP) - target_compile_definitions(${PROJECT_NAME} PUBLIC TX_ENABLE_VFP_SUPPORT) if(NOT TX_R52_FLOAT_ABI STREQUAL "hard") - message(WARNING - "TX_R52_ENABLE_VFP is on but TX_R52_FLOAT_ABI is '${TX_R52_FLOAT_ABI}'. " - "The compiler will not emit floating-point instructions, so the VFP " - "context path will never be exercised. Use -DTX_R52_FLOAT_ABI=hard.") + message(FATAL_ERROR + "TX_R52_ENABLE_VFP requires TX_R52_FLOAT_ABI=hard, but it is " + "'${TX_R52_FLOAT_ABI}'. TX_ENABLE_VFP_SUPPORT enables the VMRS, " + "VSTMDB and VLDMIA blocks in the port assembly, and a soft float " + "ABI leaves the assembler with no FPU to accept them, so this " + "combination fails to assemble. Use -DTX_R52_FLOAT_ABI=hard.") endif() + target_compile_definitions(${PROJECT_NAME} PUBLIC TX_ENABLE_VFP_SUPPORT) endif() # Armv8-R AEM FVP example builds (boot check now, kernel demo from AR1/M2). diff --git a/ports/cortex_r52/gnu/readme_threadx.txt b/ports/cortex_r52/gnu/readme_threadx.txt index ccc2c8d60..4ad3cc344 100644 --- a/ports/cortex_r52/gnu/readme_threadx.txt +++ b/ports/cortex_r52/gnu/readme_threadx.txt @@ -25,6 +25,7 @@ is empty, so no A- or R-profile port could previously be built this way. -DTX_R52_FLOAT_ABI=soft|hard floating-point ABI, default soft -DTX_R52_ENABLE_VFP=ON lazy VFP context save and restore + (requires TX_R52_FLOAT_ABI=hard) -DTX_R52_ENABLE_FIQ=ON FIQ support -DTX_R52_ENABLE_IRQ_NESTING=ON nested IRQ support -DTX_R52_ENABLE_FIQ_NESTING=ON nested FIQ support (requires the above) @@ -33,9 +34,11 @@ is empty, so no A- or R-profile port could previously be built this way. -DTX_R52_CONSOLE_PL011=ON console on the PL011 UART, not semihosting TX_R52_ENABLE_VFP is PUBLIC: it changes which registers the context switch -saves, so the library and the application must agree. Pair it with -TX_R52_FLOAT_ABI=hard, otherwise the compiler emits no floating-point -instructions and the VFP path is never exercised. +saves, so the library and the application must agree. It requires +TX_R52_FLOAT_ABI=hard, and configure refuses the combination rather than +warning about it: the flag enables the VFP blocks in the port assembly, and a +soft float ABI leaves the assembler with no FPU to accept them, so the build +fails on the first VMRS rather than quietly skipping the VFP context path. Cortex-R52 always implements at least a single-precision FPU. GCC rejects "-mcpu=cortex-r52+nofp" and offers only "+nofp.dp", so the soft-float From 8c681c188ee748c777185e229024255c054a49d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Tue, 1 Sep 2026 09:42:38 -0400 Subject: [PATCH 096/181] Asserted that the Cortex-R52 port refuses the options it documents as refused (#687) ports/cortex_r52/gnu/CMakeLists.txt rejects two option combinations at configure time -- TX_R52_ENABLE_VFP without TX_R52_FLOAT_ABI=hard, and TX_R52_ENABLE_FIQ_NESTING without TX_R52_ENABLE_FIQ. Nothing exercised either. A guard that has stopped firing looks exactly like a guard nobody has tripped, so both could have been silently disabled by a typo in a variable name at any point and no check would have noticed. check_gcc.sh gains a sixth stage that configures each rejected combination and asserts the configure fails. It needs no new harness: the script already runs cmake as a subprocess for the CMake example builds, and the port's CMakeLists is included by the toolchain file alone, so no example flags are needed and the two negative configures stop almost immediately. Two things the stage does that a thinner version would not. It asserts the message text, not just the exit status. A configure that fails for an unrelated reason would otherwise be recorded as a guard doing its job. It also configures the SUPPORTED combination and requires that to succeed. Two negative assertions on their own are satisfied by a guard that rejects everything -- the port would be unbuildable and the check would still pass. The positive case is what separates a guard that works from one that is merely always on. Verified negatively, four deliberate breaks, each caught: VFP guard condition forced false -> "configure succeeded, but this combination cannot build" FIQ nesting guard forced false -> the same, on that case guard fires, message text changed -> "configure failed, but not on the expected guard" VFP guard condition forced true -> "the supported combination was refused" The fourth is the one the positive case exists for and the only one a refusals-only stage would have missed. ports/cortex_r52/gnu/CMakeLists.txt was confirmed byte-identical to dev afterwards. Full run passes: exit 0, all six stages, and --asm-only correctly skips the new one. Assisted-by: Claude Code (Opus 5) --- scripts/check_gcc.sh | 85 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 82 insertions(+), 3 deletions(-) diff --git a/scripts/check_gcc.sh b/scripts/check_gcc.sh index 6b2cb8d5c..ae603ea61 100755 --- a/scripts/check_gcc.sh +++ b/scripts/check_gcc.sh @@ -14,11 +14,13 @@ # SPDX-License-Identifier: MIT and CC0-1.0 ############################################################################## -# Builds the Arm ports with the GNU toolchain, in five stages: assemble every +# Builds the Arm ports with the GNU toolchain, in six stages: assemble every # assembly source of every Arm gnu port, assemble again the parts guarded by # feature macros, compile the common C sources for one core per architecture -# profile, then link the example builds, both the script-driven ones and those -# driven by CMake. Only the linking stages need a target C library. +# profile, link the example builds, both the script-driven ones and those +# driven by CMake, and finally assert that the option combinations the +# Cortex-R52 port refuses are in fact refused. Only the linking stages need a +# target C library. # # scripts/check_gcc.sh # both drivers from PATH # scripts/check_gcc.sh --arm-none-eabi /path/to/toolchain/bin \ @@ -560,6 +562,83 @@ if [ "$no_examples" -eq 0 ]; then fi fi +# -------------------------------------------------------------------------- +# Option combinations the port refuses at configure time. +# +# ports/cortex_r52/gnu/CMakeLists.txt rejects two combinations outright rather +# than letting them reach the compiler. Both are cheap to get wrong in a way +# that is invisible: a typo in a variable name makes the condition constant, +# and a guard that never fires is indistinguishable from one that is never +# tripped. So these assert the exit status AND the text, because a guard that +# fires for the wrong reason would otherwise pass. +# +# No example flags are needed: the port CMakeLists is included by the toolchain +# file alone, so the guards are reached without configuring anything else. That +# keeps the stage to three configures, two of which stop almost immediately. +# +# The third is the positive counterpart, and it is not decoration: a guard that +# rejects everything would satisfy both negative cases on its own. Asserting +# that the supported combination still configures is what distinguishes a guard +# that works from one that is merely always on. +# +# This is the only negative check in the script. Everything else here asserts +# that something builds; this stage asserts that two things refuse to, and that +# a third still does not. +if [ "$asm_only" -eq 0 ]; then + say "" + say "== Option combinations the Cortex-R52 port must refuse ==" + + if ! command -v cmake >/dev/null 2>&1; then + say " skipped: cmake is required" + else + # name | expected text in the error | options + refuse_case() { + case_name="$1"; want="$2"; shift 2 + build_dir="$(mktemp -d)" + if cmake -S . -B "$build_dir" -G Ninja \ + -DCMAKE_TOOLCHAIN_FILE=cmake/cortex_r52.cmake \ + -DARM_TOOLCHAIN_PATH="$(dirname "$CC_ARM")" \ + "$@" >"$build_dir/configure.log" 2>&1; then + fail "$case_name: configure succeeded, but this combination cannot build" + failures=$((failures + 1)) + elif ! grep -q "$want" "$build_dir/configure.log"; then + fail "$case_name: configure failed, but not on the expected guard" + fail " wanted text: $want" + tail -6 "$build_dir/configure.log" | sed 's/^/ /' + failures=$((failures + 1)) + else + say " $case_name: refused" + fi + rm -rf "$build_dir" + } + + refuse_case "VFP without a hard float ABI" \ + "TX_R52_ENABLE_VFP requires TX_R52_FLOAT_ABI=hard" \ + -DTX_R52_ENABLE_VFP=ON + + refuse_case "FIQ nesting without FIQ" \ + "TX_R52_ENABLE_FIQ_NESTING requires TX_R52_ENABLE_FIQ" \ + -DTX_R52_ENABLE_FIQ_NESTING=ON + + # The counterpart: the supported spelling of the first case must still + # configure, so a guard cannot pass this stage by rejecting everything. + build_dir="$(mktemp -d)" + if cmake -S . -B "$build_dir" -G Ninja \ + -DCMAKE_TOOLCHAIN_FILE=cmake/cortex_r52.cmake \ + -DARM_TOOLCHAIN_PATH="$(dirname "$CC_ARM")" \ + -DTX_R52_ENABLE_VFP=ON -DTX_R52_FLOAT_ABI=hard \ + -DTX_R52_ENABLE_FIQ=ON -DTX_R52_ENABLE_FIQ_NESTING=ON \ + >"$build_dir/configure.log" 2>&1; then + say " the supported combination: accepted" + else + fail "the supported combination was refused" + tail -6 "$build_dir/configure.log" | sed 's/^/ /' + failures=$((failures + 1)) + fi + rm -rf "$build_dir" + fi +fi + # -------------------------------------------------------------------------- say "" if [ "$failures" -eq 0 ]; then From 13c8c768c73b9ce10c9605f6df8b02080440f953 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Wed, 2 Sep 2026 19:08:24 -0400 Subject: [PATCH 097/181] Added the boot-at-EL1 option to the S32Z280 entry path (#690) The Armv8-R AEM FVP entry path has carried TX_R52_BOOT_AT_EL1 since it was written, for the case its own comment describes: "an earlier boot stage or a vendor EL2 monitor has already dropped privilege to EL1". This board's entry path did not, so a kernel could not be built as a guest on it at all -- and it is the board where that matters most, because it is the one with silicon behind it. The bracket is the whole change. Everything from the Thumb reset trampoline to the ERET goes inside #ifndef TX_R52_BOOT_AT_EL1, and the #else supplies a one-instruction A32 _start that branches to el1_entry. A32 AND NOT T32, which is the one real difference from the standalone entry. The core resets in Thumb state here because the RTU boot instruction NXP plants is a T32 branch, but a guest is not reached by reset: it is reached by the monitor's ERET, and the monitor chooses the state through SPSR.T. Get the two out of agreement and the guest dies on its first instruction with an undefined-instruction exception, which looks exactly like a bad entry address and sends the reader to the loader instead of to the ERET. WHAT THE MONITOR INHERITS is enumerated at the #ifndef, next to the code it replaces rather than in a document, because that is where somebody adding a third board will be looking. This board's EL2 block is considerably larger than the model's, and each item on the list is something a guest at EL1 provably cannot do rather than something it merely does not: CNTFRQ is writable only at the highest implemented exception level and reads zero out of reset; HCPTR.TCP10/TCP11 reset set, trapping every EL1 floating-point access; HSCTLR.TE is an EL2 register (SCTLR.TE is EL1's, and el1_entry still clears it below); ICC_HSRE.SRE makes every other ICC_* and ICH_* register exist at all; the low-latency peripheral port enables reset to zero and an EL1 write to that register traps to EL2; and the TCM enables are per-core with ENABLEEL2 SILENTLY IGNORED from EL1 -- measured on both BTCM and CTCM, the base took and bit 0 took while bit 1 stayed clear. CNTHCTL.PL1PCTEN and PL1PCEN are the deliberate omission from that list, and the note says why. This path opens both, because a standalone kernel owns the physical timer. A monitor that TIME-partitions its guests must not: a partition's physical time keeps running while it is descheduled, so a guest reading it can observe that it was not running. That is the monitor's decision rather than this file's, which is why the list says what a guest cannot do rather than what a monitor should. Verified both ways. The three standalone images build and link unchanged, and a kernel built with the option boots at EL1 on a S32Z280-594EVB under an EL2 monitor, runs two threads through a queue and a semaphore, and reports back -- with no other change to the kernel or to its port. Assisted-by: Claude Code (Opus 5) --- .../gnu/example_build/s32z280_evb/entry.S | 97 +++++++++++++++++++ 1 file changed, 97 insertions(+) diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/entry.S b/ports/cortex_r52/gnu/example_build/s32z280_evb/entry.S index 6813251ae..3c85db9bf 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/entry.S +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/entry.S @@ -46,6 +46,19 @@ @/* vector, syndrome and return address before parking. Without */ @/* this a fault would be indistinguishable from a hang. */ @/* */ +@/* Define TX_R52_BOOT_AT_EL1 to skip the EL2 configuration, for */ +@/* targets where an earlier boot stage or a vendor EL2 monitor (for */ +@/* example NXP's EL2M, or Eclipse ThreadX ZoneX) has already dropped */ +@/* privilege to EL1. The kernel then enters at el1_entry in A32 */ +@/* state, and the register list that becomes the monitor's */ +@/* responsibility is enumerated at the #ifndef itself rather than */ +@/* here, next to the code it replaces. */ +@/* */ +@/* The Armv8-R AEM FVP entry path has carried the same option since */ +@/* it was written; this file gained it later, which is why the two */ +@/* brackets are not identical in shape -- the EL2 work this board */ +@/* does is considerably larger. */ +@/* */ @/* CNTFRQ is read and recorded rather than written. The FVP leaves it */ @/* zero and its BSP programs a known value, but the correct frequency */ @/* for this board is not yet established, and writing a wrong one would*/ @@ -191,6 +204,60 @@ el1_vectors: b el1_irq_entry /* 0x18 IRQ */ b el1_fiq_entry /* 0x1C FIQ */ +#ifndef TX_R52_BOOT_AT_EL1 + +@/**************************************************************************/ +@/* THE EL2 RESET PATH, which a guest build skips entirely. */ +@/* */ +@/* Everything between this #ifndef and its #else configures EL2 and then */ +@/* drops to EL1. With TX_R52_BOOT_AT_EL1 defined, an earlier boot stage */ +@/* or a vendor EL2 monitor has already done that, so the kernel starts */ +@/* straight at el1_entry and none of it runs. */ +@/* */ +@/* WHAT THE MONITOR MUST THEN DO, because a guest at EL1 cannot: */ +@/* */ +@/* CNTFRQ writable only at the highest implemented */ +@/* exception level, and it reads ZERO out of */ +@/* reset on this part. A guest deriving a */ +@/* tick interval from it divides by zero. */ +@/* HCPTR.TCP10/TCP11 both reset SET, trapping every EL1 and EL0 */ +@/* floating-point access to EL2. */ +@/* HSCTLR.TE an EL2 register; a guest cannot write it. */ +@/* (SCTLR.TE is EL1's and el1_entry clears it */ +@/* below, so the guest still handles its own.) */ +@/* ICC_HSRE.SRE until it is set, every other ICC_* and */ +@/* ICH_* system register is UNDEFINED -- so an */ +@/* EL1 kernel cannot acknowledge an interrupt */ +@/* at all. */ +@/* IMP_PERIPHPREGIONR the low-latency peripheral port enables */ +@/* reset to zero and an EL1 write to this */ +@/* register traps to EL2 when */ +@/* HACTLR.PERIPHPREGIONR is clear. A guest */ +@/* that needs the RTU peripheral window at */ +@/* 0x76000000 therefore depends on the monitor */ +@/* having opened it; one that does not need it */ +@/* is unaffected. */ +@/* IMP_ATCMREGIONR and the TCM bases and enables are per-core, and */ +@/* IMP_BTCMREGIONR ENABLEEL2 is silently IGNORED when written */ +@/* from EL1 -- measured on this part, on both */ +@/* BTCM and CTCM: the base took and bit 0 took */ +@/* while bit 1 stayed clear. A guest that */ +@/* places anything in a TCM therefore needs */ +@/* the monitor to program and ECC-preload it, */ +@/* because ECC is enabled here and a TCM */ +@/* location must be WRITTEN before it can be */ +@/* read (TRM 6.2.2). */ +@/* */ +@/* CNTHCTL.PL1PCTEN and PL1PCEN are the interesting omission from that */ +@/* list. This path opens both, because a standalone kernel owns the */ +@/* physical timer. A monitor that TIME-partitions its guests must NOT */ +@/* open them: a partition's physical time keeps running while it is */ +@/* descheduled, so a guest reading it can observe that it was not */ +@/* running. Such a monitor gives its guests the virtual timer and a */ +@/* per-guest CNTVOFF instead. That is the monitor's decision to make, */ +@/* not this file's, which is why this list says what a guest CANNOT do */ +@/* rather than what a monitor SHOULD do. */ +@/**************************************************************************/ @/**************************************************************************/ @/* _start -- reset entry. Entered in THUMB state, Hyp mode (EL2). */ @/**************************************************************************/ @@ -438,6 +505,36 @@ start_a32: isb eret +#else + +@/**************************************************************************/ +@/* _start, when an EL2 monitor has already dropped privilege. */ +@/* */ +@/* A32, not T32, and that is the one real difference from the standalone */ +@/* entry above. The core resets in Thumb state here because the RTU boot */ +@/* instruction NXP plants is a T32 branch -- but a guest is not reached */ +@/* by reset. It is reached by the monitor's ERET, and the monitor */ +@/* chooses the state through SPSR.T. Both ZoneX and NXP's EL2M enter a */ +@/* guest in A32, matching the vector tables in this file, so this entry */ +@/* is A32 and needs no state switch of its own. */ +@/* */ +@/* SPSR.T MUST AGREE WITH THIS. If it does not, the guest dies on its */ +@/* first instruction with an undefined-instruction exception -- which */ +@/* looks exactly like a bad entry address and sends the reader to the */ +@/* loader instead of to the ERET. */ +@/**************************************************************************/ + + .section .text.boot, "ax" + .arm + .align 2 + .global _start + .type _start, %function +_start: + b el1_entry + .size _start, . - _start + +#endif + @/**************************************************************************/ @/* el1_entry -- first instruction at EL1. */ @/**************************************************************************/ From c469a7756bb25f58bbe7af187731e20184a85c98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Thu, 3 Sep 2026 11:44:27 -0400 Subject: [PATCH 098/181] Fixed the missing immediate prefix on MOV in Cortex-M schedulers (#693) The BASEPRI-masking path in tx_thread_schedule wrote "MOV r0, 0" rather than "MOV r0, #0". UAL requires the "#" prefix on an immediate operand. GNU as and the LLVM-based assemblers accept the unprefixed form and emit the intended encoding, but stricter assemblers reject it outright, so the affected ports could not be built with those toolchains. The GNU and AC6 sources had already been corrected; this brings the IAR and AC5 sources into line. Verified that both spellings assemble to the same Thumb-2 encoding (f04f 0000), so this is a source-correctness fix with no change in generated code or runtime behaviour. Covers 31 occurrences across the Cortex-M3, M4, M7, M33, M52, M55 and M85 ports, their module manager counterparts, and the shared ARMv7-M and ARMv8-M architecture sources. Fixes #461 Assisted-by: Copilot (Opus 5) --- ports/cortex_m3/ac5/src/tx_thread_schedule.s | 4 +++- ports/cortex_m3/iar/src/tx_thread_schedule.s | 4 +++- ports/cortex_m33/iar/src/tx_thread_schedule.s | 4 +++- ports/cortex_m4/ac5/src/tx_thread_schedule.s | 4 +++- ports/cortex_m4/iar/src/tx_thread_schedule.s | 4 +++- ports/cortex_m52/iar/src/tx_thread_schedule.s | 4 +++- ports/cortex_m55/iar/src/tx_thread_schedule.s | 4 +++- ports/cortex_m7/ac5/src/tx_thread_schedule.s | 4 +++- ports/cortex_m7/iar/src/tx_thread_schedule.s | 4 +++- ports/cortex_m85/iar/src/tx_thread_schedule.s | 4 +++- ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_schedule.s | 4 +++- ports_arch/ARMv7-M/threadx/iar/src/tx_thread_schedule.s | 4 +++- .../ac5/module_manager/src/tx_thread_schedule.s | 6 ++++-- .../iar/module_manager/src/tx_thread_schedule.s | 6 ++++-- ports_arch/ARMv8-M/threadx/iar/src/tx_thread_schedule.s | 4 +++- .../cortex_m3/ac5/module_manager/src/tx_thread_schedule.s | 6 ++++-- .../cortex_m3/iar/module_manager/src/tx_thread_schedule.s | 6 ++++-- .../cortex_m33/iar/module_manager/src/tx_thread_schedule.s | 6 ++++-- .../cortex_m4/ac5/module_manager/src/tx_thread_schedule.s | 6 ++++-- .../cortex_m4/iar/module_manager/src/tx_thread_schedule.s | 6 ++++-- .../cortex_m7/ac5/module_manager/src/tx_thread_schedule.s | 6 ++++-- .../cortex_m7/iar/module_manager/src/tx_thread_schedule.s | 6 ++++-- 22 files changed, 75 insertions(+), 31 deletions(-) diff --git a/ports/cortex_m3/ac5/src/tx_thread_schedule.s b/ports/cortex_m3/ac5/src/tx_thread_schedule.s index 84613f2db..8a971d39c 100644 --- a/ports/cortex_m3/ac5/src/tx_thread_schedule.s +++ b/ports/cortex_m3/ac5/src/tx_thread_schedule.s @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -132,7 +134,7 @@ __tx_ts_handler BL _tx_execution_thread_exit // Call the thread exit function POP {r0, lr} // Recover LR #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts diff --git a/ports/cortex_m3/iar/src/tx_thread_schedule.s b/ports/cortex_m3/iar/src/tx_thread_schedule.s index 0ef3a88e6..93e17e21e 100644 --- a/ports/cortex_m3/iar/src/tx_thread_schedule.s +++ b/ports/cortex_m3/iar/src/tx_thread_schedule.s @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -132,7 +134,7 @@ __tx_ts_handler: BL _tx_execution_thread_exit // Call the thread exit function POP {r0, lr} // Recover LR #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts diff --git a/ports/cortex_m33/iar/src/tx_thread_schedule.s b/ports/cortex_m33/iar/src/tx_thread_schedule.s index af0f9196a..99fbac9e2 100644 --- a/ports/cortex_m33/iar/src/tx_thread_schedule.s +++ b/ports/cortex_m33/iar/src/tx_thread_schedule.s @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -129,7 +131,7 @@ __tx_ts_handler: BL _tx_execution_thread_exit // Call the thread exit function POP {r0, lr} // Recover LR #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts diff --git a/ports/cortex_m4/ac5/src/tx_thread_schedule.s b/ports/cortex_m4/ac5/src/tx_thread_schedule.s index f11a31c7e..79c6d6608 100644 --- a/ports/cortex_m4/ac5/src/tx_thread_schedule.s +++ b/ports/cortex_m4/ac5/src/tx_thread_schedule.s @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -132,7 +134,7 @@ __tx_ts_handler BL _tx_execution_thread_exit // Call the thread exit function POP {r0, lr} // Recover LR #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts diff --git a/ports/cortex_m4/iar/src/tx_thread_schedule.s b/ports/cortex_m4/iar/src/tx_thread_schedule.s index 229fd5df0..9f8228934 100644 --- a/ports/cortex_m4/iar/src/tx_thread_schedule.s +++ b/ports/cortex_m4/iar/src/tx_thread_schedule.s @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -132,7 +134,7 @@ __tx_ts_handler: BL _tx_execution_thread_exit // Call the thread exit function POP {r0, lr} // Recover LR #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts diff --git a/ports/cortex_m52/iar/src/tx_thread_schedule.s b/ports/cortex_m52/iar/src/tx_thread_schedule.s index b5a1c9979..ccb7c83e8 100644 --- a/ports/cortex_m52/iar/src/tx_thread_schedule.s +++ b/ports/cortex_m52/iar/src/tx_thread_schedule.s @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -129,7 +131,7 @@ __tx_ts_handler: BL _tx_execution_thread_exit // Call the thread exit function POP {r0, lr} // Recover LR #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts diff --git a/ports/cortex_m55/iar/src/tx_thread_schedule.s b/ports/cortex_m55/iar/src/tx_thread_schedule.s index 822fa83a4..f3e5f6500 100644 --- a/ports/cortex_m55/iar/src/tx_thread_schedule.s +++ b/ports/cortex_m55/iar/src/tx_thread_schedule.s @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -129,7 +131,7 @@ __tx_ts_handler: BL _tx_execution_thread_exit // Call the thread exit function POP {r0, lr} // Recover LR #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts diff --git a/ports/cortex_m7/ac5/src/tx_thread_schedule.s b/ports/cortex_m7/ac5/src/tx_thread_schedule.s index 4ff53e174..e48f8fac8 100644 --- a/ports/cortex_m7/ac5/src/tx_thread_schedule.s +++ b/ports/cortex_m7/ac5/src/tx_thread_schedule.s @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -132,7 +134,7 @@ __tx_ts_handler BL _tx_execution_thread_exit // Call the thread exit function POP {r0, lr} // Recover LR #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts diff --git a/ports/cortex_m7/iar/src/tx_thread_schedule.s b/ports/cortex_m7/iar/src/tx_thread_schedule.s index 58279c1ad..bc85b5440 100644 --- a/ports/cortex_m7/iar/src/tx_thread_schedule.s +++ b/ports/cortex_m7/iar/src/tx_thread_schedule.s @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -132,7 +134,7 @@ __tx_ts_handler: BL _tx_execution_thread_exit // Call the thread exit function POP {r0, lr} // Recover LR #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts diff --git a/ports/cortex_m85/iar/src/tx_thread_schedule.s b/ports/cortex_m85/iar/src/tx_thread_schedule.s index fa2d7ba04..1651108c1 100644 --- a/ports/cortex_m85/iar/src/tx_thread_schedule.s +++ b/ports/cortex_m85/iar/src/tx_thread_schedule.s @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -129,7 +131,7 @@ __tx_ts_handler: BL _tx_execution_thread_exit // Call the thread exit function POP {r0, lr} // Recover LR #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts diff --git a/ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_schedule.s b/ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_schedule.s index 12da7d695..9853f3734 100644 --- a/ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_schedule.s +++ b/ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_schedule.s @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -132,7 +134,7 @@ __tx_ts_handler BL _tx_execution_thread_exit // Call the thread exit function POP {r0, lr} // Recover LR #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts diff --git a/ports_arch/ARMv7-M/threadx/iar/src/tx_thread_schedule.s b/ports_arch/ARMv7-M/threadx/iar/src/tx_thread_schedule.s index d38774b85..416aeff64 100644 --- a/ports_arch/ARMv7-M/threadx/iar/src/tx_thread_schedule.s +++ b/ports_arch/ARMv7-M/threadx/iar/src/tx_thread_schedule.s @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -132,7 +134,7 @@ __tx_ts_handler: BL _tx_execution_thread_exit // Call the thread exit function POP {r0, lr} // Recover LR #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts diff --git a/ports_arch/ARMv7-M/threadx_modules/ac5/module_manager/src/tx_thread_schedule.s b/ports_arch/ARMv7-M/threadx_modules/ac5/module_manager/src/tx_thread_schedule.s index c8f6e81d8..55c94a94f 100644 --- a/ports_arch/ARMv7-M/threadx_modules/ac5/module_manager/src/tx_thread_schedule.s +++ b/ports_arch/ARMv7-M/threadx_modules/ac5/module_manager/src/tx_thread_schedule.s @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -206,7 +208,7 @@ MemManage_Handler STR r1, [r0] // Store ICSR DSB // Wait for memory access to complete #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts @@ -238,7 +240,7 @@ __tx_ts_handler BL _tx_execution_thread_exit // Call the thread exit function POP {r0, lr} // Recover LR #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts diff --git a/ports_arch/ARMv7-M/threadx_modules/iar/module_manager/src/tx_thread_schedule.s b/ports_arch/ARMv7-M/threadx_modules/iar/module_manager/src/tx_thread_schedule.s index 7b30b360f..121311ba1 100644 --- a/ports_arch/ARMv7-M/threadx_modules/iar/module_manager/src/tx_thread_schedule.s +++ b/ports_arch/ARMv7-M/threadx_modules/iar/module_manager/src/tx_thread_schedule.s @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -207,7 +209,7 @@ UsageFault_Handler: STR r1, [r0] // Store ICSR DSB // Wait for memory access to complete #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts @@ -239,7 +241,7 @@ __tx_ts_handler: BL _tx_execution_thread_exit // Call the thread exit function POP {r0, lr} // Recover LR #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts diff --git a/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_schedule.s b/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_schedule.s index 84f2043fb..de2b7bcf7 100644 --- a/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_schedule.s +++ b/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_schedule.s @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -129,7 +131,7 @@ __tx_ts_handler: BL _tx_execution_thread_exit // Call the thread exit function POP {r0, lr} // Recover LR #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts diff --git a/ports_module/cortex_m3/ac5/module_manager/src/tx_thread_schedule.s b/ports_module/cortex_m3/ac5/module_manager/src/tx_thread_schedule.s index e698f2594..b0f068145 100644 --- a/ports_module/cortex_m3/ac5/module_manager/src/tx_thread_schedule.s +++ b/ports_module/cortex_m3/ac5/module_manager/src/tx_thread_schedule.s @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -206,7 +208,7 @@ MemManage_Handler STR r1, [r0] // Store ICSR DSB // Wait for memory access to complete #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts @@ -238,7 +240,7 @@ __tx_ts_handler BL _tx_execution_thread_exit // Call the thread exit function POP {r0, lr} // Recover LR #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts diff --git a/ports_module/cortex_m3/iar/module_manager/src/tx_thread_schedule.s b/ports_module/cortex_m3/iar/module_manager/src/tx_thread_schedule.s index f97239f6c..408a8b4c9 100644 --- a/ports_module/cortex_m3/iar/module_manager/src/tx_thread_schedule.s +++ b/ports_module/cortex_m3/iar/module_manager/src/tx_thread_schedule.s @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -207,7 +209,7 @@ UsageFault_Handler: STR r1, [r0] // Store ICSR DSB // Wait for memory access to complete #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts @@ -239,7 +241,7 @@ __tx_ts_handler: BL _tx_execution_thread_exit // Call the thread exit function POP {r0, lr} // Recover LR #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts diff --git a/ports_module/cortex_m33/iar/module_manager/src/tx_thread_schedule.s b/ports_module/cortex_m33/iar/module_manager/src/tx_thread_schedule.s index 3b6a61ce8..39e2aef10 100644 --- a/ports_module/cortex_m33/iar/module_manager/src/tx_thread_schedule.s +++ b/ports_module/cortex_m33/iar/module_manager/src/tx_thread_schedule.s @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -208,7 +210,7 @@ BusFault_Handler: STR r1, [r0] // Store ICSR DSB // Wait for memory access to complete #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts @@ -239,7 +241,7 @@ __tx_ts_handler: BL _tx_execution_thread_exit // Call the thread exit function POP {r0, lr} // Recover LR #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts diff --git a/ports_module/cortex_m4/ac5/module_manager/src/tx_thread_schedule.s b/ports_module/cortex_m4/ac5/module_manager/src/tx_thread_schedule.s index 1c82b416b..9840641c4 100644 --- a/ports_module/cortex_m4/ac5/module_manager/src/tx_thread_schedule.s +++ b/ports_module/cortex_m4/ac5/module_manager/src/tx_thread_schedule.s @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -206,7 +208,7 @@ MemManage_Handler STR r1, [r0] // Store ICSR DSB // Wait for memory access to complete #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts @@ -238,7 +240,7 @@ __tx_ts_handler BL _tx_execution_thread_exit // Call the thread exit function POP {r0, lr} // Recover LR #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts diff --git a/ports_module/cortex_m4/iar/module_manager/src/tx_thread_schedule.s b/ports_module/cortex_m4/iar/module_manager/src/tx_thread_schedule.s index b6a8c2772..242f83c51 100644 --- a/ports_module/cortex_m4/iar/module_manager/src/tx_thread_schedule.s +++ b/ports_module/cortex_m4/iar/module_manager/src/tx_thread_schedule.s @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -207,7 +209,7 @@ UsageFault_Handler: STR r1, [r0] // Store ICSR DSB // Wait for memory access to complete #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts @@ -239,7 +241,7 @@ __tx_ts_handler: BL _tx_execution_thread_exit // Call the thread exit function POP {r0, lr} // Recover LR #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts diff --git a/ports_module/cortex_m7/ac5/module_manager/src/tx_thread_schedule.s b/ports_module/cortex_m7/ac5/module_manager/src/tx_thread_schedule.s index 1810905af..0c87b3ee9 100644 --- a/ports_module/cortex_m7/ac5/module_manager/src/tx_thread_schedule.s +++ b/ports_module/cortex_m7/ac5/module_manager/src/tx_thread_schedule.s @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -206,7 +208,7 @@ MemManage_Handler STR r1, [r0] // Store ICSR DSB // Wait for memory access to complete #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts @@ -238,7 +240,7 @@ __tx_ts_handler BL _tx_execution_thread_exit // Call the thread exit function POP {r0, lr} // Recover LR #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts diff --git a/ports_module/cortex_m7/iar/module_manager/src/tx_thread_schedule.s b/ports_module/cortex_m7/iar/module_manager/src/tx_thread_schedule.s index d38c8df71..392ca6162 100644 --- a/ports_module/cortex_m7/iar/module_manager/src/tx_thread_schedule.s +++ b/ports_module/cortex_m7/iar/module_manager/src/tx_thread_schedule.s @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -207,7 +209,7 @@ UsageFault_Handler: STR r1, [r0] // Store ICSR DSB // Wait for memory access to complete #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts @@ -239,7 +241,7 @@ __tx_ts_handler: BL _tx_execution_thread_exit // Call the thread exit function POP {r0, lr} // Recover LR #ifdef TX_PORT_USE_BASEPRI - MOV r0, 0 // Disable BASEPRI masking (enable interrupts) + MOV r0, #0 // Disable BASEPRI masking (enable interrupts) MSR BASEPRI, r0 #else CPSIE i // Enable interrupts From 17ff21a07f35d5c58f29a8e5dcb5ffdcd3d17dcd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Thu, 3 Sep 2026 12:58:26 -0400 Subject: [PATCH 099/181] Fixed the garbled comment in the POSIX condition variable sources (#694) The comment above the internal semaphore lookup in the POSIX condition variable implementation was garbled: it contained a capitalisation typo ("COndition") and an incomplete sentence ("into a semaphore a cast"). The four affected sources now share a single, correct wording. This is a comment-only change; there is no functional impact. Fixes #419 Assisted-by: Copilot (Opus 5) --- utility/rtos_compatibility_layers/posix/px_cond_broadcast.c | 3 ++- utility/rtos_compatibility_layers/posix/px_cond_destroy.c | 3 ++- utility/rtos_compatibility_layers/posix/px_cond_init.c | 3 ++- utility/rtos_compatibility_layers/posix/px_cond_signal.c | 3 ++- 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/utility/rtos_compatibility_layers/posix/px_cond_broadcast.c b/utility/rtos_compatibility_layers/posix/px_cond_broadcast.c index f9c8f1510..a2babdbaa 100644 --- a/utility/rtos_compatibility_layers/posix/px_cond_broadcast.c +++ b/utility/rtos_compatibility_layers/posix/px_cond_broadcast.c @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -91,7 +92,7 @@ UINT old_threshold,dummy; /* Get the condition variable's internal semaphore. */ - /* Simply convert the condition variable control block into a semaphore a cast */ + /* Simply convert the condition variable control block into a semaphore using casting. */ semaphore_ptr = (&( cond->cond_semaphore )); sem_count = semaphore_ptr->tx_semaphore_suspended_count; diff --git a/utility/rtos_compatibility_layers/posix/px_cond_destroy.c b/utility/rtos_compatibility_layers/posix/px_cond_destroy.c index efa99be1b..2ae8421aa 100644 --- a/utility/rtos_compatibility_layers/posix/px_cond_destroy.c +++ b/utility/rtos_compatibility_layers/posix/px_cond_destroy.c @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -80,7 +81,7 @@ UINT status; { cond->in_use = TX_FALSE; /* Get the condition variable's internal semaphore. */ - /* Simply convert the Condition variable control block into a semaphore a cast */ + /* Simply convert the condition variable control block into a semaphore using casting. */ semaphore_ptr = (&( cond->cond_semaphore )); status = tx_semaphore_delete(semaphore_ptr); if (status != TX_SUCCESS) diff --git a/utility/rtos_compatibility_layers/posix/px_cond_init.c b/utility/rtos_compatibility_layers/posix/px_cond_init.c index b376132db..87ea12d69 100644 --- a/utility/rtos_compatibility_layers/posix/px_cond_init.c +++ b/utility/rtos_compatibility_layers/posix/px_cond_init.c @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -72,7 +73,7 @@ UINT status; cond->in_use = TX_TRUE; /* Get the condition variable's internal semaphore. */ - /* Simply convert the COndition variable control block into a semaphore a cast */ + /* Simply convert the condition variable control block into a semaphore using casting. */ semaphore_ptr = (&( cond->cond_semaphore )); /* Now create the internal semaphore for this cond variable */ status = tx_semaphore_create(semaphore_ptr,"csem",0); diff --git a/utility/rtos_compatibility_layers/posix/px_cond_signal.c b/utility/rtos_compatibility_layers/posix/px_cond_signal.c index b1f4f2855..4b660feff 100644 --- a/utility/rtos_compatibility_layers/posix/px_cond_signal.c +++ b/utility/rtos_compatibility_layers/posix/px_cond_signal.c @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -84,7 +85,7 @@ TX_SEMAPHORE *semaphore_ptr; UINT status; /* Get the condition variable's internal semaphore. */ - /* Simply convert the COndition variable control block into a semaphore a cast */ + /* Simply convert the condition variable control block into a semaphore using casting. */ semaphore_ptr = (&( cond->cond_semaphore )); if ( semaphore_ptr->tx_semaphore_suspended_count) { From 508af549dae1c269088b8e02c45670bf87de33b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Thu, 3 Sep 2026 13:50:31 -0400 Subject: [PATCH 100/181] Fixed the incorrect loop bound constant in the IAR file lock support (#695) The IAR multithreaded library support code allocates its file lock mutexes from an array of _MAX_FLOCK entries, but the wrap-around check and the exhaustion check in __iar_file_Mtxinit() both compared against _MAX_LOCK, the bound of the unrelated system lock mutex array. When _MAX_FLOCK is greater than _MAX_LOCK, the free mutex index wrapped early and the exhaustion check reported failure while free entries remained, so *m was set to TX_NULL and the application faulted the first time a file lock was taken. When _MAX_FLOCK is smaller than _MAX_LOCK, the free mutex index was allowed to run past the end of __tx_iar_file_lock_mutexes and the exhaustion check could never fire. Corrected all four comparisons in each of the 27 copies of tx_iar.c. Fixes #444 Assisted-by: Copilot (Opus 5) --- ports/arm11/iar/src/tx_iar.c | 9 +++++---- ports/arm9/iar/src/tx_iar.c | 9 +++++---- ports/cortex_a15/iar/src/tx_iar.c | 9 +++++---- ports/cortex_a5/iar/src/tx_iar.c | 9 +++++---- ports/cortex_a7/iar/src/tx_iar.c | 9 +++++---- ports/cortex_a8/iar/src/tx_iar.c | 9 +++++---- ports/cortex_a9/iar/src/tx_iar.c | 9 +++++---- ports/cortex_m0/iar/src/tx_iar.c | 9 +++++---- ports/cortex_m23/iar/src/tx_iar.c | 9 +++++---- ports/cortex_m3/iar/src/tx_iar.c | 9 +++++---- ports/cortex_m33/iar/src/tx_iar.c | 9 +++++---- ports/cortex_m4/iar/src/tx_iar.c | 9 +++++---- ports/cortex_m52/iar/src/tx_iar.c | 9 +++++---- ports/cortex_m55/iar/src/tx_iar.c | 9 +++++---- ports/cortex_m7/iar/src/tx_iar.c | 9 +++++---- ports/cortex_m85/iar/src/tx_iar.c | 9 +++++---- ports/cortex_r4/iar/src/tx_iar.c | 9 +++++---- ports/cortex_r5/iar/src/tx_iar.c | 9 +++++---- ports_arch/ARMv7-M/threadx/iar/src/tx_iar.c | 9 +++++---- .../threadx_modules/iar/module_manager/src/tx_iar.c | 9 +++++---- ports_arch/ARMv8-M/threadx/iar/src/tx_iar.c | 9 +++++---- ports_module/cortex_a7/iar/module_manager/src/tx_iar.c | 9 +++++---- ports_module/cortex_m0+/iar/module_manager/src/tx_iar.c | 9 +++++---- ports_module/cortex_m3/iar/module_manager/src/tx_iar.c | 9 +++++---- ports_module/cortex_m4/iar/module_manager/src/tx_iar.c | 9 +++++---- ports_module/cortex_m7/iar/module_manager/src/tx_iar.c | 9 +++++---- ports_module/cortex_r4/iar/module_manager/src/tx_iar.c | 9 +++++---- 27 files changed, 135 insertions(+), 108 deletions(-) diff --git a/ports/arm11/iar/src/tx_iar.c b/ports/arm11/iar/src/tx_iar.c index 238b485ee..ddfdaf3dd 100644 --- a/ports/arm11/iar/src/tx_iar.c +++ b/ports/arm11/iar/src/tx_iar.c @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -270,7 +271,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -287,7 +288,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ @@ -678,7 +679,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -695,7 +696,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ diff --git a/ports/arm9/iar/src/tx_iar.c b/ports/arm9/iar/src/tx_iar.c index 238b485ee..ddfdaf3dd 100644 --- a/ports/arm9/iar/src/tx_iar.c +++ b/ports/arm9/iar/src/tx_iar.c @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -270,7 +271,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -287,7 +288,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ @@ -678,7 +679,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -695,7 +696,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ diff --git a/ports/cortex_a15/iar/src/tx_iar.c b/ports/cortex_a15/iar/src/tx_iar.c index 238b485ee..ddfdaf3dd 100644 --- a/ports/cortex_a15/iar/src/tx_iar.c +++ b/ports/cortex_a15/iar/src/tx_iar.c @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -270,7 +271,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -287,7 +288,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ @@ -678,7 +679,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -695,7 +696,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ diff --git a/ports/cortex_a5/iar/src/tx_iar.c b/ports/cortex_a5/iar/src/tx_iar.c index 238b485ee..ddfdaf3dd 100644 --- a/ports/cortex_a5/iar/src/tx_iar.c +++ b/ports/cortex_a5/iar/src/tx_iar.c @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -270,7 +271,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -287,7 +288,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ @@ -678,7 +679,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -695,7 +696,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ diff --git a/ports/cortex_a7/iar/src/tx_iar.c b/ports/cortex_a7/iar/src/tx_iar.c index 238b485ee..ddfdaf3dd 100644 --- a/ports/cortex_a7/iar/src/tx_iar.c +++ b/ports/cortex_a7/iar/src/tx_iar.c @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -270,7 +271,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -287,7 +288,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ @@ -678,7 +679,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -695,7 +696,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ diff --git a/ports/cortex_a8/iar/src/tx_iar.c b/ports/cortex_a8/iar/src/tx_iar.c index 238b485ee..ddfdaf3dd 100644 --- a/ports/cortex_a8/iar/src/tx_iar.c +++ b/ports/cortex_a8/iar/src/tx_iar.c @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -270,7 +271,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -287,7 +288,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ @@ -678,7 +679,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -695,7 +696,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ diff --git a/ports/cortex_a9/iar/src/tx_iar.c b/ports/cortex_a9/iar/src/tx_iar.c index 238b485ee..ddfdaf3dd 100644 --- a/ports/cortex_a9/iar/src/tx_iar.c +++ b/ports/cortex_a9/iar/src/tx_iar.c @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -270,7 +271,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -287,7 +288,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ @@ -678,7 +679,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -695,7 +696,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ diff --git a/ports/cortex_m0/iar/src/tx_iar.c b/ports/cortex_m0/iar/src/tx_iar.c index 238b485ee..ddfdaf3dd 100644 --- a/ports/cortex_m0/iar/src/tx_iar.c +++ b/ports/cortex_m0/iar/src/tx_iar.c @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -270,7 +271,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -287,7 +288,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ @@ -678,7 +679,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -695,7 +696,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ diff --git a/ports/cortex_m23/iar/src/tx_iar.c b/ports/cortex_m23/iar/src/tx_iar.c index 238b485ee..ddfdaf3dd 100644 --- a/ports/cortex_m23/iar/src/tx_iar.c +++ b/ports/cortex_m23/iar/src/tx_iar.c @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -270,7 +271,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -287,7 +288,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ @@ -678,7 +679,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -695,7 +696,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ diff --git a/ports/cortex_m3/iar/src/tx_iar.c b/ports/cortex_m3/iar/src/tx_iar.c index 238b485ee..ddfdaf3dd 100644 --- a/ports/cortex_m3/iar/src/tx_iar.c +++ b/ports/cortex_m3/iar/src/tx_iar.c @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -270,7 +271,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -287,7 +288,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ @@ -678,7 +679,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -695,7 +696,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ diff --git a/ports/cortex_m33/iar/src/tx_iar.c b/ports/cortex_m33/iar/src/tx_iar.c index 238b485ee..ddfdaf3dd 100644 --- a/ports/cortex_m33/iar/src/tx_iar.c +++ b/ports/cortex_m33/iar/src/tx_iar.c @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -270,7 +271,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -287,7 +288,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ @@ -678,7 +679,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -695,7 +696,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ diff --git a/ports/cortex_m4/iar/src/tx_iar.c b/ports/cortex_m4/iar/src/tx_iar.c index 238b485ee..ddfdaf3dd 100644 --- a/ports/cortex_m4/iar/src/tx_iar.c +++ b/ports/cortex_m4/iar/src/tx_iar.c @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -270,7 +271,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -287,7 +288,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ @@ -678,7 +679,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -695,7 +696,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ diff --git a/ports/cortex_m52/iar/src/tx_iar.c b/ports/cortex_m52/iar/src/tx_iar.c index 238b485ee..ddfdaf3dd 100644 --- a/ports/cortex_m52/iar/src/tx_iar.c +++ b/ports/cortex_m52/iar/src/tx_iar.c @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -270,7 +271,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -287,7 +288,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ @@ -678,7 +679,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -695,7 +696,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ diff --git a/ports/cortex_m55/iar/src/tx_iar.c b/ports/cortex_m55/iar/src/tx_iar.c index 238b485ee..ddfdaf3dd 100644 --- a/ports/cortex_m55/iar/src/tx_iar.c +++ b/ports/cortex_m55/iar/src/tx_iar.c @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -270,7 +271,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -287,7 +288,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ @@ -678,7 +679,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -695,7 +696,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ diff --git a/ports/cortex_m7/iar/src/tx_iar.c b/ports/cortex_m7/iar/src/tx_iar.c index 238b485ee..ddfdaf3dd 100644 --- a/ports/cortex_m7/iar/src/tx_iar.c +++ b/ports/cortex_m7/iar/src/tx_iar.c @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -270,7 +271,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -287,7 +288,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ @@ -678,7 +679,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -695,7 +696,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ diff --git a/ports/cortex_m85/iar/src/tx_iar.c b/ports/cortex_m85/iar/src/tx_iar.c index 238b485ee..ddfdaf3dd 100644 --- a/ports/cortex_m85/iar/src/tx_iar.c +++ b/ports/cortex_m85/iar/src/tx_iar.c @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -270,7 +271,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -287,7 +288,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ @@ -678,7 +679,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -695,7 +696,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ diff --git a/ports/cortex_r4/iar/src/tx_iar.c b/ports/cortex_r4/iar/src/tx_iar.c index 238b485ee..ddfdaf3dd 100644 --- a/ports/cortex_r4/iar/src/tx_iar.c +++ b/ports/cortex_r4/iar/src/tx_iar.c @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -270,7 +271,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -287,7 +288,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ @@ -678,7 +679,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -695,7 +696,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ diff --git a/ports/cortex_r5/iar/src/tx_iar.c b/ports/cortex_r5/iar/src/tx_iar.c index 238b485ee..ddfdaf3dd 100644 --- a/ports/cortex_r5/iar/src/tx_iar.c +++ b/ports/cortex_r5/iar/src/tx_iar.c @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -270,7 +271,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -287,7 +288,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ @@ -678,7 +679,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -695,7 +696,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ diff --git a/ports_arch/ARMv7-M/threadx/iar/src/tx_iar.c b/ports_arch/ARMv7-M/threadx/iar/src/tx_iar.c index 238b485ee..ddfdaf3dd 100644 --- a/ports_arch/ARMv7-M/threadx/iar/src/tx_iar.c +++ b/ports_arch/ARMv7-M/threadx/iar/src/tx_iar.c @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -270,7 +271,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -287,7 +288,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ @@ -678,7 +679,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -695,7 +696,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ diff --git a/ports_arch/ARMv7-M/threadx_modules/iar/module_manager/src/tx_iar.c b/ports_arch/ARMv7-M/threadx_modules/iar/module_manager/src/tx_iar.c index 238b485ee..ddfdaf3dd 100644 --- a/ports_arch/ARMv7-M/threadx_modules/iar/module_manager/src/tx_iar.c +++ b/ports_arch/ARMv7-M/threadx_modules/iar/module_manager/src/tx_iar.c @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -270,7 +271,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -287,7 +288,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ @@ -678,7 +679,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -695,7 +696,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ diff --git a/ports_arch/ARMv8-M/threadx/iar/src/tx_iar.c b/ports_arch/ARMv8-M/threadx/iar/src/tx_iar.c index 238b485ee..ddfdaf3dd 100644 --- a/ports_arch/ARMv8-M/threadx/iar/src/tx_iar.c +++ b/ports_arch/ARMv8-M/threadx/iar/src/tx_iar.c @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -270,7 +271,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -287,7 +288,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ @@ -678,7 +679,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -695,7 +696,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ diff --git a/ports_module/cortex_a7/iar/module_manager/src/tx_iar.c b/ports_module/cortex_a7/iar/module_manager/src/tx_iar.c index 238b485ee..ddfdaf3dd 100644 --- a/ports_module/cortex_a7/iar/module_manager/src/tx_iar.c +++ b/ports_module/cortex_a7/iar/module_manager/src/tx_iar.c @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -270,7 +271,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -287,7 +288,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ @@ -678,7 +679,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -695,7 +696,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ diff --git a/ports_module/cortex_m0+/iar/module_manager/src/tx_iar.c b/ports_module/cortex_m0+/iar/module_manager/src/tx_iar.c index 238b485ee..ddfdaf3dd 100644 --- a/ports_module/cortex_m0+/iar/module_manager/src/tx_iar.c +++ b/ports_module/cortex_m0+/iar/module_manager/src/tx_iar.c @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -270,7 +271,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -287,7 +288,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ @@ -678,7 +679,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -695,7 +696,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ diff --git a/ports_module/cortex_m3/iar/module_manager/src/tx_iar.c b/ports_module/cortex_m3/iar/module_manager/src/tx_iar.c index 238b485ee..ddfdaf3dd 100644 --- a/ports_module/cortex_m3/iar/module_manager/src/tx_iar.c +++ b/ports_module/cortex_m3/iar/module_manager/src/tx_iar.c @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -270,7 +271,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -287,7 +288,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ @@ -678,7 +679,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -695,7 +696,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ diff --git a/ports_module/cortex_m4/iar/module_manager/src/tx_iar.c b/ports_module/cortex_m4/iar/module_manager/src/tx_iar.c index 238b485ee..ddfdaf3dd 100644 --- a/ports_module/cortex_m4/iar/module_manager/src/tx_iar.c +++ b/ports_module/cortex_m4/iar/module_manager/src/tx_iar.c @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -270,7 +271,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -287,7 +288,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ @@ -678,7 +679,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -695,7 +696,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ diff --git a/ports_module/cortex_m7/iar/module_manager/src/tx_iar.c b/ports_module/cortex_m7/iar/module_manager/src/tx_iar.c index 238b485ee..ddfdaf3dd 100644 --- a/ports_module/cortex_m7/iar/module_manager/src/tx_iar.c +++ b/ports_module/cortex_m7/iar/module_manager/src/tx_iar.c @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -270,7 +271,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -287,7 +288,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ @@ -678,7 +679,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -695,7 +696,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ diff --git a/ports_module/cortex_r4/iar/module_manager/src/tx_iar.c b/ports_module/cortex_r4/iar/module_manager/src/tx_iar.c index 238b485ee..ddfdaf3dd 100644 --- a/ports_module/cortex_r4/iar/module_manager/src/tx_iar.c +++ b/ports_module/cortex_r4/iar/module_manager/src/tx_iar.c @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -270,7 +271,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -287,7 +288,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ @@ -678,7 +679,7 @@ TX_MUTEX *mutex_ptr; mutex_ptr = &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++]; /* Check for wrap-around on the next free mutex. */ - if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK) + if (__tx_iar_file_lock_next_free_mutex >= _MAX_FLOCK) { /* Yes, set the free index back to 0. */ @@ -695,7 +696,7 @@ TX_MUTEX *mutex_ptr; } /* Determine if a free mutex was found. */ - if (i >= _MAX_LOCK) + if (i >= _MAX_FLOCK) { /* Error! No more free mutexes! */ From d7789f0b1261fe897e2cdc5a525cfa06011dd35f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Thu, 3 Sep 2026 14:17:49 -0400 Subject: [PATCH 101/181] Fixed the clobbered return address in the RISC-V context save (#696) _tx_thread_context_save() returns to its caller with ret, which uses the return address held in ra. When TX_ENABLE_EXECUTION_CHANGE_NOTIFY was defined, the call to _tx_execution_isr_enter overwrote ra with the address of the instruction following the call, so the subsequent ret returned into _tx_thread_context_save itself instead of the interrupt service routine. The return address is now saved on the stack around the call and recovered afterwards, which is the same idiom already used by the Arm ports. The fix covers all three affected paths (nested save, thread save and idle system save) in the risc-v32 GNU, risc-v32 IAR and risc-v64 GNU ports. Fixes #348 Assisted-by: Copilot (Opus 5) --- ports/risc-v32/gnu/src/tx_thread_context_save.S | 14 ++++++++++++++ ports/risc-v32/iar/src/tx_thread_context_save.s | 13 +++++++++++++ ports/risc-v64/gnu/src/tx_thread_context_save.S | 13 +++++++++++++ 3 files changed, 40 insertions(+) diff --git a/ports/risc-v32/gnu/src/tx_thread_context_save.S b/ports/risc-v32/gnu/src/tx_thread_context_save.S index 0a0c0c156..d61cea86e 100644 --- a/ports/risc-v32/gnu/src/tx_thread_context_save.S +++ b/ports/risc-v32/gnu/src/tx_thread_context_save.S @@ -1,5 +1,6 @@ /*************************************************************************** * Copyright (c) 2025 10xEngineers + * 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 @@ -8,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -173,7 +175,11 @@ _tx_thread_skip_fpu_save: /* Call the ISR execution exit function if enabled. */ #ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY + addi sp, sp, -16 // Reserve space to save the return address + sw ra, 0(sp) // Save the return address call _tx_execution_isr_enter // Call the ISR execution enter function + lw ra, 0(sp) // Recover the return address + addi sp, sp, 16 // Recover the reserved stack space #endif ret // Return to ISR @@ -261,7 +267,11 @@ _tx_thread_skip_nested_fpu_save: /* Call the ISR execution exit function if enabled. */ #ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY + addi sp, sp, -16 // Reserve space to save the return address + sw ra, 0(sp) // Save the return address call _tx_execution_isr_enter // Call the ISR execution enter function + lw ra, 0(sp) // Recover the return address + addi sp, sp, 16 // Recover the reserved stack space #endif ret // Return to ISR @@ -270,7 +280,11 @@ _tx_thread_idle_system_save: #ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY + addi sp, sp, -16 // Reserve space to save the return address + sw ra, 0(sp) // Save the return address call _tx_execution_isr_enter // Call the ISR execution enter function + lw ra, 0(sp) // Recover the return address + addi sp, sp, 16 // Recover the reserved stack space #endif /* Interrupt occurred in the scheduling loop. */ diff --git a/ports/risc-v32/iar/src/tx_thread_context_save.s b/ports/risc-v32/iar/src/tx_thread_context_save.s index 00b971efb..76672cde2 100644 --- a/ports/risc-v32/iar/src/tx_thread_context_save.s +++ b/ports/risc-v32/iar/src/tx_thread_context_save.s @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +; Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -145,7 +146,11 @@ _tx_thread_context_save: #endif #ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY + addi sp, sp, -16 ; Reserve space to save the return address + sw ra, 0(sp) ; Save the return address call _tx_execution_isr_enter ; Call the ISR execution enter function + lw ra, 0(sp) ; Recover the return address + addi sp, sp, 16 ; Recover the reserved stack space #endif ret ; Return to calling ISR @@ -223,7 +228,11 @@ _tx_thread_not_nested_save: #ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY /* _tx_execution_isr_enter is called with thread stack pointer */ + addi sp, sp, -16 ; Reserve space to save the return address + sw ra, 0(sp) ; Save the return address call _tx_execution_isr_enter ; Call the ISR execution enter function + lw ra, 0(sp) ; Recover the return address + addi sp, sp, 16 ; Recover the reserved stack space #endif @@ -238,7 +247,11 @@ _tx_thread_idle_system_save: #ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY + addi sp, sp, -16 ; Reserve space to save the return address + sw ra, 0(sp) ; Save the return address call _tx_execution_isr_enter ; Call the ISR execution enter function + lw ra, 0(sp) ; Recover the return address + addi sp, sp, 16 ; Recover the reserved stack space #endif /* Interrupt occurred in the scheduling loop. */ diff --git a/ports/risc-v64/gnu/src/tx_thread_context_save.S b/ports/risc-v64/gnu/src/tx_thread_context_save.S index 7935bfee2..8cbfa32cd 100644 --- a/ports/risc-v64/gnu/src/tx_thread_context_save.S +++ b/ports/risc-v64/gnu/src/tx_thread_context_save.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -181,7 +182,11 @@ _tx_thread_context_save: #endif #ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY + addi sp, sp, -16 // Reserve space to save the return address + sd ra, 0(sp) // Save the return address call _tx_execution_isr_enter // Call the ISR execution enter function + ld ra, 0(sp) // Recover the return address + addi sp, sp, 16 // Recover the reserved stack space #endif ret // Return to calling ISR @@ -316,7 +321,11 @@ _tx_thread_not_nested_save: #ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY /* _tx_execution_isr_enter is called with thread stack pointer */ + addi sp, sp, -16 // Reserve space to save the return address + sd ra, 0(sp) // Save the return address call _tx_execution_isr_enter // Call the ISR execution enter function + ld ra, 0(sp) // Recover the return address + addi sp, sp, 16 // Recover the reserved stack space #endif la t0, _tx_thread_system_stack_ptr // Pickup system stack pointer address @@ -331,7 +340,11 @@ _tx_thread_idle_system_save: #ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY + addi sp, sp, -16 // Reserve space to save the return address + sd ra, 0(sp) // Save the return address call _tx_execution_isr_enter // Call the ISR execution enter function + ld ra, 0(sp) // Recover the return address + addi sp, sp, 16 // Recover the reserved stack space #endif /* Interrupt occurred in the scheduling loop. */ From b0ec8bfbb964a78e82c71b20bb6f79ef7597df32 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Tue, 8 Sep 2026 10:03:45 -0400 Subject: [PATCH 102/181] Fixed the invalid module data pointers in the absolute module load (#699) An absolutely located module has its code and its data placed at two independent fixed addresses by the module's linker script. The module preamble carries the code and data sizes but not the data address, so _txm_module_manager_absolute_load() could not determine where the module's data area was. It computed txm_module_instance_data_start from the code size and the preamble size, which yields a size rather than an address, and it set txm_module_instance_module_data_base_address one past the end of the byte pool allocation. Added _txm_module_manager_absolute_load_extended(), which accepts the module's data area address from the caller. Deprecated _txm_module_manager_absolute_load(), which now forwards to the extended service with an unknown data area location and rejects modules that request memory protection, since the memory protection hardware cannot be programmed to cover an unknown data area. Fixes #450 Assisted-by: Copilot (Opus 5) --- common_modules/inc/txm_module.h | 4 + .../src/txm_module_manager_absolute_load.c | 417 ++------------- ...xm_module_manager_absolute_load_extended.c | 486 ++++++++++++++++++ .../sample_threadx_module_manager.c | 12 +- .../sample_threadx_module_manager.c | 12 +- .../sample_threadx_module_manager.c | 12 +- .../sample_threadx_module_manager.c | 12 +- 7 files changed, 578 insertions(+), 377 deletions(-) create mode 100644 common_modules/module_manager/src/txm_module_manager_absolute_load_extended.c diff --git a/common_modules/inc/txm_module.h b/common_modules/inc/txm_module.h index 88f79d9ee..889f43ed0 100644 --- a/common_modules/inc/txm_module.h +++ b/common_modules/inc/txm_module.h @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -569,6 +571,7 @@ VOID _txm_module_usbx_duo_callback_request(TXM_MODULE_CALLBACK_MESSAGE *callbac #define txm_module_manager_initialize _txm_module_manager_initialize #define txm_module_manager_absolute_load _txm_module_manager_absolute_load +#define txm_module_manager_absolute_load_extended _txm_module_manager_absolute_load_extended #define txm_module_manager_in_place_load _txm_module_manager_in_place_load #define txm_module_manager_file_load _txm_module_manager_file_load #define txm_module_manager_memory_load _txm_module_manager_memory_load @@ -606,6 +609,7 @@ UINT _txm_module_manager_file_load(TXM_MODULE_INSTANCE *module_instance, CHAR * #endif UINT _txm_module_manager_initialize(VOID *module_memory_start, ULONG module_memory_size); UINT _txm_module_manager_absolute_load(TXM_MODULE_INSTANCE *module_instance, CHAR *name, VOID *module_location); +UINT _txm_module_manager_absolute_load_extended(TXM_MODULE_INSTANCE *module_instance, CHAR *name, VOID *module_location, VOID *module_data_location); UINT _txm_module_manager_in_place_load(TXM_MODULE_INSTANCE *module_instance, CHAR *name, VOID *module_location); UINT _txm_module_manager_internal_load(TXM_MODULE_INSTANCE *module_instance, CHAR *name, VOID *module_location, ULONG code_size, VOID *code_allocation_ptr, ULONG code_allocation_size); diff --git a/common_modules/module_manager/src/txm_module_manager_absolute_load.c b/common_modules/module_manager/src/txm_module_manager_absolute_load.c index dee6efd22..caa94719d 100644 --- a/common_modules/module_manager/src/txm_module_manager_absolute_load.c +++ b/common_modules/module_manager/src/txm_module_manager_absolute_load.c @@ -1,6 +1,6 @@ /*************************************************************************** * Copyright (c) 2024 Microsoft Corporation - * Copyright (c) 2026-present Eclipse ThreadX contributors + * 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 @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -23,29 +25,57 @@ #define TX_SOURCE_CODE #include "tx_api.h" -#include "tx_initialize.h" -#include "tx_mutex.h" -#include "tx_thread.h" -#include "tx_byte_pool.h" #include "txm_module.h" -#include "txm_module_manager_util.h" +#ifndef TXM_MODULE_MANAGER_ABSOLUTE_LOAD_CALL_NOT_USED + +/* DEPRECATION NOTICE + * txm_module_manager_absolute_load() is deprecated. Do not use it in new code. + * + * WHY: an absolutely located module has its code and its data placed at two + * independent fixed addresses by the module's linker script. This service + * receives only the code address, and the module preamble carries the code and + * data sizes but not the data address. The module manager therefore has no way + * to determine where the module's data area is, and cannot describe it in the + * module instance. The affected fields are left empty by this wrapper. + * + * WHAT TO DO: replace calls with txm_module_manager_absolute_load_extended(), + * passing the module's data area address as the fourth argument. That address + * is the RAM segment start defined in the module's linker script. + * + * RISK: with the data area unknown, the module manager cannot tell whether an + * object, a thread control block, or the trace buffer resides in the module's + * data area, and a memory protection unit cannot be programmed to cover it. + * Modules that request memory protection are therefore rejected with + * TXM_MODULE_INVALID_PROPERTIES. + * + * Define TXM_MODULE_MANAGER_ABSOLUTE_LOAD_CALL_NOT_USED to remove this service + * and this message from the build. + */ +#pragma message("txm_module_manager_absolute_load() is deprecated. " \ + "Use txm_module_manager_absolute_load_extended() and pass " \ + "the module's data area address.") /**************************************************************************/ /* */ /* FUNCTION RELEASE */ /* */ /* _txm_module_manager_absolute_load PORTABLE C */ -/* 6.1.3 */ +/* 6.5.2 */ /* AUTHOR */ /* */ /* Andres Mlinar, Microsoft Corporation */ /* */ /* DESCRIPTION */ /* */ -/* This function ensures the code-related and data-related parts of */ -/* the module preamble are valid and prepares the module for */ -/* execution. */ +/* DEPRECATED. Use _txm_module_manager_absolute_load_extended() */ +/* instead, passing the module's data area address. This wrapper */ +/* passes TX_NULL, which leaves the module instance's data area */ +/* description empty because the module manager cannot derive the */ +/* data area address of an absolutely located module. Modules that */ +/* request memory protection are rejected with */ +/* TXM_MODULE_INVALID_PROPERTIES, because the memory protection */ +/* hardware cannot be programmed to cover an unknown data area. */ /* */ /* INPUT */ /* */ @@ -59,9 +89,8 @@ /* */ /* CALLS */ /* */ -/* _tx_byte_allocate Allocate data area */ -/* _tx_mutex_get Get protection mutex */ -/* _tx_mutex_put Release protection mutex */ +/* _txm_module_manager_absolute_load_extended */ +/* Load the module */ /* */ /* CALLED BY */ /* */ @@ -71,363 +100,13 @@ UINT _txm_module_manager_absolute_load(TXM_MODULE_INSTANCE *module_instance, CHAR *module_name, VOID *module_location) { -TX_INTERRUPT_SAVE_AREA - -TXM_MODULE_PREAMBLE *module_preamble; -ULONG code_size; -ULONG code_alignment; -ULONG code_allocation_size_ignored; -UINT status; - -TXM_MODULE_INSTANCE *next_module, *previous_module; -ULONG start_stop_stack_size; -ULONG callback_stack_size; -ULONG code_size_ignored; -ULONG code_alignment_ignored; -ALIGN_TYPE data_start; -ULONG data_size; -ULONG data_alignment; -ULONG data_allocation_size; -ULONG module_properties; -CHAR *memory_ptr; - - - /* Check for interrupt call. */ - if (TX_THREAD_GET_SYSTEM_STATE() != 0) - { - - /* Now, make sure the call is from an interrupt and not initialization. */ - if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS) - { - - /* Invalid caller of this function, return appropriate error code. */ - return(TX_CALLER_ERROR); - } - } - - /* Determine if the module manager has not been initialized yet. */ - if (_txm_module_manager_ready != TX_TRUE) - { - - /* Module manager has not been initialized. */ - return(TX_NOT_AVAILABLE); - } - - /* Determine if the module is valid. */ - if (module_instance == TX_NULL) - { - - /* Invalid module pointer. */ - return(TX_PTR_ERROR); - } - - /* Get module manager protection mutex. */ - _tx_mutex_get(&_txm_module_manager_mutex, TX_WAIT_FOREVER); - - /* Determine if the module is already valid. */ - if (module_instance -> txm_module_instance_id == TXM_MODULE_ID) - { - - /* Release the protection mutex. */ - _tx_mutex_put(&_txm_module_manager_mutex); - - /* Module already loaded. */ - return(TXM_MODULE_ALREADY_LOADED); - } - - /* Pickup the module's information. */ - module_preamble = (TXM_MODULE_PREAMBLE *) module_location; - - /* Check to make sure there is a valid module to load. */ - if (module_preamble -> txm_module_preamble_id != TXM_MODULE_ID) - { - - /* Release the protection mutex. */ - _tx_mutex_put(&_txm_module_manager_mutex); - - /* Invalid module preamble. */ - return(TXM_MODULE_INVALID); - } - - /* Check the properties of this module. */ - module_properties = module_preamble -> txm_module_preamble_property_flags & TXM_MODULE_OPTIONS_MASK; - if (/* Ensure the requested properties are supported. */ - ((module_properties & _txm_module_manager_properties_supported) != module_properties) || - /* Ensure the required properties are there. */ - ((_txm_module_manager_properties_required & module_properties) != _txm_module_manager_properties_required) || - /* If memory protection is enabled, then so must user mode. */ - ((module_properties & TXM_MODULE_MEMORY_PROTECTION) && !(module_properties & TXM_MODULE_USER_MODE)) - ) - { - - /* Release the protection mutex. */ - _tx_mutex_put(&_txm_module_manager_mutex); - - /* Invalid properties. Return error. */ - return(TXM_MODULE_INVALID_PROPERTIES); - } - - /* Check for valid module entry offsets. */ - if ((module_preamble -> txm_module_preamble_shell_entry_function == 0) || - (module_preamble -> txm_module_preamble_start_function == 0)) - { - - /* Release the protection mutex. */ - _tx_mutex_put(&_txm_module_manager_mutex); - - /* Invalid module preamble. */ - return(TXM_MODULE_INVALID); - } - - /* Check for valid sizes. */ - if ((module_preamble -> txm_module_preamble_code_size == 0) || - /* (module_preamble -> txm_module_preamble_data_size == 0) || *** a zero data size is valid */ - (module_preamble -> txm_module_preamble_start_stop_stack_size == 0) || - (module_preamble -> txm_module_preamble_callback_stack_size == 0)) - { - - /* Release the protection mutex. */ - _tx_mutex_put(&_txm_module_manager_mutex); - - /* Invalid module preamble. */ - return(TXM_MODULE_INVALID); - } - - /* Get the amount of the bytes we need to allocate for the module's code - as well as the required alignment. Note that because this is an absolute - load, we only want the code alignment so we can check it. */ - status = _txm_module_manager_util_code_allocation_size_and_alignment_get(module_preamble, &code_alignment, &code_allocation_size_ignored); - if (status != TX_SUCCESS) - { - - /* Math overflow error occurred. */ - return(status); - } - - /* Since this is an absolute load, check the alignment of the module's instruction area (code). */ - TXM_MODULE_MANAGER_CHECK_CODE_ALIGNMENT(module_location, code_alignment) - - /* Initialize module control block to all zeros. */ - TX_MEMSET(module_instance, 0, sizeof(TXM_MODULE_INSTANCE)); - - /* Pickup the basic module sizes. */ - code_size = module_preamble -> txm_module_preamble_code_size; - data_size = module_preamble -> txm_module_preamble_data_size; - start_stop_stack_size = module_preamble -> txm_module_preamble_start_stop_stack_size; - callback_stack_size = module_preamble -> txm_module_preamble_callback_stack_size; - - TXM_MODULE_MANAGER_UTIL_MATH_ADD_ULONG(data_size, TXM_MODULE_DATA_ALIGNMENT, data_size); - data_size = ((data_size - 1)/TXM_MODULE_DATA_ALIGNMENT) * TXM_MODULE_DATA_ALIGNMENT; - - /* Adjust the size of the module elements to be aligned to the default alignment. We do this - so that when we partition the allocated memory, we can simply place these regions right beside - each other without having to align their pointers. Note this only works when they all have - the same alignment. */ - - TXM_MODULE_MANAGER_UTIL_MATH_ADD_ULONG(start_stop_stack_size, TXM_MODULE_DATA_ALIGNMENT, start_stop_stack_size); - start_stop_stack_size = ((start_stop_stack_size - 1)/TXM_MODULE_DATA_ALIGNMENT) * TXM_MODULE_DATA_ALIGNMENT; - - TXM_MODULE_MANAGER_UTIL_MATH_ADD_ULONG(callback_stack_size, TXM_MODULE_DATA_ALIGNMENT, callback_stack_size); - callback_stack_size = ((callback_stack_size - 1)/TXM_MODULE_DATA_ALIGNMENT) * TXM_MODULE_DATA_ALIGNMENT; - - /* Update the data size to account for the default thread stacks. */ - data_allocation_size = 0; - TXM_MODULE_MANAGER_UTIL_MATH_ADD_ULONG(data_allocation_size, start_stop_stack_size, data_allocation_size); - TXM_MODULE_MANAGER_UTIL_MATH_ADD_ULONG(data_allocation_size, callback_stack_size, data_allocation_size); - - /* Setup the default code and data alignments. */ - data_alignment = (ULONG) TXM_MODULE_DATA_ALIGNMENT; - - /* Get the port-specific alignment for the data size. Note we only want data - so we pass values of 1 for code (to avoid any possible div by 0 errors). */ - code_size_ignored = 1; - code_alignment_ignored = 1; - TXM_MODULE_MANAGER_ALIGNMENT_ADJUST(module_preamble, code_size_ignored, code_alignment_ignored, data_allocation_size, data_alignment) - - /* Calculate the module's total RAM memory requirement. This entire area is allocated from the module - manager's byte pool. The general layout is defined as follows: - - Lowest Address: Start of start/stop thread stack - ... [note: thread entry info is embedded near end of stack areas] - End of start/stop thread stack +UINT status; - Start of callback thread stack - ... [note: thread entry info is embedded near end of stack areas] - End of callback thread stack - Highest Address: */ + /* Call the extended service with an unknown data area location. */ + status = _txm_module_manager_absolute_load_extended(module_instance, module_name, module_location, TX_NULL); - /* Add an extra alignment increment so we can align the pointer after allocation. */ - TXM_MODULE_MANAGER_UTIL_MATH_ADD_ULONG(data_allocation_size, data_alignment, data_allocation_size); - - /* Allocate memory for the module. */ - status = _tx_byte_allocate(&_txm_module_manager_byte_pool, (VOID **) &memory_ptr, data_allocation_size, TX_NO_WAIT); - - /* Determine if the module memory allocation was successful. */ - if (status) - { - - /* Release the protection mutex. */ - _tx_mutex_put(&_txm_module_manager_mutex); - - /* No memory, return an error. */ - return(TX_NO_MEMORY); - } - - /* Clear the allocated memory. */ - TX_MEMSET(memory_ptr, ((UCHAR) 0), data_allocation_size); - - /* Disable interrupts. */ - TX_DISABLE - - /* Setup the module instance structure. */ - module_instance -> txm_module_instance_id = TXM_MODULE_ID; - - /* Save the module name. */ - module_instance -> txm_module_instance_name = module_name; - - /* Save the module properties. */ - module_instance -> txm_module_instance_property_flags = module_preamble -> txm_module_preamble_property_flags; - - /* Set the module data memory allocation. This is the address released - when the module is unloaded. */ - module_instance -> txm_module_instance_data_allocation_ptr = (VOID *) memory_ptr; - - /* Save the data allocation size. */ - module_instance -> txm_module_instance_data_allocation_size = data_allocation_size; - - /* Calculate the actual start of the data area. This needs to be adjusted based on the alignment. */ - data_start = (ALIGN_TYPE) memory_ptr; - data_start = (data_start + (((ALIGN_TYPE)data_alignment) - 1)) & ~(((ALIGN_TYPE)data_alignment) - 1); - memory_ptr = (CHAR *) data_start; - - /* Compute the beginning and end of the data area. */ -#ifdef ALIGN_TYPE_DEFINED - module_instance -> txm_module_instance_data_start = (VOID *) (((CHAR *) (ALIGN_TYPE) module_preamble->txm_module_preamble_code_size) + sizeof(TXM_MODULE_PREAMBLE)); - module_instance -> txm_module_instance_data_end = (VOID *) (((CHAR *) (ALIGN_TYPE) module_instance -> txm_module_instance_data_start) + module_preamble->txm_module_preamble_data_size); -#else - module_instance -> txm_module_instance_data_start = (VOID *) (((CHAR *) module_preamble->txm_module_preamble_code_size) + sizeof(TXM_MODULE_PREAMBLE)); - module_instance -> txm_module_instance_data_end = (VOID *) (((CHAR *) module_instance -> txm_module_instance_data_start) + module_preamble->txm_module_preamble_data_size); -#endif - - /* Save the size of the data area. */ - module_instance -> txm_module_instance_data_size = data_size; - - /* Set the module code memory allocation. This is the address released - when the module is unloaded. */ - module_instance -> txm_module_instance_code_allocation_ptr = (VOID *) NULL; - - /* Save the code allocation size. */ - module_instance -> txm_module_instance_code_allocation_size = 0; - - /* Setup the code pointers. Since the code was loaded in-place, this is effectively just the values supplied in the API call. */ - module_instance -> txm_module_instance_code_start = (VOID *) module_location; - module_instance -> txm_module_instance_code_end = (VOID *) (((CHAR *) module_location) + (code_size - 1)); - - /* Setup the code size. */ - module_instance -> txm_module_instance_code_size = code_size; - - /* Save the module's total memory usage. */ - module_instance -> txm_module_instance_total_ram_usage = 0 /* Code is executed in place */ + data_allocation_size /* just the size of stacks */; - - /* Set the module state to started. */ - module_instance -> txm_module_instance_state = TXM_MODULE_LOADED; - - /* Save the preamble pointer. */ - module_instance -> txm_module_instance_preamble_ptr = module_preamble; - - /* Save the module application ID in the module instance. */ - module_instance -> txm_module_instance_application_module_id = module_preamble -> txm_module_preamble_application_module_id; - - /* Setup the module's start/stop thread stack area. */ - module_instance -> txm_module_instance_start_stop_stack_start_address = (VOID *) (memory_ptr); - module_instance -> txm_module_instance_start_stop_stack_size = start_stop_stack_size; - module_instance -> txm_module_instance_start_stop_stack_end_address = (VOID *) (memory_ptr + (start_stop_stack_size - 1)); - - /* Move the memory pointer forward. */ - memory_ptr = memory_ptr + start_stop_stack_size; - - /* Save the start/stop thread priority. */ - module_instance -> txm_module_instance_start_stop_priority = module_preamble -> txm_module_preamble_start_stop_priority; - - /* Setup the module's callback thread stack area. */ - module_instance -> txm_module_instance_callback_stack_start_address = (VOID *) (memory_ptr); - module_instance -> txm_module_instance_callback_stack_size = callback_stack_size; - module_instance -> txm_module_instance_callback_stack_end_address = (VOID *) (memory_ptr + (callback_stack_size - 1)); - - /* Move the memory pointer forward. */ - memory_ptr = memory_ptr + callback_stack_size; - - /* Save the callback thread priority. */ - module_instance -> txm_module_instance_callback_priority = module_preamble -> txm_module_preamble_callback_priority; - - /* Setup the start of the module data section. */ - module_instance -> txm_module_instance_module_data_base_address = (VOID *) (memory_ptr); - - /* Build actual addresses based on load... Setup all the function pointers. Any adjustments needed to shell entry, start function, and callback function are defined in the - module preamble. */ -#ifdef ALIGN_TYPE_DEFINED - module_instance -> txm_module_instance_shell_entry_function = (VOID (*)(TX_THREAD *, TXM_MODULE_INSTANCE *)) ((VOID *) (ALIGN_TYPE) module_preamble -> txm_module_preamble_shell_entry_function); - module_instance -> txm_module_instance_start_thread_entry = (VOID (*)(ULONG)) ((VOID *) (ALIGN_TYPE) module_preamble -> txm_module_preamble_start_function); - module_instance -> txm_module_instance_callback_request_thread_entry = (VOID (*)(ULONG)) ((VOID *) (ALIGN_TYPE) module_preamble -> txm_module_preamble_callback_function); -#else - module_instance -> txm_module_instance_shell_entry_function = (VOID (*)(TX_THREAD *, TXM_MODULE_INSTANCE *)) ((VOID *) module_preamble -> txm_module_preamble_shell_entry_function); - module_instance -> txm_module_instance_start_thread_entry = (VOID (*)(ULONG)) ((VOID *) module_preamble -> txm_module_preamble_start_function); - module_instance -> txm_module_instance_callback_request_thread_entry = (VOID (*)(ULONG)) ((VOID *) module_preamble -> txm_module_preamble_callback_function); -#endif - - /* Determine if there is a stop function for this module. */ - if (module_preamble -> txm_module_preamble_stop_function) - { - - /* Yes, there is a stop function, build the address. */ -#ifdef ALIGN_TYPE_DEFINED - module_instance -> txm_module_instance_stop_thread_entry = (VOID (*)(ULONG)) ((VOID *) (ALIGN_TYPE) module_preamble -> txm_module_preamble_stop_function); -#else - module_instance -> txm_module_instance_stop_thread_entry = (VOID (*)(ULONG)) ((VOID *) module_preamble -> txm_module_preamble_stop_function); -#endif - } - else - { - - /* No, there is no stop function. Just set the pointer to NULL. */ - module_instance -> txm_module_instance_stop_thread_entry = TX_NULL; - } - - /* Load the module control block with port-specific information. */ - TXM_MODULE_MANAGER_MODULE_SETUP(module_instance); - - /* Now add the module to the linked list of created modules. */ - if (_txm_module_manger_loaded_count++ == 0) - { - - /* The loaded module list is empty. Add module to empty list. */ - _txm_module_manager_loaded_list_ptr = module_instance; - module_instance -> txm_module_instance_loaded_next = module_instance; - module_instance -> txm_module_instance_loaded_previous = module_instance; - } - else - { - - /* This list is not NULL, add to the end of the list. */ - next_module = _txm_module_manager_loaded_list_ptr; - previous_module = next_module -> txm_module_instance_loaded_previous; - - /* Place the new module in the list. */ - next_module -> txm_module_instance_loaded_previous = module_instance; - previous_module -> txm_module_instance_loaded_next = module_instance; - - /* Setup this module's created links. */ - module_instance -> txm_module_instance_loaded_previous = previous_module; - module_instance -> txm_module_instance_loaded_next = next_module; - } - - /* Restore interrupts. */ - TX_RESTORE - - /* Release the protection mutex. */ - _tx_mutex_put(&_txm_module_manager_mutex); - - /* Return success. */ - return(TX_SUCCESS); + /* Return completion status. */ + return(status); } +#endif diff --git a/common_modules/module_manager/src/txm_module_manager_absolute_load_extended.c b/common_modules/module_manager/src/txm_module_manager_absolute_load_extended.c new file mode 100644 index 000000000..77b356789 --- /dev/null +++ b/common_modules/module_manager/src/txm_module_manager_absolute_load_extended.c @@ -0,0 +1,486 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + +// Some portions generated by Copilot (Opus 5). + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Module Manager */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + +#include "tx_api.h" +#include "tx_initialize.h" +#include "tx_mutex.h" +#include "tx_thread.h" +#include "tx_byte_pool.h" +#include "txm_module.h" +#include "txm_module_manager_util.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txm_module_manager_absolute_load_extended PORTABLE C */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Andres Mlinar, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function ensures the code-related and data-related parts of */ +/* the module preamble are valid and prepares the module for */ +/* execution. */ +/* */ +/* An absolutely located module has its code and its data placed at */ +/* fixed addresses by the module's linker script. The module preamble */ +/* carries only the code and data sizes, so the module manager cannot */ +/* derive the module's data location on its own. This service accepts */ +/* that address from the caller, which allows the module instance's */ +/* data area to be described correctly. */ +/* */ +/* INPUT */ +/* */ +/* module_instance Module instance pointer */ +/* module_name Module name pointer */ +/* module_location Module code location */ +/* module_data_location Module data location, or TX_NULL */ +/* when the data location is not */ +/* known to the caller. Memory */ +/* protection cannot be used when */ +/* it is TX_NULL. */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_byte_allocate Allocate data area */ +/* _tx_mutex_get Get protection mutex */ +/* _tx_mutex_put Release protection mutex */ +/* */ +/* CALLED BY */ +/* */ +/* Application code */ +/* _txm_module_manager_absolute_load Deprecated wrapper */ +/* */ +/**************************************************************************/ +UINT _txm_module_manager_absolute_load_extended(TXM_MODULE_INSTANCE *module_instance, CHAR *module_name, VOID *module_location, VOID *module_data_location) +{ + +TX_INTERRUPT_SAVE_AREA + +TXM_MODULE_PREAMBLE *module_preamble; +ULONG code_size; +ULONG code_alignment; +ULONG code_allocation_size_ignored; +UINT status; + +TXM_MODULE_INSTANCE *next_module, *previous_module; +ULONG start_stop_stack_size; +ULONG callback_stack_size; +ULONG code_size_ignored; +ULONG code_alignment_ignored; +ALIGN_TYPE data_start; +ULONG data_size; +ULONG data_alignment; +ULONG data_allocation_size; +ULONG module_properties; +CHAR *memory_ptr; + + + /* Check for interrupt call. */ + if (TX_THREAD_GET_SYSTEM_STATE() != 0) + { + + /* Now, make sure the call is from an interrupt and not initialization. */ + if (TX_THREAD_GET_SYSTEM_STATE() < TX_INITIALIZE_IN_PROGRESS) + { + + /* Invalid caller of this function, return appropriate error code. */ + return(TX_CALLER_ERROR); + } + } + + /* Determine if the module manager has not been initialized yet. */ + if (_txm_module_manager_ready != TX_TRUE) + { + + /* Module manager has not been initialized. */ + return(TX_NOT_AVAILABLE); + } + + /* Determine if the module is valid. */ + if (module_instance == TX_NULL) + { + + /* Invalid module pointer. */ + return(TX_PTR_ERROR); + } + + /* Get module manager protection mutex. */ + _tx_mutex_get(&_txm_module_manager_mutex, TX_WAIT_FOREVER); + + /* Determine if the module is already valid. */ + if (module_instance -> txm_module_instance_id == TXM_MODULE_ID) + { + + /* Release the protection mutex. */ + _tx_mutex_put(&_txm_module_manager_mutex); + + /* Module already loaded. */ + return(TXM_MODULE_ALREADY_LOADED); + } + + /* Pickup the module's information. */ + module_preamble = (TXM_MODULE_PREAMBLE *) module_location; + + /* Check to make sure there is a valid module to load. */ + if (module_preamble -> txm_module_preamble_id != TXM_MODULE_ID) + { + + /* Release the protection mutex. */ + _tx_mutex_put(&_txm_module_manager_mutex); + + /* Invalid module preamble. */ + return(TXM_MODULE_INVALID); + } + + /* Check the properties of this module. */ + module_properties = module_preamble -> txm_module_preamble_property_flags & TXM_MODULE_OPTIONS_MASK; + if (/* Ensure the requested properties are supported. */ + ((module_properties & _txm_module_manager_properties_supported) != module_properties) || + /* Ensure the required properties are there. */ + ((_txm_module_manager_properties_required & module_properties) != _txm_module_manager_properties_required) || + /* If memory protection is enabled, then so must user mode. */ + ((module_properties & TXM_MODULE_MEMORY_PROTECTION) && !(module_properties & TXM_MODULE_USER_MODE)) || + /* Memory protection requires a known data area, since the memory protection hardware must + be programmed to cover it. */ + ((module_properties & TXM_MODULE_MEMORY_PROTECTION) && (module_data_location == TX_NULL)) + ) + { + + /* Release the protection mutex. */ + _tx_mutex_put(&_txm_module_manager_mutex); + + /* Invalid properties. Return error. */ + return(TXM_MODULE_INVALID_PROPERTIES); + } + + /* Check for valid module entry offsets. */ + if ((module_preamble -> txm_module_preamble_shell_entry_function == 0) || + (module_preamble -> txm_module_preamble_start_function == 0)) + { + + /* Release the protection mutex. */ + _tx_mutex_put(&_txm_module_manager_mutex); + + /* Invalid module preamble. */ + return(TXM_MODULE_INVALID); + } + + /* Check for valid sizes. */ + if ((module_preamble -> txm_module_preamble_code_size == 0) || + /* (module_preamble -> txm_module_preamble_data_size == 0) || *** a zero data size is valid */ + (module_preamble -> txm_module_preamble_start_stop_stack_size == 0) || + (module_preamble -> txm_module_preamble_callback_stack_size == 0)) + { + + /* Release the protection mutex. */ + _tx_mutex_put(&_txm_module_manager_mutex); + + /* Invalid module preamble. */ + return(TXM_MODULE_INVALID); + } + + /* Get the amount of the bytes we need to allocate for the module's code + as well as the required alignment. Note that because this is an absolute + load, we only want the code alignment so we can check it. */ + status = _txm_module_manager_util_code_allocation_size_and_alignment_get(module_preamble, &code_alignment, &code_allocation_size_ignored); + if (status != TX_SUCCESS) + { + + /* Math overflow error occurred. */ + return(status); + } + + /* Since this is an absolute load, check the alignment of the module's instruction area (code). */ + TXM_MODULE_MANAGER_CHECK_CODE_ALIGNMENT(module_location, code_alignment) + + /* Initialize module control block to all zeros. */ + TX_MEMSET(module_instance, 0, sizeof(TXM_MODULE_INSTANCE)); + + /* Pickup the basic module sizes. */ + code_size = module_preamble -> txm_module_preamble_code_size; + data_size = module_preamble -> txm_module_preamble_data_size; + start_stop_stack_size = module_preamble -> txm_module_preamble_start_stop_stack_size; + callback_stack_size = module_preamble -> txm_module_preamble_callback_stack_size; + + TXM_MODULE_MANAGER_UTIL_MATH_ADD_ULONG(data_size, TXM_MODULE_DATA_ALIGNMENT, data_size); + data_size = ((data_size - 1)/TXM_MODULE_DATA_ALIGNMENT) * TXM_MODULE_DATA_ALIGNMENT; + + /* Adjust the size of the module elements to be aligned to the default alignment. We do this + so that when we partition the allocated memory, we can simply place these regions right beside + each other without having to align their pointers. Note this only works when they all have + the same alignment. */ + + TXM_MODULE_MANAGER_UTIL_MATH_ADD_ULONG(start_stop_stack_size, TXM_MODULE_DATA_ALIGNMENT, start_stop_stack_size); + start_stop_stack_size = ((start_stop_stack_size - 1)/TXM_MODULE_DATA_ALIGNMENT) * TXM_MODULE_DATA_ALIGNMENT; + + TXM_MODULE_MANAGER_UTIL_MATH_ADD_ULONG(callback_stack_size, TXM_MODULE_DATA_ALIGNMENT, callback_stack_size); + callback_stack_size = ((callback_stack_size - 1)/TXM_MODULE_DATA_ALIGNMENT) * TXM_MODULE_DATA_ALIGNMENT; + + /* Update the data size to account for the default thread stacks. */ + data_allocation_size = 0; + TXM_MODULE_MANAGER_UTIL_MATH_ADD_ULONG(data_allocation_size, start_stop_stack_size, data_allocation_size); + TXM_MODULE_MANAGER_UTIL_MATH_ADD_ULONG(data_allocation_size, callback_stack_size, data_allocation_size); + + /* Setup the default code and data alignments. */ + data_alignment = (ULONG) TXM_MODULE_DATA_ALIGNMENT; + + /* Get the port-specific alignment for the data size. Note we only want data + so we pass values of 1 for code (to avoid any possible div by 0 errors). */ + code_size_ignored = 1; + code_alignment_ignored = 1; + TXM_MODULE_MANAGER_ALIGNMENT_ADJUST(module_preamble, code_size_ignored, code_alignment_ignored, data_allocation_size, data_alignment) + + /* Since this is an absolute load, check the alignment of the module's data area when the caller + supplied its location. */ + if (module_data_location != TX_NULL) + { + if ((((ALIGN_TYPE) module_data_location) & (((ALIGN_TYPE) data_alignment) - ((ALIGN_TYPE) 1))) != ((ALIGN_TYPE) 0)) + { + + /* Release the protection mutex. */ + _tx_mutex_put(&_txm_module_manager_mutex); + + /* Invalid alignment, return error. */ + return(TXM_MODULE_ALIGNMENT_ERROR); + } + } + + /* Calculate the module's total RAM memory requirement. This entire area is allocated from the module + manager's byte pool. The general layout is defined as follows: + + Lowest Address: Start of start/stop thread stack + ... [note: thread entry info is embedded near end of stack areas] + End of start/stop thread stack + + Start of callback thread stack + ... [note: thread entry info is embedded near end of stack areas] + End of callback thread stack + + Highest Address: */ + + /* Add an extra alignment increment so we can align the pointer after allocation. */ + TXM_MODULE_MANAGER_UTIL_MATH_ADD_ULONG(data_allocation_size, data_alignment, data_allocation_size); + + /* Allocate memory for the module. */ + status = _tx_byte_allocate(&_txm_module_manager_byte_pool, (VOID **) &memory_ptr, data_allocation_size, TX_NO_WAIT); + + /* Determine if the module memory allocation was successful. */ + if (status) + { + + /* Release the protection mutex. */ + _tx_mutex_put(&_txm_module_manager_mutex); + + /* No memory, return an error. */ + return(TX_NO_MEMORY); + } + + /* Clear the allocated memory. */ + TX_MEMSET(memory_ptr, ((UCHAR) 0), data_allocation_size); + + /* Disable interrupts. */ + TX_DISABLE + + /* Setup the module instance structure. */ + module_instance -> txm_module_instance_id = TXM_MODULE_ID; + + /* Save the module name. */ + module_instance -> txm_module_instance_name = module_name; + + /* Save the module properties. */ + module_instance -> txm_module_instance_property_flags = module_preamble -> txm_module_preamble_property_flags; + + /* Set the module data memory allocation. This is the address released + when the module is unloaded. */ + module_instance -> txm_module_instance_data_allocation_ptr = (VOID *) memory_ptr; + + /* Save the data allocation size. */ + module_instance -> txm_module_instance_data_allocation_size = data_allocation_size; + + /* Calculate the actual start of the data area. This needs to be adjusted based on the alignment. */ + data_start = (ALIGN_TYPE) memory_ptr; + data_start = (data_start + (((ALIGN_TYPE)data_alignment) - 1)) & ~(((ALIGN_TYPE)data_alignment) - 1); + memory_ptr = (CHAR *) data_start; + + /* Compute the beginning and end of the data area. An absolutely located module has its data + placed at a fixed address by its linker script, and that address is not carried in the + module preamble. It must therefore be supplied by the caller. */ + if (module_data_location != TX_NULL) + { + + module_instance -> txm_module_instance_data_start = module_data_location; + + /* A zero data size is valid, so guard against wrapping when computing the end address. */ + if (data_size != 0) + { + module_instance -> txm_module_instance_data_end = (VOID *) (((CHAR *) module_data_location) + (data_size - 1)); + } + else + { + module_instance -> txm_module_instance_data_end = module_data_location; + } + + /* Save the size of the data area. */ + module_instance -> txm_module_instance_data_size = data_size; + } + else + { + + /* The caller does not know where the module's data area is, so the module instance cannot + describe it. Report an empty data area rather than an invalid one. */ + module_instance -> txm_module_instance_data_start = TX_NULL; + module_instance -> txm_module_instance_data_end = TX_NULL; + + /* Save the size of the data area. */ + module_instance -> txm_module_instance_data_size = 0; + } + + /* Set the module code memory allocation. This is the address released + when the module is unloaded. */ + module_instance -> txm_module_instance_code_allocation_ptr = (VOID *) NULL; + + /* Save the code allocation size. */ + module_instance -> txm_module_instance_code_allocation_size = 0; + + /* Setup the code pointers. Since the code was loaded in-place, this is effectively just the values supplied in the API call. */ + module_instance -> txm_module_instance_code_start = (VOID *) module_location; + module_instance -> txm_module_instance_code_end = (VOID *) (((CHAR *) module_location) + (code_size - 1)); + + /* Setup the code size. */ + module_instance -> txm_module_instance_code_size = code_size; + + /* Save the module's total memory usage. */ + module_instance -> txm_module_instance_total_ram_usage = 0 /* Code is executed in place */ + data_allocation_size /* just the size of stacks */; + + /* Set the module state to started. */ + module_instance -> txm_module_instance_state = TXM_MODULE_LOADED; + + /* Save the preamble pointer. */ + module_instance -> txm_module_instance_preamble_ptr = module_preamble; + + /* Save the module application ID in the module instance. */ + module_instance -> txm_module_instance_application_module_id = module_preamble -> txm_module_preamble_application_module_id; + + /* Setup the module's start/stop thread stack area. */ + module_instance -> txm_module_instance_start_stop_stack_start_address = (VOID *) (memory_ptr); + module_instance -> txm_module_instance_start_stop_stack_size = start_stop_stack_size; + module_instance -> txm_module_instance_start_stop_stack_end_address = (VOID *) (memory_ptr + (start_stop_stack_size - 1)); + + /* Move the memory pointer forward. */ + memory_ptr = memory_ptr + start_stop_stack_size; + + /* Save the start/stop thread priority. */ + module_instance -> txm_module_instance_start_stop_priority = module_preamble -> txm_module_preamble_start_stop_priority; + + /* Setup the module's callback thread stack area. */ + module_instance -> txm_module_instance_callback_stack_start_address = (VOID *) (memory_ptr); + module_instance -> txm_module_instance_callback_stack_size = callback_stack_size; + module_instance -> txm_module_instance_callback_stack_end_address = (VOID *) (memory_ptr + (callback_stack_size - 1)); + + /* Save the callback thread priority. */ + module_instance -> txm_module_instance_callback_priority = module_preamble -> txm_module_preamble_callback_priority; + + /* Setup the start of the module data section. For an absolute load, the byte pool allocation + holds only the two default thread stacks. The module's data section is the absolutely + located area supplied by the caller. */ + module_instance -> txm_module_instance_module_data_base_address = module_data_location; + + /* Build actual addresses based on load... Setup all the function pointers. Any adjustments needed to shell entry, start function, and callback function are defined in the + module preamble. */ +#ifdef ALIGN_TYPE_DEFINED + module_instance -> txm_module_instance_shell_entry_function = (VOID (*)(TX_THREAD *, TXM_MODULE_INSTANCE *)) ((VOID *) (ALIGN_TYPE) module_preamble -> txm_module_preamble_shell_entry_function); + module_instance -> txm_module_instance_start_thread_entry = (VOID (*)(ULONG)) ((VOID *) (ALIGN_TYPE) module_preamble -> txm_module_preamble_start_function); + module_instance -> txm_module_instance_callback_request_thread_entry = (VOID (*)(ULONG)) ((VOID *) (ALIGN_TYPE) module_preamble -> txm_module_preamble_callback_function); +#else + module_instance -> txm_module_instance_shell_entry_function = (VOID (*)(TX_THREAD *, TXM_MODULE_INSTANCE *)) ((VOID *) module_preamble -> txm_module_preamble_shell_entry_function); + module_instance -> txm_module_instance_start_thread_entry = (VOID (*)(ULONG)) ((VOID *) module_preamble -> txm_module_preamble_start_function); + module_instance -> txm_module_instance_callback_request_thread_entry = (VOID (*)(ULONG)) ((VOID *) module_preamble -> txm_module_preamble_callback_function); +#endif + + /* Determine if there is a stop function for this module. */ + if (module_preamble -> txm_module_preamble_stop_function) + { + + /* Yes, there is a stop function, build the address. */ +#ifdef ALIGN_TYPE_DEFINED + module_instance -> txm_module_instance_stop_thread_entry = (VOID (*)(ULONG)) ((VOID *) (ALIGN_TYPE) module_preamble -> txm_module_preamble_stop_function); +#else + module_instance -> txm_module_instance_stop_thread_entry = (VOID (*)(ULONG)) ((VOID *) module_preamble -> txm_module_preamble_stop_function); +#endif + } + else + { + + /* No, there is no stop function. Just set the pointer to NULL. */ + module_instance -> txm_module_instance_stop_thread_entry = TX_NULL; + } + + /* Load the module control block with port-specific information. */ + TXM_MODULE_MANAGER_MODULE_SETUP(module_instance); + + /* Now add the module to the linked list of created modules. */ + if (_txm_module_manger_loaded_count++ == 0) + { + + /* The loaded module list is empty. Add module to empty list. */ + _txm_module_manager_loaded_list_ptr = module_instance; + module_instance -> txm_module_instance_loaded_next = module_instance; + module_instance -> txm_module_instance_loaded_previous = module_instance; + } + else + { + + /* This list is not NULL, add to the end of the list. */ + next_module = _txm_module_manager_loaded_list_ptr; + previous_module = next_module -> txm_module_instance_loaded_previous; + + /* Place the new module in the list. */ + next_module -> txm_module_instance_loaded_previous = module_instance; + previous_module -> txm_module_instance_loaded_next = module_instance; + + /* Setup this module's created links. */ + module_instance -> txm_module_instance_loaded_previous = previous_module; + module_instance -> txm_module_instance_loaded_next = next_module; + } + + /* Restore interrupts. */ + TX_RESTORE + + /* Release the protection mutex. */ + _tx_mutex_put(&_txm_module_manager_mutex); + + /* Return success. */ + return(TX_SUCCESS); +} diff --git a/ports_module/cortex_a35/ac6/example_build/sample_threadx_module_manager/sample_threadx_module_manager.c b/ports_module/cortex_a35/ac6/example_build/sample_threadx_module_manager/sample_threadx_module_manager.c index 475aabb31..c53fec02a 100644 --- a/ports_module/cortex_a35/ac6/example_build/sample_threadx_module_manager/sample_threadx_module_manager.c +++ b/ports_module/cortex_a35/ac6/example_build/sample_threadx_module_manager/sample_threadx_module_manager.c @@ -9,6 +9,8 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ +// Some portions generated by Copilot (Opus 5). + /* Small demonstration of the ThreadX module manager. */ #include "tx_api.h" @@ -33,6 +35,12 @@ TXM_MODULE_INSTANCE my_module; #define MODULE_CODE (0x80180000) +/* The module data is located here. This must match the RAM segment start address + defined in the module's linker script. */ + +#define MODULE_DATA_LOCATION (0x801A0000) + + /* Define the object pool area. */ UCHAR object_memory[1024 * 16]; @@ -125,7 +133,7 @@ void module_manager_entry(ULONG thread_input) txm_module_manager_object_pool_create(object_memory, sizeof(object_memory)); /* Load the module with absolute address linkage, in this example it is placed there by the multiple image download. */ - txm_module_manager_absolute_load(&my_module, "my module", (void *) MODULE_CODE); + txm_module_manager_absolute_load_extended(&my_module, "my module", (void *) MODULE_CODE, (void *) MODULE_DATA_LOCATION); /* Start the module. */ txm_module_manager_start(&my_module); @@ -146,7 +154,7 @@ void module_manager_entry(ULONG thread_input) txm_module_manager_unload(&my_module); /* Load the module again. */ - txm_module_manager_absolute_load(&my_module, "my module", (void *) MODULE_CODE); + txm_module_manager_absolute_load_extended(&my_module, "my module", (void *) MODULE_CODE, (void *) MODULE_DATA_LOCATION); /* Start the module again. */ txm_module_manager_start(&my_module); diff --git a/ports_module/cortex_a35/gnu/example_build/sample_threadx_module_manager/sample_threadx_module_manager.c b/ports_module/cortex_a35/gnu/example_build/sample_threadx_module_manager/sample_threadx_module_manager.c index 475aabb31..c53fec02a 100644 --- a/ports_module/cortex_a35/gnu/example_build/sample_threadx_module_manager/sample_threadx_module_manager.c +++ b/ports_module/cortex_a35/gnu/example_build/sample_threadx_module_manager/sample_threadx_module_manager.c @@ -9,6 +9,8 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ +// Some portions generated by Copilot (Opus 5). + /* Small demonstration of the ThreadX module manager. */ #include "tx_api.h" @@ -33,6 +35,12 @@ TXM_MODULE_INSTANCE my_module; #define MODULE_CODE (0x80180000) +/* The module data is located here. This must match the RAM segment start address + defined in the module's linker script. */ + +#define MODULE_DATA_LOCATION (0x801A0000) + + /* Define the object pool area. */ UCHAR object_memory[1024 * 16]; @@ -125,7 +133,7 @@ void module_manager_entry(ULONG thread_input) txm_module_manager_object_pool_create(object_memory, sizeof(object_memory)); /* Load the module with absolute address linkage, in this example it is placed there by the multiple image download. */ - txm_module_manager_absolute_load(&my_module, "my module", (void *) MODULE_CODE); + txm_module_manager_absolute_load_extended(&my_module, "my module", (void *) MODULE_CODE, (void *) MODULE_DATA_LOCATION); /* Start the module. */ txm_module_manager_start(&my_module); @@ -146,7 +154,7 @@ void module_manager_entry(ULONG thread_input) txm_module_manager_unload(&my_module); /* Load the module again. */ - txm_module_manager_absolute_load(&my_module, "my module", (void *) MODULE_CODE); + txm_module_manager_absolute_load_extended(&my_module, "my module", (void *) MODULE_CODE, (void *) MODULE_DATA_LOCATION); /* Start the module again. */ txm_module_manager_start(&my_module); diff --git a/ports_module/cortex_a35_smp/ac6/example_build/sample_threadx_module_manager/sample_threadx_module_manager.c b/ports_module/cortex_a35_smp/ac6/example_build/sample_threadx_module_manager/sample_threadx_module_manager.c index 475aabb31..c53fec02a 100644 --- a/ports_module/cortex_a35_smp/ac6/example_build/sample_threadx_module_manager/sample_threadx_module_manager.c +++ b/ports_module/cortex_a35_smp/ac6/example_build/sample_threadx_module_manager/sample_threadx_module_manager.c @@ -9,6 +9,8 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ +// Some portions generated by Copilot (Opus 5). + /* Small demonstration of the ThreadX module manager. */ #include "tx_api.h" @@ -33,6 +35,12 @@ TXM_MODULE_INSTANCE my_module; #define MODULE_CODE (0x80180000) +/* The module data is located here. This must match the RAM segment start address + defined in the module's linker script. */ + +#define MODULE_DATA_LOCATION (0x801A0000) + + /* Define the object pool area. */ UCHAR object_memory[1024 * 16]; @@ -125,7 +133,7 @@ void module_manager_entry(ULONG thread_input) txm_module_manager_object_pool_create(object_memory, sizeof(object_memory)); /* Load the module with absolute address linkage, in this example it is placed there by the multiple image download. */ - txm_module_manager_absolute_load(&my_module, "my module", (void *) MODULE_CODE); + txm_module_manager_absolute_load_extended(&my_module, "my module", (void *) MODULE_CODE, (void *) MODULE_DATA_LOCATION); /* Start the module. */ txm_module_manager_start(&my_module); @@ -146,7 +154,7 @@ void module_manager_entry(ULONG thread_input) txm_module_manager_unload(&my_module); /* Load the module again. */ - txm_module_manager_absolute_load(&my_module, "my module", (void *) MODULE_CODE); + txm_module_manager_absolute_load_extended(&my_module, "my module", (void *) MODULE_CODE, (void *) MODULE_DATA_LOCATION); /* Start the module again. */ txm_module_manager_start(&my_module); diff --git a/ports_module/cortex_a35_smp/gnu/example_build/sample_threadx_module_manager/sample_threadx_module_manager.c b/ports_module/cortex_a35_smp/gnu/example_build/sample_threadx_module_manager/sample_threadx_module_manager.c index 475aabb31..c53fec02a 100644 --- a/ports_module/cortex_a35_smp/gnu/example_build/sample_threadx_module_manager/sample_threadx_module_manager.c +++ b/ports_module/cortex_a35_smp/gnu/example_build/sample_threadx_module_manager/sample_threadx_module_manager.c @@ -9,6 +9,8 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ +// Some portions generated by Copilot (Opus 5). + /* Small demonstration of the ThreadX module manager. */ #include "tx_api.h" @@ -33,6 +35,12 @@ TXM_MODULE_INSTANCE my_module; #define MODULE_CODE (0x80180000) +/* The module data is located here. This must match the RAM segment start address + defined in the module's linker script. */ + +#define MODULE_DATA_LOCATION (0x801A0000) + + /* Define the object pool area. */ UCHAR object_memory[1024 * 16]; @@ -125,7 +133,7 @@ void module_manager_entry(ULONG thread_input) txm_module_manager_object_pool_create(object_memory, sizeof(object_memory)); /* Load the module with absolute address linkage, in this example it is placed there by the multiple image download. */ - txm_module_manager_absolute_load(&my_module, "my module", (void *) MODULE_CODE); + txm_module_manager_absolute_load_extended(&my_module, "my module", (void *) MODULE_CODE, (void *) MODULE_DATA_LOCATION); /* Start the module. */ txm_module_manager_start(&my_module); @@ -146,7 +154,7 @@ void module_manager_entry(ULONG thread_input) txm_module_manager_unload(&my_module); /* Load the module again. */ - txm_module_manager_absolute_load(&my_module, "my module", (void *) MODULE_CODE); + txm_module_manager_absolute_load_extended(&my_module, "my module", (void *) MODULE_CODE, (void *) MODULE_DATA_LOCATION); /* Start the module again. */ txm_module_manager_start(&my_module); From 29afcc394667660edd9e53cc17e6232b9e60aa96 Mon Sep 17 00:00:00 2001 From: tardigrade Date: Tue, 8 Sep 2026 20:47:57 +0530 Subject: [PATCH 103/181] Fixed a kernel stack leak when deleting user-mode module threads (#692) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * modules: free kernel stack on thread deletion Signed-off-by: Prashit Vora * Preserved the thread object release when the kernel stack cannot be freed Releasing the kernel stack ahead of the thread object made a failure of the kernel stack deallocation abort the thread object release. The thread had already been deleted at that point, so the thread object would have stayed allocated for the lifetime of the module. The thread object is now always released once the delete succeeds, and the kernel stack failure is reported only when it does not mask a thread object failure. --------- Signed-off-by: Prashit Vora Co-authored-by: Frédéric Desbiens Assisted-by: Copilot (Opus 5) --- .../inc/txm_module_manager_dispatch.h | 32 +++++++++++++++---- 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/common_modules/module_manager/inc/txm_module_manager_dispatch.h b/common_modules/module_manager/inc/txm_module_manager_dispatch.h index 03bd86ebf..465366068 100644 --- a/common_modules/module_manager/inc/txm_module_manager_dispatch.h +++ b/common_modules/module_manager/inc/txm_module_manager_dispatch.h @@ -8,6 +8,8 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (GPT-5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -2061,7 +2063,12 @@ ALIGN_TYPE return_value; static ALIGN_TYPE _txm_module_manager_tx_thread_delete_dispatch(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE param_0) { -ALIGN_TYPE return_value; +TX_THREAD *thread_ptr; +ALIGN_TYPE return_value; +ALIGN_TYPE stack_status; + + thread_ptr = (TX_THREAD *) param_0; + stack_status = (ALIGN_TYPE) TX_SUCCESS; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { @@ -2069,14 +2076,27 @@ ALIGN_TYPE return_value; return(TXM_MODULE_INVALID_MEMORY); } - return_value = (ALIGN_TYPE) _txe_thread_delete( - (TX_THREAD *) param_0 - ); + return_value = (ALIGN_TYPE) _txe_thread_delete(thread_ptr); - /* Deallocate object memory. */ + /* Deallocate the kernel stack for a user-mode thread. */ + if ((return_value == TX_SUCCESS) && + (module_instance -> txm_module_instance_property_flags & TXM_MODULE_USER_MODE)) + { + stack_status = _txm_module_manager_object_deallocate(thread_ptr -> tx_thread_module_kernel_stack_start); + } + + /* Deallocate thread object memory. This must be attempted even when the kernel + stack could not be released, otherwise a successful thread delete would leave + the thread object allocated forever. */ if (return_value == TX_SUCCESS) { - return_value = _txm_module_manager_object_deallocate((VOID *) param_0); + return_value = _txm_module_manager_object_deallocate((VOID *) thread_ptr); + + /* Report the kernel stack failure if the thread object was released. */ + if ((return_value == TX_SUCCESS) && (stack_status != TX_SUCCESS)) + { + return_value = stack_status; + } } return(return_value); } From 945f5f5caa7e2ba39a6ff5d90dda60b116c94a49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Tue, 8 Sep 2026 15:42:39 -0400 Subject: [PATCH 104/181] Moved the ARC ISR enter callout onto the system stack (#700) _tx_thread_context_save() calls _tx_execution_isr_enter when TX_ENABLE_EXECUTION_CHANGE_NOTIFY is defined. On the path where an interrupt preempted a running thread, that call was made before the switch to the system stack, so the 32-byte call frame and the whole stack footprint of the callout were taken from the interrupted thread's stack, on top of the 160-byte interrupt frame the port had already allocated there. The callout is supplied by the application, so its stack usage is not bounded by ThreadX, and it is charged to every thread that happens to be running when an interrupt arrives. The two other callout sites in the same routine, the nested save and the idle system save, already run on the system stack, as does the _tx_execution_isr_exit call in _tx_thread_context_restore. _tx_thread_schedule was reordered in 6.1.9 so that _tx_execution_thread_enter runs on the system stack rather than the thread stack; the same reorder was never applied to the context save. The switch to the system stack now happens before the callout in the ARCv2_EM, ARC_HS and SMP ARC_HS ports. _tx_thread_context_fast_save is unchanged because the fast interrupt path never switches stacks by design. Fixes #149 Assisted-by: Copilot (Opus 5) --- .../metaware/src/tx_thread_context_save.s | 36 ++++++++++--------- .../metaware/src/tx_thread_context_save.s | 19 ++++++---- .../metaware/src/tx_thread_context_save.s | 23 +++++++----- 3 files changed, 46 insertions(+), 32 deletions(-) diff --git a/ports/arc_em/metaware/src/tx_thread_context_save.s b/ports/arc_em/metaware/src/tx_thread_context_save.s index fb2a280c4..93b57d231 100644 --- a/ports/arc_em/metaware/src/tx_thread_context_save.s +++ b/ports/arc_em/metaware/src/tx_thread_context_save.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * 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 @@ -8,6 +9,8 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ +; Some portions generated by Copilot (Opus 5). + ;/**************************************************************************/ ;/**************************************************************************/ ;/** */ @@ -176,19 +179,10 @@ __tx_thread_not_nested_save: ; _tx_thread_current_ptr -> tx_thread_stack_ptr = sp; ; st sp, [r1, 8] ; Save thread's stack pointer - - .ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY ; -; /* Call the ISR enter function to indicate an ISR is executing. */ +; /* Switch to the system stack. */ +; sp = _tx_thread_system_stack_ptr; ; - sub sp, sp, 32 ; Allocating some space on the stack - st blink, [sp, 16] ; Save blink - bl.d _tx_execution_isr_enter ; Call the ISR enter function - nop ; Delay slot - ld blink, [sp, 16] ; Recover blink - add sp, sp, 32 ; Recover the stack space - .endif - .ifdef TX_ENABLE_HW_STACK_CHECKING lr r2, [status32] ; Pickup current STATUS32 and r2, r2, ~STATUS32_SC ; Clear the hardware stack checking enable bit (SC) @@ -199,16 +193,26 @@ __tx_thread_not_nested_save: sr r1, [KSTACK_BASE] ; Setup KSTACK_BASE ld sp, [gp, _tx_thread_system_stack_ptr@sda] ; Switch to system stack or r2, r2, STATUS32_SC ; Or in hardware stack checking enable bit (SC) - j_s.d [blink] ; Return to calling ISR kflag r2 ; Enable hardware stack checking .else + ld sp, [gp, _tx_thread_system_stack_ptr@sda] ; Switch to system stack + .endif + + .ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY ; -; /* Switch to the system stack. */ -; sp = _tx_thread_system_stack_ptr; +; /* Call the ISR enter function to indicate an ISR is executing. The call is +; made after the switch to the system stack so that it does not consume any +; of the interrupted thread's stack. */ ; - j_s.d [blink] ; Return to calling ISR - ld sp, [gp, _tx_thread_system_stack_ptr@sda] ; Switch to system stack + sub sp, sp, 32 ; Allocating some space on the stack + st blink, [sp, 16] ; Save blink + bl.d _tx_execution_isr_enter ; Call the ISR enter function + nop ; Delay slot + ld blink, [sp, 16] ; Recover blink + add sp, sp, 32 ; Recover the stack space .endif + + j_s [blink] ; Return to calling ISR ; ; } ; else diff --git a/ports/arc_hs/metaware/src/tx_thread_context_save.s b/ports/arc_hs/metaware/src/tx_thread_context_save.s index 27ee25b52..0c4330106 100644 --- a/ports/arc_hs/metaware/src/tx_thread_context_save.s +++ b/ports/arc_hs/metaware/src/tx_thread_context_save.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * 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 @@ -8,6 +9,8 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ +; Some portions generated by Copilot (Opus 5). + ;/**************************************************************************/ ;/**************************************************************************/ ;/** */ @@ -173,10 +176,17 @@ __tx_thread_not_nested_save: ; _tx_thread_current_ptr -> tx_thread_stack_ptr = sp; ; st sp, [r1, 8] ; Save thread's stack pointer +; +; /* Switch to the system stack. */ +; sp = _tx_thread_system_stack_ptr; +; + ld sp, [gp, _tx_thread_system_stack_ptr@sda] ; Switch to system stack .ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY ; -; /* Call the ISR enter function to indicate an ISR is executing. */ +; /* Call the ISR enter function to indicate an ISR is executing. The call is +; made after the switch to the system stack so that it does not consume any +; of the interrupted thread's stack. */ ; sub sp, sp, 32 ; Allocating some space on the stack st blink, [sp, 16] ; Save blink @@ -186,12 +196,7 @@ __tx_thread_not_nested_save: add sp, sp, 32 ; Recover the stack space .endif -; -; /* Switch to the system stack. */ -; sp = _tx_thread_system_stack_ptr; -; - j_s.d [blink] ; Return to calling ISR - ld sp, [gp, _tx_thread_system_stack_ptr@sda] ; Switch to system stack + j_s [blink] ; Return to calling ISR ; ; } ; else diff --git a/ports_smp/arc_hs_smp/metaware/src/tx_thread_context_save.s b/ports_smp/arc_hs_smp/metaware/src/tx_thread_context_save.s index 6014bdb2b..e24c15a48 100644 --- a/ports_smp/arc_hs_smp/metaware/src/tx_thread_context_save.s +++ b/ports_smp/arc_hs_smp/metaware/src/tx_thread_context_save.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * 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 @@ -8,6 +9,7 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ ; +; Some portions generated by Copilot (Opus 5). ; ;/**************************************************************************/ ;/**************************************************************************/ @@ -187,10 +189,19 @@ __tx_thread_not_nested_save: ; _tx_thread_current_ptr[core] -> tx_thread_stack_ptr = sp; ; st sp, [r1, 8] ; Save thread's stack pointer +; +; /* Switch to the system stack. */ +; sp = _tx_thread_system_stack_ptr[core]; +; + mov r1, _tx_thread_system_stack_ptr ; Build address of system stack pointer + add r1, r1, r3 ; + ld sp, [r1] ; Switch to system stack .ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY ; -; /* Call the ISR enter function to indicate an ISR is executing. */ +; /* Call the ISR enter function to indicate an ISR is executing. The call is +; made after the switch to the system stack so that it does not consume any +; of the interrupted thread's stack. */ ; sub sp, sp, 32 ; Allocating some space on the stack st blink, [sp, 16] ; Save blink @@ -199,14 +210,8 @@ __tx_thread_not_nested_save: ld blink, [sp, 16] ; Recover blink add sp, sp, 32 ; Recover the stack space .endif -; -; /* Switch to the system stack. */ -; sp = _tx_thread_system_stack_ptr[core]; -; - mov r1, _tx_thread_system_stack_ptr ; Build address of system stack pointer - add r1, r1, r3 ; - j_s.d [blink] ; Return to calling ISR - ld sp, [r1] ; Switch to system stack + + j_s [blink] ; Return to calling ISR ; ; } ; else From e99f0d42073c6418881e89ff0d98e9b9f7cee2d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Tue, 8 Sep 2026 16:44:48 -0400 Subject: [PATCH 105/181] Corrected the module kernel stack size so it no longer overstates the usable stack (#701) The module manager recorded tx_thread_module_kernel_stack_size as the raw TXM_MODULE_KERNEL_STACK_SIZE constant, but the end of the kernel stack is aligned downwards to an eight-byte boundary while _txm_module_manager_object_allocate only guarantees ULONG alignment. The recorded size could therefore overstate the usable stack by up to seven bytes. The scheduler copies this value into tx_thread_stack_size whenever a user mode module thread enters the kernel, so the overstated value is visible to RTOS-aware debuggers and to anything built on it. The size is now derived from the aligned end minus the start. Also documented that TX_ENABLE_STACK_CHECKING is not supported for module threads. Refs #181 Assisted-by: Copilot (Opus 5) --- .../src/txm_module_manager_thread_create.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/common_modules/module_manager/src/txm_module_manager_thread_create.c b/common_modules/module_manager/src/txm_module_manager_thread_create.c index c14d8e4e4..a178cc35a 100644 --- a/common_modules/module_manager/src/txm_module_manager_thread_create.c +++ b/common_modules/module_manager/src/txm_module_manager_thread_create.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -309,6 +311,13 @@ ULONG i; /* Initialize thread control block to all zeros. */ TX_MEMSET(thread_ptr, 0, sizeof(TX_THREAD)); + /* Note that TX_ENABLE_STACK_CHECKING is not supported for module threads. A user mode + module thread owns two stacks and the scheduler swaps tx_thread_stack_start, + tx_thread_stack_end and tx_thread_stack_size over to the kernel stack whenever the + thread enters the module manager. Neither tx_thread_stack_highest_ptr nor the guard + pattern beyond the end of the stack is maintained across that switch, so + TX_THREAD_STACK_CHECK may report spurious stack errors for module threads. */ + /* If the thread runs on user mode, allocate the kernel stack for syscall. */ if((module_instance -> txm_module_instance_property_flags) & TXM_MODULE_USER_MODE) { @@ -331,8 +340,10 @@ ULONG i; /* Align kernel stack pointer. */ thread_ptr -> tx_thread_module_kernel_stack_end = (VOID *) (((ALIGN_TYPE)(thread_ptr -> tx_thread_module_kernel_stack_start) + TXM_MODULE_KERNEL_STACK_SIZE) & ~0x07); - /* Set kernel stack size. */ - thread_ptr -> tx_thread_module_kernel_stack_size = TXM_MODULE_KERNEL_STACK_SIZE; + /* Set kernel stack size. Aligning the end of the kernel stack downwards can consume + up to seven bytes of the block returned by the allocator, so the usable size must be + derived from the aligned range instead of from TXM_MODULE_KERNEL_STACK_SIZE. */ + thread_ptr -> tx_thread_module_kernel_stack_size = (ULONG) ((ALIGN_TYPE) (thread_ptr -> tx_thread_module_kernel_stack_end) - (ALIGN_TYPE) (thread_ptr -> tx_thread_module_kernel_stack_start)); } #if TXM_MODULE_MEMORY_PROTECTION From 515ab8aba1a42a9d85e18288e1a76e579b177831 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Wed, 9 Sep 2026 09:10:36 -0400 Subject: [PATCH 106/181] Added the missing memory barrier so ARMv7-A SMP schedulers no longer miss preemptions (#704) _tx_thread_schedule stores the newly selected thread into _tx_thread_current_ptr[core] and then reloads _tx_thread_execute_ptr[core] to detect a concurrent scheduling decision made by another core. On the other side, _tx_thread_smp_core_interrupt stores the execute pointer and then reads the current pointer to decide whether an inter-core interrupt is required. This is a store-buffer pattern: without a barrier both cores can observe stale values, the interrupt is skipped, and a ready thread with the highest priority is never scheduled. The barrier was added to the ARMv8-A SMP scheduler in 6.2.1, but the ARMv7-A SMP ports were left untouched even though they implement the same protocol. This adds the corresponding DMB to the Cortex-A5, Cortex-A7 and Cortex-A9 SMP schedulers for both the AC5 and GNU toolchains. The GNU variants were verified by assembling them with arm-none-eabi-gcc 13.2.1 for their respective cores. Refs #209 Assisted-by: Copilot (Opus 5) --- ports_smp/cortex_a5_smp/ac5/src/tx_thread_schedule.s | 4 ++++ ports_smp/cortex_a5_smp/gnu/src/tx_thread_schedule.S | 4 ++++ ports_smp/cortex_a7_smp/ac5/src/tx_thread_schedule.s | 4 ++++ ports_smp/cortex_a7_smp/gnu/src/tx_thread_schedule.S | 4 ++++ ports_smp/cortex_a9_smp/ac5/src/tx_thread_schedule.s | 4 ++++ ports_smp/cortex_a9_smp/gnu/src/tx_thread_schedule.S | 4 ++++ 6 files changed, 24 insertions(+) diff --git a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_schedule.s b/ports_smp/cortex_a5_smp/ac5/src/tx_thread_schedule.s index e4c232aaf..4be82f138 100644 --- a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_schedule.s +++ b/ports_smp/cortex_a5_smp/ac5/src/tx_thread_schedule.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * 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 @@ -8,6 +9,8 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ ; +; Some portions generated by Copilot (Opus 5). +; ; ;/**************************************************************************/ ;/**************************************************************************/ @@ -164,6 +167,7 @@ _tx_thread_ready_for_execution LDR r2, =_tx_thread_current_ptr ; Pickup address of current thread ADD r2, r2, r12 ; Build index into the current thread array STR r0, [r2, #0] ; Setup current thread pointer + DMB ; Ensure the current thread pointer write completes ; ; /* In the time between reading the execute pointer and assigning ; it to the current pointer, the execute pointer was changed by diff --git a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_schedule.S b/ports_smp/cortex_a5_smp/gnu/src/tx_thread_schedule.S index 00f254dde..dd34da804 100644 --- a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_schedule.S +++ b/ports_smp/cortex_a5_smp/gnu/src/tx_thread_schedule.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * 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 @@ -8,6 +9,8 @@ @ * SPDX-License-Identifier: MIT @ **************************************************************************/ @ +@ Some portions generated by Copilot (Opus 5). +@ @ @/**************************************************************************/ @/**************************************************************************/ @@ -166,6 +169,7 @@ _tx_thread_ready_for_execution: LDR r2, =_tx_thread_current_ptr @ Pickup address of current thread ADD r2, r2, r12 @ Build index into the current thread array STR r0, [r2, #0] @ Setup current thread pointer + DMB @ Ensure the current thread pointer write completes @ @ /* In the time between reading the execute pointer and assigning @ it to the current pointer, the execute pointer was changed by diff --git a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_schedule.s b/ports_smp/cortex_a7_smp/ac5/src/tx_thread_schedule.s index 1ced36e9f..a70110ece 100644 --- a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_schedule.s +++ b/ports_smp/cortex_a7_smp/ac5/src/tx_thread_schedule.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * 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 @@ -8,6 +9,8 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ ; +; Some portions generated by Copilot (Opus 5). +; ; ;/**************************************************************************/ ;/**************************************************************************/ @@ -163,6 +166,7 @@ _tx_thread_ready_for_execution LDR r2, =_tx_thread_current_ptr ; Pickup address of current thread ADD r2, r2, r12 ; Build index into the current thread array STR r0, [r2, #0] ; Setup current thread pointer + DMB ; Ensure the current thread pointer write completes ; ; /* In the time between reading the execute pointer and assigning ; it to the current pointer, the execute pointer was changed by diff --git a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_schedule.S b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_schedule.S index 889177529..56bbd5eb5 100644 --- a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_schedule.S +++ b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_schedule.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * 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 @@ -8,6 +9,8 @@ @ * SPDX-License-Identifier: MIT @ **************************************************************************/ @ +@ Some portions generated by Copilot (Opus 5). +@ @ @/**************************************************************************/ @/**************************************************************************/ @@ -180,6 +183,7 @@ _tx_thread_ready_for_execution: LDR r2, =_tx_thread_current_ptr @ Pickup address of current thread ADD r2, r2, r12 @ Build index into the current thread array STR r0, [r2, #0] @ Setup current thread pointer + DMB @ Ensure the current thread pointer write completes @ @ /* In the time between reading the execute pointer and assigning @ it to the current pointer, the execute pointer was changed by diff --git a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_schedule.s b/ports_smp/cortex_a9_smp/ac5/src/tx_thread_schedule.s index 63e7492c6..81f0b2848 100644 --- a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_schedule.s +++ b/ports_smp/cortex_a9_smp/ac5/src/tx_thread_schedule.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * 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 @@ -8,6 +9,8 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ ; +; Some portions generated by Copilot (Opus 5). +; ; ;/**************************************************************************/ ;/**************************************************************************/ @@ -163,6 +166,7 @@ _tx_thread_ready_for_execution LDR r2, =_tx_thread_current_ptr ; Pickup address of current thread ADD r2, r2, r12 ; Build index into the current thread array STR r0, [r2, #0] ; Setup current thread pointer + DMB ; Ensure the current thread pointer write completes ; ; /* In the time between reading the execute pointer and assigning ; it to the current pointer, the execute pointer was changed by diff --git a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_schedule.S b/ports_smp/cortex_a9_smp/gnu/src/tx_thread_schedule.S index 84fec67df..e59be021b 100644 --- a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_schedule.S +++ b/ports_smp/cortex_a9_smp/gnu/src/tx_thread_schedule.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * 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 @@ -8,6 +9,8 @@ @ * SPDX-License-Identifier: MIT @ **************************************************************************/ @ +@ Some portions generated by Copilot (Opus 5). +@ @ @/**************************************************************************/ @/**************************************************************************/ @@ -165,6 +168,7 @@ _tx_thread_ready_for_execution: LDR r2, =_tx_thread_current_ptr @ Pickup address of current thread ADD r2, r2, r12 @ Build index into the current thread array STR r0, [r2, #0] @ Setup current thread pointer + DMB @ Ensure the current thread pointer write completes @ @ /* In the time between reading the execute pointer and assigning @ it to the current pointer, the execute pointer was changed by From 164f211a01f6bc756c6620ec8ca55f4ccf9f6041 Mon Sep 17 00:00:00 2001 From: Akif Ejaz Date: Wed, 9 Sep 2026 18:26:11 +0500 Subject: [PATCH 107/181] riscv64: spec compliance and regression test fix (#698) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * spec compliance Signed-off-by: Akif Ejaz * revert the demo changes Signed-off-by: Akif Ejaz * Restored the FPU demo hook so the RISC-V64 functional test can pass The new check-functional-riscv64 target verifies FPU context switching by watching fpu_test_val advance by 1.1f on each pass through thread_6_and_7_entry. The GDB script deliberately treats a missing symbol as a failure rather than silently skipping the check, but the demo no longer defined it, so the target failed on every run: FPU_VERIFIED_FAIL_NO_SYMBOL The definition and the increment are restored, matching what the risc-v32 demo already carries. The functional target now passes end to end. Three small corrections are folded in: - tx_port.h carried a comment stating that the ISA string must include Zicsr, but nothing enforced it, so an rv64imac build failed with a wall of assembler "unrecognized opcode" errors. It now stops at one clear diagnostic. - Removed TX_RISCV_TRAP_CALL_FRAME_SIZE, which nothing referenced. - The example .gitignore listed qemu-riscv32.log, but the runner writes qemu-riscv64.log, so the generated log showed up as an untracked file. Assisted-by: Claude Code (Opus 5) --------- Signed-off-by: Akif Ejaz Co-authored-by: Frédéric Desbiens --- build-rv64/.ninja_deps | Bin 0 -> 88232 bytes build-rv64/.ninja_log | 402 ++ build-rv64/CPackConfig.cmake | 76 + build-rv64/CPackSourceConfig.cmake | 83 + build-rv64/build.ninja | 3950 +++++++++++++++++ build-rv64/custom_inc/tx_user.h | 298 ++ .../gnu/example_build/qemu_virt/kernel.elf | Bin 0 -> 239112 bytes .../example_build/qemu_virt/qemu-riscv64.log | 235 + .../gnu/example_build/qemu_virt/test_cmds.gdb | 182 + ports/risc-v64/gnu/CMakeLists.txt | 1 + .../gnu/example_build/qemu_virt/.gitignore | 4 + .../example_build/qemu_virt/CMakeLists.txt | 51 + .../gnu/example_build/qemu_virt/board.c | 14 +- .../qemu_virt/build_libthreadx.sh | 28 +- .../example_build/qemu_virt/demo_threadx.c | 3 + .../gnu/example_build/qemu_virt/entry.S | 7 +- .../gnu/example_build/qemu_virt/hwtimer.c | 31 +- .../gnu/example_build/qemu_virt/hwtimer.h | 4 +- .../gnu/example_build/qemu_virt/link.lds | 27 +- .../test/threadx_test_tx_gnu_riscv64_qemu.py | 228 +- .../qemu_virt/tx_initialize_low_level.S | 31 +- ports/risc-v64/gnu/inc/tx_port.h | 50 +- ports/risc-v64/gnu/readme_threadx.txt | 9 + .../gnu/src/tx_initialize_low_level.S | 16 + .../gnu/src/tx_thread_context_restore.S | 122 +- .../risc-v64/gnu/src/tx_thread_context_save.S | 56 +- .../gnu/src/tx_thread_interrupt_control.S | 32 +- ports/risc-v64/gnu/src/tx_thread_schedule.S | 35 +- .../risc-v64/gnu/src/tx_thread_stack_build.S | 14 +- .../gnu/src/tx_thread_system_return.S | 12 +- ports/risc-v64/gnu/src/tx_timer_interrupt.S | 4 +- ports/risc-v_common/example_build/plic/plic.c | 53 +- ports/risc-v_common/example_build/plic/plic.h | 4 +- .../example_build/trap/trap_qemu.c | 71 +- 34 files changed, 5868 insertions(+), 265 deletions(-) create mode 100644 build-rv64/.ninja_deps create mode 100644 build-rv64/.ninja_log create mode 100644 build-rv64/CPackConfig.cmake create mode 100644 build-rv64/CPackSourceConfig.cmake create mode 100644 build-rv64/build.ninja create mode 100644 build-rv64/custom_inc/tx_user.h create mode 100755 build-rv64/ports/risc-v64/gnu/example_build/qemu_virt/kernel.elf create mode 100644 build-rv64/ports/risc-v64/gnu/example_build/qemu_virt/qemu-riscv64.log create mode 100644 build-rv64/ports/risc-v64/gnu/example_build/qemu_virt/test_cmds.gdb create mode 100644 ports/risc-v64/gnu/example_build/qemu_virt/.gitignore create mode 100644 ports/risc-v64/gnu/example_build/qemu_virt/CMakeLists.txt diff --git a/build-rv64/.ninja_deps b/build-rv64/.ninja_deps new file mode 100644 index 0000000000000000000000000000000000000000..240c1db443b8618d68ecc1d0218e2ba77a19c244 GIT binary patch literal 88232 zcmd5_2bfdE8XZv(v4W^rP!J0!yP-Ex7U{hg6$shvT{e(SmK0cuveEe;sHXAfI=HI*T`{rfzGjq;==5KTF-P{KC0=~dlPo7m2 zu5pMEqBlmTKAv$_SD)VsyCMZ4%ad1}o#zX=ih`j?*cI}Hy;&1lwQ!9IL|x&K*A*#t z$NnpK*jr%bMg3OxpzL7oSRww#|E|Y+u1H~#%j@?<^Q^3s@#7L{QZR~Ip;xF);;}|brKx#&6W*3M*!KJnkC7>fNJLj2mTd&KRD6twiGDj68S|Ej^bzVqZm018eCNK zL8(U#%+tyfO7n2U;~nSDjr#m~I&F)eDv?i=;RjoPR6cPy<~mOtf%$)pjqs#!#41Fp zh(tpHrNj@FNr$rh#6G3Nk%kUODILzQN%aEZ$bFMqKNGOCdB@~Rg0`>U|b+LF_2~X^IiCoA1$6M90~aXWAMd2_P*!# z1i}*UYkS`dSQGueT;P3$@3l{zr#tpV_XH~x_5}mk1z+O(ZBqX}Qicl!B;QB2eqj&0 z(Bm!e1uU1(vaI|feE)NM-zV&R%Y$TPh4F16cH8G3vaA5Lpkf!kOL1fDF9das@p_Z) zbJLdD&9a*q+ntwZ<>lPQa*xaU#Y^7$;+#f>9UaRE*Ow>S5H!I31$_#u*rAVw{CR@tRtl zn-sBwW|SjSuC1}S38A!l!m74zb4s%WF3*F9A930W_Pp@x z7gDp->vQLM5&2hJ6AE=ag`Ql8JV%ID}zf4R4xjMKK5XFAW3 zzfqi~QrBo|-~%p?DecIn>;8C2YS$5Sj+|#NR!jSSuMw<|I;)+$ z{;&BwqO`jZdL8xd2U5FE4BAnyOIJI6?xy<`4_5;1G@pmSg?bgLfjQ03YeGG77bfj= zo%o0Qo(Jj;%p+WBPak_+MLY-_7J+lcpWWiUOLBhT^Z>Z!LEo;JkE`>C^v!Mz`lj2* zlxYINYYX@~-N(c^fzSQmL)U1!W4`;rko3eDh<@d7opx`EUG$*sOfB zC-l^@--|(8dpR>6Q#wUSA@2oOXKHmhKH?s5p`6(pTFqVZsPxG`47xSOn!49X{frXl zYaR!rhMU0Knb=OsN!+b;>zMlW1>#)h@`Bh1zRva8aW3L6r5n}J z6(2q)bsNB}Tgv{2=N1DIcfQ{uOCz;&Q)%4(+a>gMuwe<-tt35Ixy$@(!H@c|A>g?Ek>SlK*9^rx z)8{Md!*Vce>KnE^A#Z`Y$+HGr9ja*ifxl~;)9A<<2G==2A>t4FAu~ETvjN59EtfY{?*bSM`51nSWnv@ z;|Igo*=l)Z@W(hOA#Md9s^e~GrsH`ugMO4NNy8QxDfwcdFC6m3ipw%^oQm&NxZf!b zOMyQc8hOCMH*ufzv0ThE?PF=>JAFYh=3Zh6xH_KiG$&}ZSoxP1^KaH5Y^$kuljkxRhakz98`UP9aqPBUR=#l?Z@{YyE?XOI@DJ+;8) z;%eLEp5`;`=@_g@c_Xd*h23-qf)QW-B>fnYxXGzKHS3qj3%1>;v_uXTkFJ_3we(@0 z>D;2@Bjp@Zy65f!-*oI9(4u61=%R^f3O zwhBE(1@z~J1=l&H!T6{Z1^%^8;TJ~ncbC}(*8qPGYBc^7Sgd%eLkp@i!H7|%>z9kZtbeM&vsSB{Sm3%~`omK4FZxp_}ZZO3EIk)w2< zNayvG`b3kjc~hg@)s$F+G#|Ds$J!Mat4VbIN1j5=14r~oB_Z&9Xx`US?=a?>)|-4b z2gA0`rH}lHt15$^NeF$p9#vO%B0^jN&XuH3SG1Y0?D_^7jS8H}DlV+6n($Gy`{gegxa%XkZTttb|?K0T3 zxyez|*QPP(rfUW1)*r)0jQ(SnKw?gV4UXI=h{f$c^1BS&sD~+m&9fJemHJ+ed8Tt9 z>6(LKN7sbMpv9%&inBw-_k>DEgO8XBF4SvJ2cIjRsoIKa#|+Fft()nWozv29lG|J0 z35-$Cl1~Bed5&vX%4stAP%WXlrgfafprfuOy=`h}+?!6g`zORCaKGL`Et7HspJMQ$ zn4XRKJB>z2-@F3zO#7y-8Y8bixZ^zp<;98MN&8;mXS@V16O<29Zn^pS#Zs@i40@3d z(lv-S70(_BOVJSax#yq$YtU#Z!(Oq%JOmV@oBiz{H;>Ig_v{XxHNn&-yaR@$GOBfXMIj_5n`LAkzo z47fTH%ZYqoM?Sbv{h)o_^rTnnb~EN2u}uB2&E774C&>cO5`5pG-cIt!0|%-bw}8h_ z`E#UJi!tZWielK-H31bP#u;2z4zE+bR-TW@Rr)P4^jpfPUmCR|Yz6Z4C3)ciUk7`< z7#HX>TIse7^NlBNlYVzAvu>TSeo8qme(&DxwS0d3h@rbkpU2$bO?`ZY$Ls+(jZ!); z2dBHo?vOgJz?>_73$b=@jFfaNU*pQvjgjE*$n}(e;s*OhfEU%?+c5X{jkcxQdpqWt z*40++HGIJQt&K~-)sfnpgwMs`LbZ1#v}#zRkJN1ygKkty$QN@kQu0NEt9jSi6g)DS4_{D$ubjASioryInypM_bUYtvR zrQ2QL^6qgzO5HXx>PCK-R^HRsiqy5Me&FqR-qW05Q(y3*x_h^w<0d8@ZTVhlti;c~ zeVp>W1TMXm@7)8PhCF^~JL>W7Wzvjt9_f~Yky5`Bixa9AWgeC91vj`t1vQ0n_2=9%_g(l?EIgX;}t!d`R% zUx(|B$w_nuAF4MG!M+;4E$310e3(H$>K94FlzSch4k6=^*9lx5>2(sgTnHY1X!Z!~ zIj+WTsoA4Unq^^KdImKe-%GsS+OZP&p211vC>v3g zu<3^{r%BzO#yr!y>1W4NuFGnV&1NTQQ3luZV1pxdITeoJ*G~E7Gnk*$cbU|9D}%=A z`KCT_#SVdO9rsPm2lpVAZ$4}2_8fz5RF6r!-WYb`+VsuDM!Yq+J8};oiBFbt6QY&! z#phw`t8MO+zPJtZOvgLv+1;j|s4k&NZmZar&?mM8XL<&x!uxKeWfESZh4Rf8z-!aa zAEk~jVxDOowQt(hvIuX$DlCfN-Ct!Mn-$L%jDSTBz>1Gy+#g@?ip(hRO%uf=-Xu8YAQOZAQ)LJY!e4u-~%Ot3<@v z4(q14h_jS#J7LfEM#o)1wf7xH-6(c*Fzn>Ma5P+0dWRXm8wSo!=Ds)|*l`B9P^`X- z`PRKJN&Vi#oGVs4+tseX^84MggN;8g*8rU7VI8MxN7&>99;bs(9yEL(^F1}+ks5x0 zd8Rd_Gl^~eto~Pz-;>q+br!wG+Ge>4ZXG zApRN_aT>Tf8M_7_aVoeVAC-Izn}*H0Tk7@+=9%`p##oblk8)pk3|so)C!gG5zYnkF zGynWm)CG4Z`xg2sssvu*6s6~!hBaVa};%PTG3L(&5QY`(s?kZ0|`*zg@7Y z#v`vv{dP0xM}A2DNPcNMA5IEKtU~hzbe^{U5yk^cD=gRW`S z=@{pDYevVr<0^+=#yQnie)%;tyCbV%4%O*B4Ej-AYrjnS?|5WFk3Y^Njs@2etW)tZ zO$kx*5VgR8dh2h%L+kY|=3H@XPpi@&C9CPER*U;)aMy*mm`(i&sWqX&S z!F49MIpSNTT*OgIv+u#BYweCQ9``Y7mV>qJ)QE{5+zIjI21Dw16OII5Cwpg;&k;(y zA7Inb9}Sn<{m7&p)dRbIvw3~j{8`?^!Q08cIT^1S;6!!xC)oMY&UsSHpBc0y9dj`3 z_#l;qpuYKm?;hr`561a`OLgUgzhFM$lUt;2zha*0`arr-JQ zys^~sAj~;(oxK_>IhQ`3qwY!m3BJzsc?o>rZ+|H5sz9#+*)yef2Qz4=^Id;n+NiPS zBUniv58My_i?F6cXN`a4_djr>zV8s|dExk1q_$NVw52*?GrpCUX6cJL=kMU`O#du> zGYKytep5PDGju$ZNyi*}{%QUluN3fCaCJ1ceG#9>@1uKJ;umnCyjb1P?Jx%2bpPDj zo_1#Jl*^GngS#`=NTnYp=LY+JQodLNI?iwNr;O>t88o%m8-_f%f0XA7dvg8ixs4ye z)0y6|ESDdYUPnNqFY2}LM19VY40=(0>726vNsj7G4?e%~^Y3CG_|C&R6<<%1Z~~9- zm3~J-v%U4Qq<%+NCjFv;d{e>iDuaHdoWx$G-!ahak7&NsuO^dzsh{OydmShZSMe=) zIvB5(;v&9LdewqP(NWu^UdJ-&m18en%hlRF;Ob1RmHTJ%5nn6aY8$#8$D~{8y`JKU z1Q&`HMciKem`5n+*Y_d60%vD>y#w(Q;!AL%p5=IG_u#U#J5#+lfk{W|TT-tXW`A1t z0@fGc>`cu_&gpaIi*=w|r1MOv;fV|yQje0lesa%o*Vghz@OZ%(AD%N%Z(Z5#n10DQ z?Na)k1kHY$@v+qJWCs1x=vnX*)7T%-_yS=|-#7ZqS^dg!`c&z63N&jv<;X4+!*!YT zvzZH(|3w33Jy3{Gz}dlEn1q)QA1fVCHFP|!a_E>F&Ckbe-~1>ZJ~eN@iI1GsF&QuM zq0+G)w42>KOZsE|%AsQvQS6Q#M9hd5;sa-OOu|cu_mz&PL%YlGTOoC9z@%g9bw$=d z^Dp^ydn4WhUkB@QSx%^x?}88YHfKPy&wm&w^*fV6KdQ@iu2Wm?Tz}9z&h7Ez!?>aO z4*1T&S`~d3F3$(o^}z*pm7E2=ey_DlYIin+cKTY@SvGnb&9^8R^t<)Ds@1jrw;l4q zq?};WTi{a!9UDTs={FqPm1=V%1|8||Xa2L6`fi!h^3BSirRD_t-cUYy4)p8RyoJ>A zTm~&o9c}hIvNxmm8{$oor41vv?*MlP`3Be1uYzYG45i}k#b}XMk@F7z;{x_Dpz8}tKjNTjVa3q zcDw>ElpC8st2w=Hk^a||K{qouHUe&{y-t}uPq<_9GPpa@>l}cScuDzSGw9d6E8_3NEl*h8Y=RGOb56su ze8A;-<$J9R4O=s4n6B^X7J^F1bI$2T`A_fDZc6I&Lq>kq?=$Nj4iEYf&l|Vm}(^E>n_Ry^4lozFb z=QHV->ODKvzm!RPPlD%6D05^(_}bqeUYQ?@n>sfkChIYlgbj?)Qud zprGzog#pnLNv0Sa=kCoymF0I0^BH z^1%zCS>39SO8q)9=x6$1`daFW7dyl~Tq(5FoP>A?e5ek0Hni-*prx+Eq+{ymVRQcx z%VjVBiwD8oiR%iMx{98!b4;9<5D$P8U03J|4NuMeUHWD>20cl~9E{Y?!={d%>r6c^%Vo3DttYe^P_0uBs>i(; zb))yw+10Jo<60UOvHEa3 zI6G4x68Q*m8@Nz?7y-@tyj!go`Q1nc{p{7%7|+C)9IkL!HMUl)AYY zbo(!UXVx?FyjvaC&*ZaA`Q2z}_Vli)Qa=xae&lzl*N2$j8L!n8OTp8b`e1SqVu|v% zTxhhc#?4YMFN0pDzomZdsq{zE%e~|p`Y#4|XRbXRfEPI3qWmup8vgEHD)qD&^ehBc z>iu2mp2shf#Y%>_8GPqqt%|>=k%SX?EK>UAL$hn2ep~7{hC#n{>PGy9ph~-&z}3lm z8|MSvZUh&^SV@7Qn~y;^GmdkBo7#D{G+xYJ?*_;8E6?Y8rQcX+Hth^gZ|YaZG3ckS zeNz0Uqn~*_Wnm@IPxHABT9v&LBUumjg@pJh5-S7Tlf5fyp=t zaSixT?;L=B&um*IwG1+7nXV6-=iI9+fe-4l?gFJ-5w!CE_<_`IJd zm-yGO1}w)|4n4lFZDBr`DZ-kUtV?vI6HIZI54l-O2=YD z$4Lx2W~JG)nD-uMfvYn;b7@}D_aA413;KwX$?v>nG~-moCVrQqsJ9#nCx`5>oHRk}@w zR)^P}Cv}^_q+9BJb16^#0O=I)bf#}E%Vjcn6rgU*ghox5ua$buV$zH1M(VwDoM+jW z3u28);OtEAoP-nj6f2*bZD@D}lZH9KOYJ(9;;JudsOx+a!PU`N)qG&b1aP6AWe&93 z{^wc!sOHXP(9OKgVp~7+A|E(Moz_qD0hfsKyDOpDmw(lk`d!7KpS@mL`Ca_YA~DAc zJFQ!sj}RfH+dOD>$FmcqZu6ORv)$_@d3hBnI3AoG?e&uIDpEQwfOcPxY$tWRnn_1` zhNTE^n+Ur?zOXlILaP?8F@dPdD)tl>`SAxXQJ+80HQp+Wx+nNT5tor7$629(<H5d4>5-3qv0WP`dQ2wnm3I|ljj8bjY}F}Gbq&6i`SI#7tU9j&1z zC)ny&zH}Yz8(+Ox`qDxsU$W7+$scIZDVL-h2c8b~ZDqKO1rO@mu7^hJ4sO_=YUd41 zdQsn&gJA?!EXfzki1G#t3xfeyIOKIjiY+%KijX_;*O`6b>rmfOj!%K|wHpoXZeq}m zbi*EHCT~TG@iQ3u2a?_X;6%3{e}&=CmYGb5F|cVpuqszBJ0NM1555)j+vhfNuQwdZ zE)W*D)j@16f=^Vh-c-ic&6wYUQ3V>?%^$kurTmeHwVli#nu`}a;GZRnVbdY!6i6GF zV4mss4y4(8%a~2LTqttE*~uJI%0~zfxa2{-RR6>J5CEcfidc5Ax43xqj9RZj06vg(-nqZw=wATU*fdv zFUsQgkDT*2nKw%L2yuz>x7(pvquI~MI9l)+r#{Q{Qi>zp1Tp&0xkcE?>t7*&ZX4y?#zJS*s&9hwL zNS-ecK`S7JVVxFb*P#O_&YxwzU+#-T@x3-SzBeiCLVp(tM~kuxhNSUb&3G`rTlxH@ z2rmiGE*KQEt7H}8&%3Yr06MeWf%$3->aEsbti?DLx}Ah^0>(Q0^PL#$F)|ikl1}V} z#se#_UfuypuMM!h-$G03b(hlO-}E{K+Ks@l(fk_6yM${dc~)W2t&e;$-TH&ua;#su z&KqTk_5(-i(KZ_T-HmysdtCD0;hEC9V4^%g>mP#c3mcYHI-TPrMW0H|uR!z$zhd~n zChXBS-L8`{bPt0MnDMA{*1f>VSkB4~dO~?Iujo}NHCF`Tt3AOl2bym-G`|mX%HgI? z$?`mDM)5@XD`VP4LY^WOP(8q{^3}%}!S3LOGe^n&u>X-wA4^}|l7eQW7wJa&()Eej z7{_58k5LEXM2wR$NYlC)r(x8?sE=_vMgxp9FwVrF+(>69tWk0(K7017l|2b{x;o}+ z?UKVW4^FKk|NRlhzprZi_tlJlk7;}zP>ip0r19^MQvaUvbxq7y55LJpxV13PbiStF zz9XET_$+#FL=(d4#e{|K+18K&i*U%M_6E-R3^=4AVbOl|Hn93IVQCG?wj5x*-(s57up(9@+syX>#HwG;2??bTm_xpBBoS{rOq@5RQdqxjx zLH5ADjQ1I|Pt?PbzxT!G$E}-5tbR;bdauZ~VZb=)GfUzPXTZ}~WZNYM)(8eH(vk4A zmPMHBeH+h=M_Rgpv8=__Qp?c{c&2Urv3|V^N+i|*1}v?mjymg7;zjQ0}k0mSaX0i*1#Iagk|0b zDg*}oy&K`vZ{bj{rTr#^`L0jjllq1+&-58h>uVV}`3yMPUhrX81M*7+ecb1GVpF@!qc|hg7xbUH63gJ^;xhj;mlybG53t@ng@&y4G(Tdc=H+X zDChfub0t2zRB0=5u42G3?IK^CW8lqYz$4!v+X!nWK5uy_ByF3;gr)uCdaQqX?=2GR z1_msxqu#e`47_WZ@yH)<1IDQF)6XM+yqy7$>>`}m_?#vBN}MYgaP)pH!P=KLSR`?l zGTkq8| zro_6M5sUnB4c7nYuw&1seOt?brT6PDti5kgiNx8+fMfb2<;FXJv334>iMN^wk8C5X z>+o5B!wQMDkO_-?gZ%y;d@lH_<^{B0_cCEojnTHP#C&n5juLMb1D?hrU%VgduiHLc zVr^l-(l*_VwOz#vCC(-W9P&lNBAaf+=jdJ=h(|gS-YfX*_tmi-$nRfe#-n|E02q6JJX_*D$bhHqdd#rvaRwZ{Z`vQ9 z0LHq%Ka+Mn$$*!IH7O@PgwLf-hvm?IJ>|H-9-sU6 z{3NlqF<=qSXyCkN;B05WA>E$Bx+OL1cBDOengK&!S0Su7uzr_GLnYRm3|QLF3F`%{ zzxB|F#Cnk#>m{ro+&M#Hz08Q^hh1-B{RNYsmRN5yV$r^luRmkpZDqhCUnjdB!RI{z z&xPcNk22tB-_Uk_XyARsfTwfCPgwh{&PR75yMAWEA^mn5IPWmvX#IdC{o+e}_S~~W z+VvF!p4RVu1Lp%K9MW$W*1mdJ>&~=KyBTmuH?oOzB)r%0+2Z;fiMIpuV=<~=)W$dt z<9Lh{FzR5Oh;b6e$rz_#)WtXz<1~zV81*qu$7q0Y2F95fgrj0h*2j18&l>MN%o*`Y zJ~psE;l+}+{Q`_@SI&`I{>p%-b)wgB;erBw{u>OR$&81y`Gh^+=`lnZ$-i>_Y zJ4P(>_d^cC^Ccy3O024wXFBJTzY|V1to`Yz>fOnvLz!^M*Q*#f2Q%Q9aaG;GI*b9! z%(=qAI*0*__KEOluWDfZ2R=Mg?$zN;ScFp#YmfaqB5~?7;Lu(XPA#l`_t7gQ&asR* zb+GoGC%qtXPGrE*v2=uib0h)J@2q?Jt$_6X2PMEJ;T5`lL1HjHenr)^?#pH zrzhET0s|Ilr{kzL)?c}*wZuA(35)#u6s#S+A|P?Rp-bSbKBsClcpu2Ao9w zP6vkn%wHs40|q>@i}Y)SwOwmw_omot&48o#sU6mS>b>0(=R5|SMrxnhVC^*%w)G)< z+A`qieIh*4uf2hHJ_8=%Pz+yywYPphtS{NsfdR*iVU5`YI5mPkiP^M*Fk1lU`wdeh zX3Gk|q}c9kV0K}^)IKv<`OHvYXkCXf;Axz$hF#qladNPByXp(&o^@oxp%}OjYr7wR zM&fj0z%gThG$h~X4xH-;ZSF^L*MkAm^bNAHFECpFe5J(e$AD+r7*sa)1kN?{K9HEb z7%;Vsghx4ZFfg>HLm2S1UBj_<#~zLP)81XgfTOk4b`1o^#oO(DTF6eeSZ?9ElF!{+C1{|HIref_ik@iCf=TZh7(vR$! zfVJm#?JaR8GT><4im>*xs|HD&@k}_B4|B10gN;#%<7L1xW0>^25*WEFzmj-YG2rQa zD#qG-mt84wCNbiaVC@b|8xJMFyPOec9@gH~VZFqe&xkV{YfsrRRN`F0h%+5)N3Zxu z;>=*gq2I`@_u9$BXn&S7;ZPjSF>vNG;Fvuw#nEL3-ZTb0iX*zOG1I`A#e_pSf^1rV z^=J2QCim)UCM?3a&cIp7go9_Nq~Bt!y~DLp;w)jnG4-Q3xE>f6T=bg6yMY0Z z;*B&c2G%C5-*0cfi^w(^b literal 0 HcmV?d00001 diff --git a/build-rv64/.ninja_log b/build-rv64/.ninja_log new file mode 100644 index 000000000..c682ca139 --- /dev/null +++ b/build-rv64/.ninja_log @@ -0,0 +1,402 @@ +# ninja log v5 +4 21 1788959531418790526 CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_schedule.S.obj 3a400b6364e6794f +3 21 1788959531418790526 CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_initialize_low_level.S.obj 472097a3a070a693 +3 22 1788959531420614748 CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_context_restore.S.obj 685aa5da7671cc59 +3 22 1788959531419790394 CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_context_save.S.obj f89a6693e7ccf5df +4 22 1788959531418063193 CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_interrupt_control.S.obj c4f86abe3e1b2447 +4 23 1788959531418790526 CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_stack_build.S.obj 1d795aef6c2bcbb2 +4 23 1788959531418790526 CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_system_return.S.obj ea0323b283e0ce95 +4 23 1788959531419790394 CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_timer_interrupt.S.obj 2f8572c59cf518f +12 43 1788959531447351109 CMakeFiles/threadx.dir/common/src/tx_block_pool_initialize.c.obj a4254151a0de29e8 +23 54 1788959531457106052 CMakeFiles/threadx.dir/common/src/tx_byte_pool_initialize.c.obj 203e12b6fa18b976 +5 59 1788959531464047464 CMakeFiles/threadx.dir/common/src/tx_thread_delete.c.obj 1f9cc10cdfe42d77 +12 62 1788959531464047464 CMakeFiles/threadx.dir/common/src/tx_block_pool_info_get.c.obj c0e05c465fb36da2 +17 64 1788959531468209253 CMakeFiles/threadx.dir/common/src/tx_block_pool_performance_system_info_get.c.obj 38ee451e9c0d593d +23 69 1788959531473346045 CMakeFiles/threadx.dir/common/src/tx_byte_pool_info_get.c.obj 2d67f364cfcd6861 +5 74 1788959531469232697 CMakeFiles/threadx.dir/common/src/tx_thread_reset.c.obj 5e33a49b68c693fb +21 74 1788959531471468490 CMakeFiles/threadx.dir/common/src/tx_block_release.c.obj 77ba14c7d78b8401 +22 75 1788959531478246273 CMakeFiles/threadx.dir/common/src/tx_byte_pool_cleanup.c.obj b25a962a81e80ed3 +21 75 1788959531473979861 CMakeFiles/threadx.dir/common/src/tx_block_pool_prioritize.c.obj 7b3a1aae88c17849 +22 78 1788959531478246273 CMakeFiles/threadx.dir/common/src/tx_byte_pool_create.c.obj 1d2322a0cde5af84 +22 82 1788959531486125291 CMakeFiles/threadx.dir/common/src/tx_byte_allocate.c.obj 7e4476822cc9433a +5 84 1788959531486477458 CMakeFiles/threadx.dir/common/src/tx_block_allocate.c.obj d7d226a397e6572f +5 90 1788959531487582734 CMakeFiles/threadx.dir/common/src/tx_block_pool_create.c.obj e4bc5356fd952712 +5 90 1788959531493700416 CMakeFiles/threadx.dir/common/src/tx_block_pool_delete.c.obj 3bd4ffac3b2c556e +43 91 1788959531489564779 CMakeFiles/threadx.dir/common/src/tx_byte_pool_performance_info_get.c.obj 7d06ee00aa77354c +5 98 1788959531497339365 CMakeFiles/threadx.dir/common/src/tx_block_pool_cleanup.c.obj a3dc9eba3bdd181a +14 100 1788959531493700416 CMakeFiles/threadx.dir/common/src/tx_block_pool_performance_info_get.c.obj 7894825bd3dd6bfc +23 106 1788959531502247049 CMakeFiles/threadx.dir/common/src/tx_byte_pool_delete.c.obj 33e0eeb36e2aa751 +60 114 1788959531518326758 CMakeFiles/threadx.dir/common/src/tx_byte_pool_prioritize.c.obj 38960f2f17ed3440 +64 115 1788959531519696545 CMakeFiles/threadx.dir/common/src/tx_byte_release.c.obj 19dc4637dc26fd81 +75 117 1788959531520811800 CMakeFiles/threadx.dir/common/src/tx_event_flags_info_get.c.obj 66af35295b6da083 +54 125 1788959531529190609 CMakeFiles/threadx.dir/common/src/tx_byte_pool_performance_system_info_get.c.obj 110a033022e7444c +62 126 1788959531520811800 CMakeFiles/threadx.dir/common/src/tx_byte_pool_search.c.obj 9a61e94cefd27694 +82 128 1788959531532837669 CMakeFiles/threadx.dir/common/src/tx_event_flags_performance_info_get.c.obj 337df1037e3d2047 +74 129 1788959531532837669 CMakeFiles/threadx.dir/common/src/tx_event_flags_delete.c.obj 7ef3395284f28880 +78 130 1788959531534347418 CMakeFiles/threadx.dir/common/src/tx_event_flags_initialize.c.obj 93dde25808b98e6c +69 132 1788959531532837669 CMakeFiles/threadx.dir/common/src/tx_event_flags_cleanup.c.obj 60beac5c7fe1b560 +106 136 1788959531539199849 CMakeFiles/threadx.dir/common/src/tx_misra.c.obj 952ce45509eb109d +74 143 1788959531543144684 CMakeFiles/threadx.dir/common/src/tx_event_flags_create.c.obj 632222be81dd5d5b +101 149 1788959531553326682 CMakeFiles/threadx.dir/common/src/tx_initialize_kernel_setup.c.obj 98c55ef279b6009 +90 154 1788959531548321213 CMakeFiles/threadx.dir/common/src/tx_event_flags_set_notify.c.obj cdd84434b87875d2 +91 160 1788959531561108129 CMakeFiles/threadx.dir/common/src/tx_initialize_high_level.c.obj a6774cc5db7f561d +75 166 1788959531569734793 CMakeFiles/threadx.dir/common/src/tx_event_flags_get.c.obj 68fc0697aaaedd3 +84 168 1788959531572300986 CMakeFiles/threadx.dir/common/src/tx_event_flags_performance_system_info_get.c.obj 7ed5e8a80c67c6e1 +90 169 1788959531569734793 CMakeFiles/threadx.dir/common/src/tx_event_flags_set.c.obj 6e231edde5656b7 +128 170 1788959531566085907 CMakeFiles/threadx.dir/common/src/tx_mutex_initialize.c.obj f2b1d22759155cb2 +98 171 1788959531575694971 CMakeFiles/threadx.dir/common/src/tx_initialize_kernel_enter.c.obj 3dabae31eb34d8bf +114 172 1788959531573857091 CMakeFiles/threadx.dir/common/src/tx_mutex_cleanup.c.obj db77a90bbe057cf4 +115 173 1788959531573857091 CMakeFiles/threadx.dir/common/src/tx_mutex_create.c.obj ab26c351648a525 +117 173 1788959531574636724 CMakeFiles/threadx.dir/common/src/tx_mutex_delete.c.obj 710f849a6070536a +130 177 1788959531580693382 CMakeFiles/threadx.dir/common/src/tx_mutex_performance_system_info_get.c.obj c109f68be8570a2b +132 187 1788959531590861959 CMakeFiles/threadx.dir/common/src/tx_mutex_prioritize.c.obj 998b0f6327c92876 +136 188 1788959531590861959 CMakeFiles/threadx.dir/common/src/tx_mutex_priority_change.c.obj 25dcd6e0db7d3812 +129 193 1788959531596523993 CMakeFiles/threadx.dir/common/src/tx_mutex_performance_info_get.c.obj 90d20e734eb3dd3c +149 196 1788959531600693401 CMakeFiles/threadx.dir/common/src/tx_queue_cleanup.c.obj f328f5cf950605b7 +143 202 1788959531603659898 CMakeFiles/threadx.dir/common/src/tx_mutex_put.c.obj e42a3e9d195c8da6 +170 202 1788959531603659898 CMakeFiles/threadx.dir/common/src/tx_queue_initialize.c.obj 42aab2c6a4fe823b +154 206 1788959531609120470 CMakeFiles/threadx.dir/common/src/tx_queue_create.c.obj 967d69d170ae5594 +160 210 1788959531612389986 CMakeFiles/threadx.dir/common/src/tx_queue_delete.c.obj b4fd83c9a28a901d +169 215 1788959531617687050 CMakeFiles/threadx.dir/common/src/tx_queue_info_get.c.obj 57649b3d6ff8f773 +166 216 1788959531617687050 CMakeFiles/threadx.dir/common/src/tx_queue_flush.c.obj 109743a2367ccfdc +172 221 1788959531624731978 CMakeFiles/threadx.dir/common/src/tx_queue_performance_system_info_get.c.obj 8f1132d0a840ae94 +126 226 1788959531630576049 CMakeFiles/threadx.dir/common/src/tx_mutex_info_get.c.obj 5233718d3dc46829 +125 230 1788959531632977652 CMakeFiles/threadx.dir/common/src/tx_mutex_get.c.obj ca82c4591c13ae29 +173 230 1788959531632977652 CMakeFiles/threadx.dir/common/src/tx_queue_prioritize.c.obj afa2f28d470b7d89 +177 235 1788959531637217711 CMakeFiles/threadx.dir/common/src/tx_queue_send.c.obj e7262927a917bdb9 +188 238 1788959531637893808 CMakeFiles/threadx.dir/common/src/tx_semaphore_ceiling_put.c.obj 768be723db352257 +171 244 1788959531648503404 CMakeFiles/threadx.dir/common/src/tx_queue_performance_info_get.c.obj 25b3559a9d843353 +193 245 1788959531645864488 CMakeFiles/threadx.dir/common/src/tx_semaphore_cleanup.c.obj 8e545190286d87b3 +196 246 1788959531649750621 CMakeFiles/threadx.dir/common/src/tx_semaphore_create.c.obj a022461d144394b1 +210 247 1788959531651644714 CMakeFiles/threadx.dir/common/src/tx_semaphore_initialize.c.obj ddcd20611e889a84 +168 247 1788959531650719921 CMakeFiles/threadx.dir/common/src/tx_queue_front_send.c.obj 7c6d2908e277afb2 +202 249 1788959531652424946 CMakeFiles/threadx.dir/common/src/tx_semaphore_delete.c.obj 3dd3f8ab254bf87c +173 255 1788959531656746458 CMakeFiles/threadx.dir/common/src/tx_queue_receive.c.obj d94d0946f0e1bad2 +206 255 1788959531656746458 CMakeFiles/threadx.dir/common/src/tx_semaphore_info_get.c.obj 25e6391ee40aae7a +202 260 1788959531658100565 CMakeFiles/threadx.dir/common/src/tx_semaphore_get.c.obj 22b016f726279d6b +187 266 1788959531670409034 CMakeFiles/threadx.dir/common/src/tx_queue_send_notify.c.obj 11b625a2e85d057f +215 266 1788959531664780318 CMakeFiles/threadx.dir/common/src/tx_semaphore_performance_info_get.c.obj 6c027cdd916a37c6 +216 270 1788959531672163253 CMakeFiles/threadx.dir/common/src/tx_semaphore_performance_system_info_get.c.obj 309b844d40c8454b +230 283 1788959531686390026 CMakeFiles/threadx.dir/common/src/tx_semaphore_put_notify.c.obj 570d831c409c872e +230 285 1788959531689380373 CMakeFiles/threadx.dir/common/src/tx_thread_create.c.obj adce0aa1054309d0 +221 286 1788959531689380373 CMakeFiles/threadx.dir/common/src/tx_semaphore_prioritize.c.obj 13e6ef6614d8595e +238 289 1788959531692987584 CMakeFiles/threadx.dir/common/src/tx_thread_identify.c.obj f981455e63570649 +245 295 1788959531699529970 CMakeFiles/threadx.dir/common/src/tx_thread_initialize.c.obj 3726afe17928f7f4 +247 297 1788959531701521946 CMakeFiles/threadx.dir/common/src/tx_thread_performance_system_info_get.c.obj 7c1af7efff31e49 +245 297 1788959531701521946 CMakeFiles/threadx.dir/common/src/tx_thread_info_get.c.obj efd705dd1c02b3e5 +246 299 1788959531703023823 CMakeFiles/threadx.dir/common/src/tx_thread_performance_info_get.c.obj 9416e192b5fe2306 +235 302 1788959531707127985 CMakeFiles/threadx.dir/common/src/tx_thread_entry_exit_notify.c.obj 869a26c327d63e53 +248 306 1788959531708927483 CMakeFiles/threadx.dir/common/src/tx_thread_preemption_change.c.obj 2dd13672b59e0659 +226 307 1788959531707716383 CMakeFiles/threadx.dir/common/src/tx_semaphore_put.c.obj 342cdcd34546c48d +270 307 1788959531711049216 CMakeFiles/threadx.dir/common/src/tx_thread_stack_error_handler.c.obj c7e2d17fb3a714fc +255 310 1788959531708927483 CMakeFiles/threadx.dir/common/src/tx_thread_relinquish.c.obj 9a9ab4d3334de311 +249 310 1788959531711049216 CMakeFiles/threadx.dir/common/src/tx_thread_priority_change.c.obj 489cf9d756529475 +255 314 1788959531714679487 CMakeFiles/threadx.dir/common/src/tx_thread_resume.c.obj 24a748f76813777d +266 322 1788959531726088657 CMakeFiles/threadx.dir/common/src/tx_thread_sleep.c.obj 48ccd71ad4cfc88f +285 335 1788959531738132165 CMakeFiles/threadx.dir/common/src/tx_thread_suspend.c.obj 44da4f9f191e827f +260 335 1788959531738927595 CMakeFiles/threadx.dir/common/src/tx_thread_shell_entry.c.obj 802dc948aedb90eb +266 339 1788959531742968947 CMakeFiles/threadx.dir/common/src/tx_thread_stack_analyze.c.obj 89539c8a1590e36a +297 349 1788959531753047383 CMakeFiles/threadx.dir/common/src/tx_thread_terminate.c.obj e6403e00e325bd74 +299 350 1788959531751051650 CMakeFiles/threadx.dir/common/src/tx_thread_time_slice_change.c.obj 174461221eab7977 +297 351 1788959531755093002 CMakeFiles/threadx.dir/common/src/tx_thread_time_slice.c.obj 7a271de98f7774 +289 351 1788959531755093002 CMakeFiles/threadx.dir/common/src/tx_thread_system_resume.c.obj e4f3fb4824571685 +286 353 1788959531757649547 CMakeFiles/threadx.dir/common/src/tx_thread_system_preempt_check.c.obj 28834ac3b7165cb +295 357 1788959531760889254 CMakeFiles/threadx.dir/common/src/tx_thread_system_suspend.c.obj 14fd9ec8a9d46e91 +307 358 1788959531760889254 CMakeFiles/threadx.dir/common/src/tx_time_get.c.obj cbc97d503eb128de +307 358 1788959531760889254 CMakeFiles/threadx.dir/common/src/tx_time_set.c.obj b6accfada4ea7ee8 +310 359 1788959531762521158 CMakeFiles/threadx.dir/common/src/tx_timer_change.c.obj 49dd976494ad6969 +306 362 1788959531764080399 CMakeFiles/threadx.dir/common/src/tx_thread_wait_abort.c.obj bda57a12055fbd31 +283 363 1788959531767486668 CMakeFiles/threadx.dir/common/src/tx_thread_stack_error_notify.c.obj 7987bf465b5df827 +302 366 1788959531768406390 CMakeFiles/threadx.dir/common/src/tx_thread_timeout.c.obj 73b35a3ddea852ea +310 371 1788959531775097682 CMakeFiles/threadx.dir/common/src/tx_timer_activate.c.obj eb2e6658f137087e +322 382 1788959531786391171 CMakeFiles/threadx.dir/common/src/tx_timer_deactivate.c.obj cd66cf0575ef14fd +314 386 1788959531788793909 CMakeFiles/threadx.dir/common/src/tx_timer_create.c.obj c6866a6d2017df09 +335 389 1788959531792265652 CMakeFiles/threadx.dir/common/src/tx_timer_delete.c.obj b21c8d17e88b1844 +335 390 1788959531794716888 CMakeFiles/threadx.dir/common/src/tx_timer_expiration_process.c.obj eead1c56756c00c8 +339 397 1788959531800473169 CMakeFiles/threadx.dir/common/src/tx_timer_info_get.c.obj 28ca652cfa102dff +351 401 1788959531805339970 CMakeFiles/threadx.dir/common/src/tx_timer_performance_system_info_get.c.obj c024628d0644d579 +353 401 1788959531805339970 CMakeFiles/threadx.dir/common/src/tx_timer_system_deactivate.c.obj 10869c004b77eca0 +349 403 1788959531805339970 CMakeFiles/threadx.dir/common/src/tx_timer_initialize.c.obj fcc1fad694d8f6bc +350 407 1788959531808405645 CMakeFiles/threadx.dir/common/src/tx_timer_performance_info_get.c.obj 5ff819261cdb89af +358 410 1788959531812528359 CMakeFiles/threadx.dir/common/src/tx_trace_disable.c.obj f6b4c28de287dc1d +362 410 1788959531811545326 CMakeFiles/threadx.dir/common/src/tx_trace_event_filter.c.obj 40ca2e165de1d67a +363 411 1788959531815302652 CMakeFiles/threadx.dir/common/src/tx_trace_event_unfilter.c.obj 151b5420a89df4f6 +359 417 1788959531821784693 CMakeFiles/threadx.dir/common/src/tx_trace_enable.c.obj d6b35df11c0dd4ac +366 422 1788959531821784693 CMakeFiles/threadx.dir/common/src/tx_trace_initialize.c.obj 683bc07343dc4d2c +371 423 1788959531827961529 CMakeFiles/threadx.dir/common/src/tx_trace_interrupt_control.c.obj 50c4772b5d621535 +351 434 1788959531834033268 CMakeFiles/threadx.dir/common/src/tx_timer_system_activate.c.obj fb38dda7ea3cffd6 +389 436 1788959531840078836 CMakeFiles/threadx.dir/common/src/tx_trace_object_register.c.obj 22c12a47cc074d2a +386 438 1788959531843025713 CMakeFiles/threadx.dir/common/src/tx_trace_isr_exit_insert.c.obj a9ce0f456d6b5e53 +390 439 1788959531843025713 CMakeFiles/threadx.dir/common/src/tx_trace_object_unregister.c.obj cdd3aa479dc341dd +358 445 1788959531845110918 CMakeFiles/threadx.dir/common/src/tx_trace_buffer_full_notify.c.obj 64ba5346090e1b63 +397 449 1788959531852739969 CMakeFiles/threadx.dir/common/src/tx_trace_user_event_insert.c.obj 2537e8458f153ffb +357 450 1788959531847578342 CMakeFiles/threadx.dir/common/src/tx_timer_thread_entry.c.obj 326c9e51f5b1da36 +401 454 1788959531857089273 CMakeFiles/threadx.dir/common/src/txe_block_allocate.c.obj f84f7c25917d2182 +401 458 1788959531860202882 CMakeFiles/threadx.dir/common/src/txe_block_pool_create.c.obj 4b5f98b899a08cfe +403 458 1788959531862340423 CMakeFiles/threadx.dir/common/src/txe_block_pool_delete.c.obj e9c481ce52eff5fa +382 462 1788959531865264988 CMakeFiles/threadx.dir/common/src/tx_trace_isr_enter_insert.c.obj 9b1aa92002a490db +410 462 1788959531860202882 CMakeFiles/threadx.dir/common/src/txe_block_pool_prioritize.c.obj e86098cdc9612109 +411 466 1788959531869031304 CMakeFiles/threadx.dir/common/src/txe_byte_allocate.c.obj e9bcc54954522cfd +407 466 1788959531870008627 CMakeFiles/threadx.dir/common/src/txe_block_pool_info_get.c.obj be2c996989bbe3df +417 470 1788959531873871911 CMakeFiles/threadx.dir/common/src/txe_byte_pool_create.c.obj 11863d6f1b3d8142 +410 474 1788959531873871911 CMakeFiles/threadx.dir/common/src/txe_block_release.c.obj 76a412317e1991a +422 474 1788959531876908539 CMakeFiles/threadx.dir/common/src/txe_byte_pool_delete.c.obj 6a76087879162c12 +423 478 1788959531876117533 CMakeFiles/threadx.dir/common/src/txe_byte_pool_info_get.c.obj 86b1416cccef300c +434 488 1788959531889007744 CMakeFiles/threadx.dir/common/src/txe_byte_pool_prioritize.c.obj d620399eb038f01e +436 491 1788959531893218456 CMakeFiles/threadx.dir/common/src/txe_byte_release.c.obj 2f0f0404340da8e5 +450 500 1788959531904523114 CMakeFiles/threadx.dir/common/src/txe_event_flags_set.c.obj c038b135c3bd5fde +438 502 1788959531904861469 CMakeFiles/threadx.dir/common/src/txe_event_flags_create.c.obj 68e89ef1bf2a6d81 +439 502 1788959531904861469 CMakeFiles/threadx.dir/common/src/txe_event_flags_delete.c.obj bdb83eee6e23ac07 +454 504 1788959531908817438 CMakeFiles/threadx.dir/common/src/txe_event_flags_set_notify.c.obj bdcef8369128ddd6 +445 506 1788959531908817438 CMakeFiles/threadx.dir/common/src/txe_event_flags_get.c.obj 545521f3c11551d6 +458 512 1788959531913643601 CMakeFiles/threadx.dir/common/src/txe_mutex_delete.c.obj 63df38f752b13e7 +462 514 1788959531917911221 CMakeFiles/threadx.dir/common/src/txe_mutex_get.c.obj 355c3a9632bebbf3 +458 518 1788959531917911221 CMakeFiles/threadx.dir/common/src/txe_mutex_create.c.obj 7050344f91f5c0a1 +470 519 1788959531922556170 CMakeFiles/threadx.dir/common/src/txe_queue_create.c.obj a77e43cedf87b69a +462 519 1788959531924107183 CMakeFiles/threadx.dir/common/src/txe_mutex_info_get.c.obj d5c5ecfc54a1cd9f +466 520 1788959531924107183 CMakeFiles/threadx.dir/common/src/txe_mutex_prioritize.c.obj 856af1d73ccdb848 +449 522 1788959531924947597 CMakeFiles/threadx.dir/common/src/txe_event_flags_info_get.c.obj 3465b2317a7a3f73 +466 526 1788959531928222240 CMakeFiles/threadx.dir/common/src/txe_mutex_put.c.obj 72b7efeb8056daa +474 530 1788959531932667754 CMakeFiles/threadx.dir/common/src/txe_queue_delete.c.obj 3abb5d884f58e9c4 +488 542 1788959531943254605 CMakeFiles/threadx.dir/common/src/txe_queue_info_get.c.obj a42e0031a8a47849 +478 544 1788959531947076386 CMakeFiles/threadx.dir/common/src/txe_queue_front_send.c.obj 2896a1b8bd9aead9 +491 547 1788959531950990531 CMakeFiles/threadx.dir/common/src/txe_queue_prioritize.c.obj 84bc4dcc5c3ed399 +502 550 1788959531952835230 CMakeFiles/threadx.dir/common/src/txe_queue_send.c.obj 3d58854467d61373 +504 552 1788959531953119225 CMakeFiles/threadx.dir/common/src/txe_semaphore_ceiling_put.c.obj f3f50c33d5892285 +502 552 1788959531956945809 CMakeFiles/threadx.dir/common/src/txe_queue_send_notify.c.obj be64c0ca4f55405c +500 553 1788959531956945809 CMakeFiles/threadx.dir/common/src/txe_queue_receive.c.obj 7f36d4cd58f9fddb +512 561 1788959531965949055 CMakeFiles/threadx.dir/common/src/txe_semaphore_delete.c.obj 7ccd4b9b5c30c54f +506 565 1788959531968534186 CMakeFiles/threadx.dir/common/src/txe_semaphore_create.c.obj 71606cfb103e7f51 +518 568 1788959531970447812 CMakeFiles/threadx.dir/common/src/txe_semaphore_info_get.c.obj 8683984653f27803 +519 570 1788959531974128492 CMakeFiles/threadx.dir/common/src/txe_semaphore_put.c.obj 5ba55d0fe8a81f5 +474 578 1788959531981863731 CMakeFiles/threadx.dir/common/src/txe_queue_flush.c.obj 70ee584c446248de +519 578 1788959531977853704 CMakeFiles/threadx.dir/common/src/txe_semaphore_prioritize.c.obj 4e05bf9d76f91053 +520 579 1788959531981863731 CMakeFiles/threadx.dir/common/src/txe_semaphore_put_notify.c.obj a02635f5859b5d2c +530 579 1788959531981863731 CMakeFiles/threadx.dir/common/src/txe_thread_entry_exit_notify.c.obj cdbb2c4171a8d74e +514 588 1788959531991769330 CMakeFiles/threadx.dir/common/src/txe_semaphore_get.c.obj 6af475949cd3b4cf +542 592 1788959531996143015 CMakeFiles/threadx.dir/common/src/txe_thread_info_get.c.obj cb5d7e1bbc229060 +544 594 1788959531997357089 CMakeFiles/threadx.dir/common/src/txe_thread_preemption_change.c.obj 7f2f48efb01bb803 +547 598 1788959532000496224 CMakeFiles/threadx.dir/common/src/txe_thread_priority_change.c.obj d6f6c01fcace9654 +552 598 1788959532002319627 CMakeFiles/threadx.dir/common/src/txe_thread_resume.c.obj cab8d219df477e79 +552 601 1788959532004253745 CMakeFiles/threadx.dir/common/src/txe_thread_reset.c.obj dabba2078d434a2c +550 602 1788959532004253745 CMakeFiles/threadx.dir/common/src/txe_thread_relinquish.c.obj ff82f22cd0c95db5 +522 614 1788959532012469713 CMakeFiles/threadx.dir/common/src/txe_thread_create.c.obj e0c4166f2b2f276b +526 614 1788959532011290344 CMakeFiles/threadx.dir/common/src/txe_thread_delete.c.obj e17b227d67f855e0 +553 615 1788959532017764006 CMakeFiles/threadx.dir/common/src/txe_thread_suspend.c.obj 14f03bf866fadf55 +565 615 1788959532013739498 CMakeFiles/threadx.dir/common/src/txe_thread_time_slice_change.c.obj 813ddb25fc79c35d +594 615 1788959532013739498 ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/entry.S.obj 2b1ac9c639f3fa76 +568 616 1788959532017780849 CMakeFiles/threadx.dir/common/src/txe_thread_wait_abort.c.obj 50db60f5566dc095 +579 625 1788959532029313962 CMakeFiles/threadx.dir/common/src/txe_timer_delete.c.obj 15f20bf94ae8e255 +579 626 1788959532029313962 CMakeFiles/threadx.dir/common/src/txe_timer_deactivate.c.obj 9f2841ee6b4a52dc +614 627 1788959532029904904 ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/tx_initialize_low_level.S.obj 1beece3673f7981 +578 629 1788959532033518084 CMakeFiles/threadx.dir/common/src/txe_timer_create.c.obj 184a61b49fd88e68 +588 633 1788959532038065402 CMakeFiles/threadx.dir/common/src/txe_timer_info_get.c.obj ec3843e84a6e6a6a +562 634 1788959532038065402 CMakeFiles/threadx.dir/common/src/txe_thread_terminate.c.obj 5c174ad2c4940e32 +578 634 1788959532038065402 CMakeFiles/threadx.dir/common/src/txe_timer_change.c.obj aa988079e705f37f +570 635 1788959532039570985 CMakeFiles/threadx.dir/common/src/txe_timer_activate.c.obj 727cb3b86a957e3c +598 642 1788959532046872931 ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/uart.c.obj ed7e60ac1a5c0722 +598 645 1788959532050125647 ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/plic.c.obj cf5687b3e78f6683 +592 647 1788959532050125647 ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/demo_threadx.c.obj d23c7052f7b75543 +601 648 1788959532053055468 ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/hwtimer.c.obj c74642f511df35fe +614 648 1788959532053055468 ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/board.c.obj c7800d48d98128f8 +602 654 1788959532058194364 ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/trap.c.obj 33362e38797d81bc +635 676 1788959532078401122 libthreadx.a f7365c202adc57c6 +676 778 1788959532175393559 ports/risc-v64/gnu/example_build/qemu_virt/kernel.elf 87866ac7df6584e7 +4 24 1788959814925307722 CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_context_save.S.obj f89a6693e7ccf5df +5 27 1788959814925712495 CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_stack_build.S.obj 1d795aef6c2bcbb2 +4 27 1788959814925307722 CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_context_restore.S.obj 685aa5da7671cc59 +5 31 1788959814925307722 CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_schedule.S.obj 3a400b6364e6794f +5 39 1788959814925307722 CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_system_return.S.obj ea0323b283e0ce95 +7 43 1788959814950803623 CMakeFiles/threadx.dir/common/src/tx_block_pool_initialize.c.obj a4254151a0de29e8 +7 56 1788959814963747696 CMakeFiles/threadx.dir/common/src/tx_block_pool_performance_info_get.c.obj 7894825bd3dd6bfc +6 63 1788959814966238622 CMakeFiles/threadx.dir/common/src/tx_block_pool_info_get.c.obj c0e05c465fb36da2 +5 64 1788959814970210776 CMakeFiles/threadx.dir/common/src/tx_thread_delete.c.obj 1f9cc10cdfe42d77 +6 64 1788959814970210776 CMakeFiles/threadx.dir/common/src/tx_block_pool_cleanup.c.obj a3dc9eba3bdd181a +6 64 1788959814967022931 CMakeFiles/threadx.dir/common/src/tx_block_pool_create.c.obj e4bc5356fd952712 +6 65 1788959814970210776 CMakeFiles/threadx.dir/common/src/tx_block_pool_delete.c.obj 3bd4ffac3b2c556e +11 65 1788959814967022931 CMakeFiles/threadx.dir/common/src/tx_block_release.c.obj 77ba14c7d78b8401 +5 66 1788959814970210776 CMakeFiles/threadx.dir/common/src/tx_thread_reset.c.obj 5e33a49b68c693fb +7 67 1788959814974156452 CMakeFiles/threadx.dir/common/src/tx_block_pool_performance_system_info_get.c.obj 38ee451e9c0d593d +8 76 1788959814978189148 CMakeFiles/threadx.dir/common/src/tx_block_pool_prioritize.c.obj 7b3a1aae88c17849 +13 83 1788959814985282255 CMakeFiles/threadx.dir/common/src/tx_byte_allocate.c.obj 7e4476822cc9433a +39 86 1788959814993348931 CMakeFiles/threadx.dir/common/src/tx_byte_pool_initialize.c.obj 203e12b6fa18b976 +27 87 1788959814993348931 CMakeFiles/threadx.dir/common/src/tx_byte_pool_create.c.obj 1d2322a0cde5af84 +27 88 1788959814993348931 CMakeFiles/threadx.dir/common/src/tx_byte_pool_delete.c.obj 33e0eeb36e2aa751 +6 99 1788959814999553244 CMakeFiles/threadx.dir/common/src/tx_block_allocate.c.obj d7d226a397e6572f +31 100 1788959815007042494 CMakeFiles/threadx.dir/common/src/tx_byte_pool_info_get.c.obj 2d67f364cfcd6861 +24 101 1788959815007042494 CMakeFiles/threadx.dir/common/src/tx_byte_pool_cleanup.c.obj b25a962a81e80ed3 +43 113 1788959815017115021 CMakeFiles/threadx.dir/common/src/tx_byte_pool_performance_info_get.c.obj 7d06ee00aa77354c +56 117 1788959815023063536 CMakeFiles/threadx.dir/common/src/tx_byte_pool_performance_system_info_get.c.obj 110a033022e7444c +65 123 1788959815030235233 CMakeFiles/threadx.dir/common/src/tx_event_flags_create.c.obj 632222be81dd5d5b +63 125 1788959815028062176 CMakeFiles/threadx.dir/common/src/tx_byte_pool_prioritize.c.obj 38960f2f17ed3440 +64 125 1788959815031448346 CMakeFiles/threadx.dir/common/src/tx_byte_pool_search.c.obj 9a61e94cefd27694 +65 125 1788959815031448346 CMakeFiles/threadx.dir/common/src/tx_event_flags_delete.c.obj 7ef3395284f28880 +66 126 1788959815030235233 CMakeFiles/threadx.dir/common/src/tx_event_flags_get.c.obj 68fc0697aaaedd3 +64 128 1788959815034156190 CMakeFiles/threadx.dir/common/src/tx_event_flags_cleanup.c.obj 60beac5c7fe1b560 +64 128 1788959815033175584 CMakeFiles/threadx.dir/common/src/tx_byte_release.c.obj 19dc4637dc26fd81 +76 143 1788959815050210464 CMakeFiles/threadx.dir/common/src/tx_event_flags_initialize.c.obj 93dde25808b98e6c +88 156 1788959815055834116 CMakeFiles/threadx.dir/common/src/tx_event_flags_set.c.obj 6e231edde5656b7 +83 162 1788959815064768574 CMakeFiles/threadx.dir/common/src/tx_event_flags_performance_info_get.c.obj 337df1037e3d2047 +88 163 1788959815064768574 CMakeFiles/threadx.dir/common/src/tx_event_flags_set_notify.c.obj cdd84434b87875d2 +99 166 1788959815064768574 CMakeFiles/threadx.dir/common/src/tx_initialize_high_level.c.obj a6774cc5db7f561d +86 167 1788959815072735972 CMakeFiles/threadx.dir/common/src/tx_event_flags_performance_system_info_get.c.obj 7ed5e8a80c67c6e1 +101 170 1788959815072735972 CMakeFiles/threadx.dir/common/src/tx_initialize_kernel_setup.c.obj 98c55ef279b6009 +126 177 1788959815068145683 CMakeFiles/threadx.dir/common/src/tx_mutex_initialize.c.obj f2b1d22759155cb2 +67 179 1788959815081237716 CMakeFiles/threadx.dir/common/src/tx_event_flags_info_get.c.obj 66af35295b6da083 +100 179 1788959815084391745 CMakeFiles/threadx.dir/common/src/tx_initialize_kernel_enter.c.obj 3dabae31eb34d8bf +113 182 1788959815074636910 CMakeFiles/threadx.dir/common/src/tx_misra.c.obj 952ce45509eb109d +117 184 1788959815084391745 CMakeFiles/threadx.dir/common/src/tx_mutex_cleanup.c.obj db77a90bbe057cf4 +123 186 1788959815086111687 CMakeFiles/threadx.dir/common/src/tx_mutex_create.c.obj ab26c351648a525 +125 192 1788959815090099418 CMakeFiles/threadx.dir/common/src/tx_mutex_delete.c.obj 710f849a6070536a +125 195 1788959815090099418 CMakeFiles/threadx.dir/common/src/tx_mutex_info_get.c.obj 5233718d3dc46829 +125 200 1788959815088559595 CMakeFiles/threadx.dir/common/src/tx_mutex_get.c.obj ca82c4591c13ae29 +128 203 1788959815097278469 CMakeFiles/threadx.dir/common/src/tx_mutex_performance_system_info_get.c.obj c109f68be8570a2b +143 218 1788959815115990014 CMakeFiles/threadx.dir/common/src/tx_mutex_prioritize.c.obj 998b0f6327c92876 +180 220 1788959815125641279 CMakeFiles/threadx.dir/common/src/tx_queue_initialize.c.obj 42aab2c6a4fe823b +162 222 1788959815129170501 CMakeFiles/threadx.dir/common/src/tx_mutex_put.c.obj e42a3e9d195c8da6 +163 224 1788959815129170501 CMakeFiles/threadx.dir/common/src/tx_queue_cleanup.c.obj f328f5cf950605b7 +156 227 1788959815132953242 CMakeFiles/threadx.dir/common/src/tx_mutex_priority_change.c.obj 25dcd6e0db7d3812 +170 230 1788959815137446946 CMakeFiles/threadx.dir/common/src/tx_queue_flush.c.obj 109743a2367ccfdc +167 231 1788959815137446946 CMakeFiles/threadx.dir/common/src/tx_queue_delete.c.obj b4fd83c9a28a901d +182 243 1788959815150760286 CMakeFiles/threadx.dir/common/src/tx_queue_performance_info_get.c.obj 25b3559a9d843353 +128 244 1788959815147323525 CMakeFiles/threadx.dir/common/src/tx_mutex_performance_info_get.c.obj 90d20e734eb3dd3c +186 248 1788959815152182141 CMakeFiles/threadx.dir/common/src/tx_queue_prioritize.c.obj afa2f28d470b7d89 +203 263 1788959815170362085 CMakeFiles/threadx.dir/common/src/tx_semaphore_ceiling_put.c.obj 768be723db352257 +177 264 1788959815170491256 CMakeFiles/threadx.dir/common/src/tx_queue_front_send.c.obj 7c6d2908e277afb2 +200 264 1788959815170806744 CMakeFiles/threadx.dir/common/src/tx_queue_send_notify.c.obj 11b625a2e85d057f +166 267 1788959815172956498 CMakeFiles/threadx.dir/common/src/tx_queue_create.c.obj 967d69d170ae5594 +230 272 1788959815177013727 CMakeFiles/threadx.dir/common/src/tx_semaphore_initialize.c.obj ddcd20611e889a84 +192 278 1788959815184176113 CMakeFiles/threadx.dir/common/src/tx_queue_receive.c.obj d94d0946f0e1bad2 +220 281 1788959815187074501 CMakeFiles/threadx.dir/common/src/tx_semaphore_create.c.obj a022461d144394b1 +179 284 1788959815186361633 CMakeFiles/threadx.dir/common/src/tx_queue_info_get.c.obj 57649b3d6ff8f773 +224 288 1788959815193722510 CMakeFiles/threadx.dir/common/src/tx_semaphore_get.c.obj 22b016f726279d6b +218 290 1788959815196820379 CMakeFiles/threadx.dir/common/src/tx_semaphore_cleanup.c.obj 8e545190286d87b3 +231 291 1788959815198364074 CMakeFiles/threadx.dir/common/src/tx_semaphore_performance_info_get.c.obj 6c027cdd916a37c6 +227 295 1788959815202207791 CMakeFiles/threadx.dir/common/src/tx_semaphore_info_get.c.obj 25e6391ee40aae7a +184 297 1788959815204531552 CMakeFiles/threadx.dir/common/src/tx_queue_performance_system_info_get.c.obj 8f1132d0a840ae94 +195 300 1788959815207003841 CMakeFiles/threadx.dir/common/src/tx_queue_send.c.obj e7262927a917bdb9 +222 301 1788959815208563845 CMakeFiles/threadx.dir/common/src/tx_semaphore_delete.c.obj 3dd3f8ab254bf87c +248 303 1788959815210625359 CMakeFiles/threadx.dir/common/src/tx_semaphore_put.c.obj 342cdcd34546c48d +243 304 1788959815211938798 CMakeFiles/threadx.dir/common/src/tx_semaphore_performance_system_info_get.c.obj 309b844d40c8454b +244 305 1788959815210625359 CMakeFiles/threadx.dir/common/src/tx_semaphore_prioritize.c.obj 13e6ef6614d8595e +267 317 1788959815224262570 CMakeFiles/threadx.dir/common/src/tx_thread_identify.c.obj f981455e63570649 +263 326 1788959815231811997 CMakeFiles/threadx.dir/common/src/tx_semaphore_put_notify.c.obj 570d831c409c872e +272 334 1788959815239656032 CMakeFiles/threadx.dir/common/src/tx_thread_info_get.c.obj efd705dd1c02b3e5 +281 336 1788959815242148849 CMakeFiles/threadx.dir/common/src/tx_thread_performance_info_get.c.obj 9416e192b5fe2306 +303 336 1788959815242148849 CMakeFiles/threadx.dir/common/src/tx_thread_stack_error_handler.c.obj c7e2d17fb3a714fc +279 338 1788959815244779904 CMakeFiles/threadx.dir/common/src/tx_thread_initialize.c.obj 3726afe17928f7f4 +291 342 1788959815248542021 CMakeFiles/threadx.dir/common/src/tx_thread_priority_change.c.obj 489cf9d756529475 +264 343 1788959815250479045 CMakeFiles/threadx.dir/common/src/tx_thread_entry_exit_notify.c.obj 869a26c327d63e53 +288 347 1788959815251515503 CMakeFiles/threadx.dir/common/src/tx_thread_preemption_change.c.obj 2dd13672b59e0659 +295 348 1788959815255685774 CMakeFiles/threadx.dir/common/src/tx_thread_resume.c.obj 24a748f76813777d +284 349 1788959815255685774 CMakeFiles/threadx.dir/common/src/tx_thread_performance_system_info_get.c.obj 7c1af7efff31e49 +264 366 1788959815266037426 CMakeFiles/threadx.dir/common/src/tx_thread_create.c.obj adce0aa1054309d0 +301 370 1788959815266037426 CMakeFiles/threadx.dir/common/src/tx_thread_stack_analyze.c.obj 89539c8a1590e36a +304 371 1788959815277429974 CMakeFiles/threadx.dir/common/src/tx_thread_stack_error_notify.c.obj 7987bf465b5df827 +300 375 1788959815277429974 CMakeFiles/threadx.dir/common/src/tx_thread_sleep.c.obj 48ccd71ad4cfc88f +317 383 1788959815290317642 CMakeFiles/threadx.dir/common/src/tx_thread_system_preempt_check.c.obj 28834ac3b7165cb +297 384 1788959815290317642 CMakeFiles/threadx.dir/common/src/tx_thread_shell_entry.c.obj 802dc948aedb90eb +337 390 1788959815296833423 CMakeFiles/threadx.dir/common/src/tx_thread_time_slice.c.obj 7a271de98f7774 +291 392 1788959815297438772 CMakeFiles/threadx.dir/common/src/tx_thread_relinquish.c.obj 9a9ab4d3334de311 +305 395 1788959815297438772 CMakeFiles/threadx.dir/common/src/tx_thread_suspend.c.obj 44da4f9f191e827f +336 398 1788959815297438772 CMakeFiles/threadx.dir/common/src/tx_thread_terminate.c.obj e6403e00e325bd74 +342 400 1788959815302161553 CMakeFiles/threadx.dir/common/src/tx_thread_timeout.c.obj 73b35a3ddea852ea +334 403 1788959815310351965 CMakeFiles/threadx.dir/common/src/tx_thread_system_suspend.c.obj 14fd9ec8a9d46e91 +338 404 1788959815305946755 CMakeFiles/threadx.dir/common/src/tx_thread_time_slice_change.c.obj 174461221eab7977 +343 405 1788959815310351965 CMakeFiles/threadx.dir/common/src/tx_thread_wait_abort.c.obj bda57a12055fbd31 +326 411 1788959815310351965 CMakeFiles/threadx.dir/common/src/tx_thread_system_resume.c.obj e4f3fb4824571685 +349 418 1788959815318797822 CMakeFiles/threadx.dir/common/src/tx_timer_activate.c.obj eb2e6658f137087e +347 424 1788959815329103529 CMakeFiles/threadx.dir/common/src/tx_time_get.c.obj cbc97d503eb128de +366 427 1788959815333989328 CMakeFiles/threadx.dir/common/src/tx_timer_change.c.obj 49dd976494ad6969 +370 431 1788959815336949765 CMakeFiles/threadx.dir/common/src/tx_timer_create.c.obj c6866a6d2017df09 +371 432 1788959815336949765 CMakeFiles/threadx.dir/common/src/tx_timer_deactivate.c.obj cd66cf0575ef14fd +375 434 1788959815330118006 CMakeFiles/threadx.dir/common/src/tx_timer_delete.c.obj b21c8d17e88b1844 +348 447 1788959815352059426 CMakeFiles/threadx.dir/common/src/tx_time_set.c.obj b6accfada4ea7ee8 +395 451 1788959815357530209 CMakeFiles/threadx.dir/common/src/tx_timer_performance_system_info_get.c.obj c024628d0644d579 +400 453 1788959815360863970 CMakeFiles/threadx.dir/common/src/tx_timer_system_deactivate.c.obj 10869c004b77eca0 +384 455 1788959815360863970 CMakeFiles/threadx.dir/common/src/tx_timer_info_get.c.obj 28ca652cfa102dff +390 455 1788959815360863970 CMakeFiles/threadx.dir/common/src/tx_timer_initialize.c.obj fcc1fad694d8f6bc +384 459 1788959815360863970 CMakeFiles/threadx.dir/common/src/tx_timer_expiration_process.c.obj eead1c56756c00c8 +392 461 1788959815362797240 CMakeFiles/threadx.dir/common/src/tx_timer_performance_info_get.c.obj 5ff819261cdb89af +404 462 1788959815367982954 CMakeFiles/threadx.dir/common/src/tx_trace_buffer_full_notify.c.obj 64ba5346090e1b63 +411 464 1788959815371067312 CMakeFiles/threadx.dir/common/src/tx_trace_enable.c.obj d6b35df11c0dd4ac +398 468 1788959815373560491 CMakeFiles/threadx.dir/common/src/tx_timer_system_activate.c.obj fb38dda7ea3cffd6 +405 474 1788959815373560491 CMakeFiles/threadx.dir/common/src/tx_trace_disable.c.obj f6b4c28de287dc1d +418 476 1788959815381748108 CMakeFiles/threadx.dir/common/src/tx_trace_event_filter.c.obj 40ca2e165de1d67a +403 480 1788959815381748108 CMakeFiles/threadx.dir/common/src/tx_timer_thread_entry.c.obj 326c9e51f5b1da36 +431 490 1788959815395476473 CMakeFiles/threadx.dir/common/src/tx_trace_interrupt_control.c.obj 50c4772b5d621535 +427 495 1788959815397516708 CMakeFiles/threadx.dir/common/src/tx_trace_initialize.c.obj 683bc07343dc4d2c +434 495 1788959815401113461 CMakeFiles/threadx.dir/common/src/tx_trace_isr_exit_insert.c.obj a9ce0f456d6b5e53 +424 500 1788959815401113461 CMakeFiles/threadx.dir/common/src/tx_trace_event_unfilter.c.obj 151b5420a89df4f6 +432 501 1788959815405328004 CMakeFiles/threadx.dir/common/src/tx_trace_isr_enter_insert.c.obj 9b1aa92002a490db +451 509 1788959815415657321 CMakeFiles/threadx.dir/common/src/tx_trace_object_unregister.c.obj cdd3aa479dc341dd +462 510 1788959815417538805 CMakeFiles/threadx.dir/common/src/txe_block_pool_prioritize.c.obj e86098cdc9612109 +459 514 1788959815421386647 CMakeFiles/threadx.dir/common/src/txe_block_pool_delete.c.obj e9c481ce52eff5fa +455 516 1788959815419389275 CMakeFiles/threadx.dir/common/src/txe_block_pool_create.c.obj 4b5f98b899a08cfe +461 516 1788959815423994468 CMakeFiles/threadx.dir/common/src/txe_block_pool_info_get.c.obj be2c996989bbe3df +448 517 1788959815422952795 CMakeFiles/threadx.dir/common/src/tx_trace_object_register.c.obj 22c12a47cc074d2a +455 518 1788959815425417908 CMakeFiles/threadx.dir/common/src/txe_block_allocate.c.obj f84f7c25917d2182 +453 519 1788959815426778476 CMakeFiles/threadx.dir/common/src/tx_trace_user_event_insert.c.obj 2537e8458f153ffb +464 529 1788959815436249135 CMakeFiles/threadx.dir/common/src/txe_block_release.c.obj 76a412317e1991a +480 535 1788959815442488258 CMakeFiles/threadx.dir/common/src/txe_byte_pool_info_get.c.obj 86b1416cccef300c +476 551 1788959815457404584 CMakeFiles/threadx.dir/common/src/txe_byte_pool_delete.c.obj 6a76087879162c12 +490 560 1788959815457404584 CMakeFiles/threadx.dir/common/src/txe_byte_pool_prioritize.c.obj d620399eb038f01e +495 561 1788959815466741957 CMakeFiles/threadx.dir/common/src/txe_byte_release.c.obj 2f0f0404340da8e5 +468 562 1788959815467888394 CMakeFiles/threadx.dir/common/src/txe_byte_allocate.c.obj e9bcc54954522cfd +474 563 1788959815469084144 CMakeFiles/threadx.dir/common/src/txe_byte_pool_create.c.obj 11863d6f1b3d8142 +500 563 1788959815469084144 CMakeFiles/threadx.dir/common/src/txe_event_flags_delete.c.obj bdb83eee6e23ac07 +509 563 1788959815467888394 CMakeFiles/threadx.dir/common/src/txe_event_flags_info_get.c.obj 3465b2317a7a3f73 +514 565 1788959815469084144 CMakeFiles/threadx.dir/common/src/txe_event_flags_set_notify.c.obj bdcef8369128ddd6 +510 565 1788959815470614586 CMakeFiles/threadx.dir/common/src/txe_event_flags_set.c.obj c038b135c3bd5fde +495 575 1788959815473872735 CMakeFiles/threadx.dir/common/src/txe_event_flags_create.c.obj 68e89ef1bf2a6d81 +501 582 1788959815489573780 CMakeFiles/threadx.dir/common/src/txe_event_flags_get.c.obj 545521f3c11551d6 +516 585 1788959815486862647 CMakeFiles/threadx.dir/common/src/txe_mutex_create.c.obj 7050344f91f5c0a1 +516 585 1788959815492275344 CMakeFiles/threadx.dir/common/src/txe_mutex_delete.c.obj 63df38f752b13e7 +519 586 1788959815489573780 CMakeFiles/threadx.dir/common/src/txe_mutex_prioritize.c.obj 856af1d73ccdb848 +529 592 1788959815497238849 CMakeFiles/threadx.dir/common/src/txe_mutex_put.c.obj 72b7efeb8056daa +518 599 1788959815505465690 CMakeFiles/threadx.dir/common/src/txe_mutex_info_get.c.obj d5c5ecfc54a1cd9f +517 615 1788959815520647387 CMakeFiles/threadx.dir/common/src/txe_mutex_get.c.obj 355c3a9632bebbf3 +551 619 1788959815520647387 CMakeFiles/threadx.dir/common/src/txe_queue_delete.c.obj 3abb5d884f58e9c4 +563 620 1788959815520647387 CMakeFiles/threadx.dir/common/src/txe_queue_receive.c.obj 7f36d4cd58f9fddb +562 620 1788959815524317191 CMakeFiles/threadx.dir/common/src/txe_queue_info_get.c.obj a42e0031a8a47849 +563 622 1788959815524317191 CMakeFiles/threadx.dir/common/src/txe_queue_prioritize.c.obj 84bc4dcc5c3ed399 +565 624 1788959815524317191 CMakeFiles/threadx.dir/common/src/txe_semaphore_ceiling_put.c.obj f3f50c33d5892285 +561 627 1788959815528476091 CMakeFiles/threadx.dir/common/src/txe_queue_front_send.c.obj 2896a1b8bd9aead9 +561 634 1788959815533315516 CMakeFiles/threadx.dir/common/src/txe_queue_flush.c.obj 70ee584c446248de +582 636 1788959815542559384 CMakeFiles/threadx.dir/common/src/txe_semaphore_delete.c.obj 7ccd4b9b5c30c54f +535 639 1788959815545056867 CMakeFiles/threadx.dir/common/src/txe_queue_create.c.obj a77e43cedf87b69a +575 647 1788959815553266661 CMakeFiles/threadx.dir/common/src/txe_semaphore_create.c.obj 71606cfb103e7f51 +586 648 1788959815553266661 CMakeFiles/threadx.dir/common/src/txe_semaphore_prioritize.c.obj 4e05bf9d76f91053 +585 651 1788959815558162261 CMakeFiles/threadx.dir/common/src/txe_semaphore_get.c.obj 6af475949cd3b4cf +585 653 1788959815560987871 CMakeFiles/threadx.dir/common/src/txe_semaphore_info_get.c.obj 8683984653f27803 +565 655 1788959815561777827 CMakeFiles/threadx.dir/common/src/txe_queue_send_notify.c.obj be64c0ca4f55405c +620 676 1788959815582381224 CMakeFiles/threadx.dir/common/src/txe_thread_info_get.c.obj cb5d7e1bbc229060 +599 677 1788959815583417993 CMakeFiles/threadx.dir/common/src/txe_semaphore_put_notify.c.obj a02635f5859b5d2c +592 679 1788959815583901126 CMakeFiles/threadx.dir/common/src/txe_semaphore_put.c.obj 5ba55d0fe8a81f5 +563 687 1788959815586131747 CMakeFiles/threadx.dir/common/src/txe_queue_send.c.obj 3d58854467d61373 +619 687 1788959815593731170 CMakeFiles/threadx.dir/common/src/txe_thread_delete.c.obj e17b227d67f855e0 +620 688 1788959815587503854 CMakeFiles/threadx.dir/common/src/txe_thread_entry_exit_notify.c.obj cdbb2c4171a8d74e +624 698 1788959815598120255 CMakeFiles/threadx.dir/common/src/txe_thread_priority_change.c.obj d6f6c01fcace9654 +639 700 1788959815606484964 CMakeFiles/threadx.dir/common/src/txe_thread_suspend.c.obj 14f03bf866fadf55 +627 703 1788959815600886651 CMakeFiles/threadx.dir/common/src/txe_thread_relinquish.c.obj ff82f22cd0c95db5 +636 703 1788959815609845621 CMakeFiles/threadx.dir/common/src/txe_thread_resume.c.obj cab8d219df477e79 +647 707 1788959815613796384 CMakeFiles/threadx.dir/common/src/txe_thread_terminate.c.obj 5c174ad2c4940e32 +615 707 1788959815613796384 CMakeFiles/threadx.dir/common/src/txe_thread_create.c.obj e0c4166f2b2f276b +622 707 1788959815613796384 CMakeFiles/threadx.dir/common/src/txe_thread_preemption_change.c.obj 7f2f48efb01bb803 +634 708 1788959815613796384 CMakeFiles/threadx.dir/common/src/txe_thread_reset.c.obj dabba2078d434a2c +648 708 1788959815615271046 CMakeFiles/threadx.dir/common/src/txe_thread_time_slice_change.c.obj 813ddb25fc79c35d +651 708 1788959815615271046 CMakeFiles/threadx.dir/common/src/txe_thread_wait_abort.c.obj 50db60f5566dc095 +700 713 1788959815620133766 ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/tx_initialize_low_level.S.obj 1beece3673f7981 +655 722 1788959815629147293 CMakeFiles/threadx.dir/common/src/txe_timer_change.c.obj aa988079e705f37f +653 728 1788959815635848602 CMakeFiles/threadx.dir/common/src/txe_timer_activate.c.obj 727cb3b86a957e3c +677 732 1788959815638446822 CMakeFiles/threadx.dir/common/src/txe_timer_deactivate.c.obj 9f2841ee6b4a52dc +676 732 1788959815640231891 CMakeFiles/threadx.dir/common/src/txe_timer_create.c.obj 184a61b49fd88e68 +679 735 1788959815642405182 CMakeFiles/threadx.dir/common/src/txe_timer_delete.c.obj 15f20bf94ae8e255 +688 744 1788959815650766415 ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/hwtimer.c.obj c74642f511df35fe +698 744 1788959815650766415 ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/trap.c.obj 33362e38797d81bc +687 746 1788959815653912749 CMakeFiles/threadx.dir/common/src/txe_timer_info_get.c.obj ec3843e84a6e6a6a +688 755 1788959815662129768 ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/demo_threadx.c.obj d23c7052f7b75543 +746 791 1788959815693736239 libthreadx.a f7365c202adc57c6 +791 909 1788959815812226206 ports/risc-v64/gnu/example_build/qemu_virt/kernel.elf 87866ac7df6584e7 +4 226 0 ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/check-functional-riscv64 5d05461e8e889612 +4 226 0 /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/check-functional-riscv64 5d05461e8e889612 diff --git a/build-rv64/CPackConfig.cmake b/build-rv64/CPackConfig.cmake new file mode 100644 index 000000000..128314f29 --- /dev/null +++ b/build-rv64/CPackConfig.cmake @@ -0,0 +1,76 @@ +# This file will be configured to contain variables for CPack. These variables +# should be set in the CMake list file of the project before CPack module is +# included. The list of available CPACK_xxx variables and their associated +# documentation may be obtained using +# cpack --help-variable-list +# +# Some variables are common to all generators (e.g. CPACK_PACKAGE_NAME) +# and some are specific to a generator +# (e.g. CPACK_NSIS_EXTRA_INSTALL_COMMANDS). The generator specific variables +# usually begin with CPACK__xxxx. + + +set(CPACK_ARCHIVE_GID "-1") +set(CPACK_ARCHIVE_UID "-1") +set(CPACK_BINARY_7Z "OFF") +set(CPACK_BINARY_IFW "OFF") +set(CPACK_BINARY_INNOSETUP "OFF") +set(CPACK_BINARY_NSIS "ON") +set(CPACK_BINARY_NUGET "OFF") +set(CPACK_BINARY_WIX "OFF") +set(CPACK_BINARY_ZIP "OFF") +set(CPACK_BUILD_SOURCE_DIRS "/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698;/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64") +set(CPACK_CMAKE_GENERATOR "Ninja") +set(CPACK_COMPONENTS_ALL "") +set(CPACK_COMPONENT_UNSPECIFIED_HIDDEN "TRUE") +set(CPACK_COMPONENT_UNSPECIFIED_REQUIRED "TRUE") +set(CPACK_DEFAULT_PACKAGE_DESCRIPTION_FILE "/usr/share/cmake-4.4/Templates/CPack.GenericDescription.txt") +set(CPACK_DEFAULT_PACKAGE_DESCRIPTION_SUMMARY "threadx built using CMake") +set(CPACK_GENERATOR "NSIS") +set(CPACK_INNOSETUP_ARCHITECTURE "x64") +set(CPACK_INSTALL_CMAKE_PROJECTS "/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64;threadx;ALL;/") +set(CPACK_INSTALL_PREFIX "/usr/local") +set(CPACK_MODULE_PATH "") +set(CPACK_NSIS_DISPLAY_NAME "threadx 0.1.1") +set(CPACK_NSIS_INSTALLER_ICON_CODE "") +set(CPACK_NSIS_INSTALLER_MUI_ICON_CODE "") +set(CPACK_NSIS_INSTALL_ROOT "\$PROGRAMFILES") +set(CPACK_NSIS_PACKAGE_NAME "threadx 0.1.1") +set(CPACK_NSIS_UNINSTALL_NAME "Uninstall") +set(CPACK_OBJCOPY_EXECUTABLE "/opt/riscv/bin/riscv64-unknown-elf-objcopy") +set(CPACK_OBJDUMP_EXECUTABLE "/opt/riscv/bin/riscv64-unknown-elf-objdump") +set(CPACK_OUTPUT_CONFIG_FILE "/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/CPackConfig.cmake") +set(CPACK_PACKAGE_DEFAULT_LOCATION "/") +set(CPACK_PACKAGE_DESCRIPTION_FILE "/usr/share/cmake-4.4/Templates/CPack.GenericDescription.txt") +set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "threadx built using CMake") +set(CPACK_PACKAGE_FILE_NAME "threadx-0.1.1-Generic") +set(CPACK_PACKAGE_INSTALL_DIRECTORY "threadx 0.1.1") +set(CPACK_PACKAGE_INSTALL_REGISTRY_KEY "threadx 0.1.1") +set(CPACK_PACKAGE_NAME "threadx") +set(CPACK_PACKAGE_RELOCATABLE "true") +set(CPACK_PACKAGE_VENDOR "Humanity") +set(CPACK_PACKAGE_VERSION "0.1.1") +set(CPACK_PACKAGE_VERSION_MAJOR "0") +set(CPACK_PACKAGE_VERSION_MINOR "1") +set(CPACK_PACKAGE_VERSION_PATCH "1") +set(CPACK_READELF_EXECUTABLE "/opt/riscv/bin/riscv64-unknown-elf-readelf") +set(CPACK_RESOURCE_FILE_LICENSE "/usr/share/cmake-4.4/Templates/CPack.GenericLicense.txt") +set(CPACK_RESOURCE_FILE_README "/usr/share/cmake-4.4/Templates/CPack.GenericDescription.txt") +set(CPACK_RESOURCE_FILE_WELCOME "/usr/share/cmake-4.4/Templates/CPack.GenericWelcome.txt") +set(CPACK_SET_DESTDIR "OFF") +set(CPACK_SOURCE_GENERATOR "ZIP") +set(CPACK_SOURCE_IGNORE_FILES "\\.git/;\\.github/;_build/;\\.git;\\.gitattributes;\\.gitignore;.*~\$") +set(CPACK_SOURCE_OUTPUT_CONFIG_FILE "/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/CPackSourceConfig.cmake") +set(CPACK_SYSTEM_NAME "Generic") +set(CPACK_THREADS "1") +set(CPACK_TOPLEVEL_TAG "Generic") +set(CPACK_VERBATIM_VARIABLES "YES") +set(CPACK_WIX_SIZEOF_VOID_P "8") + +if(NOT CPACK_PROPERTIES_FILE) + set(CPACK_PROPERTIES_FILE "/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/CPackProperties.cmake") +endif() + +if(EXISTS ${CPACK_PROPERTIES_FILE}) + include(${CPACK_PROPERTIES_FILE}) +endif() diff --git a/build-rv64/CPackSourceConfig.cmake b/build-rv64/CPackSourceConfig.cmake new file mode 100644 index 000000000..c858219c0 --- /dev/null +++ b/build-rv64/CPackSourceConfig.cmake @@ -0,0 +1,83 @@ +# This file will be configured to contain variables for CPack. These variables +# should be set in the CMake list file of the project before CPack module is +# included. The list of available CPACK_xxx variables and their associated +# documentation may be obtained using +# cpack --help-variable-list +# +# Some variables are common to all generators (e.g. CPACK_PACKAGE_NAME) +# and some are specific to a generator +# (e.g. CPACK_NSIS_EXTRA_INSTALL_COMMANDS). The generator specific variables +# usually begin with CPACK__xxxx. + + +set(CPACK_ARCHIVE_GID "-1") +set(CPACK_ARCHIVE_UID "-1") +set(CPACK_BINARY_7Z "OFF") +set(CPACK_BINARY_IFW "OFF") +set(CPACK_BINARY_INNOSETUP "OFF") +set(CPACK_BINARY_NSIS "ON") +set(CPACK_BINARY_NUGET "OFF") +set(CPACK_BINARY_WIX "OFF") +set(CPACK_BINARY_ZIP "OFF") +set(CPACK_BUILD_SOURCE_DIRS "/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698;/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64") +set(CPACK_CMAKE_GENERATOR "Ninja") +set(CPACK_COMPONENTS_ALL "") +set(CPACK_COMPONENT_UNSPECIFIED_HIDDEN "TRUE") +set(CPACK_COMPONENT_UNSPECIFIED_REQUIRED "TRUE") +set(CPACK_DEFAULT_PACKAGE_DESCRIPTION_FILE "/usr/share/cmake-4.4/Templates/CPack.GenericDescription.txt") +set(CPACK_DEFAULT_PACKAGE_DESCRIPTION_SUMMARY "threadx built using CMake") +set(CPACK_GENERATOR "ZIP") +set(CPACK_IGNORE_FILES "\\.git/;\\.github/;_build/;\\.git;\\.gitattributes;\\.gitignore;.*~\$") +set(CPACK_INNOSETUP_ARCHITECTURE "x64") +set(CPACK_INSTALLED_DIRECTORIES "/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698;/") +set(CPACK_INSTALL_CMAKE_PROJECTS "") +set(CPACK_INSTALL_PREFIX "/usr/local") +set(CPACK_MODULE_PATH "") +set(CPACK_NSIS_DISPLAY_NAME "threadx 0.1.1") +set(CPACK_NSIS_INSTALLER_ICON_CODE "") +set(CPACK_NSIS_INSTALLER_MUI_ICON_CODE "") +set(CPACK_NSIS_INSTALL_ROOT "\$PROGRAMFILES") +set(CPACK_NSIS_PACKAGE_NAME "threadx 0.1.1") +set(CPACK_NSIS_UNINSTALL_NAME "Uninstall") +set(CPACK_OBJCOPY_EXECUTABLE "/opt/riscv/bin/riscv64-unknown-elf-objcopy") +set(CPACK_OBJDUMP_EXECUTABLE "/opt/riscv/bin/riscv64-unknown-elf-objdump") +set(CPACK_OUTPUT_CONFIG_FILE "/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/CPackConfig.cmake") +set(CPACK_PACKAGE_DEFAULT_LOCATION "/") +set(CPACK_PACKAGE_DESCRIPTION_FILE "/usr/share/cmake-4.4/Templates/CPack.GenericDescription.txt") +set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "threadx built using CMake") +set(CPACK_PACKAGE_FILE_NAME "threadx-0.1.1-Source") +set(CPACK_PACKAGE_INSTALL_DIRECTORY "threadx 0.1.1") +set(CPACK_PACKAGE_INSTALL_REGISTRY_KEY "threadx 0.1.1") +set(CPACK_PACKAGE_NAME "threadx") +set(CPACK_PACKAGE_RELOCATABLE "true") +set(CPACK_PACKAGE_VENDOR "Humanity") +set(CPACK_PACKAGE_VERSION "0.1.1") +set(CPACK_PACKAGE_VERSION_MAJOR "0") +set(CPACK_PACKAGE_VERSION_MINOR "1") +set(CPACK_PACKAGE_VERSION_PATCH "1") +set(CPACK_READELF_EXECUTABLE "/opt/riscv/bin/riscv64-unknown-elf-readelf") +set(CPACK_RESOURCE_FILE_LICENSE "/usr/share/cmake-4.4/Templates/CPack.GenericLicense.txt") +set(CPACK_RESOURCE_FILE_README "/usr/share/cmake-4.4/Templates/CPack.GenericDescription.txt") +set(CPACK_RESOURCE_FILE_WELCOME "/usr/share/cmake-4.4/Templates/CPack.GenericWelcome.txt") +set(CPACK_RPM_PACKAGE_SOURCES "ON") +set(CPACK_SET_DESTDIR "OFF") +set(CPACK_SOURCE_GENERATOR "ZIP") +set(CPACK_SOURCE_IGNORE_FILES "\\.git/;\\.github/;_build/;\\.git;\\.gitattributes;\\.gitignore;.*~\$") +set(CPACK_SOURCE_INSTALLED_DIRECTORIES "/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698;/") +set(CPACK_SOURCE_OUTPUT_CONFIG_FILE "/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/CPackSourceConfig.cmake") +set(CPACK_SOURCE_PACKAGE_FILE_NAME "threadx-0.1.1-Source") +set(CPACK_SOURCE_TOPLEVEL_TAG "Generic-Source") +set(CPACK_STRIP_FILES "") +set(CPACK_SYSTEM_NAME "Generic") +set(CPACK_THREADS "1") +set(CPACK_TOPLEVEL_TAG "Generic-Source") +set(CPACK_VERBATIM_VARIABLES "YES") +set(CPACK_WIX_SIZEOF_VOID_P "8") + +if(NOT CPACK_PROPERTIES_FILE) + set(CPACK_PROPERTIES_FILE "/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/CPackProperties.cmake") +endif() + +if(EXISTS ${CPACK_PROPERTIES_FILE}) + include(${CPACK_PROPERTIES_FILE}) +endif() diff --git a/build-rv64/build.ninja b/build-rv64/build.ninja new file mode 100644 index 000000000..28cff4b75 --- /dev/null +++ b/build-rv64/build.ninja @@ -0,0 +1,3950 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Ninja" Generator, CMake Version 4.4 + +# This file contains all the build statements describing the +# compilation DAG. + +# ============================================================================= +# Write statements declared in CMakeLists.txt: +# +# Which is the root file. +# ============================================================================= + +# ============================================================================= +# Project: threadx +# Configurations: +# ============================================================================= + +############################################# +# Minimal version of Ninja required by this file + +ninja_required_version = 1.5 + +# ============================================================================= +# Include auxiliary files. + + +############################################# +# Include rules file. + +include CMakeFiles/rules.ninja + +# ============================================================================= + +############################################# +# Logical path to working directory; prefix for absolute paths. + +cmake_ninja_workdir = /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/ +# ============================================================================= +# Object build statements for STATIC_LIBRARY target threadx + + +############################################# +# Order-only phony target for threadx + +build cmake_object_order_depends_target_threadx: phony || . + +build CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_initialize_low_level.S.obj: ASM_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/src/tx_initialize_low_level.S || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_initialize_low_level.S.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany -D__ASSEMBLER__ + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/ports/risc-v64/gnu/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_context_restore.S.obj: ASM_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/src/tx_thread_context_restore.S || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_context_restore.S.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany -D__ASSEMBLER__ + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/ports/risc-v64/gnu/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_context_save.S.obj: ASM_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/src/tx_thread_context_save.S || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_context_save.S.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany -D__ASSEMBLER__ + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/ports/risc-v64/gnu/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_interrupt_control.S.obj: ASM_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/src/tx_thread_interrupt_control.S || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_interrupt_control.S.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany -D__ASSEMBLER__ + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/ports/risc-v64/gnu/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_schedule.S.obj: ASM_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/src/tx_thread_schedule.S || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_schedule.S.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany -D__ASSEMBLER__ + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/ports/risc-v64/gnu/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_stack_build.S.obj: ASM_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/src/tx_thread_stack_build.S || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_stack_build.S.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany -D__ASSEMBLER__ + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/ports/risc-v64/gnu/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_system_return.S.obj: ASM_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/src/tx_thread_system_return.S || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_system_return.S.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany -D__ASSEMBLER__ + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/ports/risc-v64/gnu/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_timer_interrupt.S.obj: ASM_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/src/tx_timer_interrupt.S || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_timer_interrupt.S.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany -D__ASSEMBLER__ + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/ports/risc-v64/gnu/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_thread_delete.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_delete.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_delete.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_thread_reset.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_reset.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_reset.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_block_allocate.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_block_allocate.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_block_allocate.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_block_pool_cleanup.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_block_pool_cleanup.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_block_pool_cleanup.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_block_pool_create.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_block_pool_create.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_block_pool_create.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_block_pool_delete.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_block_pool_delete.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_block_pool_delete.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_block_pool_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_block_pool_info_get.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_block_pool_info_get.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_block_pool_initialize.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_block_pool_initialize.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_block_pool_initialize.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_block_pool_performance_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_block_pool_performance_info_get.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_block_pool_performance_info_get.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_block_pool_performance_system_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_block_pool_performance_system_info_get.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_block_pool_performance_system_info_get.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_block_pool_prioritize.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_block_pool_prioritize.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_block_pool_prioritize.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_block_release.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_block_release.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_block_release.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_byte_allocate.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_byte_allocate.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_byte_allocate.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_byte_pool_cleanup.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_byte_pool_cleanup.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_byte_pool_cleanup.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_byte_pool_create.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_byte_pool_create.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_byte_pool_create.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_byte_pool_delete.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_byte_pool_delete.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_byte_pool_delete.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_byte_pool_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_byte_pool_info_get.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_byte_pool_info_get.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_byte_pool_initialize.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_byte_pool_initialize.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_byte_pool_initialize.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_byte_pool_performance_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_byte_pool_performance_info_get.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_byte_pool_performance_info_get.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_byte_pool_performance_system_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_byte_pool_performance_system_info_get.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_byte_pool_performance_system_info_get.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_byte_pool_prioritize.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_byte_pool_prioritize.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_byte_pool_prioritize.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_byte_pool_search.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_byte_pool_search.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_byte_pool_search.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_byte_release.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_byte_release.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_byte_release.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_event_flags_cleanup.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_event_flags_cleanup.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_event_flags_cleanup.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_event_flags_create.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_event_flags_create.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_event_flags_create.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_event_flags_delete.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_event_flags_delete.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_event_flags_delete.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_event_flags_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_event_flags_get.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_event_flags_get.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_event_flags_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_event_flags_info_get.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_event_flags_info_get.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_event_flags_initialize.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_event_flags_initialize.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_event_flags_initialize.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_event_flags_performance_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_event_flags_performance_info_get.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_event_flags_performance_info_get.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_event_flags_performance_system_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_event_flags_performance_system_info_get.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_event_flags_performance_system_info_get.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_event_flags_set.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_event_flags_set.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_event_flags_set.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_event_flags_set_notify.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_event_flags_set_notify.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_event_flags_set_notify.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_initialize_high_level.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_initialize_high_level.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_initialize_high_level.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_initialize_kernel_enter.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_initialize_kernel_enter.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_initialize_kernel_enter.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_initialize_kernel_setup.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_initialize_kernel_setup.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_initialize_kernel_setup.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_misra.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_misra.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_misra.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_mutex_cleanup.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_mutex_cleanup.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_mutex_cleanup.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_mutex_create.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_mutex_create.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_mutex_create.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_mutex_delete.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_mutex_delete.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_mutex_delete.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_mutex_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_mutex_get.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_mutex_get.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_mutex_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_mutex_info_get.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_mutex_info_get.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_mutex_initialize.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_mutex_initialize.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_mutex_initialize.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_mutex_performance_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_mutex_performance_info_get.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_mutex_performance_info_get.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_mutex_performance_system_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_mutex_performance_system_info_get.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_mutex_performance_system_info_get.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_mutex_prioritize.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_mutex_prioritize.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_mutex_prioritize.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_mutex_priority_change.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_mutex_priority_change.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_mutex_priority_change.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_mutex_put.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_mutex_put.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_mutex_put.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_queue_cleanup.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_queue_cleanup.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_queue_cleanup.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_queue_create.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_queue_create.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_queue_create.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_queue_delete.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_queue_delete.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_queue_delete.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_queue_flush.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_queue_flush.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_queue_flush.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_queue_front_send.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_queue_front_send.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_queue_front_send.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_queue_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_queue_info_get.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_queue_info_get.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_queue_initialize.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_queue_initialize.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_queue_initialize.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_queue_performance_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_queue_performance_info_get.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_queue_performance_info_get.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_queue_performance_system_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_queue_performance_system_info_get.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_queue_performance_system_info_get.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_queue_prioritize.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_queue_prioritize.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_queue_prioritize.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_queue_receive.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_queue_receive.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_queue_receive.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_queue_send.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_queue_send.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_queue_send.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_queue_send_notify.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_queue_send_notify.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_queue_send_notify.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_semaphore_ceiling_put.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_semaphore_ceiling_put.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_semaphore_ceiling_put.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_semaphore_cleanup.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_semaphore_cleanup.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_semaphore_cleanup.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_semaphore_create.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_semaphore_create.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_semaphore_create.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_semaphore_delete.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_semaphore_delete.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_semaphore_delete.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_semaphore_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_semaphore_get.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_semaphore_get.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_semaphore_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_semaphore_info_get.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_semaphore_info_get.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_semaphore_initialize.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_semaphore_initialize.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_semaphore_initialize.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_semaphore_performance_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_semaphore_performance_info_get.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_semaphore_performance_info_get.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_semaphore_performance_system_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_semaphore_performance_system_info_get.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_semaphore_performance_system_info_get.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_semaphore_prioritize.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_semaphore_prioritize.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_semaphore_prioritize.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_semaphore_put.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_semaphore_put.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_semaphore_put.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_semaphore_put_notify.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_semaphore_put_notify.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_semaphore_put_notify.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_thread_create.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_create.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_create.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_thread_entry_exit_notify.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_entry_exit_notify.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_entry_exit_notify.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_thread_identify.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_identify.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_identify.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_thread_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_info_get.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_info_get.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_thread_initialize.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_initialize.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_initialize.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_thread_performance_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_performance_info_get.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_performance_info_get.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_thread_performance_system_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_performance_system_info_get.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_performance_system_info_get.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_thread_preemption_change.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_preemption_change.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_preemption_change.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_thread_priority_change.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_priority_change.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_priority_change.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_thread_relinquish.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_relinquish.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_relinquish.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_thread_resume.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_resume.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_resume.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_thread_shell_entry.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_shell_entry.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_shell_entry.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_thread_sleep.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_sleep.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_sleep.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_thread_stack_analyze.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_stack_analyze.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_stack_analyze.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_thread_stack_error_handler.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_stack_error_handler.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_stack_error_handler.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_thread_stack_error_notify.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_stack_error_notify.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_stack_error_notify.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_thread_suspend.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_suspend.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_suspend.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_thread_system_preempt_check.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_system_preempt_check.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_system_preempt_check.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_thread_system_resume.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_system_resume.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_system_resume.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_thread_system_suspend.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_system_suspend.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_system_suspend.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_thread_terminate.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_terminate.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_terminate.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_thread_time_slice.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_time_slice.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_time_slice.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_thread_time_slice_change.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_time_slice_change.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_time_slice_change.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_thread_timeout.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_timeout.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_timeout.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_thread_wait_abort.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_wait_abort.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_wait_abort.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_time_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_time_get.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_time_get.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_time_set.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_time_set.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_time_set.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_timer_activate.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_timer_activate.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_timer_activate.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_timer_change.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_timer_change.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_timer_change.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_timer_create.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_timer_create.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_timer_create.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_timer_deactivate.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_timer_deactivate.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_timer_deactivate.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_timer_delete.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_timer_delete.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_timer_delete.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_timer_expiration_process.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_timer_expiration_process.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_timer_expiration_process.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_timer_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_timer_info_get.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_timer_info_get.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_timer_initialize.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_timer_initialize.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_timer_initialize.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_timer_performance_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_timer_performance_info_get.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_timer_performance_info_get.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_timer_performance_system_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_timer_performance_system_info_get.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_timer_performance_system_info_get.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_timer_system_activate.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_timer_system_activate.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_timer_system_activate.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_timer_system_deactivate.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_timer_system_deactivate.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_timer_system_deactivate.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_timer_thread_entry.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_timer_thread_entry.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_timer_thread_entry.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_trace_buffer_full_notify.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_trace_buffer_full_notify.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_trace_buffer_full_notify.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_trace_disable.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_trace_disable.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_trace_disable.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_trace_enable.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_trace_enable.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_trace_enable.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_trace_event_filter.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_trace_event_filter.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_trace_event_filter.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_trace_event_unfilter.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_trace_event_unfilter.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_trace_event_unfilter.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_trace_initialize.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_trace_initialize.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_trace_initialize.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_trace_interrupt_control.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_trace_interrupt_control.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_trace_interrupt_control.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_trace_isr_enter_insert.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_trace_isr_enter_insert.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_trace_isr_enter_insert.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_trace_isr_exit_insert.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_trace_isr_exit_insert.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_trace_isr_exit_insert.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_trace_object_register.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_trace_object_register.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_trace_object_register.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_trace_object_unregister.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_trace_object_unregister.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_trace_object_unregister.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/tx_trace_user_event_insert.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_trace_user_event_insert.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_trace_user_event_insert.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_block_allocate.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_block_allocate.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_block_allocate.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_block_pool_create.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_block_pool_create.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_block_pool_create.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_block_pool_delete.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_block_pool_delete.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_block_pool_delete.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_block_pool_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_block_pool_info_get.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_block_pool_info_get.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_block_pool_prioritize.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_block_pool_prioritize.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_block_pool_prioritize.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_block_release.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_block_release.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_block_release.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_byte_allocate.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_byte_allocate.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_byte_allocate.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_byte_pool_create.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_byte_pool_create.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_byte_pool_create.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_byte_pool_delete.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_byte_pool_delete.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_byte_pool_delete.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_byte_pool_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_byte_pool_info_get.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_byte_pool_info_get.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_byte_pool_prioritize.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_byte_pool_prioritize.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_byte_pool_prioritize.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_byte_release.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_byte_release.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_byte_release.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_event_flags_create.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_event_flags_create.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_event_flags_create.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_event_flags_delete.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_event_flags_delete.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_event_flags_delete.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_event_flags_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_event_flags_get.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_event_flags_get.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_event_flags_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_event_flags_info_get.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_event_flags_info_get.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_event_flags_set.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_event_flags_set.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_event_flags_set.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_event_flags_set_notify.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_event_flags_set_notify.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_event_flags_set_notify.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_mutex_create.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_mutex_create.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_mutex_create.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_mutex_delete.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_mutex_delete.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_mutex_delete.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_mutex_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_mutex_get.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_mutex_get.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_mutex_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_mutex_info_get.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_mutex_info_get.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_mutex_prioritize.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_mutex_prioritize.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_mutex_prioritize.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_mutex_put.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_mutex_put.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_mutex_put.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_queue_create.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_queue_create.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_queue_create.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_queue_delete.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_queue_delete.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_queue_delete.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_queue_flush.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_queue_flush.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_queue_flush.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_queue_front_send.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_queue_front_send.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_queue_front_send.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_queue_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_queue_info_get.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_queue_info_get.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_queue_prioritize.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_queue_prioritize.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_queue_prioritize.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_queue_receive.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_queue_receive.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_queue_receive.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_queue_send.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_queue_send.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_queue_send.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_queue_send_notify.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_queue_send_notify.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_queue_send_notify.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_semaphore_ceiling_put.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_semaphore_ceiling_put.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_semaphore_ceiling_put.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_semaphore_create.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_semaphore_create.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_semaphore_create.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_semaphore_delete.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_semaphore_delete.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_semaphore_delete.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_semaphore_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_semaphore_get.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_semaphore_get.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_semaphore_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_semaphore_info_get.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_semaphore_info_get.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_semaphore_prioritize.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_semaphore_prioritize.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_semaphore_prioritize.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_semaphore_put.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_semaphore_put.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_semaphore_put.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_semaphore_put_notify.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_semaphore_put_notify.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_semaphore_put_notify.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_thread_create.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_thread_create.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_thread_create.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_thread_delete.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_thread_delete.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_thread_delete.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_thread_entry_exit_notify.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_thread_entry_exit_notify.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_thread_entry_exit_notify.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_thread_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_thread_info_get.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_thread_info_get.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_thread_preemption_change.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_thread_preemption_change.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_thread_preemption_change.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_thread_priority_change.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_thread_priority_change.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_thread_priority_change.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_thread_relinquish.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_thread_relinquish.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_thread_relinquish.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_thread_reset.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_thread_reset.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_thread_reset.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_thread_resume.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_thread_resume.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_thread_resume.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_thread_suspend.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_thread_suspend.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_thread_suspend.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_thread_terminate.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_thread_terminate.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_thread_terminate.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_thread_time_slice_change.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_thread_time_slice_change.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_thread_time_slice_change.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_thread_wait_abort.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_thread_wait_abort.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_thread_wait_abort.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_timer_activate.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_timer_activate.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_timer_activate.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_timer_change.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_timer_change.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_timer_change.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_timer_create.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_timer_create.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_timer_create.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_timer_deactivate.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_timer_deactivate.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_timer_deactivate.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_timer_delete.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_timer_delete.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_timer_delete.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +build CMakeFiles/threadx.dir/common/src/txe_timer_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_timer_info_get.c || cmake_object_order_depends_target_threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_timer_info_get.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/threadx.dir + OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + + +# ============================================================================= +# Link build statements for STATIC_LIBRARY target threadx + + +############################################# +# Link the static library libthreadx.a + +build libthreadx.a: C_STATIC_LIBRARY_LINKER__threadx_ CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_initialize_low_level.S.obj CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_context_restore.S.obj CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_context_save.S.obj CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_interrupt_control.S.obj CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_schedule.S.obj CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_stack_build.S.obj CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_system_return.S.obj CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_timer_interrupt.S.obj CMakeFiles/threadx.dir/common/src/tx_thread_delete.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_reset.c.obj CMakeFiles/threadx.dir/common/src/tx_block_allocate.c.obj CMakeFiles/threadx.dir/common/src/tx_block_pool_cleanup.c.obj CMakeFiles/threadx.dir/common/src/tx_block_pool_create.c.obj CMakeFiles/threadx.dir/common/src/tx_block_pool_delete.c.obj CMakeFiles/threadx.dir/common/src/tx_block_pool_info_get.c.obj CMakeFiles/threadx.dir/common/src/tx_block_pool_initialize.c.obj CMakeFiles/threadx.dir/common/src/tx_block_pool_performance_info_get.c.obj CMakeFiles/threadx.dir/common/src/tx_block_pool_performance_system_info_get.c.obj CMakeFiles/threadx.dir/common/src/tx_block_pool_prioritize.c.obj CMakeFiles/threadx.dir/common/src/tx_block_release.c.obj CMakeFiles/threadx.dir/common/src/tx_byte_allocate.c.obj CMakeFiles/threadx.dir/common/src/tx_byte_pool_cleanup.c.obj CMakeFiles/threadx.dir/common/src/tx_byte_pool_create.c.obj CMakeFiles/threadx.dir/common/src/tx_byte_pool_delete.c.obj CMakeFiles/threadx.dir/common/src/tx_byte_pool_info_get.c.obj CMakeFiles/threadx.dir/common/src/tx_byte_pool_initialize.c.obj CMakeFiles/threadx.dir/common/src/tx_byte_pool_performance_info_get.c.obj CMakeFiles/threadx.dir/common/src/tx_byte_pool_performance_system_info_get.c.obj CMakeFiles/threadx.dir/common/src/tx_byte_pool_prioritize.c.obj CMakeFiles/threadx.dir/common/src/tx_byte_pool_search.c.obj CMakeFiles/threadx.dir/common/src/tx_byte_release.c.obj CMakeFiles/threadx.dir/common/src/tx_event_flags_cleanup.c.obj CMakeFiles/threadx.dir/common/src/tx_event_flags_create.c.obj CMakeFiles/threadx.dir/common/src/tx_event_flags_delete.c.obj CMakeFiles/threadx.dir/common/src/tx_event_flags_get.c.obj CMakeFiles/threadx.dir/common/src/tx_event_flags_info_get.c.obj CMakeFiles/threadx.dir/common/src/tx_event_flags_initialize.c.obj CMakeFiles/threadx.dir/common/src/tx_event_flags_performance_info_get.c.obj CMakeFiles/threadx.dir/common/src/tx_event_flags_performance_system_info_get.c.obj CMakeFiles/threadx.dir/common/src/tx_event_flags_set.c.obj CMakeFiles/threadx.dir/common/src/tx_event_flags_set_notify.c.obj CMakeFiles/threadx.dir/common/src/tx_initialize_high_level.c.obj CMakeFiles/threadx.dir/common/src/tx_initialize_kernel_enter.c.obj CMakeFiles/threadx.dir/common/src/tx_initialize_kernel_setup.c.obj CMakeFiles/threadx.dir/common/src/tx_misra.c.obj CMakeFiles/threadx.dir/common/src/tx_mutex_cleanup.c.obj CMakeFiles/threadx.dir/common/src/tx_mutex_create.c.obj CMakeFiles/threadx.dir/common/src/tx_mutex_delete.c.obj CMakeFiles/threadx.dir/common/src/tx_mutex_get.c.obj CMakeFiles/threadx.dir/common/src/tx_mutex_info_get.c.obj CMakeFiles/threadx.dir/common/src/tx_mutex_initialize.c.obj CMakeFiles/threadx.dir/common/src/tx_mutex_performance_info_get.c.obj CMakeFiles/threadx.dir/common/src/tx_mutex_performance_system_info_get.c.obj CMakeFiles/threadx.dir/common/src/tx_mutex_prioritize.c.obj CMakeFiles/threadx.dir/common/src/tx_mutex_priority_change.c.obj CMakeFiles/threadx.dir/common/src/tx_mutex_put.c.obj CMakeFiles/threadx.dir/common/src/tx_queue_cleanup.c.obj CMakeFiles/threadx.dir/common/src/tx_queue_create.c.obj CMakeFiles/threadx.dir/common/src/tx_queue_delete.c.obj CMakeFiles/threadx.dir/common/src/tx_queue_flush.c.obj CMakeFiles/threadx.dir/common/src/tx_queue_front_send.c.obj CMakeFiles/threadx.dir/common/src/tx_queue_info_get.c.obj CMakeFiles/threadx.dir/common/src/tx_queue_initialize.c.obj CMakeFiles/threadx.dir/common/src/tx_queue_performance_info_get.c.obj CMakeFiles/threadx.dir/common/src/tx_queue_performance_system_info_get.c.obj CMakeFiles/threadx.dir/common/src/tx_queue_prioritize.c.obj CMakeFiles/threadx.dir/common/src/tx_queue_receive.c.obj CMakeFiles/threadx.dir/common/src/tx_queue_send.c.obj CMakeFiles/threadx.dir/common/src/tx_queue_send_notify.c.obj CMakeFiles/threadx.dir/common/src/tx_semaphore_ceiling_put.c.obj CMakeFiles/threadx.dir/common/src/tx_semaphore_cleanup.c.obj CMakeFiles/threadx.dir/common/src/tx_semaphore_create.c.obj CMakeFiles/threadx.dir/common/src/tx_semaphore_delete.c.obj CMakeFiles/threadx.dir/common/src/tx_semaphore_get.c.obj CMakeFiles/threadx.dir/common/src/tx_semaphore_info_get.c.obj CMakeFiles/threadx.dir/common/src/tx_semaphore_initialize.c.obj CMakeFiles/threadx.dir/common/src/tx_semaphore_performance_info_get.c.obj CMakeFiles/threadx.dir/common/src/tx_semaphore_performance_system_info_get.c.obj CMakeFiles/threadx.dir/common/src/tx_semaphore_prioritize.c.obj CMakeFiles/threadx.dir/common/src/tx_semaphore_put.c.obj CMakeFiles/threadx.dir/common/src/tx_semaphore_put_notify.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_create.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_entry_exit_notify.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_identify.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_info_get.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_initialize.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_performance_info_get.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_performance_system_info_get.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_preemption_change.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_priority_change.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_relinquish.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_resume.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_shell_entry.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_sleep.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_stack_analyze.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_stack_error_handler.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_stack_error_notify.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_suspend.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_system_preempt_check.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_system_resume.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_system_suspend.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_terminate.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_time_slice.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_time_slice_change.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_timeout.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_wait_abort.c.obj CMakeFiles/threadx.dir/common/src/tx_time_get.c.obj CMakeFiles/threadx.dir/common/src/tx_time_set.c.obj CMakeFiles/threadx.dir/common/src/tx_timer_activate.c.obj CMakeFiles/threadx.dir/common/src/tx_timer_change.c.obj CMakeFiles/threadx.dir/common/src/tx_timer_create.c.obj CMakeFiles/threadx.dir/common/src/tx_timer_deactivate.c.obj CMakeFiles/threadx.dir/common/src/tx_timer_delete.c.obj CMakeFiles/threadx.dir/common/src/tx_timer_expiration_process.c.obj CMakeFiles/threadx.dir/common/src/tx_timer_info_get.c.obj CMakeFiles/threadx.dir/common/src/tx_timer_initialize.c.obj CMakeFiles/threadx.dir/common/src/tx_timer_performance_info_get.c.obj CMakeFiles/threadx.dir/common/src/tx_timer_performance_system_info_get.c.obj CMakeFiles/threadx.dir/common/src/tx_timer_system_activate.c.obj CMakeFiles/threadx.dir/common/src/tx_timer_system_deactivate.c.obj CMakeFiles/threadx.dir/common/src/tx_timer_thread_entry.c.obj CMakeFiles/threadx.dir/common/src/tx_trace_buffer_full_notify.c.obj CMakeFiles/threadx.dir/common/src/tx_trace_disable.c.obj CMakeFiles/threadx.dir/common/src/tx_trace_enable.c.obj CMakeFiles/threadx.dir/common/src/tx_trace_event_filter.c.obj CMakeFiles/threadx.dir/common/src/tx_trace_event_unfilter.c.obj CMakeFiles/threadx.dir/common/src/tx_trace_initialize.c.obj CMakeFiles/threadx.dir/common/src/tx_trace_interrupt_control.c.obj CMakeFiles/threadx.dir/common/src/tx_trace_isr_enter_insert.c.obj CMakeFiles/threadx.dir/common/src/tx_trace_isr_exit_insert.c.obj CMakeFiles/threadx.dir/common/src/tx_trace_object_register.c.obj CMakeFiles/threadx.dir/common/src/tx_trace_object_unregister.c.obj CMakeFiles/threadx.dir/common/src/tx_trace_user_event_insert.c.obj CMakeFiles/threadx.dir/common/src/txe_block_allocate.c.obj CMakeFiles/threadx.dir/common/src/txe_block_pool_create.c.obj CMakeFiles/threadx.dir/common/src/txe_block_pool_delete.c.obj CMakeFiles/threadx.dir/common/src/txe_block_pool_info_get.c.obj CMakeFiles/threadx.dir/common/src/txe_block_pool_prioritize.c.obj CMakeFiles/threadx.dir/common/src/txe_block_release.c.obj CMakeFiles/threadx.dir/common/src/txe_byte_allocate.c.obj CMakeFiles/threadx.dir/common/src/txe_byte_pool_create.c.obj CMakeFiles/threadx.dir/common/src/txe_byte_pool_delete.c.obj CMakeFiles/threadx.dir/common/src/txe_byte_pool_info_get.c.obj CMakeFiles/threadx.dir/common/src/txe_byte_pool_prioritize.c.obj CMakeFiles/threadx.dir/common/src/txe_byte_release.c.obj CMakeFiles/threadx.dir/common/src/txe_event_flags_create.c.obj CMakeFiles/threadx.dir/common/src/txe_event_flags_delete.c.obj CMakeFiles/threadx.dir/common/src/txe_event_flags_get.c.obj CMakeFiles/threadx.dir/common/src/txe_event_flags_info_get.c.obj CMakeFiles/threadx.dir/common/src/txe_event_flags_set.c.obj CMakeFiles/threadx.dir/common/src/txe_event_flags_set_notify.c.obj CMakeFiles/threadx.dir/common/src/txe_mutex_create.c.obj CMakeFiles/threadx.dir/common/src/txe_mutex_delete.c.obj CMakeFiles/threadx.dir/common/src/txe_mutex_get.c.obj CMakeFiles/threadx.dir/common/src/txe_mutex_info_get.c.obj CMakeFiles/threadx.dir/common/src/txe_mutex_prioritize.c.obj CMakeFiles/threadx.dir/common/src/txe_mutex_put.c.obj CMakeFiles/threadx.dir/common/src/txe_queue_create.c.obj CMakeFiles/threadx.dir/common/src/txe_queue_delete.c.obj CMakeFiles/threadx.dir/common/src/txe_queue_flush.c.obj CMakeFiles/threadx.dir/common/src/txe_queue_front_send.c.obj CMakeFiles/threadx.dir/common/src/txe_queue_info_get.c.obj CMakeFiles/threadx.dir/common/src/txe_queue_prioritize.c.obj CMakeFiles/threadx.dir/common/src/txe_queue_receive.c.obj CMakeFiles/threadx.dir/common/src/txe_queue_send.c.obj CMakeFiles/threadx.dir/common/src/txe_queue_send_notify.c.obj CMakeFiles/threadx.dir/common/src/txe_semaphore_ceiling_put.c.obj CMakeFiles/threadx.dir/common/src/txe_semaphore_create.c.obj CMakeFiles/threadx.dir/common/src/txe_semaphore_delete.c.obj CMakeFiles/threadx.dir/common/src/txe_semaphore_get.c.obj CMakeFiles/threadx.dir/common/src/txe_semaphore_info_get.c.obj CMakeFiles/threadx.dir/common/src/txe_semaphore_prioritize.c.obj CMakeFiles/threadx.dir/common/src/txe_semaphore_put.c.obj CMakeFiles/threadx.dir/common/src/txe_semaphore_put_notify.c.obj CMakeFiles/threadx.dir/common/src/txe_thread_create.c.obj CMakeFiles/threadx.dir/common/src/txe_thread_delete.c.obj CMakeFiles/threadx.dir/common/src/txe_thread_entry_exit_notify.c.obj CMakeFiles/threadx.dir/common/src/txe_thread_info_get.c.obj CMakeFiles/threadx.dir/common/src/txe_thread_preemption_change.c.obj CMakeFiles/threadx.dir/common/src/txe_thread_priority_change.c.obj CMakeFiles/threadx.dir/common/src/txe_thread_relinquish.c.obj CMakeFiles/threadx.dir/common/src/txe_thread_reset.c.obj CMakeFiles/threadx.dir/common/src/txe_thread_resume.c.obj CMakeFiles/threadx.dir/common/src/txe_thread_suspend.c.obj CMakeFiles/threadx.dir/common/src/txe_thread_terminate.c.obj CMakeFiles/threadx.dir/common/src/txe_thread_time_slice_change.c.obj CMakeFiles/threadx.dir/common/src/txe_thread_wait_abort.c.obj CMakeFiles/threadx.dir/common/src/txe_timer_activate.c.obj CMakeFiles/threadx.dir/common/src/txe_timer_change.c.obj CMakeFiles/threadx.dir/common/src/txe_timer_create.c.obj CMakeFiles/threadx.dir/common/src/txe_timer_deactivate.c.obj CMakeFiles/threadx.dir/common/src/txe_timer_delete.c.obj CMakeFiles/threadx.dir/common/src/txe_timer_info_get.c.obj + LANGUAGE_COMPILE_FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + OBJECT_DIR = CMakeFiles/threadx.dir + POST_BUILD = : + PRE_LINK = : + TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb + TARGET_FILE = libthreadx.a + TARGET_PDB = libthreadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir + +# ============================================================================= +# Object build statements for STATIC_LIBRARY target freertos-threadx + + +############################################# +# Order-only phony target for freertos-threadx + +build cmake_object_order_depends_target_freertos-threadx: phony || cmake_object_order_depends_target_threadx + +build CMakeFiles/freertos-threadx.dir/utility/rtos_compatibility_layers/FreeRTOS/tx_freertos.c.obj: C_COMPILER__freertos-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/FreeRTOS/tx_freertos.c || cmake_object_order_depends_target_freertos-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = CMakeFiles/freertos-threadx.dir/utility/rtos_compatibility_layers/FreeRTOS/tx_freertos.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/FreeRTOS -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = CMakeFiles/freertos-threadx.dir + OBJECT_FILE_DIR = CMakeFiles/freertos-threadx.dir/utility/rtos_compatibility_layers/FreeRTOS + TARGET_COMPILE_PDB = CMakeFiles/freertos-threadx.dir/freertos-threadx.pdb + TARGET_PDB = libfreertos-threadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/freertos-threadx.dir + + +# ============================================================================= +# Link build statements for STATIC_LIBRARY target freertos-threadx + + +############################################# +# Link the static library libfreertos-threadx.a + +build libfreertos-threadx.a: C_STATIC_LIBRARY_LINKER__freertos-threadx_ CMakeFiles/freertos-threadx.dir/utility/rtos_compatibility_layers/FreeRTOS/tx_freertos.c.obj || libthreadx.a + LANGUAGE_COMPILE_FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + OBJECT_DIR = CMakeFiles/freertos-threadx.dir + POST_BUILD = : + PRE_LINK = : + TARGET_COMPILE_PDB = CMakeFiles/freertos-threadx.dir/freertos-threadx.pdb + TARGET_FILE = libfreertos-threadx.a + TARGET_PDB = libfreertos-threadx.pdb + TARGET_SUPPORT_DIR = CMakeFiles/freertos-threadx.dir + + +############################################# +# Utility command for package + +build CMakeFiles/package.util: CUSTOM_COMMAND all + COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64 && /usr/bin/cpack --config ./CPackConfig.cmake + DESC = Run CPack packaging tool... + pool = console + restat = 1 + +build package: phony CMakeFiles/package.util + + +############################################# +# Utility command for package_source + +build CMakeFiles/package_source.util: CUSTOM_COMMAND + COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64 && /usr/bin/cpack --config ./CPackSourceConfig.cmake + DESC = Run CPack packaging tool for source... + pool = console + restat = 1 + +build package_source: phony CMakeFiles/package_source.util + + +############################################# +# Utility command for test + +build CMakeFiles/test.util: CUSTOM_COMMAND + COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64 && /usr/bin/ctest + DESC = Running tests... + pool = console + restat = 1 + +build test: phony CMakeFiles/test.util + + +############################################# +# Utility command for edit_cache + +build CMakeFiles/edit_cache.util: CUSTOM_COMMAND + COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64 && /usr/bin/cmake -E echo No\ interactive\ CMake\ dialog\ available. + DESC = No interactive CMake dialog available... + restat = 1 + +build edit_cache: phony CMakeFiles/edit_cache.util + + +############################################# +# Utility command for rebuild_cache + +build CMakeFiles/rebuild_cache.util: CUSTOM_COMMAND + COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64 && /usr/bin/cmake --regenerate-during-build -S/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698 -B/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64 + DESC = Running CMake to regenerate build system... + pool = console + restat = 1 + +build rebuild_cache: phony CMakeFiles/rebuild_cache.util + +# ============================================================================= +# Write statements declared in CMakeLists.txt: +# /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/CMakeLists.txt +# ============================================================================= + + +############################################# +# Utility command for package + +build ports/risc-v64/gnu/CMakeFiles/package.util: CUSTOM_COMMAND ports/risc-v64/gnu/all + COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64 && /usr/bin/cpack --config ./CPackConfig.cmake + DESC = Run CPack packaging tool... + pool = console + restat = 1 + +build ports/risc-v64/gnu/package: phony ports/risc-v64/gnu/CMakeFiles/package.util + + +############################################# +# Utility command for package_source + +build ports/risc-v64/gnu/CMakeFiles/package_source.util: CUSTOM_COMMAND + COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64 && /usr/bin/cpack --config ./CPackSourceConfig.cmake + DESC = Run CPack packaging tool for source... + pool = console + restat = 1 + +build ports/risc-v64/gnu/package_source: phony ports/risc-v64/gnu/CMakeFiles/package_source.util + + +############################################# +# Utility command for test + +build ports/risc-v64/gnu/CMakeFiles/test.util: CUSTOM_COMMAND + COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/ports/risc-v64/gnu && /usr/bin/ctest + DESC = Running tests... + pool = console + restat = 1 + +build ports/risc-v64/gnu/test: phony ports/risc-v64/gnu/CMakeFiles/test.util + + +############################################# +# Utility command for edit_cache + +build ports/risc-v64/gnu/CMakeFiles/edit_cache.util: CUSTOM_COMMAND + COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/ports/risc-v64/gnu && /usr/bin/cmake -E echo No\ interactive\ CMake\ dialog\ available. + DESC = No interactive CMake dialog available... + restat = 1 + +build ports/risc-v64/gnu/edit_cache: phony ports/risc-v64/gnu/CMakeFiles/edit_cache.util + + +############################################# +# Utility command for rebuild_cache + +build ports/risc-v64/gnu/CMakeFiles/rebuild_cache.util: CUSTOM_COMMAND + COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/ports/risc-v64/gnu && /usr/bin/cmake --regenerate-during-build -S/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698 -B/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64 + DESC = Running CMake to regenerate build system... + pool = console + restat = 1 + +build ports/risc-v64/gnu/rebuild_cache: phony ports/risc-v64/gnu/CMakeFiles/rebuild_cache.util + +# ============================================================================= +# Write statements declared in CMakeLists.txt: +# /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/CMakeLists.txt +# ============================================================================= + +# ============================================================================= +# Object build statements for EXECUTABLE target kernel.elf + + +############################################# +# Order-only phony target for kernel.elf + +build cmake_object_order_depends_target_kernel.elf: phony || cmake_object_order_depends_target_threadx + +build ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/demo_threadx.c.obj: C_COMPILER__kernel.2eelf_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/example_build/qemu_virt/demo_threadx.c || cmake_object_order_depends_target_kernel.elf + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/demo_threadx.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/example_build/qemu_virt -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir + OBJECT_FILE_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir + TARGET_COMPILE_PDB = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/ + TARGET_PDB = ports/risc-v64/gnu/example_build/qemu_virt/kernel.elf.pdb + TARGET_SUPPORT_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir + +build ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/entry.S.obj: ASM_COMPILER__kernel.2eelf_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/example_build/qemu_virt/entry.S || cmake_object_order_depends_target_kernel.elf + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/entry.S.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany -D__ASSEMBLER__ + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/example_build/qemu_virt -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir + OBJECT_FILE_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir + TARGET_COMPILE_PDB = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/ + TARGET_PDB = ports/risc-v64/gnu/example_build/qemu_virt/kernel.elf.pdb + TARGET_SUPPORT_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir + +build ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/uart.c.obj: C_COMPILER__kernel.2eelf_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/example_build/qemu_virt/uart.c || cmake_object_order_depends_target_kernel.elf + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/uart.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/example_build/qemu_virt -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir + OBJECT_FILE_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir + TARGET_COMPILE_PDB = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/ + TARGET_PDB = ports/risc-v64/gnu/example_build/qemu_virt/kernel.elf.pdb + TARGET_SUPPORT_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir + +build ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/plic.c.obj: C_COMPILER__kernel.2eelf_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/example_build/qemu_virt/plic.c || cmake_object_order_depends_target_kernel.elf + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/plic.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/example_build/qemu_virt -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir + OBJECT_FILE_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir + TARGET_COMPILE_PDB = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/ + TARGET_PDB = ports/risc-v64/gnu/example_build/qemu_virt/kernel.elf.pdb + TARGET_SUPPORT_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir + +build ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/hwtimer.c.obj: C_COMPILER__kernel.2eelf_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/example_build/qemu_virt/hwtimer.c || cmake_object_order_depends_target_kernel.elf + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/hwtimer.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/example_build/qemu_virt -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir + OBJECT_FILE_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir + TARGET_COMPILE_PDB = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/ + TARGET_PDB = ports/risc-v64/gnu/example_build/qemu_virt/kernel.elf.pdb + TARGET_SUPPORT_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir + +build ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/trap.c.obj: C_COMPILER__kernel.2eelf_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/example_build/qemu_virt/trap.c || cmake_object_order_depends_target_kernel.elf + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/trap.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/example_build/qemu_virt -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir + OBJECT_FILE_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir + TARGET_COMPILE_PDB = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/ + TARGET_PDB = ports/risc-v64/gnu/example_build/qemu_virt/kernel.elf.pdb + TARGET_SUPPORT_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir + +build ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/board.c.obj: C_COMPILER__kernel.2eelf_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/example_build/qemu_virt/board.c || cmake_object_order_depends_target_kernel.elf + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/board.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/example_build/qemu_virt -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir + OBJECT_FILE_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir + TARGET_COMPILE_PDB = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/ + TARGET_PDB = ports/risc-v64/gnu/example_build/qemu_virt/kernel.elf.pdb + TARGET_SUPPORT_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir + +build ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/tx_initialize_low_level.S.obj: ASM_COMPILER__kernel.2eelf_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/example_build/qemu_virt/tx_initialize_low_level.S || cmake_object_order_depends_target_kernel.elf + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/tx_initialize_low_level.S.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany -D__ASSEMBLER__ + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/example_build/qemu_virt -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir + OBJECT_FILE_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir + TARGET_COMPILE_PDB = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/ + TARGET_PDB = ports/risc-v64/gnu/example_build/qemu_virt/kernel.elf.pdb + TARGET_SUPPORT_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir + + +# ============================================================================= +# Link build statements for EXECUTABLE target kernel.elf + + +############################################# +# Link the executable ports/risc-v64/gnu/example_build/qemu_virt/kernel.elf + +build ports/risc-v64/gnu/example_build/qemu_virt/kernel.elf: C_EXECUTABLE_LINKER__kernel.2eelf_ ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/demo_threadx.c.obj ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/entry.S.obj ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/uart.c.obj ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/plic.c.obj ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/hwtimer.c.obj ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/trap.c.obj ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/board.c.obj ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/tx_initialize_low_level.S.obj | libthreadx.a || libthreadx.a + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + LINK_FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany -T/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/example_build/qemu_virt/link.lds -nostartfiles -Wl,-Map=kernel.map + LINK_LIBRARIES = libthreadx.a -lgcc + OBJECT_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir + POST_BUILD = : + PRE_LINK = : + TARGET_COMPILE_PDB = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/ + TARGET_FILE = ports/risc-v64/gnu/example_build/qemu_virt/kernel.elf + TARGET_PDB = ports/risc-v64/gnu/example_build/qemu_virt/kernel.elf.pdb + TARGET_SUPPORT_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir + + +############################################# +# Utility command for check-functional-riscv64 + +build ports/risc-v64/gnu/example_build/qemu_virt/check-functional-riscv64: phony ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/check-functional-riscv64 ports/risc-v64/gnu/example_build/qemu_virt/kernel.elf + + +############################################# +# Utility command for package + +build ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/package.util: CUSTOM_COMMAND ports/risc-v64/gnu/example_build/qemu_virt/all + COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64 && /usr/bin/cpack --config ./CPackConfig.cmake + DESC = Run CPack packaging tool... + pool = console + restat = 1 + +build ports/risc-v64/gnu/example_build/qemu_virt/package: phony ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/package.util + + +############################################# +# Utility command for package_source + +build ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/package_source.util: CUSTOM_COMMAND + COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64 && /usr/bin/cpack --config ./CPackSourceConfig.cmake + DESC = Run CPack packaging tool for source... + pool = console + restat = 1 + +build ports/risc-v64/gnu/example_build/qemu_virt/package_source: phony ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/package_source.util + + +############################################# +# Utility command for test + +build ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/test.util: CUSTOM_COMMAND + COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/ports/risc-v64/gnu/example_build/qemu_virt && /usr/bin/ctest + DESC = Running tests... + pool = console + restat = 1 + +build ports/risc-v64/gnu/example_build/qemu_virt/test: phony ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/test.util + + +############################################# +# Utility command for edit_cache + +build ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/edit_cache.util: CUSTOM_COMMAND + COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/ports/risc-v64/gnu/example_build/qemu_virt && /usr/bin/cmake -E echo No\ interactive\ CMake\ dialog\ available. + DESC = No interactive CMake dialog available... + restat = 1 + +build ports/risc-v64/gnu/example_build/qemu_virt/edit_cache: phony ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/edit_cache.util + + +############################################# +# Utility command for rebuild_cache + +build ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/rebuild_cache.util: CUSTOM_COMMAND + COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/ports/risc-v64/gnu/example_build/qemu_virt && /usr/bin/cmake --regenerate-during-build -S/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698 -B/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64 + DESC = Running CMake to regenerate build system... + pool = console + restat = 1 + +build ports/risc-v64/gnu/example_build/qemu_virt/rebuild_cache: phony ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/rebuild_cache.util + + +############################################# +# Custom command for ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/check-functional-riscv64 + +build ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/check-functional-riscv64 | ${cmake_ninja_workdir}ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/check-functional-riscv64: CUSTOM_COMMAND ports/risc-v64/gnu/example_build/qemu_virt/kernel.elf || libthreadx.a ports/risc-v64/gnu/example_build/qemu_virt/kernel.elf + COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/ports/risc-v64/gnu/example_build/qemu_virt && /usr/bin/python3.12 /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/example_build/qemu_virt/test/threadx_test_tx_gnu_riscv64_qemu.py --elf /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/ports/risc-v64/gnu/example_build/qemu_virt/kernel.elf --qemu /usr/bin/qemu-system-riscv64 --gdb /opt/riscv/bin/riscv64-unknown-elf-gdb + DESC = Running RISC-V64 QEMU/GDB functional test runner... + +# ============================================================================= +# Write statements declared in CMakeLists.txt: +# /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/CMakeLists.txt +# ============================================================================= + + +############################################# +# Utility command for package + +build common/CMakeFiles/package.util: CUSTOM_COMMAND common/all + COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64 && /usr/bin/cpack --config ./CPackConfig.cmake + DESC = Run CPack packaging tool... + pool = console + restat = 1 + +build common/package: phony common/CMakeFiles/package.util + + +############################################# +# Utility command for package_source + +build common/CMakeFiles/package_source.util: CUSTOM_COMMAND + COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64 && /usr/bin/cpack --config ./CPackSourceConfig.cmake + DESC = Run CPack packaging tool for source... + pool = console + restat = 1 + +build common/package_source: phony common/CMakeFiles/package_source.util + + +############################################# +# Utility command for test + +build common/CMakeFiles/test.util: CUSTOM_COMMAND + COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/common && /usr/bin/ctest + DESC = Running tests... + pool = console + restat = 1 + +build common/test: phony common/CMakeFiles/test.util + + +############################################# +# Utility command for edit_cache + +build common/CMakeFiles/edit_cache.util: CUSTOM_COMMAND + COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/common && /usr/bin/cmake -E echo No\ interactive\ CMake\ dialog\ available. + DESC = No interactive CMake dialog available... + restat = 1 + +build common/edit_cache: phony common/CMakeFiles/edit_cache.util + + +############################################# +# Utility command for rebuild_cache + +build common/CMakeFiles/rebuild_cache.util: CUSTOM_COMMAND + COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/common && /usr/bin/cmake --regenerate-during-build -S/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698 -B/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64 + DESC = Running CMake to regenerate build system... + pool = console + restat = 1 + +build common/rebuild_cache: phony common/CMakeFiles/rebuild_cache.util + +# ============================================================================= +# Write statements declared in CMakeLists.txt: +# /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/CMakeLists.txt +# ============================================================================= + +# ============================================================================= +# Object build statements for STATIC_LIBRARY target posix-threadx + + +############################################# +# Order-only phony target for posix-threadx + +build cmake_object_order_depends_target_posix-threadx: phony || cmake_object_order_depends_target_threadx + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_abs_time_to_rel_ticks.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_abs_time_to_rel_ticks.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_abs_time_to_rel_ticks.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_clock_getres.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_clock_getres.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_clock_getres.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_clock_gettime.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_clock_gettime.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_clock_gettime.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_clock_settime.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_clock_settime.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_clock_settime.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_cond_broadcast.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_cond_broadcast.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_cond_broadcast.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_cond_destroy.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_cond_destroy.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_cond_destroy.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_cond_init.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_cond_init.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_cond_init.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_cond_signal.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_cond_signal.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_cond_signal.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_cond_timedwait.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_cond_timedwait.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_cond_timedwait.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_cond_wait.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_cond_wait.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_cond_wait.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_error.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_error.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_error.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_in_thread_context.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_in_thread_context.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_in_thread_context.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_internal_signal_dispatch.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_internal_signal_dispatch.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_internal_signal_dispatch.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_memory_allocate.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_memory_allocate.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_memory_allocate.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_memory_release.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_memory_release.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_memory_release.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_arrange_msg.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mq_arrange_msg.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_arrange_msg.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_attr_init.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mq_attr_init.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_attr_init.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_close.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mq_close.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_close.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_create.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mq_create.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_create.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_find_queue.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mq_find_queue.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_find_queue.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_get_new_queue.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mq_get_new_queue.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_get_new_queue.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_get_queue_desc.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mq_get_queue_desc.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_get_queue_desc.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_open.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mq_open.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_open.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_priority_search.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mq_priority_search.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_priority_search.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_putback_queue.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mq_putback_queue.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_putback_queue.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_queue_delete.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mq_queue_delete.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_queue_delete.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_queue_init.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mq_queue_init.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_queue_init.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_receive.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mq_receive.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_receive.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_reset_queue.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mq_reset_queue.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_reset_queue.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_send.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mq_send.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_send.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_unlink.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mq_unlink.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_unlink.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_attr_destroy.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mx_attr_destroy.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_attr_destroy.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_attr_getprotocol.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mx_attr_getprotocol.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_attr_getprotocol.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_attr_getpshared.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mx_attr_getpshared.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_attr_getpshared.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_attr_gettype.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mx_attr_gettype.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_attr_gettype.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_attr_initi.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mx_attr_initi.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_attr_initi.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_attr_setprotocol.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mx_attr_setprotocol.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_attr_setprotocol.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_attr_setpshared.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mx_attr_setpshared.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_attr_setpshared.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_attr_settype.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mx_attr_settype.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_attr_settype.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_destroy.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mx_destroy.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_destroy.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_init.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mx_init.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_init.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_lock.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mx_lock.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_lock.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_set_default_mutexattr.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mx_set_default_mutexattr.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_set_default_mutexattr.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_timedlock.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mx_timedlock.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_timedlock.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_trylock.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mx_trylock.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_trylock.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_unlock.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mx_unlock.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_unlock.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_nanosleep.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_nanosleep.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_nanosleep.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_destroy.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_attr_destroy.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_destroy.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_getdetachstate.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_attr_getdetachstate.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_getdetachstate.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_getinheritsched.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_attr_getinheritsched.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_getinheritsched.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_getschedparam.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_attr_getschedparam.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_getschedparam.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_getschedpolicy.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_attr_getschedpolicy.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_getschedpolicy.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_getstack.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_attr_getstack.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_getstack.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_getstackaddr.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_attr_getstackaddr.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_getstackaddr.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_getstacksize.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_attr_getstacksize.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_getstacksize.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_init.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_attr_init.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_init.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_setdetachstate.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_attr_setdetachstate.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_setdetachstate.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_setinheritsched.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_attr_setinheritsched.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_setinheritsched.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_setschedparam.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_attr_setschedparam.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_setschedparam.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_setschedpolicyl.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_attr_setschedpolicyl.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_setschedpolicyl.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_setstack.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_attr_setstack.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_setstack.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_setstackaddr.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_attr_setstackaddr.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_setstackaddr.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_setstacksize.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_attr_setstacksize.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_setstacksize.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_cancel.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_cancel.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_cancel.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_create.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_create.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_create.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_detach.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_detach.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_detach.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_equal.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_equal.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_equal.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_exit.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_exit.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_exit.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_getcanceltype.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_getcanceltype.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_getcanceltype.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_getschedparam.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_getschedparam.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_getschedparam.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_init.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_init.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_init.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_join.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_join.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_join.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_kill.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_kill.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_kill.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_once.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_once.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_once.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_self.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_self.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_self.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_set_default_pthread_attr.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_set_default_pthread_attr.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_set_default_pthread_attr.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_setcancelstate.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_setcancelstate.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_setcancelstate.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_setcanceltype.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_setcanceltype.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_setcanceltype.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_setschedparam.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_setschedparam.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_setschedparam.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_sigmask.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_sigmask.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_sigmask.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_testcancel.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_testcancel.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_testcancel.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_yield.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_yield.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_yield.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_px_initialize.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_px_initialize.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_px_initialize.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sched_get_prio.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_sched_get_prio.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sched_get_prio.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sched_yield.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_sched_yield.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sched_yield.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_close.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_sem_close.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_close.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_destroy.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_sem_destroy.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_destroy.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_find_sem.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_sem_find_sem.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_find_sem.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_get_new_sem.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_sem_get_new_sem.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_get_new_sem.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_getvalue.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_sem_getvalue.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_getvalue.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_init.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_sem_init.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_init.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_open.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_sem_open.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_open.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_post.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_sem_post.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_post.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_reset.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_sem_reset.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_reset.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_set_sem_name.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_sem_set_sem_name.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_set_sem_name.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_trywait.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_sem_trywait.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_trywait.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_unlink.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_sem_unlink.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_unlink.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_wait.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_sem_wait.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_wait.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sig_addset.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_sig_addset.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sig_addset.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sig_delset.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_sig_delset.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sig_delset.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sig_emptyset.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_sig_emptyset.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sig_emptyset.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sig_fillset.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_sig_fillset.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sig_fillset.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sig_signal.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_sig_signal.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sig_signal.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sig_wait.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_sig_wait.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sig_wait.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sleep.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_sleep.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sleep.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + +build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_system_manager.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_system_manager.c || cmake_object_order_depends_target_posix-threadx + DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE + DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_system_manager.c.obj.d + FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + + +# ============================================================================= +# Link build statements for STATIC_LIBRARY target posix-threadx + + +############################################# +# Link the static library utility/rtos_compatibility_layers/posix/libposix-threadx.a + +build utility/rtos_compatibility_layers/posix/libposix-threadx.a: C_STATIC_LIBRARY_LINKER__posix-threadx_ utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_abs_time_to_rel_ticks.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_clock_getres.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_clock_gettime.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_clock_settime.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_cond_broadcast.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_cond_destroy.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_cond_init.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_cond_signal.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_cond_timedwait.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_cond_wait.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_error.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_in_thread_context.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_internal_signal_dispatch.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_memory_allocate.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_memory_release.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_arrange_msg.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_attr_init.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_close.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_create.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_find_queue.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_get_new_queue.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_get_queue_desc.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_open.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_priority_search.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_putback_queue.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_queue_delete.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_queue_init.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_receive.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_reset_queue.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_send.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_unlink.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_attr_destroy.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_attr_getprotocol.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_attr_getpshared.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_attr_gettype.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_attr_initi.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_attr_setprotocol.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_attr_setpshared.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_attr_settype.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_destroy.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_init.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_lock.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_set_default_mutexattr.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_timedlock.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_trylock.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_unlock.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_nanosleep.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_destroy.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_getdetachstate.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_getinheritsched.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_getschedparam.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_getschedpolicy.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_getstack.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_getstackaddr.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_getstacksize.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_init.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_setdetachstate.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_setinheritsched.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_setschedparam.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_setschedpolicyl.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_setstack.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_setstackaddr.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_setstacksize.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_cancel.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_create.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_detach.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_equal.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_exit.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_getcanceltype.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_getschedparam.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_init.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_join.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_kill.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_once.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_self.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_set_default_pthread_attr.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_setcancelstate.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_setcanceltype.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_setschedparam.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_sigmask.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_testcancel.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_yield.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_px_initialize.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sched_get_prio.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sched_yield.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_close.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_destroy.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_find_sem.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_get_new_sem.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_getvalue.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_init.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_open.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_post.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_reset.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_set_sem_name.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_trywait.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_unlink.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_wait.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sig_addset.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sig_delset.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sig_emptyset.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sig_fillset.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sig_signal.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sig_wait.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sleep.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_system_manager.c.obj || libthreadx.a + LANGUAGE_COMPILE_FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany + OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + POST_BUILD = : + PRE_LINK = : + TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb + TARGET_FILE = utility/rtos_compatibility_layers/posix/libposix-threadx.a + TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb + TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir + + +############################################# +# Utility command for package + +build utility/rtos_compatibility_layers/posix/CMakeFiles/package.util: CUSTOM_COMMAND utility/rtos_compatibility_layers/posix/all + COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64 && /usr/bin/cpack --config ./CPackConfig.cmake + DESC = Run CPack packaging tool... + pool = console + restat = 1 + +build utility/rtos_compatibility_layers/posix/package: phony utility/rtos_compatibility_layers/posix/CMakeFiles/package.util + + +############################################# +# Utility command for package_source + +build utility/rtos_compatibility_layers/posix/CMakeFiles/package_source.util: CUSTOM_COMMAND + COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64 && /usr/bin/cpack --config ./CPackSourceConfig.cmake + DESC = Run CPack packaging tool for source... + pool = console + restat = 1 + +build utility/rtos_compatibility_layers/posix/package_source: phony utility/rtos_compatibility_layers/posix/CMakeFiles/package_source.util + + +############################################# +# Utility command for test + +build utility/rtos_compatibility_layers/posix/CMakeFiles/test.util: CUSTOM_COMMAND + COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/utility/rtos_compatibility_layers/posix && /usr/bin/ctest + DESC = Running tests... + pool = console + restat = 1 + +build utility/rtos_compatibility_layers/posix/test: phony utility/rtos_compatibility_layers/posix/CMakeFiles/test.util + + +############################################# +# Utility command for edit_cache + +build utility/rtos_compatibility_layers/posix/CMakeFiles/edit_cache.util: CUSTOM_COMMAND + COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/utility/rtos_compatibility_layers/posix && /usr/bin/cmake -E echo No\ interactive\ CMake\ dialog\ available. + DESC = No interactive CMake dialog available... + restat = 1 + +build utility/rtos_compatibility_layers/posix/edit_cache: phony utility/rtos_compatibility_layers/posix/CMakeFiles/edit_cache.util + + +############################################# +# Utility command for rebuild_cache + +build utility/rtos_compatibility_layers/posix/CMakeFiles/rebuild_cache.util: CUSTOM_COMMAND + COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/utility/rtos_compatibility_layers/posix && /usr/bin/cmake --regenerate-during-build -S/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698 -B/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64 + DESC = Running CMake to regenerate build system... + pool = console + restat = 1 + +build utility/rtos_compatibility_layers/posix/rebuild_cache: phony utility/rtos_compatibility_layers/posix/CMakeFiles/rebuild_cache.util + +# ============================================================================= +# Target aliases. + +build check-functional-riscv64: phony ports/risc-v64/gnu/example_build/qemu_virt/check-functional-riscv64 + +build freertos-threadx: phony libfreertos-threadx.a + +build kernel.elf: phony ports/risc-v64/gnu/example_build/qemu_virt/kernel.elf + +build libposix-threadx.a: phony utility/rtos_compatibility_layers/posix/libposix-threadx.a + +build posix-threadx: phony utility/rtos_compatibility_layers/posix/libposix-threadx.a + +build threadx: phony libthreadx.a + +# ============================================================================= +# Folder targets. + +# ============================================================================= + +############################################# +# Folder: /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64 + +build all: phony libthreadx.a ports/risc-v64/gnu/all common/all utility/rtos_compatibility_layers/posix/all + +# ============================================================================= + +############################################# +# Folder: /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/common + +build common/all: phony + +# ============================================================================= + +############################################# +# Folder: /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/ports/risc-v64/gnu + +build ports/risc-v64/gnu/all: phony ports/risc-v64/gnu/example_build/qemu_virt/all + +# ============================================================================= + +############################################# +# Folder: /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/ports/risc-v64/gnu/example_build/qemu_virt + +build ports/risc-v64/gnu/example_build/qemu_virt/all: phony + +# ============================================================================= + +############################################# +# Folder: /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/utility/rtos_compatibility_layers/posix + +build utility/rtos_compatibility_layers/posix/all: phony + +# ============================================================================= +# Built-in targets + + +############################################# +# Re-run CMake if any of its inputs changed. + +build build.ninja /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/cmake_install.cmake /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/ports/risc-v64/gnu/cmake_install.cmake /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/ports/risc-v64/gnu/example_build/qemu_virt/cmake_install.cmake /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/common/cmake_install.cmake /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/utility/rtos_compatibility_layers/posix/cmake_install.cmake /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/CTestTestfile.cmake /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/ports/risc-v64/gnu/CTestTestfile.cmake /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/ports/risc-v64/gnu/example_build/qemu_virt/CTestTestfile.cmake /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/common/CTestTestfile.cmake /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/utility/rtos_compatibility_layers/posix/CTestTestfile.cmake: RERUN_CMAKE | /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/CMakeLists.txt /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/cmake/riscv64-unknown-elf.cmake /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/cmake/riscv64_gnu.cmake /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/cmake/threadx_riscv_port.cmake /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/CMakeLists.txt /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc/tx_user_sample.h /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/CMakeLists.txt /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/example_build/qemu_virt/CMakeLists.txt /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/CMakeLists.txt /usr/share/cmake-4.4/Modules/CMakeASMCompiler.cmake.in /usr/share/cmake-4.4/Modules/CMakeASMInformation.cmake /usr/share/cmake-4.4/Modules/CMakeCCompiler.cmake.in /usr/share/cmake-4.4/Modules/CMakeCCompilerABI.c /usr/share/cmake-4.4/Modules/CMakeCInformation.cmake /usr/share/cmake-4.4/Modules/CMakeCommonLanguageInclude.cmake /usr/share/cmake-4.4/Modules/CMakeCompilerIdDetection.cmake /usr/share/cmake-4.4/Modules/CMakeDetermineASMCompiler.cmake /usr/share/cmake-4.4/Modules/CMakeDetermineCCompiler.cmake /usr/share/cmake-4.4/Modules/CMakeDetermineCompiler.cmake /usr/share/cmake-4.4/Modules/CMakeDetermineCompilerABI.cmake /usr/share/cmake-4.4/Modules/CMakeDetermineCompilerId.cmake /usr/share/cmake-4.4/Modules/CMakeDetermineCompilerSupport.cmake /usr/share/cmake-4.4/Modules/CMakeDetermineSystem.cmake /usr/share/cmake-4.4/Modules/CMakeFindBinUtils.cmake /usr/share/cmake-4.4/Modules/CMakeGenericSystem.cmake /usr/share/cmake-4.4/Modules/CMakeInitializeConfigs.cmake /usr/share/cmake-4.4/Modules/CMakeLanguageInformation.cmake /usr/share/cmake-4.4/Modules/CMakeNinjaFindMake.cmake /usr/share/cmake-4.4/Modules/CMakeParseImplicitIncludeInfo.cmake /usr/share/cmake-4.4/Modules/CMakeParseImplicitLinkInfo.cmake /usr/share/cmake-4.4/Modules/CMakeParseLibraryArchitecture.cmake /usr/share/cmake-4.4/Modules/CMakeSystem.cmake.in /usr/share/cmake-4.4/Modules/CMakeSystemSpecificInformation.cmake /usr/share/cmake-4.4/Modules/CMakeSystemSpecificInitialize.cmake /usr/share/cmake-4.4/Modules/CMakeTestASMCompiler.cmake /usr/share/cmake-4.4/Modules/CMakeTestCCompiler.cmake /usr/share/cmake-4.4/Modules/CMakeTestCompilerCommon.cmake /usr/share/cmake-4.4/Modules/CPack.cmake /usr/share/cmake-4.4/Modules/CPackComponent.cmake /usr/share/cmake-4.4/Modules/Compiler/ADSP-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/ARMCC-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/ARMClang-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/AppleClang-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/Borland-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/Bruce-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/CMakeCommonCompilerMacros.cmake /usr/share/cmake-4.4/Modules/Compiler/Clang-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/Clang-DetermineCompilerInternal.cmake /usr/share/cmake-4.4/Modules/Compiler/Compaq-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/Cray-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/CrayClang-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/Diab-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/Embarcadero-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/Fujitsu-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/GHS-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/GNU-ASM.cmake /usr/share/cmake-4.4/Modules/Compiler/GNU-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/GNU-C.cmake /usr/share/cmake-4.4/Modules/Compiler/GNU-FindBinUtils.cmake /usr/share/cmake-4.4/Modules/Compiler/GNU.cmake /usr/share/cmake-4.4/Modules/Compiler/HP-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/IAR-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake /usr/share/cmake-4.4/Modules/Compiler/IBMClang-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/Intel-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/LCC-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/MSVC-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/NVHPC-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/NVIDIA-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/OrangeC-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/PGI-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/PathScale-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/PellesC-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/Renesas-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/SCO-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/SDCC-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/SunPro-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/TI-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/TIClang-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/Tasking-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/Watcom-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/XL-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/XLClang-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/zOS-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/FindPackageHandleStandardArgs.cmake /usr/share/cmake-4.4/Modules/FindPackageMessage.cmake /usr/share/cmake-4.4/Modules/FindPython/Support.cmake /usr/share/cmake-4.4/Modules/FindPython3.cmake /usr/share/cmake-4.4/Modules/Internal/CMakeASMLinkerInformation.cmake /usr/share/cmake-4.4/Modules/Internal/CMakeCLinkerInformation.cmake /usr/share/cmake-4.4/Modules/Internal/CMakeCommonLinkerInformation.cmake /usr/share/cmake-4.4/Modules/Internal/CMakeDetermineLinkerId.cmake /usr/share/cmake-4.4/Modules/Internal/CMakeInspectASMLinker.cmake /usr/share/cmake-4.4/Modules/Internal/CMakeInspectCLinker.cmake /usr/share/cmake-4.4/Modules/Internal/FeatureTesting.cmake /usr/share/cmake-4.4/Modules/Platform/Generic.cmake /usr/share/cmake-4.4/Templates/CPackConfig.cmake.in CMakeCache.txt CMakeFiles/4.4.3/CMakeASMCompiler.cmake CMakeFiles/4.4.3/CMakeCCompiler.cmake CMakeFiles/4.4.3/CMakeSystem.cmake + pool = console + + +############################################# +# A missing CMake input file is not an error. + +build /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/CMakeLists.txt /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/cmake/riscv64-unknown-elf.cmake /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/cmake/riscv64_gnu.cmake /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/cmake/threadx_riscv_port.cmake /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/CMakeLists.txt /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc/tx_user_sample.h /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/CMakeLists.txt /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/example_build/qemu_virt/CMakeLists.txt /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/CMakeLists.txt /usr/share/cmake-4.4/Modules/CMakeASMCompiler.cmake.in /usr/share/cmake-4.4/Modules/CMakeASMInformation.cmake /usr/share/cmake-4.4/Modules/CMakeCCompiler.cmake.in /usr/share/cmake-4.4/Modules/CMakeCCompilerABI.c /usr/share/cmake-4.4/Modules/CMakeCInformation.cmake /usr/share/cmake-4.4/Modules/CMakeCommonLanguageInclude.cmake /usr/share/cmake-4.4/Modules/CMakeCompilerIdDetection.cmake /usr/share/cmake-4.4/Modules/CMakeDetermineASMCompiler.cmake /usr/share/cmake-4.4/Modules/CMakeDetermineCCompiler.cmake /usr/share/cmake-4.4/Modules/CMakeDetermineCompiler.cmake /usr/share/cmake-4.4/Modules/CMakeDetermineCompilerABI.cmake /usr/share/cmake-4.4/Modules/CMakeDetermineCompilerId.cmake /usr/share/cmake-4.4/Modules/CMakeDetermineCompilerSupport.cmake /usr/share/cmake-4.4/Modules/CMakeDetermineSystem.cmake /usr/share/cmake-4.4/Modules/CMakeFindBinUtils.cmake /usr/share/cmake-4.4/Modules/CMakeGenericSystem.cmake /usr/share/cmake-4.4/Modules/CMakeInitializeConfigs.cmake /usr/share/cmake-4.4/Modules/CMakeLanguageInformation.cmake /usr/share/cmake-4.4/Modules/CMakeNinjaFindMake.cmake /usr/share/cmake-4.4/Modules/CMakeParseImplicitIncludeInfo.cmake /usr/share/cmake-4.4/Modules/CMakeParseImplicitLinkInfo.cmake /usr/share/cmake-4.4/Modules/CMakeParseLibraryArchitecture.cmake /usr/share/cmake-4.4/Modules/CMakeSystem.cmake.in /usr/share/cmake-4.4/Modules/CMakeSystemSpecificInformation.cmake /usr/share/cmake-4.4/Modules/CMakeSystemSpecificInitialize.cmake /usr/share/cmake-4.4/Modules/CMakeTestASMCompiler.cmake /usr/share/cmake-4.4/Modules/CMakeTestCCompiler.cmake /usr/share/cmake-4.4/Modules/CMakeTestCompilerCommon.cmake /usr/share/cmake-4.4/Modules/CPack.cmake /usr/share/cmake-4.4/Modules/CPackComponent.cmake /usr/share/cmake-4.4/Modules/Compiler/ADSP-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/ARMCC-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/ARMClang-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/AppleClang-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/Borland-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/Bruce-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/CMakeCommonCompilerMacros.cmake /usr/share/cmake-4.4/Modules/Compiler/Clang-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/Clang-DetermineCompilerInternal.cmake /usr/share/cmake-4.4/Modules/Compiler/Compaq-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/Cray-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/CrayClang-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/Diab-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/Embarcadero-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/Fujitsu-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/GHS-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/GNU-ASM.cmake /usr/share/cmake-4.4/Modules/Compiler/GNU-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/GNU-C.cmake /usr/share/cmake-4.4/Modules/Compiler/GNU-FindBinUtils.cmake /usr/share/cmake-4.4/Modules/Compiler/GNU.cmake /usr/share/cmake-4.4/Modules/Compiler/HP-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/IAR-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake /usr/share/cmake-4.4/Modules/Compiler/IBMClang-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/Intel-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/LCC-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/MSVC-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/NVHPC-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/NVIDIA-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/OrangeC-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/PGI-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/PathScale-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/PellesC-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/Renesas-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/SCO-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/SDCC-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/SunPro-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/TI-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/TIClang-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/Tasking-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/Watcom-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/XL-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/XLClang-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/zOS-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/FindPackageHandleStandardArgs.cmake /usr/share/cmake-4.4/Modules/FindPackageMessage.cmake /usr/share/cmake-4.4/Modules/FindPython/Support.cmake /usr/share/cmake-4.4/Modules/FindPython3.cmake /usr/share/cmake-4.4/Modules/Internal/CMakeASMLinkerInformation.cmake /usr/share/cmake-4.4/Modules/Internal/CMakeCLinkerInformation.cmake /usr/share/cmake-4.4/Modules/Internal/CMakeCommonLinkerInformation.cmake /usr/share/cmake-4.4/Modules/Internal/CMakeDetermineLinkerId.cmake /usr/share/cmake-4.4/Modules/Internal/CMakeInspectASMLinker.cmake /usr/share/cmake-4.4/Modules/Internal/CMakeInspectCLinker.cmake /usr/share/cmake-4.4/Modules/Internal/FeatureTesting.cmake /usr/share/cmake-4.4/Modules/Platform/Generic.cmake /usr/share/cmake-4.4/Templates/CPackConfig.cmake.in CMakeCache.txt CMakeFiles/4.4.3/CMakeASMCompiler.cmake CMakeFiles/4.4.3/CMakeCCompiler.cmake CMakeFiles/4.4.3/CMakeSystem.cmake: phony + + +############################################# +# Clean all the built files. + +build clean: CLEAN + + +############################################# +# Print all primary targets available. + +build help: HELP + + +############################################# +# Make the all target the default. + +default all diff --git a/build-rv64/custom_inc/tx_user.h b/build-rv64/custom_inc/tx_user.h new file mode 100644 index 000000000..0733c16c4 --- /dev/null +++ b/build-rv64/custom_inc/tx_user.h @@ -0,0 +1,298 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** User Specific */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* PORT SPECIFIC C INFORMATION RELEASE */ +/* */ +/* tx_user.h PORTABLE C */ +/* 6.3.0 */ +/* */ +/* AUTHOR */ +/* */ +/* William E. Lamie, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains user defines for configuring ThreadX in specific */ +/* ways. This file will have an effect only if the application and */ +/* ThreadX library are built with TX_INCLUDE_USER_DEFINE_FILE defined. */ +/* Note that all the defines in this file may also be made on the */ +/* command line when building ThreadX library and application objects. */ +/* */ +/**************************************************************************/ + +#ifndef TX_USER_H +#define TX_USER_H + + +/* Define various build options for the ThreadX port. The application should either make changes + here by commenting or un-commenting the conditional compilation defined OR supply the defines + though the compiler's equivalent of the -D option. + + For maximum speed, the following should be defined: + + TX_MAX_PRIORITIES 32 + TX_DISABLE_PREEMPTION_THRESHOLD + TX_DISABLE_REDUNDANT_CLEARING + TX_DISABLE_NOTIFY_CALLBACKS + TX_NOT_INTERRUPTABLE + TX_TIMER_PROCESS_IN_ISR + TX_REACTIVATE_INLINE + TX_DISABLE_STACK_FILLING + TX_INLINE_THREAD_RESUME_SUSPEND + + For minimum size, the following should be defined: + + TX_MAX_PRIORITIES 32 + TX_DISABLE_PREEMPTION_THRESHOLD + TX_DISABLE_REDUNDANT_CLEARING + TX_DISABLE_NOTIFY_CALLBACKS + TX_NO_FILEX_POINTER + TX_NOT_INTERRUPTABLE + TX_TIMER_PROCESS_IN_ISR + + Of course, many of these defines reduce functionality and/or change the behavior of the + system in ways that may not be worth the trade-off. For example, the TX_TIMER_PROCESS_IN_ISR + results in faster and smaller code, however, it increases the amount of processing in the ISR. + In addition, some services that are available in timers are not available from ISRs and will + therefore return an error if this option is used. This may or may not be desirable for a + given application. */ + + +/* Override various options with default values already assigned in tx_port.h. Please also refer + to tx_port.h for descriptions on each of these options. */ + +/* +#define TX_MAX_PRIORITIES 32 +#define TX_MINIMUM_STACK ???? +#define TX_THREAD_USER_EXTENSION ???? +#define TX_TIMER_THREAD_STACK_SIZE ???? +#define TX_TIMER_THREAD_PRIORITY ???? +*/ + +/* Define the maximum size of a message in the a queue. the Default value is TX_ULONG_16. + the new value must be a multiple of ULONG. */ + +/* +#define TX_QUEUE_MESSAGE_MAX_SIZE TX_16_ULONG +*/ + +/* Define the common timer tick reference for use by other middleware components. The default + value is 10ms (i.e. 100 ticks, defined in tx_api.h), but may be replaced by a port-specific + version in tx_port.h or here. + Note: the actual hardware timer value may need to be changed (usually in tx_initialize_low_level). */ + +/* +#define TX_TIMER_TICKS_PER_SECOND (100UL) +*/ + +/* Determine if there is a FileX pointer in the thread control block. + By default, the pointer is there for legacy/backwards compatibility. + The pointer must also be there for applications using FileX. + Define this to save space in the thread control block. +*/ + +/* +#define TX_NO_FILEX_POINTER +*/ + +/* Determine if timer expirations (application timers, timeouts, and tx_thread_sleep calls + should be processed within the a system timer thread or directly in the timer ISR. + By default, the timer thread is used. When the following is defined, the timer expiration + processing is done directly from the timer ISR, thereby eliminating the timer thread control + block, stack, and context switching to activate it. */ + +/* +#define TX_TIMER_PROCESS_IN_ISR +*/ + +/* Determine if in-line timer reactivation should be used within the timer expiration processing. + By default, this is disabled and a function call is used. When the following is defined, + reactivating is performed in-line resulting in faster timer processing but slightly larger + code size. */ + +/* +#define TX_REACTIVATE_INLINE +*/ + +/* Determine is stack filling is enabled. By default, ThreadX stack filling is enabled, + which places an 0xEF pattern in each byte of each thread's stack. This is used by + debuggers with ThreadX-awareness and by the ThreadX run-time stack checking feature. */ + +/* +#define TX_DISABLE_STACK_FILLING +*/ + +/* Determine whether or not stack checking is enabled. By default, ThreadX stack checking is + disabled. When the following is defined, ThreadX thread stack checking is enabled. If stack + checking is enabled (TX_ENABLE_STACK_CHECKING is defined), the TX_DISABLE_STACK_FILLING + define is negated, thereby forcing the stack fill which is necessary for the stack checking + logic. */ + +/* +#define TX_ENABLE_STACK_CHECKING +*/ + +/* Determine if random number is used for stack filling. By default, ThreadX uses a fixed + pattern for stack filling. When the following is defined, ThreadX uses a random number + for stack filling. This is effective only when TX_ENABLE_STACK_CHECKING is defined. */ + +/* +#define TX_ENABLE_RANDOM_NUMBER_STACK_FILLING +*/ + +/* Determine if preemption-threshold should be disabled. By default, preemption-threshold is + enabled. If the application does not use preemption-threshold, it may be disabled to reduce + code size and improve performance. */ + +/* +#define TX_DISABLE_PREEMPTION_THRESHOLD +*/ + +/* Determine if global ThreadX variables should be cleared. If the compiler startup code clears + the .bss section prior to ThreadX running, the define can be used to eliminate unnecessary + clearing of ThreadX global variables. */ + +/* +#define TX_DISABLE_REDUNDANT_CLEARING +*/ + +/* Determine if no timer processing is required. This option will help eliminate the timer + processing when not needed. The user will also have to comment out the call to + tx_timer_interrupt, which is typically made from assembly language in + tx_initialize_low_level. Note: if TX_NO_TIMER is used, the define TX_TIMER_PROCESS_IN_ISR + must also be used and tx_timer_initialize must be removed from ThreadX library. */ + +/* +#define TX_NO_TIMER +#ifndef TX_TIMER_PROCESS_IN_ISR +#define TX_TIMER_PROCESS_IN_ISR +#endif +*/ + +/* Determine if the notify callback option should be disabled. By default, notify callbacks are + enabled. If the application does not use notify callbacks, they may be disabled to reduce + code size and improve performance. */ + +/* +#define TX_DISABLE_NOTIFY_CALLBACKS +*/ + + +/* Determine if the tx_thread_resume and tx_thread_suspend services should have their internal + code in-line. This results in a larger image, but improves the performance of the thread + resume and suspend services. */ + +/* +#define TX_INLINE_THREAD_RESUME_SUSPEND +*/ + + +/* Determine if the internal ThreadX code is non-interruptable. This results in smaller code + size and less processing overhead, but increases the interrupt lockout time. */ + +/* +#define TX_NOT_INTERRUPTABLE +*/ + + +/* Determine if the trace event logging code should be enabled. This causes slight increases in + code size and overhead, but provides the ability to generate system trace information which + is available for viewing in TraceX. */ + +/* +#define TX_ENABLE_EVENT_TRACE +*/ + + +/* Determine if block pool performance gathering is required by the application. When the following is + defined, ThreadX gathers various block pool performance information. */ + +/* +#define TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO +*/ + +/* Determine if byte pool performance gathering is required by the application. When the following is + defined, ThreadX gathers various byte pool performance information. */ + +/* +#define TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO +*/ + +/* Determine if event flags performance gathering is required by the application. When the following is + defined, ThreadX gathers various event flags performance information. */ + +/* +#define TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO +*/ + +/* Determine if mutex performance gathering is required by the application. When the following is + defined, ThreadX gathers various mutex performance information. */ + +/* +#define TX_MUTEX_ENABLE_PERFORMANCE_INFO +*/ + +/* Determine if queue performance gathering is required by the application. When the following is + defined, ThreadX gathers various queue performance information. */ + +/* +#define TX_QUEUE_ENABLE_PERFORMANCE_INFO +*/ + +/* Determine if semaphore performance gathering is required by the application. When the following is + defined, ThreadX gathers various semaphore performance information. */ + +/* +#define TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO +*/ + +/* Determine if thread performance gathering is required by the application. When the following is + defined, ThreadX gathers various thread performance information. */ + +/* +#define TX_THREAD_ENABLE_PERFORMANCE_INFO +*/ + +/* Determine if timer performance gathering is required by the application. When the following is + defined, ThreadX gathers various timer performance information. */ + +/* +#define TX_TIMER_ENABLE_PERFORMANCE_INFO +*/ + +/* Override options for byte pool searches of multiple blocks. */ + +/* +#define TX_BYTE_POOL_MULTIPLE_BLOCK_SEARCH 20 +*/ + +/* Override options for byte pool search delay to avoid thrashing. */ + +/* +#define TX_BYTE_POOL_DELAY_VALUE 3 +*/ + +#endif + diff --git a/build-rv64/ports/risc-v64/gnu/example_build/qemu_virt/kernel.elf b/build-rv64/ports/risc-v64/gnu/example_build/qemu_virt/kernel.elf new file mode 100755 index 0000000000000000000000000000000000000000..b9e83bcc83bb84f3954a023df8d70185ac937184 GIT binary patch literal 239112 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 1 && $fpu_err > -0.01 && $fpu_err < 0.01 + printf "FPU_VERIFIED_OK value=%f adds=%d\n", fpu_test_val, $fpu_n + else + printf "FPU_VERIFIED_FAIL value=%f adds=%d passes=%d\n", fpu_test_val, $fpu_n, $fpu_iter + end +end + +# Await Timer Interrupt. Arm only the timer breakpoint, so this stop is +# _tx_timer_interrupt and $ra below really is the ISR return address. +disable 1 +disable 2 +disable 3 +enable 4 +continue +print "Hit Timer Interrupt" + +# Verify MEPC Integrity - Save State +print/x $mepc +set $saved_pc = $mepc + +# Verify System Timer Before ISR +set $clock_before = _tx_timer_system_clock +print $clock_before + +# Configure Time-Slice Test Conditions +set _tx_timer_time_slice = 1 +set _tx_timer_expired_time_slice = 0 +set $ts_handler_called = 0 + +# Set Breakpoint at Time-Slice Handler with Auto-Continue +tbreak _tx_thread_time_slice +commands + set $ts_handler_called = 1 + continue +end + +# Set Breakpoint at ISR Return Address. Disable the timer breakpoint for +# this window, so the next tick cannot stop us short of the return. +set $ret_addr = $ra +disable 4 +tbreak *$ret_addr +continue + +# Verify that the live CSR and saved frame still contain the interrupted PC. +set $frame_pc = ((unsigned long *)_tx_thread_current_ptr->tx_thread_stack_ptr)[30] +if $mepc == $saved_pc && $frame_pc == $saved_pc + printf "MEPC_VERIFIED_OK mepc=0x%lx frame_pc=0x%lx\n", $mepc, $frame_pc +else + printf "MEPC_VERIFIED_FAIL saved=0x%lx mepc=0x%lx frame_pc=0x%lx\n", $saved_pc, $mepc, $frame_pc +end + +# Verify Time-Slice Handler Was Called +if $ts_handler_called == 1 + print "SUCCESS: Time-slice handler called." +else + print "FAILURE: Time-slice handler NOT called." +end + +# Verify System Timer Increment (Monotonicity) +set $clock_after = _tx_timer_system_clock +print $clock_after + +if $clock_after > $clock_before + print "SUCCESS: System timer incremented." +else + print "FAILURE: System timer did not increment." +end + +# Verify Preemption Logic (Thread Priority) +# +# We are now stopped at the return address from _tx_timer_interrupt, +# after _tx_thread_time_slice and the timer expiration processing have had +# a chance to update _tx_thread_execute_ptr but before trap_handler +# returns into _tx_thread_context_restore. +# +# Whether any ONE tick lands inside a preemption window depends on +# scheduling phase, not on the tick rate, so poll consecutive ticks at +# this same sample point until the priority relation holds. Each retry +# re-arms the time slice and re-derives the return address from $ra, so +# the sample point is identical every iteration. The cap bounds ticks and +# fails loudly on exhaustion; it never passes the check. +set $preempt_ok = 0 +set $preempt_null = 0 +set $preempt_iter = 0 +while $preempt_iter < 250 && $preempt_ok == 0 + set $curr_ptr = _tx_thread_current_ptr + set $exec_ptr = _tx_thread_execute_ptr + if $curr_ptr == 0 || $exec_ptr == 0 + set $preempt_null = $preempt_null + 1 + else + set $curr_prio = $curr_ptr->tx_thread_priority + set $exec_prio = $exec_ptr->tx_thread_priority + if $exec_prio < $curr_prio + printf "PREEMPT_CHECK current_prio=%d execute_prio=%d\n", $curr_prio, $exec_prio + set $preempt_ok = 1 + end + end + if $preempt_ok == 0 + set $preempt_iter = $preempt_iter + 1 + enable 4 + continue + set _tx_timer_time_slice = 1 + set _tx_timer_expired_time_slice = 0 + set $ret_addr = $ra + disable 4 + tbreak *$ret_addr + continue + end +end + +if $preempt_ok == 1 + printf "PREEMPT_VERIFIED_OK ticks=%d\n", $preempt_iter +else + if $preempt_null == $preempt_iter + printf "PREEMPT_VERIFIED_FAIL_NULL\n" + else + printf "PREEMPT_VERIFIED_FAIL_NOT_OBSERVED ticks=%d\n", $preempt_iter + end +end + +quit diff --git a/ports/risc-v64/gnu/CMakeLists.txt b/ports/risc-v64/gnu/CMakeLists.txt index e51de7355..050007573 100644 --- a/ports/risc-v64/gnu/CMakeLists.txt +++ b/ports/risc-v64/gnu/CMakeLists.txt @@ -3,4 +3,5 @@ include(${CMAKE_CURRENT_LIST_DIR}/../../../cmake/threadx_riscv_port.cmake) threadx_add_riscv_port( SRC_DIR ${CMAKE_CURRENT_LIST_DIR}/src INC_DIR ${CMAKE_CURRENT_LIST_DIR}/inc + EXAMPLE_DIR ${CMAKE_CURRENT_LIST_DIR}/example_build/qemu_virt ) diff --git a/ports/risc-v64/gnu/example_build/qemu_virt/.gitignore b/ports/risc-v64/gnu/example_build/qemu_virt/.gitignore new file mode 100644 index 000000000..d90c0dfd4 --- /dev/null +++ b/ports/risc-v64/gnu/example_build/qemu_virt/.gitignore @@ -0,0 +1,4 @@ +# Ignore generated QEMU test files. +kernel.elf +qemu-riscv64.log +test_cmds.gdb diff --git a/ports/risc-v64/gnu/example_build/qemu_virt/CMakeLists.txt b/ports/risc-v64/gnu/example_build/qemu_virt/CMakeLists.txt new file mode 100644 index 000000000..1928fbbdb --- /dev/null +++ b/ports/risc-v64/gnu/example_build/qemu_virt/CMakeLists.txt @@ -0,0 +1,51 @@ +set(QEMU_DEMO_DIR ${CMAKE_CURRENT_LIST_DIR}) + +add_executable(kernel.elf EXCLUDE_FROM_ALL + ${QEMU_DEMO_DIR}/demo_threadx.c + ${QEMU_DEMO_DIR}/entry.S + ${QEMU_DEMO_DIR}/uart.c + ${QEMU_DEMO_DIR}/plic.c + ${QEMU_DEMO_DIR}/hwtimer.c + ${QEMU_DEMO_DIR}/trap.c + ${QEMU_DEMO_DIR}/board.c + ${QEMU_DEMO_DIR}/tx_initialize_low_level.S +) + +target_link_libraries(kernel.elf PRIVATE threadx gcc) + +target_include_directories(kernel.elf PRIVATE + ${CMAKE_SOURCE_DIR}/common/inc + ${CMAKE_SOURCE_DIR}/ports/${THREADX_ARCH}/${THREADX_TOOLCHAIN}/inc + ${QEMU_DEMO_DIR} +) + +target_link_options(kernel.elf PRIVATE + -T${QEMU_DEMO_DIR}/link.lds + -nostartfiles + -Wl,-Map=kernel.map +) + +find_package(Python3 COMPONENTS Interpreter) +find_program(RISCV64_GDB NAMES riscv64-unknown-elf-gdb gdb-multiarch) +find_program(RISCV64_QEMU NAMES qemu-system-riscv64) +if(Python3_FOUND AND RISCV64_GDB AND RISCV64_QEMU) + add_custom_target(check-functional-riscv64 + COMMAND ${Python3_EXECUTABLE} + ${QEMU_DEMO_DIR}/test/threadx_test_tx_gnu_riscv64_qemu.py + --elf $ + --qemu ${RISCV64_QEMU} + --gdb ${RISCV64_GDB} + DEPENDS kernel.elf + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Running RISC-V64 QEMU/GDB functional test runner..." + ) +elseif(NOT Python3_FOUND) + message(STATUS + "Python3 not found; check-functional-riscv64 target unavailable.") +elseif(NOT RISCV64_GDB) + message(STATUS + "RISC-V GDB not found; check-functional-riscv64 target unavailable.") +else() + message(STATUS + "qemu-system-riscv64 not found; check-functional-riscv64 target unavailable.") +endif() diff --git a/ports/risc-v64/gnu/example_build/qemu_virt/board.c b/ports/risc-v64/gnu/example_build/qemu_virt/board.c index 805a1ac8e..160eb5921 100644 --- a/ports/risc-v64/gnu/example_build/qemu_virt/board.c +++ b/ports/risc-v64/gnu/example_build/qemu_virt/board.c @@ -15,15 +15,13 @@ #include #include -void *memset(const void *des, int c,size_t n) +void *memset(void *des, int c, size_t n) { - if((des == NULL) || n <=0) - return (void*)des; - char* t = (char*)des; - int i; - for(i=0;i -#define TICKNUM_PER_SECOND 10000000 -#define TICKNUM_PER_TIMER (TICKNUM_PER_SECOND / 10) +#define TICKNUM_PER_SECOND 10000000UL +#define TICKNUM_PER_TIMER (TICKNUM_PER_SECOND / TX_TIMER_TICKS_PER_SECOND) int hwtimer_init(void); diff --git a/ports/risc-v64/gnu/example_build/qemu_virt/link.lds b/ports/risc-v64/gnu/example_build/qemu_virt/link.lds index d0d8a6bc1..63803acb7 100644 --- a/ports/risc-v64/gnu/example_build/qemu_virt/link.lds +++ b/ports/risc-v64/gnu/example_build/qemu_virt/link.lds @@ -1,6 +1,12 @@ OUTPUT_ARCH( "riscv" ) ENTRY( _start ) +PHDRS +{ + text PT_LOAD FLAGS(5); + data PT_LOAD FLAGS(6); +} + SECTIONS { /* @@ -10,43 +16,44 @@ SECTIONS . = 0x80000000; .text : { + KEEP(*(.text.entry)) *(.text .text.*) . = ALIGN(0x1000); PROVIDE(etext = .); - } + } :text .rodata : { . = ALIGN(16); *(.srodata .srodata.*) /* do not need to distinguish this from .rodata */ . = ALIGN(16); *(.rodata .rodata.*) - } + } :text + . = ALIGN(0x1000); .data : { . = ALIGN(16); + PROVIDE( __global_pointer$ = . + 0x800 ); *(.sdata .sdata.*) /* do not need to distinguish this from .data */ . = ALIGN(16); *(.data .data.*) - } + } :data - .bss : { + .bss (NOLOAD) : { . = ALIGN(16); _bss_start = .; *(.sbss .sbss.*) /* do not need to distinguish this from .bss */ . = ALIGN(16); *(.bss .bss.*) _bss_end = .; - } + } :data - .stack : { + .stack (NOLOAD) : { . = ALIGN(4096); _sysstack_start = .; . += 0x1000; -#ifdef __riscv_vector - . += 0x4000; -#endif + . += 0x4000; /* Vector headroom */ _sysstack_end = .; - } + } :data PROVIDE(_end = .); } diff --git a/ports/risc-v64/gnu/example_build/qemu_virt/test/threadx_test_tx_gnu_riscv64_qemu.py b/ports/risc-v64/gnu/example_build/qemu_virt/test/threadx_test_tx_gnu_riscv64_qemu.py index 861f50e61..e86d2e3f6 100644 --- a/ports/risc-v64/gnu/example_build/qemu_virt/test/threadx_test_tx_gnu_riscv64_qemu.py +++ b/ports/risc-v64/gnu/example_build/qemu_virt/test/threadx_test_tx_gnu_riscv64_qemu.py @@ -18,19 +18,16 @@ def print_content(content): """Prints content using os.write to handle non-blocking stdout robustly.""" - try: - msg = f"{content}\n".encode('utf-8') - total_len = len(msg) - written = 0 - fd = sys.stdout.fileno() - while written < total_len: - try: - n = os.write(fd, msg[written:]) - written += n - except BlockingIOError: - select.select([], [fd], []) - except Exception: - pass + msg = f"{content}\n".encode('utf-8') + total_len = len(msg) + written = 0 + fd = sys.stdout.fileno() + while written < total_len: + try: + n = os.write(fd, msg[written:]) + written += n + except BlockingIOError: + select.select([], [fd], []) def get_free_port(): """Finds a free TCP port.""" @@ -38,7 +35,7 @@ def get_free_port(): s.bind(('', 0)) return s.getsockname()[1] -def run_qemu_test(elf_path, qemu_bin, gdb_bin): +def run_qemu_test(elf_path, qemu_bin, gdb_bin, cpu): """ Runs a test cycle using QEMU and GDB. """ @@ -51,6 +48,8 @@ def run_qemu_test(elf_path, qemu_bin, gdb_bin): print(f"Using GDB port: {gdb_port}") # 1. Start QEMU in the background + GDB_TIMEOUT_S = 120 + qemu_log_path = os.path.abspath("qemu-riscv64.log") qemu_cmd = [ qemu_bin, "-M", "virt", @@ -61,18 +60,33 @@ def run_qemu_test(elf_path, qemu_bin, gdb_bin): "-monitor", "none", # Disable monitor "-serial", "stdio" # Redirect serial output to stdio ] + if cpu: + qemu_cmd.extend(["-cpu", cpu]) print(f"Starting QEMU: {' '.join(qemu_cmd)}") - qemu_process = subprocess.Popen( - qemu_cmd, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - text=True + qemu_log = open(qemu_log_path, "w", encoding="utf-8") + try: + qemu_process = subprocess.Popen( + qemu_cmd, + stdout=qemu_log, + stderr=subprocess.STDOUT, + text=True + ) + except OSError as e: + qemu_log.close() + print_content(f"FAILURE: QEMU did not start: {e}") + return False + + print_content( + f"QEMU PID {qemu_process.pid}; expected runtime under 30s; " + f"wall timeout {GDB_TIMEOUT_S}s; log {qemu_log_path}" ) if qemu_process.poll() is not None: - print("QEMU failed to start.") - print(qemu_process.stderr.read()) + qemu_log.close() + print_content("FAILURE: QEMU exited during startup.") + with open(qemu_log_path, encoding="utf-8") as failed_log: + print_content(failed_log.read()) return False # 2. Create a GDB command file @@ -88,6 +102,13 @@ def run_qemu_test(elf_path, qemu_bin, gdb_bin): break thread_6_and_7_entry break _tx_timer_interrupt +# The timer interrupt fires at TX_TIMER_TICKS_PER_SECOND Hz. With every +# breakpoint armed at once a bare `continue` is a race: a tick can steal +# the stop that the script expects on an application breakpoint. Keep the +# timer breakpoint disabled until the timer phase, so every stop below is +# unambiguous at any tick rate. +disable 4 + # Execute to Application Definition continue @@ -95,17 +116,54 @@ def run_qemu_test(elf_path, qemu_bin, gdb_bin): continue print/x $mstatus -# Verify FPU Logic and Register State exercised by thread_6/7 +# Verify FPU Logic and Register State exercised by thread_6/7. +# Only breakpoint 3 can stop us here, so this is thread_6_and_7_entry on +# its first pass, before the thread has touched fpu_test_val. continue -finish -step -step -step + +# fpu_test_val exists only in a demo that builds the FPU exercise. GDB +# aborts a sourced command file on an unknown symbol, which would skip +# every later check without saying so, so probe for the symbol first. A +# missing symbol still FAILS the FPU check below; it is not tolerated. +python gdb.execute("set $fpu_sym = %d" % (1 if gdb.lookup_global_symbol("fpu_test_val") else 0)) + +set $fpu_iter = 0 +if $fpu_sym != 0 + set $fpu_before = fpu_test_val + # Wait for the FPU add (fpu_test_val += 1.1f) to retire, instead of + # stepping a fixed number of instructions past an assumed stop. Each + # further stop is another pass through thread_6_and_7_entry, so the cap + # bounds thread passes rather than ticks, and exhausting it fails below. + while fpu_test_val == $fpu_before && $fpu_iter < 64 + set $fpu_iter = $fpu_iter + 1 + continue + end +end + print/x $mstatus info registers float -print fpu_test_val -# Await Timer Interrupt +if $fpu_sym == 0 + printf "FPU_VERIFIED_FAIL_NO_SYMBOL\\n" +else + print fpu_test_val + # Assert the float unit produced an exact multiple of 1.1f. This does + # not assume how many passes ran, only that every pass added 1.1f. + set $fpu_n = (int)((fpu_test_val / 1.1) + 0.5) + set $fpu_err = fpu_test_val - ($fpu_n * 1.1) + if $fpu_n >= 1 && $fpu_err > -0.01 && $fpu_err < 0.01 + printf "FPU_VERIFIED_OK value=%f adds=%d\\n", fpu_test_val, $fpu_n + else + printf "FPU_VERIFIED_FAIL value=%f adds=%d passes=%d\\n", fpu_test_val, $fpu_n, $fpu_iter + end +end + +# Await Timer Interrupt. Arm only the timer breakpoint, so this stop is +# _tx_timer_interrupt and $ra below really is the ISR return address. +disable 1 +disable 2 +disable 3 +enable 4 continue print "Hit Timer Interrupt" @@ -129,11 +187,21 @@ def run_qemu_test(elf_path, qemu_bin, gdb_bin): continue end -# Set Breakpoint at ISR Return Address +# Set Breakpoint at ISR Return Address. Disable the timer breakpoint for +# this window, so the next tick cannot stop us short of the return. set $ret_addr = $ra +disable 4 tbreak *$ret_addr continue +# Verify that the live CSR and saved frame still contain the interrupted PC. +set $frame_pc = ((unsigned long *)_tx_thread_current_ptr->tx_thread_stack_ptr)[30] +if $mepc == $saved_pc && $frame_pc == $saved_pc + printf "MEPC_VERIFIED_OK mepc=0x%lx frame_pc=0x%lx\\n", $mepc, $frame_pc +else + printf "MEPC_VERIFIED_FAIL saved=0x%lx mepc=0x%lx frame_pc=0x%lx\\n", $saved_pc, $mepc, $frame_pc +end + # Verify Time-Slice Handler Was Called if $ts_handler_called == 1 print "SUCCESS: Time-slice handler called." @@ -152,19 +220,55 @@ def run_qemu_test(elf_path, qemu_bin, gdb_bin): end # Verify Preemption Logic (Thread Priority) -set $curr_ptr = _tx_thread_current_ptr -set $exec_ptr = _tx_thread_execute_ptr -if $curr_ptr != 0 && $exec_ptr != 0 - set $curr_prio = $curr_ptr->tx_thread_priority - set $exec_prio = $exec_ptr->tx_thread_priority - printf "PREEMPT_CHECK current_prio=%d execute_prio=%d\\n", $curr_prio, $exec_prio - if $exec_prio < $curr_prio - printf "PREEMPT_VERIFIED_OK\\n" +# +# We are now stopped at the return address from _tx_timer_interrupt, +# after _tx_thread_time_slice and the timer expiration processing have had +# a chance to update _tx_thread_execute_ptr but before trap_handler +# returns into _tx_thread_context_restore. +# +# Whether any ONE tick lands inside a preemption window depends on +# scheduling phase, not on the tick rate, so poll consecutive ticks at +# this same sample point until the priority relation holds. Each retry +# re-arms the time slice and re-derives the return address from $ra, so +# the sample point is identical every iteration. The cap bounds ticks and +# fails loudly on exhaustion; it never passes the check. +set $preempt_ok = 0 +set $preempt_null = 0 +set $preempt_iter = 0 +while $preempt_iter < 250 && $preempt_ok == 0 + set $curr_ptr = _tx_thread_current_ptr + set $exec_ptr = _tx_thread_execute_ptr + if $curr_ptr == 0 || $exec_ptr == 0 + set $preempt_null = $preempt_null + 1 else - printf "PREEMPT_VERIFIED_FAIL_NOT_OBSERVED\\n" + set $curr_prio = $curr_ptr->tx_thread_priority + set $exec_prio = $exec_ptr->tx_thread_priority + if $exec_prio < $curr_prio + printf "PREEMPT_CHECK current_prio=%d execute_prio=%d\\n", $curr_prio, $exec_prio + set $preempt_ok = 1 + end + end + if $preempt_ok == 0 + set $preempt_iter = $preempt_iter + 1 + enable 4 + continue + set _tx_timer_time_slice = 1 + set _tx_timer_expired_time_slice = 0 + set $ret_addr = $ra + disable 4 + tbreak *$ret_addr + continue end +end + +if $preempt_ok == 1 + printf "PREEMPT_VERIFIED_OK ticks=%d\\n", $preempt_iter else - printf "PREEMPT_VERIFIED_FAIL_NULL\\n" + if $preempt_null == $preempt_iter + printf "PREEMPT_VERIFIED_FAIL_NULL\\n" + else + printf "PREEMPT_VERIFIED_FAIL_NOT_OBSERVED ticks=%d\\n", $preempt_iter + end end quit @@ -183,8 +287,11 @@ def run_qemu_test(elf_path, qemu_bin, gdb_bin): print_content(f"Starting GDB: {' '.join(gdb_cmd)}") - GDB_TIMEOUT_S = 30 - + # Cap the GDB session so a wedged batch script (e.g. a `continue` that + # never hits its breakpoint) cannot hang CI. The preemption poll may + # step through up to 250 ticks; at the port's 100 Hz tick that is 2.5 s + # of guest time, but each tick costs two gdbstub round trips, so allow + # 120 s of wall clock before declaring the session wedged. try: gdb_process = subprocess.run( gdb_cmd, @@ -228,17 +335,32 @@ def run_qemu_test(elf_path, qemu_bin, gdb_bin): except subprocess.TimeoutExpired: print_content("QEMU did not terminate gracefully, killing it forcefully.") qemu_process.kill() + qemu_process.wait() + qemu_log.close() # Verify results stdout = gdb_process.stdout + gdb_succeeded = gdb_process.returncode == 0 timer_hit = "Breakpoint 4, _tx_timer_interrupt" in stdout fpu_verified = False + mepc_verified = "MEPC_VERIFIED_OK" in stdout preemption_verified = "PREEMPT_VERIFIED_OK" in stdout + time_slice_verified = "SUCCESS: Time-slice handler called." in stdout + system_timer_verified = "SUCCESS: System timer incremented." in stdout + + if not gdb_succeeded: + print_content(f"FAILURE: GDB exited with status {gdb_process.returncode}.") if "Breakpoint 3, thread_6_and_7_entry" in stdout: - if "1.10" in stdout or "fpu_test_val" in stdout: + if "FPU_VERIFIED_OK" in stdout: print_content("SUCCESS: FPU instructions executed and registers inspected.") fpu_verified = True + elif "FPU_VERIFIED_FAIL_NO_SYMBOL" in stdout: + print_content("FAILURE: Hit thread, but this demo defines no " + "fpu_test_val, so the FPU result is unverifiable.") + elif "FPU_VERIFIED_FAIL" in stdout: + print_content("FAILURE: Hit thread, but fpu_test_val is not an exact " + "multiple of 1.1f. Output does not contain expected value.") else: print_content("FAILURE: Hit thread, but failed to inspect FPU. " "Output does not contain expected value.") @@ -248,6 +370,21 @@ def run_qemu_test(elf_path, qemu_bin, gdb_bin): else: print_content("FAILURE: Did not hit timer interrupt.") + if mepc_verified: + print_content("SUCCESS: MEPC and the saved frame PC are unchanged.") + else: + print_content("FAILURE: MEPC or the saved frame PC changed in the ISR.") + + if time_slice_verified: + print_content("SUCCESS: Time-slice handler verified.") + else: + print_content("FAILURE: Time-slice handler was not called.") + + if system_timer_verified: + print_content("SUCCESS: System timer increment verified.") + else: + print_content("FAILURE: System timer did not increment.") + if preemption_verified: print_content("SUCCESS: Preemption verified (higher-priority thread " "preempted a lower-priority one).") @@ -263,7 +400,9 @@ def run_qemu_test(elf_path, qemu_bin, gdb_bin): else: print_content("FAILURE: Preemption check did not run to completion.") - if timer_hit and fpu_verified and preemption_verified: + if (gdb_succeeded and timer_hit and fpu_verified and mepc_verified and + time_slice_verified and system_timer_verified and + preemption_verified): return True else: return False @@ -275,10 +414,11 @@ def run_qemu_test(elf_path, qemu_bin, gdb_bin): help="Path to QEMU binary") parser.add_argument("--gdb", default="riscv64-unknown-elf-gdb", help="Path to GDB binary") + parser.add_argument("--cpu", help="QEMU CPU model and properties") args = parser.parse_args() - success = run_qemu_test(args.elf, args.qemu, args.gdb) + success = run_qemu_test(args.elf, args.qemu, args.gdb, args.cpu) if success: sys.exit(0) diff --git a/ports/risc-v64/gnu/example_build/qemu_virt/tx_initialize_low_level.S b/ports/risc-v64/gnu/example_build/qemu_virt/tx_initialize_low_level.S index a9b2fda76..9b1d87586 100644 --- a/ports/risc-v64/gnu/example_build/qemu_virt/tx_initialize_low_level.S +++ b/ports/risc-v64/gnu/example_build/qemu_virt/tx_initialize_low_level.S @@ -10,6 +10,7 @@ **************************************************************************/ #include "csr.h" +#include "tx_port.h" .section .text .align 4 @@ -61,17 +62,18 @@ .extern trap_handler .extern _tx_thread_context_restore trap_entry: -#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - addi sp, sp, -520 // Allocate space for all registers - with floating point enabled (65*8) -#else - addi sp, sp, -256 // Allocate space for all registers - without floating point enabled (32*8) -#endif + addi sp, sp, -TX_RISCV_TRAP_FRAME_SIZE // Interrupt frame from the port contract (528 with FP, 256 without) #if defined(__riscv_vector) - /* Allocate space for vector registers */ + /* Allocate space for vector registers. No register is saved yet, so + park t4 in the frame first and recover it after the allocation: + _tx_thread_context_save must still see the interrupted thread's t4. */ + sd t4, 15*8(sp) // Park t4 (pre-vector sp) csrr t4, vlenb slli t4, t4, 5 addi t4, t4, 4*8 sub sp, sp, t4 + add t4, sp, t4 // Rebuild the pre-vector sp + ld t4, 15*8(t4) // Recover the parked t4 #endif sd x1, 224(sp) // Store RA (28*8 = 224, because call will override ra [ra is a callee register in riscv]) @@ -81,11 +83,11 @@ csrr a0, mcause csrr a1, mepc csrr a2, mtval - addi sp, sp, -8 + addi sp, sp, -16 // 16 bytes keep sp 16-byte aligned at the call sd ra, 0(sp) call trap_handler ld ra, 0(sp) - addi sp, sp, 8 + addi sp, sp, 16 call _tx_thread_context_restore // it will nerver return _err: @@ -135,8 +137,7 @@ _err: /**************************************************************************/ /* VOID _tx_initialize_low_level(VOID) { */ - .global _tx_initialize_low_level - .weak _tx_initialize_low_level + .global _tx_initialize_low_level // Strong definition: must beat the port's weak default in any link order .extern _end .extern board_init _tx_initialize_low_level: @@ -150,9 +151,9 @@ _tx_initialize_low_level: 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, (MIE_MTIE | MIE_MEIE) + csrrs zero, mie, t0 // set mie (no MIE_MSIE: cause 3 has no dispatch path and msip is never written) +#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) li t0, MSTATUS_FS csrrs zero, mstatus, t0 // set MSTATUS_FS bit to open f/d isa in riscv fscsr x0 @@ -161,11 +162,11 @@ _tx_initialize_low_level: li t0, MSTATUS_VS csrrs zero, mstatus, t0 // set MSTATUS_VS bit to open vector isa in riscv #endif - addi sp, sp, -8 + addi sp, sp, -16 // 16 bytes keep sp 16-byte aligned at the call sd ra, 0(sp) call board_init ld ra, 0(sp) - addi sp, sp, 8 + addi sp, sp, 16 la t0, trap_entry csrw mtvec, t0 ret diff --git a/ports/risc-v64/gnu/inc/tx_port.h b/ports/risc-v64/gnu/inc/tx_port.h index 115178fb4..0e31cc426 100644 --- a/ports/risc-v64/gnu/inc/tx_port.h +++ b/ports/risc-v64/gnu/inc/tx_port.h @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Claude Code (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -26,7 +28,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* tx_port.h RISC-V64/GNU */ -/* 6.2.1 */ +/* 6.5.1.202602a */ /* */ /* AUTHOR */ /* */ @@ -48,6 +50,48 @@ #ifndef TX_PORT_H #define TX_PORT_H +#ifdef __riscv_float_abi_quad +#error "The ThreadX RISC-V64 port does not support the LP64Q ABI." +#endif + +#if defined(__riscv_flen) && !defined(__riscv_float_abi_single) && !defined(__riscv_float_abi_double) +#error "The ThreadX RISC-V64 port does not preserve FP state for a soft-float ABI. Remove F and D ISA extensions or use LP64F or LP64D." +#endif + +#if defined(__riscv_float_abi_single) && (!defined(__riscv_flen) || (__riscv_flen < 32)) +#error "The ThreadX RISC-V64 LP64F port requires FLEN>=32." +#endif + +#if defined(__riscv_float_abi_double) && (!defined(__riscv_flen) || (__riscv_flen < 64)) +#error "The ThreadX RISC-V64 LP64D port requires FLEN>=64." +#endif + +#if defined(__riscv_flen) && (__riscv_flen != 32) && (__riscv_flen != 64) +#error "The ThreadX RISC-V64 port supports only FLEN=32 or FLEN=64." +#endif + +/* Every port .S file uses CSR instructions, so the ISA string must include + Zicsr. Catch its absence here rather than in a wall of assembler + "unrecognized opcode" errors. */ +#if !defined(__riscv_zicsr) +#error "The ThreadX RISC-V64 port requires the Zicsr extension. Add it to the ISA string, for example rv64imac_zicsr." +#endif + +/* Publish the interrupt frame contract to GNU BSP assembly files. */ +#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) +#define TX_RISCV_TRAP_FRAME_SIZE 528 +#else +#define TX_RISCV_TRAP_FRAME_SIZE 256 +#endif + + +#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) +#define TX_RISCV_SOL_FRAME_SIZE 240 +#else +#define TX_RISCV_SOL_FRAME_SIZE 128 +#endif + + #ifndef __ASSEMBLER__ /* Include for memset. */ @@ -62,6 +106,7 @@ /* Yes, include the user defines in tx_user.h. The defines in this file may alternately be defined on the command line. */ + #include "tx_user.h" #endif /* TX_INCLUDE_USER_DEFINE_FILE */ @@ -90,10 +135,9 @@ typedef unsigned long long ULONG64; typedef short SHORT; typedef unsigned short USHORT; #define ULONG64_DEFINED -#endif /* __ASSEMBLER__ */ - #define ALIGN_TYPE_DEFINED typedef unsigned long long ALIGN_TYPE; +#endif /* __ASSEMBLER__ */ /* On RV64, ULONG is 32-bit but pointers are 64-bit. Store the thread pointer in the timer's VOID * extension field so _tx_thread_timeout diff --git a/ports/risc-v64/gnu/readme_threadx.txt b/ports/risc-v64/gnu/readme_threadx.txt index 83e666c7b..a83da8426 100644 --- a/ports/risc-v64/gnu/readme_threadx.txt +++ b/ports/risc-v64/gnu/readme_threadx.txt @@ -13,6 +13,15 @@ Verify the toolchain: riscv64-unknown-elf-gcc --version riscv64-unknown-elf-objdump --version +ISA and ABI requirements +- The ISA string must include Zicsr. rv64gc and rv64imafdc imply it; + rv64imac does not, so write rv64imac_zicsr for an integer-only build. +- Supported ABIs: lp64d (FLEN=64), lp64f (FLEN=32 or FLEN=64), and lp64 + only when the ISA has no F or D extension. lp64q is not supported. +- The vector extension (V) is optional; the port saves the full vector + state and sizes the frame from vlenb. +- tx_port.h rejects every other combination at compile time. + CMake-based build (recommended) From the ThreadX top-level directory: diff --git a/ports/risc-v64/gnu/src/tx_initialize_low_level.S b/ports/risc-v64/gnu/src/tx_initialize_low_level.S index 6a35272f6..952be9571 100644 --- a/ports/risc-v64/gnu/src/tx_initialize_low_level.S +++ b/ports/risc-v64/gnu/src/tx_initialize_low_level.S @@ -79,10 +79,26 @@ _tx_initialize_low_level: /* Initialize floating point control/status register if floating point is enabled. */ #ifdef __riscv_flen +#ifdef TX_RISCV_SMODE + li t0, 0x2000 // Set sstatus.FS to Initial (bits 14:13 = 01) so the fcsr write cannot trap + csrrs zero, sstatus, t0 +#else + li t0, 0x2000 // Set mstatus.FS to Initial (bits 14:13 = 01) so the fcsr write cannot trap + csrrs zero, mstatus, t0 +#endif li t0, 0 csrw fcsr, t0 // Clear FP control/status register #endif +#ifdef __riscv_vector + li t0, 0x200 // Set VS=Initial before a vector restore +#ifdef TX_RISCV_SMODE + csrrs zero, sstatus, t0 +#else + csrrs zero, mstatus, t0 +#endif +#endif + ret /* Timer Interrupt Handler Note: diff --git a/ports/risc-v64/gnu/src/tx_thread_context_restore.S b/ports/risc-v64/gnu/src/tx_thread_context_restore.S index cebc8a062..6ffb541e7 100644 --- a/ports/risc-v64/gnu/src/tx_thread_context_restore.S +++ b/ports/risc-v64/gnu/src/tx_thread_context_restore.S @@ -58,6 +58,8 @@ /**************************************************************************/ /* VOID _tx_thread_context_restore(VOID) { */ +#include "tx_port.h" + .equ TX_TRAP_FRAME_SIZE, TX_RISCV_TRAP_FRAME_SIZE .global _tx_thread_context_restore _tx_thread_context_restore: @@ -89,7 +91,7 @@ _tx_thread_context_restore: interrupt. */ /* Recover floating point registers. */ -#if defined(__riscv_float_abi_single) +#if (__riscv_flen == 32) flw f0, 31*8(sp) // Recover ft0 flw f1, 32*8(sp) // Recover ft1 flw f2, 33*8(sp) // Recover ft2 @@ -112,7 +114,7 @@ _tx_thread_context_restore: flw f31,62*8(sp) // Recover ft11 ld t0, 63*8(sp) // Recover fcsr csrw fcsr, t0 // Restore fcsr -#elif defined(__riscv_float_abi_double) +#elif (__riscv_flen == 64) fld f0, 31*8(sp) // Recover ft0 fld f1, 32*8(sp) // Recover ft1 fld f2, 33*8(sp) // Recover ft2 @@ -121,6 +123,20 @@ _tx_thread_context_restore: fld f5, 36*8(sp) // Recover ft5 fld f6, 37*8(sp) // Recover ft6 fld f7, 38*8(sp) // Recover ft7 +#if defined(__riscv_float_abi_single) + fld f8, 39*8(sp) // Recover fs0 + fld f9, 40*8(sp) // Recover fs1 + fld f18, 49*8(sp) // Recover fs2 + fld f19, 50*8(sp) // Recover fs3 + fld f20, 51*8(sp) // Recover fs4 + fld f21, 52*8(sp) // Recover fs5 + fld f22, 53*8(sp) // Recover fs6 + fld f23, 54*8(sp) // Recover fs7 + fld f24, 55*8(sp) // Recover fs8 + fld f25, 56*8(sp) // Recover fs9 + fld f26, 57*8(sp) // Recover fs10 + fld f27, 58*8(sp) // Recover fs11 +#endif fld f10,41*8(sp) // Recover fa0 fld f11,42*8(sp) // Recover fa1 fld f12,43*8(sp) // Recover fa2 @@ -188,6 +204,10 @@ _tx_thread_context_restore: #if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) li t0, 0x6000 // Set FS=Dirty (bits 14:13) for FP state or t1, t1, t0 +#endif +#if defined(__riscv_vector) + li t0, 0x0600 + or t1, t1, t0 #endif csrw sstatus, t1 // Update sstatus safely #else @@ -203,11 +223,11 @@ _tx_thread_context_restore: andi t1, t1, ~0x8 // Clear MIE, Hardware will restore it from MPIE #if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - li t0, 0x2000 // Set FS bits (bits 14:13 to 01) for FP state + li t0, 0x6000 or t1, t1, t0 #endif #if defined(__riscv_vector) - li t0, 0x0200 // Set VS bits (bits 10:9 to 01) for vector state + li t0, 0x0600 or t1, t1, t0 #endif csrw mstatus, t1 // Update mstatus safely @@ -231,18 +251,10 @@ _tx_thread_context_restore: ld t5, 14*8(sp) // Recover t5 ld t6, 13*8(sp) // Recover t6 -#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - addi sp, sp, 65*8 // Recover stack frame - with floating point enabled -#else - addi sp, sp, 32*8 // Recover stack frame - without floating point enabled -#endif + addi sp, sp, TX_TRAP_FRAME_SIZE // Recover stack frame - with floating point enabled (65*8 data + 8 pad) #if defined(__riscv_vector) -#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - addi t0, sp, -65*8 -#else - addi t0, sp, -32*8 -#endif + addi t0, sp, -TX_TRAP_FRAME_SIZE csrr t1, vlenb // Get vector register byte length slli t1, t1, 5 // Multiply by 32 (number of vector registers) addi t1, t1, 4*8 // Add vector CSR space: vstart, vtype, vl, vcsr @@ -270,7 +282,7 @@ _tx_thread_not_nested_restore: la t0, _tx_thread_preempt_disable // Pickup preempt disable flag address lw t2, 0(t0) // Pickup preempt disable flag (UINT) - bgtz t2, _tx_thread_no_preempt_restore // If set, restore interrupted thread + bnez t2, _tx_thread_no_preempt_restore // If set (nonzero), restore interrupted thread la t0, _tx_thread_execute_ptr // Pickup thread execute pointer address ld t2, 0(t0) // Pickup thread execute pointer @@ -286,7 +298,7 @@ _tx_thread_no_preempt_restore: ld sp, 8(t1) // Switch back to thread's stack /* Recover floating point registers. */ -#if defined(__riscv_float_abi_single) +#if (__riscv_flen == 32) flw f0, 31*8(sp) // Recover ft0 flw f1, 32*8(sp) // Recover ft1 flw f2, 33*8(sp) // Recover ft2 @@ -309,7 +321,7 @@ _tx_thread_no_preempt_restore: flw f31,62*8(sp) // Recover ft11 ld t0, 63*8(sp) // Recover fcsr csrw fcsr, t0 // Restore fcsr -#elif defined(__riscv_float_abi_double) +#elif (__riscv_flen == 64) fld f0, 31*8(sp) // Recover ft0 fld f1, 32*8(sp) // Recover ft1 fld f2, 33*8(sp) // Recover ft2 @@ -318,6 +330,20 @@ _tx_thread_no_preempt_restore: fld f5, 36*8(sp) // Recover ft5 fld f6, 37*8(sp) // Recover ft6 fld f7, 38*8(sp) // Recover ft7 +#if defined(__riscv_float_abi_single) + fld f8, 39*8(sp) // Recover fs0 + fld f9, 40*8(sp) // Recover fs1 + fld f18, 49*8(sp) // Recover fs2 + fld f19, 50*8(sp) // Recover fs3 + fld f20, 51*8(sp) // Recover fs4 + fld f21, 52*8(sp) // Recover fs5 + fld f22, 53*8(sp) // Recover fs6 + fld f23, 54*8(sp) // Recover fs7 + fld f24, 55*8(sp) // Recover fs8 + fld f25, 56*8(sp) // Recover fs9 + fld f26, 57*8(sp) // Recover fs10 + fld f27, 58*8(sp) // Recover fs11 +#endif fld f10,41*8(sp) // Recover fa0 fld f11,42*8(sp) // Recover fa1 fld f12,43*8(sp) // Recover fa2 @@ -383,6 +409,10 @@ _tx_thread_no_preempt_restore: #if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) li t0, 0x6000 // Set FS=Dirty (bits 14:13) for FP state or t1, t1, t0 +#endif +#if defined(__riscv_vector) + li t0, 0x0600 // Set VS bits (bits 10:9 to 11, Dirty) for restored vector state + or t1, t1, t0 #endif csrw sstatus, t1 // Update sstatus safely #else @@ -399,11 +429,11 @@ _tx_thread_no_preempt_restore: andi t1, t1, ~0x8 // Clear MIE, Hardware will restore it from MPIE #if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - li t0, 0x2000 // Set FS bits for FP state + li t0, 0x6000 or t1, t1, t0 #endif #if defined(__riscv_vector) - li t0, 0x0200 // Set VS bits (bits 10:9 to 01) for vector state + li t0, 0x0600 or t1, t1, t0 #endif csrw mstatus, t1 // Update mstatus safely @@ -427,18 +457,10 @@ _tx_thread_no_preempt_restore: ld t5, 14*8(sp) // Recover t5 ld t6, 13*8(sp) // Recover t6 -#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - addi sp, sp, 65*8 // Recover stack frame - with floating point enabled -#else - addi sp, sp, 32*8 // Recover stack frame - without floating point enabled -#endif + addi sp, sp, TX_TRAP_FRAME_SIZE // Recover stack frame #if defined(__riscv_vector) -#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - addi t0, sp, -65*8 -#else - addi t0, sp, -32*8 -#endif + addi t0, sp, -TX_TRAP_FRAME_SIZE csrr t1, vlenb // Get vector register byte length slli t1, t1, 5 // Multiply by 32 (number of vector registers) addi t1, t1, 4*8 // Add vector CSR space: vstart, vtype, vl, vcsr @@ -464,8 +486,10 @@ _tx_thread_preempt_restore: ori t3, zero, 1 // Build interrupt stack type sd t3, 0(t0) // Store stack type - /* Store floating point preserved registers. */ -#ifdef __riscv_float_abi_single + /* Store floating point preserved registers. LP64F saved the complete + FLEN=64 state before the C interrupt handler ran. */ +#if !defined(__riscv_float_abi_single) || (__riscv_flen != 64) +#if (__riscv_flen == 32) fsw f8, 39*8(t0) // Store fs0 fsw f9, 40*8(t0) // Store fs1 fsw f18, 49*8(t0) // Store fs2 @@ -478,7 +502,7 @@ _tx_thread_preempt_restore: fsw f25, 56*8(t0) // Store fs9 fsw f26, 57*8(t0) // Store fs10 fsw f27, 58*8(t0) // Store fs11 -#elif defined(__riscv_float_abi_double) +#elif (__riscv_flen == 64) fsd f8, 39*8(t0) // Store fs0 fsd f9, 40*8(t0) // Store fs1 fsd f18, 49*8(t0) // Store fs2 @@ -492,37 +516,13 @@ _tx_thread_preempt_restore: fsd f26, 57*8(t0) // Store fs10 fsd f27, 58*8(t0) // Store fs11 #endif - -#if defined(__riscv_vector) - /* Store vector registers and CSRs */ -#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - addi t1, t0, 64*8 -#else - addi t1, t0, 31*8 -#endif - /* Store vector CSRs */ - csrr t2, vstart // Store vstart - sd t2, 0*8(t1) - csrr t2, vtype // Store vtype - sd t2, 1*8(t1) - csrr t2, vl // Store vl - sd t2, 2*8(t1) - csrr t2, vcsr // Store vcsr - sd t2, 3*8(t1) - - /* Store vector registers v0-v31 */ - addi t2, t1, 4*8 - vsetvli t3, zero, e8, m8, ta, ma - vse8.v v0, 0(t2) // Store v0 ~ v7 - add t2, t2, t3 - vse8.v v8, 0(t2) // Store v8 ~ v15 - add t2, t2, t3 - vse8.v v16, 0(t2) // Store v16 ~ v23 - add t2, t2, t3 - vse8.v v24, 0(t2) // Store v24 ~ v31 - add t2, t2, t3 #endif + /* No vector save here. _tx_thread_context_save stored v0-v31 and the + vector CSRs before the C handler ran. The psABI treats v0-v31, vl and + vtype as caller-saved, so the handler may have changed them; a second + store here would overwrite the good copy with the handler's state. */ + /* Store standard preserved registers. */ sd x9, 11*8(t0) // Store s1 diff --git a/ports/risc-v64/gnu/src/tx_thread_context_save.S b/ports/risc-v64/gnu/src/tx_thread_context_save.S index 8cbfa32cd..d8526fd98 100644 --- a/ports/risc-v64/gnu/src/tx_thread_context_save.S +++ b/ports/risc-v64/gnu/src/tx_thread_context_save.S @@ -22,6 +22,8 @@ /**************************************************************************/ .section .text +#include "tx_port.h" + .equ TX_TRAP_FRAME_SIZE, TX_RISCV_TRAP_FRAME_SIZE /**************************************************************************/ /* */ /* FUNCTION RELEASE */ @@ -68,14 +70,14 @@ _tx_thread_context_save: sd t1, 18*8(sp) la t0, _tx_thread_system_state // Pickup address of system state - ld t1, 0(t0) // Pickup system state + lw t1, 0(t0) // Pickup system state /* Check for a nested interrupt condition. */ /* if (_tx_thread_system_state++) { */ beqz t1, _tx_thread_not_nested_save // If 0, first interrupt condition addi t1, t1, 1 // Increment the interrupt counter - sd t1, 0(t0) // Store the interrupt counter + sw t1, 0(t0) // Store the interrupt counter /* Nested interrupt condition. Save the rest of the scratch registers on the stack and return to the @@ -103,7 +105,7 @@ _tx_thread_context_save: sd t0, 30*8(sp) // Save it on the stack /* Save floating point scratch registers if floating point is enabled. */ -#ifdef __riscv_float_abi_single +#if (__riscv_flen == 32) fsw f0, 31*8(sp) // Store ft0 fsw f1, 32*8(sp) // Store ft1 fsw f2, 33*8(sp) // Store ft2 @@ -126,7 +128,7 @@ _tx_thread_context_save: fsw f31,62*8(sp) // Store ft11 csrr t0, fcsr sd t0, 63*8(sp) // Store fcsr -#elif defined(__riscv_float_abi_double) +#elif (__riscv_flen == 64) fsd f0, 31*8(sp) // Store ft0 fsd f1, 32*8(sp) // Store ft1 fsd f2, 33*8(sp) // Store ft2 @@ -135,6 +137,20 @@ _tx_thread_context_save: fsd f5, 36*8(sp) // Store ft5 fsd f6, 37*8(sp) // Store ft6 fsd f7, 38*8(sp) // Store ft7 +#if defined(__riscv_float_abi_single) + fsd f8, 39*8(sp) // Store fs0 + fsd f9, 40*8(sp) // Store fs1 + fsd f18, 49*8(sp) // Store fs2 + fsd f19, 50*8(sp) // Store fs3 + fsd f20, 51*8(sp) // Store fs4 + fsd f21, 52*8(sp) // Store fs5 + fsd f22, 53*8(sp) // Store fs6 + fsd f23, 54*8(sp) // Store fs7 + fsd f24, 55*8(sp) // Store fs8 + fsd f25, 56*8(sp) // Store fs9 + fsd f26, 57*8(sp) // Store fs10 + fsd f27, 58*8(sp) // Store fs11 +#endif fsd f10,41*8(sp) // Store fa0 fsd f11,42*8(sp) // Store fa1 fsd f12,43*8(sp) // Store fa2 @@ -198,7 +214,7 @@ _tx_thread_not_nested_save: /* else if (_tx_thread_current_ptr) { */ addi t1, t1, 1 // Increment the interrupt counter - sd t1, 0(t0) // Store the interrupt counter + sw t1, 0(t0) // Store the interrupt counter /* Not nested: Find the user thread that was running and load our SP */ @@ -231,7 +247,7 @@ _tx_thread_not_nested_save: sd t1, 30*8(sp) // Save it on the stack /* Save floating point scratch registers if floating point is enabled. */ -#ifdef __riscv_float_abi_single +#if (__riscv_flen == 32) fsw f0, 31*8(sp) // Store ft0 fsw f1, 32*8(sp) // Store ft1 fsw f2, 33*8(sp) // Store ft2 @@ -254,7 +270,7 @@ _tx_thread_not_nested_save: fsw f31,62*8(sp) // Store ft11 csrr t0, fcsr sd t0, 63*8(sp) // Store fcsr -#elif defined(__riscv_float_abi_double) +#elif (__riscv_flen == 64) fsd f0, 31*8(sp) // Store ft0 fsd f1, 32*8(sp) // Store ft1 fsd f2, 33*8(sp) // Store ft2 @@ -263,6 +279,20 @@ _tx_thread_not_nested_save: fsd f5, 36*8(sp) // Store ft5 fsd f6, 37*8(sp) // Store ft6 fsd f7, 38*8(sp) // Store ft7 +#if defined(__riscv_float_abi_single) + fsd f8, 39*8(sp) // Store fs0 + fsd f9, 40*8(sp) // Store fs1 + fsd f18, 49*8(sp) // Store fs2 + fsd f19, 50*8(sp) // Store fs3 + fsd f20, 51*8(sp) // Store fs4 + fsd f21, 52*8(sp) // Store fs5 + fsd f22, 53*8(sp) // Store fs6 + fsd f23, 54*8(sp) // Store fs7 + fsd f24, 55*8(sp) // Store fs8 + fsd f25, 56*8(sp) // Store fs9 + fsd f26, 57*8(sp) // Store fs10 + fsd f27, 58*8(sp) // Store fs11 +#endif fsd f10,41*8(sp) // Store fa0 fsd f11,42*8(sp) // Store fa1 fsd f12,43*8(sp) // Store fa2 @@ -351,18 +381,10 @@ _tx_thread_idle_system_save: /* } } */ -#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - addi sp, sp, 65*8 // Recover stack frame - with floating point enabled -#else - addi sp, sp, 32*8 // Recover the reserved stack space -#endif + addi sp, sp, TX_TRAP_FRAME_SIZE // Recover stack frame - with floating point enabled (65*8 data + 8 pad) #if defined(__riscv_vector) -#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - addi t0, sp, -65*8 -#else - addi t0, sp, -32*8 -#endif + addi t0, sp, -TX_TRAP_FRAME_SIZE csrr t1, vlenb // Get vector register byte length slli t1, t1, 5 // Multiply by 32 (number of vector registers) addi t1, t1, 4*8 // Add vector CSR space: vstart, vtype, vl, vcsr diff --git a/ports/risc-v64/gnu/src/tx_thread_interrupt_control.S b/ports/risc-v64/gnu/src/tx_thread_interrupt_control.S index b43d95589..d791e5089 100644 --- a/ports/risc-v64/gnu/src/tx_thread_interrupt_control.S +++ b/ports/risc-v64/gnu/src/tx_thread_interrupt_control.S @@ -27,7 +27,7 @@ /* FUNCTION RELEASE */ /* */ /* _tx_thread_interrupt_control RISC-V64/GNU */ -/* 6.2.1 */ +/* 6.5.1.202602a */ /* AUTHOR */ /* */ /* Scott Larson, Microsoft Corporation */ @@ -61,23 +61,25 @@ _tx_thread_interrupt_control: /* Pickup current interrupt lockout posture. */ #ifdef TX_RISCV_SMODE - csrr t0, sstatus - mv t1, t0 // Save original sstatus for return - li t2, ~0x02 // Build mask to clear SIE (bit 1) - and t0, t0, t2 // Clear SIE bit + li t1, 0x02 // Build SIE bit mask (bit 1) andi a0, a0, 0x02 // Mask incoming to only SIE bit - or t0, t0, a0 // Set requested SIE state - csrw sstatus, t0 - andi a0, t1, 0x02 // Return original SIE bit + bnez a0, 1f // If set, enable interrupts + csrrc t0, sstatus, t1 // Atomically clear SIE, read old sstatus + j 2f +1: + csrrs t0, sstatus, t1 // Atomically set SIE, read old sstatus +2: + andi a0, t0, 0x02 // Return original SIE bit #else - csrr t0, mstatus - mv t1, t0 // Save original mstatus for return - li t2, ~0x08 // Build mask to clear MIE - and t0, t0, t2 // Clear MIE bit + li t1, 0x08 // Build MIE bit mask (bit 3) andi a0, a0, 0x08 // Mask incoming to only MIE bit - or t0, t0, a0 // Set requested MIE state - csrw mstatus, t0 - andi a0, t1, 0x08 // Return original MIE bit + bnez a0, 1f // If set, enable interrupts + csrrc t0, mstatus, t1 // Atomically clear MIE, read old mstatus + j 2f +1: + csrrs t0, mstatus, t1 // Atomically set MIE, read old mstatus +2: + andi a0, t0, 0x08 // Return original MIE bit #endif ret /* } */ diff --git a/ports/risc-v64/gnu/src/tx_thread_schedule.S b/ports/risc-v64/gnu/src/tx_thread_schedule.S index 860adf0b6..85405c9e0 100644 --- a/ports/risc-v64/gnu/src/tx_thread_schedule.S +++ b/ports/risc-v64/gnu/src/tx_thread_schedule.S @@ -58,6 +58,9 @@ /**************************************************************************/ /* VOID _tx_thread_schedule(VOID) { */ +#include "tx_port.h" + .equ TX_TRAP_FRAME_SIZE, TX_RISCV_TRAP_FRAME_SIZE + .equ TX_SOL_FRAME_SIZE, TX_RISCV_SOL_FRAME_SIZE .global _tx_thread_schedule _tx_thread_schedule: @@ -142,7 +145,7 @@ _tx_thread_schedule_loop: /* Determine if floating point registers need to be recovered. */ -#if defined(__riscv_float_abi_single) +#if (__riscv_flen == 32) flw f0, 31*8(sp) // Recover ft0 flw f1, 32*8(sp) // Recover ft1 flw f2, 33*8(sp) // Recover ft2 @@ -177,7 +180,7 @@ _tx_thread_schedule_loop: flw f31,62*8(sp) // Recover ft11 ld t0, 63*8(sp) // Recover fcsr csrw fcsr, t0 // Restore fcsr -#elif defined(__riscv_float_abi_double) +#elif (__riscv_flen == 64) fld f0, 31*8(sp) // Recover ft0 fld f1, 32*8(sp) // Recover ft1 fld f2, 33*8(sp) // Recover ft2 @@ -258,6 +261,10 @@ _tx_thread_schedule_loop: #if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) li t1, 0x6000 // Set FS=Dirty (bits 14:13) or t0, t0, t1 +#endif +#if defined(__riscv_vector) + li t1, 0x0600 + or t0, t0, t1 #endif csrw sstatus, t0 // Update sstatus safely #else @@ -274,7 +281,7 @@ _tx_thread_schedule_loop: or t0, t0, t1 #endif #if defined(__riscv_vector) - li t1, 0x0200 // Set VS bits (bits 10:9 to 01) for vector state + li t1, 0x0600 or t0, t0, t1 #endif csrw mstatus, t0 // Set mstatus @@ -309,17 +316,9 @@ _tx_thread_schedule_loop: ld t5, 14*8(sp) // Recover t5 ld t6, 13*8(sp) // Recover t6 -#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - addi sp, sp, 65*8 // Recover stack frame - with floating point registers -#else - addi sp, sp, 32*8 // Recover stack frame - without floating point registers -#endif + addi sp, sp, TX_TRAP_FRAME_SIZE // Recover stack frame - with floating point registers (65*8 data + 8 pad) #if defined(__riscv_vector) -#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - addi t0, sp, -65*8 -#else - addi t0, sp, -32*8 -#endif + addi t0, sp, -TX_TRAP_FRAME_SIZE csrr t1, vlenb // Get vector register byte length slli t1, t1, 5 // Multiply by 32 (number of vector registers) addi t1, t1, 4*8 // Add vector CSR space: vstart, vtype, vl, vcsr @@ -336,7 +335,7 @@ _tx_thread_schedule_loop: _tx_thread_synch_return: -#if defined(__riscv_float_abi_single) +#if (__riscv_flen == 32) flw f8, 15*8(sp) // Recover fs0 flw f9, 16*8(sp) // Recover fs1 flw f18,17*8(sp) // Recover fs2 @@ -351,7 +350,7 @@ _tx_thread_synch_return: flw f27,26*8(sp) // Recover fs11 ld t0, 27*8(sp) // Recover fcsr csrw fcsr, t0 // -#elif defined(__riscv_float_abi_double) +#elif (__riscv_flen == 64) fld f8, 15*8(sp) // Recover fs0 fld f9, 16*8(sp) // Recover fs1 fld f18,17*8(sp) // Recover fs2 @@ -418,11 +417,7 @@ _tx_thread_synch_return: #else csrw mstatus, t0 // Store mstatus, enables interrupt #endif -#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - addi sp, sp, 29*8 // Recover stack frame -#else - addi sp, sp, 16*8 // Recover stack frame -#endif + addi sp, sp, TX_SOL_FRAME_SIZE // Recover stack frame (29*8 data + 8 pad) #if defined(__riscv_vector) csrr t1, vlenb // Get vector register byte length slli t1, t1, 5 // Multiply by 32 (number of vector registers) diff --git a/ports/risc-v64/gnu/src/tx_thread_stack_build.S b/ports/risc-v64/gnu/src/tx_thread_stack_build.S index 86cab4f09..8d478242e 100644 --- a/ports/risc-v64/gnu/src/tx_thread_stack_build.S +++ b/ports/risc-v64/gnu/src/tx_thread_stack_build.S @@ -21,6 +21,8 @@ /**************************************************************************/ .section .text +#include "tx_port.h" + .equ TX_TRAP_FRAME_SIZE, TX_RISCV_TRAP_FRAME_SIZE /**************************************************************************/ /* */ /* FUNCTION RELEASE */ @@ -138,6 +140,9 @@ If vector extension support: ... v31 99 Initial v31 + With floating point enabled, 8 pad bytes sit at the top of the frame + (bytes 520-527) so the 528-byte total keeps sp 16-byte aligned. + Stack Bottom: (higher memory address) */ ld t0, 24(a0) // Pickup end of stack area @@ -146,11 +151,7 @@ If vector extension support: /* Actually build the stack frame. */ -#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - addi t0, t0, -65*8 -#else - addi t0, t0, -32*8 // Allocate space for the stack frame -#endif + addi t0, t0, -TX_TRAP_FRAME_SIZE #if defined(__riscv_vector) /* Vector extension support: calculate space based on vlenb */ @@ -226,8 +227,7 @@ If vector extension support: sd zero, 60*8(t0) // Initial ft9 sd zero, 61*8(t0) // Initial ft10 sd zero, 62*8(t0) // Initial ft11 - csrr a1, fcsr // Read fcsr for initial value - sd a1, 63*8(t0) // Initial fcsr + sd zero, 63*8(t0) // Initial fcsr (0: no sticky flags, round-to-nearest) #endif #if defined(__riscv_vector) diff --git a/ports/risc-v64/gnu/src/tx_thread_system_return.S b/ports/risc-v64/gnu/src/tx_thread_system_return.S index 583b3f3ee..2f4daeede 100644 --- a/ports/risc-v64/gnu/src/tx_thread_system_return.S +++ b/ports/risc-v64/gnu/src/tx_thread_system_return.S @@ -57,17 +57,15 @@ /**************************************************************************/ /* VOID _tx_thread_system_return(VOID) { */ +#include "tx_port.h" + .equ TX_SOL_FRAME_SIZE, TX_RISCV_SOL_FRAME_SIZE .global _tx_thread_system_return _tx_thread_system_return: /* Save minimal context on the stack. */ /* sp -= sizeof(stack_frame); */ -#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - addi sp, sp, -29*8 // Allocate space on the stack - with floating point enabled -#else - addi sp, sp, -16*8 // Allocate space on the stack - without floating point enabled -#endif + addi sp, sp, -TX_SOL_FRAME_SIZE // Allocate space on the stack #if defined(__riscv_vector) csrr t1, vlenb // Get vector register byte length slli t1, t1, 5 // Multiply by 32 (number of vector registers) @@ -76,7 +74,7 @@ _tx_thread_system_return: #endif /* Store floating point preserved registers. */ -#if defined(__riscv_float_abi_single) +#if (__riscv_flen == 32) fsw f8, 15*8(sp) // Store fs0 fsw f9, 16*8(sp) // Store fs1 fsw f18, 17*8(sp) // Store fs2 @@ -91,7 +89,7 @@ _tx_thread_system_return: fsw f27, 26*8(sp) // Store fs11 csrr t0, fcsr sd t0, 27*8(sp) // Store fcsr -#elif defined(__riscv_float_abi_double) +#elif (__riscv_flen == 64) fsd f8, 15*8(sp) // Store fs0 fsd f9, 16*8(sp) // Store fs1 fsd f18, 17*8(sp) // Store fs2 diff --git a/ports/risc-v64/gnu/src/tx_timer_interrupt.S b/ports/risc-v64/gnu/src/tx_timer_interrupt.S index 53e572f32..207d66772 100644 --- a/ports/risc-v64/gnu/src/tx_timer_interrupt.S +++ b/ports/risc-v64/gnu/src/tx_timer_interrupt.S @@ -88,7 +88,7 @@ _tx_timer_interrupt: /* Check for expiration. */ /* if (_tx_timer_time_slice == 0) */ - bgtz t3, _tx_timer_no_time_slice // If not 0, has not expired yet + bnez t3, _tx_timer_no_time_slice // If not 0, has not expired yet li t1, 1 // Build expired flag /* Set the time-slice expired flag. */ @@ -181,7 +181,7 @@ _tx_timer_dont_activate: /* if (_tx_timer_expired_time_slice) { */ - andi t2, t6, 1 // Is the timer expired bit set? + andi t2, t6, 1 // Is the time-slice expired bit set? beqz t2, _tx_timer_not_ts_expiration // If not, skip time slice processing /* Time slice interrupted thread. */ diff --git a/ports/risc-v_common/example_build/plic/plic.c b/ports/risc-v_common/example_build/plic/plic.c index 21421a725..3af6f8a9a 100644 --- a/ports/risc-v_common/example_build/plic/plic.c +++ b/ports/risc-v_common/example_build/plic/plic.c @@ -9,21 +9,42 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* PLIC driver for the QEMU virt machine (RV32 and RV64), + M-mode context. */ + #include "plic.h" #include irq_callback callbacks[MAX_CALLBACK_NUM]; +/* Enable word that holds source irqno for this hart's M-mode context. */ +static volatile uint32_t *plic_enable_word(int hart, int irqno) +{ + return (volatile uint32_t *)(PLIC_MENABLE(hart) + ((unsigned int)irqno / 32u) * 4u); +} + void plic_irq_enable(int irqno) { int hart = riscv_get_core(); - *(uint32_t*)PLIC_MENABLE(hart) = (*(uint32_t*)PLIC_MENABLE(hart) | (1 << irqno)); + volatile uint32_t *reg; + + if ((irqno <= 0) || (irqno >= MAX_CALLBACK_NUM)) + return; + + reg = plic_enable_word(hart, irqno); + *reg = *reg | (1u << ((unsigned int)irqno % 32u)); } void plic_irq_disable(int irqno) { int hart = riscv_get_core(); - *(uint32_t*)PLIC_MENABLE(hart) = (*(uint32_t*)PLIC_MENABLE(hart) & (~(1 << irqno))); + volatile uint32_t *reg; + + if ((irqno <= 0) || (irqno >= MAX_CALLBACK_NUM)) + return; + + reg = plic_enable_word(hart, irqno); + *reg = *reg & ~(1u << ((unsigned int)irqno % 32u)); } void plic_prio_set(int irqno, int prio) @@ -33,7 +54,7 @@ void plic_prio_set(int irqno, int prio) int plic_prio_get(int irqno) { - return PLIC_GET_PRIO(irqno); + return (int)PLIC_GET_PRIO(irqno); } int plic_register_callback(int irqno, irq_callback callback) @@ -51,29 +72,51 @@ int plic_unregister_callback(int irqno) int plic_init(void) { + int hart = riscv_get_core(); + for (int i = 0; i < MAX_CALLBACK_NUM; i++) callbacks[i] = NULL; + + /* Do not depend on the reset state or on a prior boot stage: accept + every priority (threshold 0) and start with all sources for this + hart disabled. Drivers enable their own sources. */ + *(volatile uint32_t *)PLIC_MPRIORITY(hart) = 0; + for (int w = 0; w < MAX_CALLBACK_NUM / 32; w++) + *(volatile uint32_t *)(PLIC_MENABLE(hart) + (unsigned int)w * 4u) = 0; + return 0; } int plic_claim(void) { int hart = riscv_get_core(); - return (*(uint32_t*)PLIC_MCLAIM(hart)); + return (int)(*(volatile uint32_t *)PLIC_MCLAIM(hart)); } void plic_complete(int irqno) { int hart = riscv_get_core(); - *(uint32_t*)(PLIC_MCOMPLETE(hart)) = (uint32_t)irqno; + *(volatile uint32_t *)(PLIC_MCOMPLETE(hart)) = (uint32_t)irqno; } int plic_irq_intr(void) { int ret = -1; int irqno = plic_claim(); + + if (irqno == 0) + return 0; + + if ((irqno < 0) || (irqno >= MAX_CALLBACK_NUM)) + { + if (irqno > 0) + plic_complete(irqno); + return -1; + } + if (callbacks[irqno] != NULL) ret = (callbacks[irqno])(irqno); + plic_complete(irqno); return ret; } diff --git a/ports/risc-v_common/example_build/plic/plic.h b/ports/risc-v_common/example_build/plic/plic.h index 29d29c57c..3b5403635 100644 --- a/ports/risc-v_common/example_build/plic/plic.h +++ b/ports/risc-v_common/example_build/plic/plic.h @@ -27,8 +27,8 @@ #define PLIC_MCOMPLETE(hart) (PLIC + 0x200004 + (hart)*0x2000) #define PLIC_SCOMPLETE(hart) (PLIC + 0x201004 + (hart)*0x2000) -#define PLIC_GET_PRIO(irqno) (*(uint32_t *)(PLIC_PRIORITY + (irqno)*4)) -#define PLIC_SET_PRIO(irqno, prio) (*(uint32_t *)(PLIC_PRIORITY + (irqno)*4) = (prio)) +#define PLIC_GET_PRIO(irqno) (*(volatile uint32_t *)(PLIC_PRIORITY + (irqno)*4)) +#define PLIC_SET_PRIO(irqno, prio) (*(volatile uint32_t *)(PLIC_PRIORITY + (irqno)*4) = (prio)) #define MAX_CALLBACK_NUM 128 typedef int (*irq_callback)(int irqno); diff --git a/ports/risc-v_common/example_build/trap/trap_qemu.c b/ports/risc-v_common/example_build/trap/trap_qemu.c index c9d8a0033..8326cd7c2 100644 --- a/ports/risc-v_common/example_build/trap/trap_qemu.c +++ b/ports/risc-v_common/example_build/trap/trap_qemu.c @@ -14,6 +14,7 @@ * mcause constants use __riscv_xlen to resolve correctly for both ISAs: * RV32: interrupt bit = bit 31 (0x80000000) * RV64: interrupt bit = bit 63 (0x8000000000000000) + * */ #include "csr.h" @@ -23,6 +24,7 @@ #include "plic.h" #include #include +#include #define MCAUSE_INT_BIT ((uintptr_t)1 << (__riscv_xlen - 1)) @@ -30,11 +32,21 @@ #define OS_IS_TICK_INT(mcause) ((mcause) == (MCAUSE_INT_BIT | 7u)) #define OS_IS_SOFT_INT(mcause) ((mcause) == (MCAUSE_INT_BIT | 3u)) #define OS_IS_EXT_INT(mcause) ((mcause) == (MCAUSE_INT_BIT | 11u)) -#define OS_IS_TRAP_USER(mcause) ((mcause) == 11u) + +/* Synchronous exception codes (interrupt bit clear), privileged spec table + "Machine cause register (mcause) values after trap". */ +#define CAUSE_BREAKPOINT 3u +#define CAUSE_ECALL_U 8u +#define CAUSE_ECALL_S 9u +#define CAUSE_ECALL_M 11u + +/* Saved mepc lives in slot 30 of the interrupt frame that the trap entry + and _tx_thread_context_save build. One slot is XLEN/8 bytes on both + ports, so a uintptr_t index works for RV32 and RV64. */ +#define TX_RISCV_FRAME_MEPC_SLOT 30 extern void _tx_timer_interrupt(void); -#ifdef TX_RISCV_TRAP_DEBUG static void print_hex(uintptr_t val) { const char digits[] = "0123456789ABCDEF"; @@ -42,12 +54,29 @@ static void print_hex(uintptr_t val) uart_putc('x'); for (int i = (int)(sizeof(uintptr_t) * 2) - 1; i >= 0; i--) { - int d = (val >> (i * 4)) & 0xF; + int d = (int)((val >> (i * 4)) & 0xFu); uart_putc(digits[d]); } uart_putc('\n'); } -#endif /* TX_RISCV_TRAP_DEBUG */ + +static int trap_skip_instruction(uintptr_t mepc) +{ + TX_THREAD *thread_ptr = _tx_thread_current_ptr; + uintptr_t *frame; + uintptr_t length; + + if ((TX_THREAD_GET_SYSTEM_STATE() != 1u) || (thread_ptr == TX_NULL)) + return -1; + + /* A 32-bit instruction has its two low bits set; a compressed one does + not. ecall and ebreak are 32-bit, c.ebreak is 16-bit. */ + length = ((*(volatile uint16_t *)mepc & 3u) == 3u) ? 4u : 2u; + + frame = (uintptr_t *)thread_ptr->tx_thread_stack_ptr; + frame[TX_RISCV_FRAME_MEPC_SLOT] = mepc + length; + return 0; +} void trap_handler(uintptr_t mcause, uintptr_t mepc, uintptr_t mtval) { @@ -63,30 +92,42 @@ void trap_handler(uintptr_t mcause, uintptr_t mepc, uintptr_t mtval) int ret = plic_irq_intr(); if (ret) { - puts("[INTERRUPT]: handler irq error!"); + uart_puts("[INTERRUPT]: handler irq error!"); while (1) ; } } else { - puts("[INTERRUPT]: now can't deal with the interrupt!"); + uart_puts("[INTERRUPT]: unhandled interrupt, halting"); + uart_puts("mcause:"); + print_hex(mcause); while (1) ; } } else { - puts("[EXCEPTION] : Unknown Error!!"); -#ifdef TX_RISCV_TRAP_DEBUG - puts("mcause:"); + uart_puts("[EXCEPTION]"); + uart_puts("mcause:"); print_hex(mcause); - puts("mepc:"); + uart_puts("mepc:"); print_hex(mepc); - puts("mtval:"); + uart_puts("mtval:"); print_hex(mtval); -#else - (void)mepc; - (void)mtval; -#endif /* TX_RISCV_TRAP_DEBUG */ + + if ((mcause == CAUSE_BREAKPOINT) || (mcause == CAUSE_ECALL_U) || + (mcause == CAUSE_ECALL_S) || (mcause == CAUSE_ECALL_M)) + { + if (trap_skip_instruction(mepc) == 0) + { + uart_puts("[EXCEPTION]: ecall/ebreak skipped, resuming"); + return; + } + uart_puts("[EXCEPTION]: ecall/ebreak outside a thread, halting"); + } + else + { + uart_puts("[EXCEPTION]: unhandled exception, halting"); + } while (1) ; } } From 2e48ce0d1bf165a01335373f1b26cd33a11d9886 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Wed, 9 Sep 2026 09:31:00 -0400 Subject: [PATCH 108/181] Removed the stray build artifacts committed with the RISC-V64 port fix (#706) A local CMake build tree was staged by mistake alongside the RISC-V64 spec compliance work in #698, putting nine generated files on dev, including a compiled kernel.elf, build.ninja, the Ninja dependency logs and a QEMU run log. None of it belongs in the repository. The root .gitignore listed build directories by name rather than by pattern, so build/, build_qemu/, build_m7/ and the build_r52 variants were covered but a differently named tree was not. Those entries are replaced with a single build*/ pattern, which covers every existing name and any future one. No tracked file matches the new pattern. The artifacts remain reachable in history; only the working tree is corrected, since rewriting a shared branch is the greater harm. Assisted-by: Claude Code (Opus 5) --- .gitignore | 9 +- build-rv64/.ninja_deps | Bin 88232 -> 0 bytes build-rv64/.ninja_log | 402 -- build-rv64/CPackConfig.cmake | 76 - build-rv64/CPackSourceConfig.cmake | 83 - build-rv64/build.ninja | 3950 ----------------- build-rv64/custom_inc/tx_user.h | 298 -- .../gnu/example_build/qemu_virt/kernel.elf | Bin 239112 -> 0 bytes .../example_build/qemu_virt/qemu-riscv64.log | 235 - .../gnu/example_build/qemu_virt/test_cmds.gdb | 182 - 10 files changed, 1 insertion(+), 5234 deletions(-) delete mode 100644 build-rv64/.ninja_deps delete mode 100644 build-rv64/.ninja_log delete mode 100644 build-rv64/CPackConfig.cmake delete mode 100644 build-rv64/CPackSourceConfig.cmake delete mode 100644 build-rv64/build.ninja delete mode 100644 build-rv64/custom_inc/tx_user.h delete mode 100755 build-rv64/ports/risc-v64/gnu/example_build/qemu_virt/kernel.elf delete mode 100644 build-rv64/ports/risc-v64/gnu/example_build/qemu_virt/qemu-riscv64.log delete mode 100644 build-rv64/ports/risc-v64/gnu/example_build/qemu_virt/test_cmds.gdb diff --git a/.gitignore b/.gitignore index cadb24438..087f0e67e 100644 --- a/.gitignore +++ b/.gitignore @@ -3,8 +3,7 @@ .metadata/ .tmp/ _deps/ -build/ -build_qemu/ +build*/ Debug/ CMakeFiles/ CMakeScripts/ @@ -25,15 +24,9 @@ CTestTestfile.cmake # Local build artifacts -build_m7/ .codex -build_r52/ __pycache__/ *.pyc -build_r52_vfp/ -build_r52_uart/ -build_r52_mpu/ -build_r52_all/ # Keil uVision per-user state, regenerated when a project is opened. # The .uvprojx / .uvproj project files are the ones worth tracking. diff --git a/build-rv64/.ninja_deps b/build-rv64/.ninja_deps deleted file mode 100644 index 240c1db443b8618d68ecc1d0218e2ba77a19c244..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 88232 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 diff --git a/build-rv64/.ninja_log b/build-rv64/.ninja_log deleted file mode 100644 index c682ca139..000000000 --- a/build-rv64/.ninja_log +++ /dev/null @@ -1,402 +0,0 @@ -# ninja log v5 -4 21 1788959531418790526 CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_schedule.S.obj 3a400b6364e6794f -3 21 1788959531418790526 CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_initialize_low_level.S.obj 472097a3a070a693 -3 22 1788959531420614748 CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_context_restore.S.obj 685aa5da7671cc59 -3 22 1788959531419790394 CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_context_save.S.obj f89a6693e7ccf5df -4 22 1788959531418063193 CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_interrupt_control.S.obj c4f86abe3e1b2447 -4 23 1788959531418790526 CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_stack_build.S.obj 1d795aef6c2bcbb2 -4 23 1788959531418790526 CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_system_return.S.obj ea0323b283e0ce95 -4 23 1788959531419790394 CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_timer_interrupt.S.obj 2f8572c59cf518f -12 43 1788959531447351109 CMakeFiles/threadx.dir/common/src/tx_block_pool_initialize.c.obj a4254151a0de29e8 -23 54 1788959531457106052 CMakeFiles/threadx.dir/common/src/tx_byte_pool_initialize.c.obj 203e12b6fa18b976 -5 59 1788959531464047464 CMakeFiles/threadx.dir/common/src/tx_thread_delete.c.obj 1f9cc10cdfe42d77 -12 62 1788959531464047464 CMakeFiles/threadx.dir/common/src/tx_block_pool_info_get.c.obj c0e05c465fb36da2 -17 64 1788959531468209253 CMakeFiles/threadx.dir/common/src/tx_block_pool_performance_system_info_get.c.obj 38ee451e9c0d593d -23 69 1788959531473346045 CMakeFiles/threadx.dir/common/src/tx_byte_pool_info_get.c.obj 2d67f364cfcd6861 -5 74 1788959531469232697 CMakeFiles/threadx.dir/common/src/tx_thread_reset.c.obj 5e33a49b68c693fb -21 74 1788959531471468490 CMakeFiles/threadx.dir/common/src/tx_block_release.c.obj 77ba14c7d78b8401 -22 75 1788959531478246273 CMakeFiles/threadx.dir/common/src/tx_byte_pool_cleanup.c.obj b25a962a81e80ed3 -21 75 1788959531473979861 CMakeFiles/threadx.dir/common/src/tx_block_pool_prioritize.c.obj 7b3a1aae88c17849 -22 78 1788959531478246273 CMakeFiles/threadx.dir/common/src/tx_byte_pool_create.c.obj 1d2322a0cde5af84 -22 82 1788959531486125291 CMakeFiles/threadx.dir/common/src/tx_byte_allocate.c.obj 7e4476822cc9433a -5 84 1788959531486477458 CMakeFiles/threadx.dir/common/src/tx_block_allocate.c.obj d7d226a397e6572f -5 90 1788959531487582734 CMakeFiles/threadx.dir/common/src/tx_block_pool_create.c.obj e4bc5356fd952712 -5 90 1788959531493700416 CMakeFiles/threadx.dir/common/src/tx_block_pool_delete.c.obj 3bd4ffac3b2c556e -43 91 1788959531489564779 CMakeFiles/threadx.dir/common/src/tx_byte_pool_performance_info_get.c.obj 7d06ee00aa77354c -5 98 1788959531497339365 CMakeFiles/threadx.dir/common/src/tx_block_pool_cleanup.c.obj a3dc9eba3bdd181a -14 100 1788959531493700416 CMakeFiles/threadx.dir/common/src/tx_block_pool_performance_info_get.c.obj 7894825bd3dd6bfc -23 106 1788959531502247049 CMakeFiles/threadx.dir/common/src/tx_byte_pool_delete.c.obj 33e0eeb36e2aa751 -60 114 1788959531518326758 CMakeFiles/threadx.dir/common/src/tx_byte_pool_prioritize.c.obj 38960f2f17ed3440 -64 115 1788959531519696545 CMakeFiles/threadx.dir/common/src/tx_byte_release.c.obj 19dc4637dc26fd81 -75 117 1788959531520811800 CMakeFiles/threadx.dir/common/src/tx_event_flags_info_get.c.obj 66af35295b6da083 -54 125 1788959531529190609 CMakeFiles/threadx.dir/common/src/tx_byte_pool_performance_system_info_get.c.obj 110a033022e7444c -62 126 1788959531520811800 CMakeFiles/threadx.dir/common/src/tx_byte_pool_search.c.obj 9a61e94cefd27694 -82 128 1788959531532837669 CMakeFiles/threadx.dir/common/src/tx_event_flags_performance_info_get.c.obj 337df1037e3d2047 -74 129 1788959531532837669 CMakeFiles/threadx.dir/common/src/tx_event_flags_delete.c.obj 7ef3395284f28880 -78 130 1788959531534347418 CMakeFiles/threadx.dir/common/src/tx_event_flags_initialize.c.obj 93dde25808b98e6c -69 132 1788959531532837669 CMakeFiles/threadx.dir/common/src/tx_event_flags_cleanup.c.obj 60beac5c7fe1b560 -106 136 1788959531539199849 CMakeFiles/threadx.dir/common/src/tx_misra.c.obj 952ce45509eb109d -74 143 1788959531543144684 CMakeFiles/threadx.dir/common/src/tx_event_flags_create.c.obj 632222be81dd5d5b -101 149 1788959531553326682 CMakeFiles/threadx.dir/common/src/tx_initialize_kernel_setup.c.obj 98c55ef279b6009 -90 154 1788959531548321213 CMakeFiles/threadx.dir/common/src/tx_event_flags_set_notify.c.obj cdd84434b87875d2 -91 160 1788959531561108129 CMakeFiles/threadx.dir/common/src/tx_initialize_high_level.c.obj a6774cc5db7f561d -75 166 1788959531569734793 CMakeFiles/threadx.dir/common/src/tx_event_flags_get.c.obj 68fc0697aaaedd3 -84 168 1788959531572300986 CMakeFiles/threadx.dir/common/src/tx_event_flags_performance_system_info_get.c.obj 7ed5e8a80c67c6e1 -90 169 1788959531569734793 CMakeFiles/threadx.dir/common/src/tx_event_flags_set.c.obj 6e231edde5656b7 -128 170 1788959531566085907 CMakeFiles/threadx.dir/common/src/tx_mutex_initialize.c.obj f2b1d22759155cb2 -98 171 1788959531575694971 CMakeFiles/threadx.dir/common/src/tx_initialize_kernel_enter.c.obj 3dabae31eb34d8bf -114 172 1788959531573857091 CMakeFiles/threadx.dir/common/src/tx_mutex_cleanup.c.obj db77a90bbe057cf4 -115 173 1788959531573857091 CMakeFiles/threadx.dir/common/src/tx_mutex_create.c.obj ab26c351648a525 -117 173 1788959531574636724 CMakeFiles/threadx.dir/common/src/tx_mutex_delete.c.obj 710f849a6070536a -130 177 1788959531580693382 CMakeFiles/threadx.dir/common/src/tx_mutex_performance_system_info_get.c.obj c109f68be8570a2b -132 187 1788959531590861959 CMakeFiles/threadx.dir/common/src/tx_mutex_prioritize.c.obj 998b0f6327c92876 -136 188 1788959531590861959 CMakeFiles/threadx.dir/common/src/tx_mutex_priority_change.c.obj 25dcd6e0db7d3812 -129 193 1788959531596523993 CMakeFiles/threadx.dir/common/src/tx_mutex_performance_info_get.c.obj 90d20e734eb3dd3c -149 196 1788959531600693401 CMakeFiles/threadx.dir/common/src/tx_queue_cleanup.c.obj f328f5cf950605b7 -143 202 1788959531603659898 CMakeFiles/threadx.dir/common/src/tx_mutex_put.c.obj e42a3e9d195c8da6 -170 202 1788959531603659898 CMakeFiles/threadx.dir/common/src/tx_queue_initialize.c.obj 42aab2c6a4fe823b -154 206 1788959531609120470 CMakeFiles/threadx.dir/common/src/tx_queue_create.c.obj 967d69d170ae5594 -160 210 1788959531612389986 CMakeFiles/threadx.dir/common/src/tx_queue_delete.c.obj b4fd83c9a28a901d -169 215 1788959531617687050 CMakeFiles/threadx.dir/common/src/tx_queue_info_get.c.obj 57649b3d6ff8f773 -166 216 1788959531617687050 CMakeFiles/threadx.dir/common/src/tx_queue_flush.c.obj 109743a2367ccfdc -172 221 1788959531624731978 CMakeFiles/threadx.dir/common/src/tx_queue_performance_system_info_get.c.obj 8f1132d0a840ae94 -126 226 1788959531630576049 CMakeFiles/threadx.dir/common/src/tx_mutex_info_get.c.obj 5233718d3dc46829 -125 230 1788959531632977652 CMakeFiles/threadx.dir/common/src/tx_mutex_get.c.obj ca82c4591c13ae29 -173 230 1788959531632977652 CMakeFiles/threadx.dir/common/src/tx_queue_prioritize.c.obj afa2f28d470b7d89 -177 235 1788959531637217711 CMakeFiles/threadx.dir/common/src/tx_queue_send.c.obj e7262927a917bdb9 -188 238 1788959531637893808 CMakeFiles/threadx.dir/common/src/tx_semaphore_ceiling_put.c.obj 768be723db352257 -171 244 1788959531648503404 CMakeFiles/threadx.dir/common/src/tx_queue_performance_info_get.c.obj 25b3559a9d843353 -193 245 1788959531645864488 CMakeFiles/threadx.dir/common/src/tx_semaphore_cleanup.c.obj 8e545190286d87b3 -196 246 1788959531649750621 CMakeFiles/threadx.dir/common/src/tx_semaphore_create.c.obj a022461d144394b1 -210 247 1788959531651644714 CMakeFiles/threadx.dir/common/src/tx_semaphore_initialize.c.obj ddcd20611e889a84 -168 247 1788959531650719921 CMakeFiles/threadx.dir/common/src/tx_queue_front_send.c.obj 7c6d2908e277afb2 -202 249 1788959531652424946 CMakeFiles/threadx.dir/common/src/tx_semaphore_delete.c.obj 3dd3f8ab254bf87c -173 255 1788959531656746458 CMakeFiles/threadx.dir/common/src/tx_queue_receive.c.obj d94d0946f0e1bad2 -206 255 1788959531656746458 CMakeFiles/threadx.dir/common/src/tx_semaphore_info_get.c.obj 25e6391ee40aae7a -202 260 1788959531658100565 CMakeFiles/threadx.dir/common/src/tx_semaphore_get.c.obj 22b016f726279d6b -187 266 1788959531670409034 CMakeFiles/threadx.dir/common/src/tx_queue_send_notify.c.obj 11b625a2e85d057f -215 266 1788959531664780318 CMakeFiles/threadx.dir/common/src/tx_semaphore_performance_info_get.c.obj 6c027cdd916a37c6 -216 270 1788959531672163253 CMakeFiles/threadx.dir/common/src/tx_semaphore_performance_system_info_get.c.obj 309b844d40c8454b -230 283 1788959531686390026 CMakeFiles/threadx.dir/common/src/tx_semaphore_put_notify.c.obj 570d831c409c872e -230 285 1788959531689380373 CMakeFiles/threadx.dir/common/src/tx_thread_create.c.obj adce0aa1054309d0 -221 286 1788959531689380373 CMakeFiles/threadx.dir/common/src/tx_semaphore_prioritize.c.obj 13e6ef6614d8595e -238 289 1788959531692987584 CMakeFiles/threadx.dir/common/src/tx_thread_identify.c.obj f981455e63570649 -245 295 1788959531699529970 CMakeFiles/threadx.dir/common/src/tx_thread_initialize.c.obj 3726afe17928f7f4 -247 297 1788959531701521946 CMakeFiles/threadx.dir/common/src/tx_thread_performance_system_info_get.c.obj 7c1af7efff31e49 -245 297 1788959531701521946 CMakeFiles/threadx.dir/common/src/tx_thread_info_get.c.obj efd705dd1c02b3e5 -246 299 1788959531703023823 CMakeFiles/threadx.dir/common/src/tx_thread_performance_info_get.c.obj 9416e192b5fe2306 -235 302 1788959531707127985 CMakeFiles/threadx.dir/common/src/tx_thread_entry_exit_notify.c.obj 869a26c327d63e53 -248 306 1788959531708927483 CMakeFiles/threadx.dir/common/src/tx_thread_preemption_change.c.obj 2dd13672b59e0659 -226 307 1788959531707716383 CMakeFiles/threadx.dir/common/src/tx_semaphore_put.c.obj 342cdcd34546c48d -270 307 1788959531711049216 CMakeFiles/threadx.dir/common/src/tx_thread_stack_error_handler.c.obj c7e2d17fb3a714fc -255 310 1788959531708927483 CMakeFiles/threadx.dir/common/src/tx_thread_relinquish.c.obj 9a9ab4d3334de311 -249 310 1788959531711049216 CMakeFiles/threadx.dir/common/src/tx_thread_priority_change.c.obj 489cf9d756529475 -255 314 1788959531714679487 CMakeFiles/threadx.dir/common/src/tx_thread_resume.c.obj 24a748f76813777d -266 322 1788959531726088657 CMakeFiles/threadx.dir/common/src/tx_thread_sleep.c.obj 48ccd71ad4cfc88f -285 335 1788959531738132165 CMakeFiles/threadx.dir/common/src/tx_thread_suspend.c.obj 44da4f9f191e827f -260 335 1788959531738927595 CMakeFiles/threadx.dir/common/src/tx_thread_shell_entry.c.obj 802dc948aedb90eb -266 339 1788959531742968947 CMakeFiles/threadx.dir/common/src/tx_thread_stack_analyze.c.obj 89539c8a1590e36a -297 349 1788959531753047383 CMakeFiles/threadx.dir/common/src/tx_thread_terminate.c.obj e6403e00e325bd74 -299 350 1788959531751051650 CMakeFiles/threadx.dir/common/src/tx_thread_time_slice_change.c.obj 174461221eab7977 -297 351 1788959531755093002 CMakeFiles/threadx.dir/common/src/tx_thread_time_slice.c.obj 7a271de98f7774 -289 351 1788959531755093002 CMakeFiles/threadx.dir/common/src/tx_thread_system_resume.c.obj e4f3fb4824571685 -286 353 1788959531757649547 CMakeFiles/threadx.dir/common/src/tx_thread_system_preempt_check.c.obj 28834ac3b7165cb -295 357 1788959531760889254 CMakeFiles/threadx.dir/common/src/tx_thread_system_suspend.c.obj 14fd9ec8a9d46e91 -307 358 1788959531760889254 CMakeFiles/threadx.dir/common/src/tx_time_get.c.obj cbc97d503eb128de -307 358 1788959531760889254 CMakeFiles/threadx.dir/common/src/tx_time_set.c.obj b6accfada4ea7ee8 -310 359 1788959531762521158 CMakeFiles/threadx.dir/common/src/tx_timer_change.c.obj 49dd976494ad6969 -306 362 1788959531764080399 CMakeFiles/threadx.dir/common/src/tx_thread_wait_abort.c.obj bda57a12055fbd31 -283 363 1788959531767486668 CMakeFiles/threadx.dir/common/src/tx_thread_stack_error_notify.c.obj 7987bf465b5df827 -302 366 1788959531768406390 CMakeFiles/threadx.dir/common/src/tx_thread_timeout.c.obj 73b35a3ddea852ea -310 371 1788959531775097682 CMakeFiles/threadx.dir/common/src/tx_timer_activate.c.obj eb2e6658f137087e -322 382 1788959531786391171 CMakeFiles/threadx.dir/common/src/tx_timer_deactivate.c.obj cd66cf0575ef14fd -314 386 1788959531788793909 CMakeFiles/threadx.dir/common/src/tx_timer_create.c.obj c6866a6d2017df09 -335 389 1788959531792265652 CMakeFiles/threadx.dir/common/src/tx_timer_delete.c.obj b21c8d17e88b1844 -335 390 1788959531794716888 CMakeFiles/threadx.dir/common/src/tx_timer_expiration_process.c.obj eead1c56756c00c8 -339 397 1788959531800473169 CMakeFiles/threadx.dir/common/src/tx_timer_info_get.c.obj 28ca652cfa102dff -351 401 1788959531805339970 CMakeFiles/threadx.dir/common/src/tx_timer_performance_system_info_get.c.obj c024628d0644d579 -353 401 1788959531805339970 CMakeFiles/threadx.dir/common/src/tx_timer_system_deactivate.c.obj 10869c004b77eca0 -349 403 1788959531805339970 CMakeFiles/threadx.dir/common/src/tx_timer_initialize.c.obj fcc1fad694d8f6bc -350 407 1788959531808405645 CMakeFiles/threadx.dir/common/src/tx_timer_performance_info_get.c.obj 5ff819261cdb89af -358 410 1788959531812528359 CMakeFiles/threadx.dir/common/src/tx_trace_disable.c.obj f6b4c28de287dc1d -362 410 1788959531811545326 CMakeFiles/threadx.dir/common/src/tx_trace_event_filter.c.obj 40ca2e165de1d67a -363 411 1788959531815302652 CMakeFiles/threadx.dir/common/src/tx_trace_event_unfilter.c.obj 151b5420a89df4f6 -359 417 1788959531821784693 CMakeFiles/threadx.dir/common/src/tx_trace_enable.c.obj d6b35df11c0dd4ac -366 422 1788959531821784693 CMakeFiles/threadx.dir/common/src/tx_trace_initialize.c.obj 683bc07343dc4d2c -371 423 1788959531827961529 CMakeFiles/threadx.dir/common/src/tx_trace_interrupt_control.c.obj 50c4772b5d621535 -351 434 1788959531834033268 CMakeFiles/threadx.dir/common/src/tx_timer_system_activate.c.obj fb38dda7ea3cffd6 -389 436 1788959531840078836 CMakeFiles/threadx.dir/common/src/tx_trace_object_register.c.obj 22c12a47cc074d2a -386 438 1788959531843025713 CMakeFiles/threadx.dir/common/src/tx_trace_isr_exit_insert.c.obj a9ce0f456d6b5e53 -390 439 1788959531843025713 CMakeFiles/threadx.dir/common/src/tx_trace_object_unregister.c.obj cdd3aa479dc341dd -358 445 1788959531845110918 CMakeFiles/threadx.dir/common/src/tx_trace_buffer_full_notify.c.obj 64ba5346090e1b63 -397 449 1788959531852739969 CMakeFiles/threadx.dir/common/src/tx_trace_user_event_insert.c.obj 2537e8458f153ffb -357 450 1788959531847578342 CMakeFiles/threadx.dir/common/src/tx_timer_thread_entry.c.obj 326c9e51f5b1da36 -401 454 1788959531857089273 CMakeFiles/threadx.dir/common/src/txe_block_allocate.c.obj f84f7c25917d2182 -401 458 1788959531860202882 CMakeFiles/threadx.dir/common/src/txe_block_pool_create.c.obj 4b5f98b899a08cfe -403 458 1788959531862340423 CMakeFiles/threadx.dir/common/src/txe_block_pool_delete.c.obj e9c481ce52eff5fa -382 462 1788959531865264988 CMakeFiles/threadx.dir/common/src/tx_trace_isr_enter_insert.c.obj 9b1aa92002a490db -410 462 1788959531860202882 CMakeFiles/threadx.dir/common/src/txe_block_pool_prioritize.c.obj e86098cdc9612109 -411 466 1788959531869031304 CMakeFiles/threadx.dir/common/src/txe_byte_allocate.c.obj e9bcc54954522cfd -407 466 1788959531870008627 CMakeFiles/threadx.dir/common/src/txe_block_pool_info_get.c.obj be2c996989bbe3df -417 470 1788959531873871911 CMakeFiles/threadx.dir/common/src/txe_byte_pool_create.c.obj 11863d6f1b3d8142 -410 474 1788959531873871911 CMakeFiles/threadx.dir/common/src/txe_block_release.c.obj 76a412317e1991a -422 474 1788959531876908539 CMakeFiles/threadx.dir/common/src/txe_byte_pool_delete.c.obj 6a76087879162c12 -423 478 1788959531876117533 CMakeFiles/threadx.dir/common/src/txe_byte_pool_info_get.c.obj 86b1416cccef300c -434 488 1788959531889007744 CMakeFiles/threadx.dir/common/src/txe_byte_pool_prioritize.c.obj d620399eb038f01e -436 491 1788959531893218456 CMakeFiles/threadx.dir/common/src/txe_byte_release.c.obj 2f0f0404340da8e5 -450 500 1788959531904523114 CMakeFiles/threadx.dir/common/src/txe_event_flags_set.c.obj c038b135c3bd5fde -438 502 1788959531904861469 CMakeFiles/threadx.dir/common/src/txe_event_flags_create.c.obj 68e89ef1bf2a6d81 -439 502 1788959531904861469 CMakeFiles/threadx.dir/common/src/txe_event_flags_delete.c.obj bdb83eee6e23ac07 -454 504 1788959531908817438 CMakeFiles/threadx.dir/common/src/txe_event_flags_set_notify.c.obj bdcef8369128ddd6 -445 506 1788959531908817438 CMakeFiles/threadx.dir/common/src/txe_event_flags_get.c.obj 545521f3c11551d6 -458 512 1788959531913643601 CMakeFiles/threadx.dir/common/src/txe_mutex_delete.c.obj 63df38f752b13e7 -462 514 1788959531917911221 CMakeFiles/threadx.dir/common/src/txe_mutex_get.c.obj 355c3a9632bebbf3 -458 518 1788959531917911221 CMakeFiles/threadx.dir/common/src/txe_mutex_create.c.obj 7050344f91f5c0a1 -470 519 1788959531922556170 CMakeFiles/threadx.dir/common/src/txe_queue_create.c.obj a77e43cedf87b69a -462 519 1788959531924107183 CMakeFiles/threadx.dir/common/src/txe_mutex_info_get.c.obj d5c5ecfc54a1cd9f -466 520 1788959531924107183 CMakeFiles/threadx.dir/common/src/txe_mutex_prioritize.c.obj 856af1d73ccdb848 -449 522 1788959531924947597 CMakeFiles/threadx.dir/common/src/txe_event_flags_info_get.c.obj 3465b2317a7a3f73 -466 526 1788959531928222240 CMakeFiles/threadx.dir/common/src/txe_mutex_put.c.obj 72b7efeb8056daa -474 530 1788959531932667754 CMakeFiles/threadx.dir/common/src/txe_queue_delete.c.obj 3abb5d884f58e9c4 -488 542 1788959531943254605 CMakeFiles/threadx.dir/common/src/txe_queue_info_get.c.obj a42e0031a8a47849 -478 544 1788959531947076386 CMakeFiles/threadx.dir/common/src/txe_queue_front_send.c.obj 2896a1b8bd9aead9 -491 547 1788959531950990531 CMakeFiles/threadx.dir/common/src/txe_queue_prioritize.c.obj 84bc4dcc5c3ed399 -502 550 1788959531952835230 CMakeFiles/threadx.dir/common/src/txe_queue_send.c.obj 3d58854467d61373 -504 552 1788959531953119225 CMakeFiles/threadx.dir/common/src/txe_semaphore_ceiling_put.c.obj f3f50c33d5892285 -502 552 1788959531956945809 CMakeFiles/threadx.dir/common/src/txe_queue_send_notify.c.obj be64c0ca4f55405c -500 553 1788959531956945809 CMakeFiles/threadx.dir/common/src/txe_queue_receive.c.obj 7f36d4cd58f9fddb -512 561 1788959531965949055 CMakeFiles/threadx.dir/common/src/txe_semaphore_delete.c.obj 7ccd4b9b5c30c54f -506 565 1788959531968534186 CMakeFiles/threadx.dir/common/src/txe_semaphore_create.c.obj 71606cfb103e7f51 -518 568 1788959531970447812 CMakeFiles/threadx.dir/common/src/txe_semaphore_info_get.c.obj 8683984653f27803 -519 570 1788959531974128492 CMakeFiles/threadx.dir/common/src/txe_semaphore_put.c.obj 5ba55d0fe8a81f5 -474 578 1788959531981863731 CMakeFiles/threadx.dir/common/src/txe_queue_flush.c.obj 70ee584c446248de -519 578 1788959531977853704 CMakeFiles/threadx.dir/common/src/txe_semaphore_prioritize.c.obj 4e05bf9d76f91053 -520 579 1788959531981863731 CMakeFiles/threadx.dir/common/src/txe_semaphore_put_notify.c.obj a02635f5859b5d2c -530 579 1788959531981863731 CMakeFiles/threadx.dir/common/src/txe_thread_entry_exit_notify.c.obj cdbb2c4171a8d74e -514 588 1788959531991769330 CMakeFiles/threadx.dir/common/src/txe_semaphore_get.c.obj 6af475949cd3b4cf -542 592 1788959531996143015 CMakeFiles/threadx.dir/common/src/txe_thread_info_get.c.obj cb5d7e1bbc229060 -544 594 1788959531997357089 CMakeFiles/threadx.dir/common/src/txe_thread_preemption_change.c.obj 7f2f48efb01bb803 -547 598 1788959532000496224 CMakeFiles/threadx.dir/common/src/txe_thread_priority_change.c.obj d6f6c01fcace9654 -552 598 1788959532002319627 CMakeFiles/threadx.dir/common/src/txe_thread_resume.c.obj cab8d219df477e79 -552 601 1788959532004253745 CMakeFiles/threadx.dir/common/src/txe_thread_reset.c.obj dabba2078d434a2c -550 602 1788959532004253745 CMakeFiles/threadx.dir/common/src/txe_thread_relinquish.c.obj ff82f22cd0c95db5 -522 614 1788959532012469713 CMakeFiles/threadx.dir/common/src/txe_thread_create.c.obj e0c4166f2b2f276b -526 614 1788959532011290344 CMakeFiles/threadx.dir/common/src/txe_thread_delete.c.obj e17b227d67f855e0 -553 615 1788959532017764006 CMakeFiles/threadx.dir/common/src/txe_thread_suspend.c.obj 14f03bf866fadf55 -565 615 1788959532013739498 CMakeFiles/threadx.dir/common/src/txe_thread_time_slice_change.c.obj 813ddb25fc79c35d -594 615 1788959532013739498 ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/entry.S.obj 2b1ac9c639f3fa76 -568 616 1788959532017780849 CMakeFiles/threadx.dir/common/src/txe_thread_wait_abort.c.obj 50db60f5566dc095 -579 625 1788959532029313962 CMakeFiles/threadx.dir/common/src/txe_timer_delete.c.obj 15f20bf94ae8e255 -579 626 1788959532029313962 CMakeFiles/threadx.dir/common/src/txe_timer_deactivate.c.obj 9f2841ee6b4a52dc -614 627 1788959532029904904 ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/tx_initialize_low_level.S.obj 1beece3673f7981 -578 629 1788959532033518084 CMakeFiles/threadx.dir/common/src/txe_timer_create.c.obj 184a61b49fd88e68 -588 633 1788959532038065402 CMakeFiles/threadx.dir/common/src/txe_timer_info_get.c.obj ec3843e84a6e6a6a -562 634 1788959532038065402 CMakeFiles/threadx.dir/common/src/txe_thread_terminate.c.obj 5c174ad2c4940e32 -578 634 1788959532038065402 CMakeFiles/threadx.dir/common/src/txe_timer_change.c.obj aa988079e705f37f -570 635 1788959532039570985 CMakeFiles/threadx.dir/common/src/txe_timer_activate.c.obj 727cb3b86a957e3c -598 642 1788959532046872931 ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/uart.c.obj ed7e60ac1a5c0722 -598 645 1788959532050125647 ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/plic.c.obj cf5687b3e78f6683 -592 647 1788959532050125647 ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/demo_threadx.c.obj d23c7052f7b75543 -601 648 1788959532053055468 ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/hwtimer.c.obj c74642f511df35fe -614 648 1788959532053055468 ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/board.c.obj c7800d48d98128f8 -602 654 1788959532058194364 ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/trap.c.obj 33362e38797d81bc -635 676 1788959532078401122 libthreadx.a f7365c202adc57c6 -676 778 1788959532175393559 ports/risc-v64/gnu/example_build/qemu_virt/kernel.elf 87866ac7df6584e7 -4 24 1788959814925307722 CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_context_save.S.obj f89a6693e7ccf5df -5 27 1788959814925712495 CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_stack_build.S.obj 1d795aef6c2bcbb2 -4 27 1788959814925307722 CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_context_restore.S.obj 685aa5da7671cc59 -5 31 1788959814925307722 CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_schedule.S.obj 3a400b6364e6794f -5 39 1788959814925307722 CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_system_return.S.obj ea0323b283e0ce95 -7 43 1788959814950803623 CMakeFiles/threadx.dir/common/src/tx_block_pool_initialize.c.obj a4254151a0de29e8 -7 56 1788959814963747696 CMakeFiles/threadx.dir/common/src/tx_block_pool_performance_info_get.c.obj 7894825bd3dd6bfc -6 63 1788959814966238622 CMakeFiles/threadx.dir/common/src/tx_block_pool_info_get.c.obj c0e05c465fb36da2 -5 64 1788959814970210776 CMakeFiles/threadx.dir/common/src/tx_thread_delete.c.obj 1f9cc10cdfe42d77 -6 64 1788959814970210776 CMakeFiles/threadx.dir/common/src/tx_block_pool_cleanup.c.obj a3dc9eba3bdd181a -6 64 1788959814967022931 CMakeFiles/threadx.dir/common/src/tx_block_pool_create.c.obj e4bc5356fd952712 -6 65 1788959814970210776 CMakeFiles/threadx.dir/common/src/tx_block_pool_delete.c.obj 3bd4ffac3b2c556e -11 65 1788959814967022931 CMakeFiles/threadx.dir/common/src/tx_block_release.c.obj 77ba14c7d78b8401 -5 66 1788959814970210776 CMakeFiles/threadx.dir/common/src/tx_thread_reset.c.obj 5e33a49b68c693fb -7 67 1788959814974156452 CMakeFiles/threadx.dir/common/src/tx_block_pool_performance_system_info_get.c.obj 38ee451e9c0d593d -8 76 1788959814978189148 CMakeFiles/threadx.dir/common/src/tx_block_pool_prioritize.c.obj 7b3a1aae88c17849 -13 83 1788959814985282255 CMakeFiles/threadx.dir/common/src/tx_byte_allocate.c.obj 7e4476822cc9433a -39 86 1788959814993348931 CMakeFiles/threadx.dir/common/src/tx_byte_pool_initialize.c.obj 203e12b6fa18b976 -27 87 1788959814993348931 CMakeFiles/threadx.dir/common/src/tx_byte_pool_create.c.obj 1d2322a0cde5af84 -27 88 1788959814993348931 CMakeFiles/threadx.dir/common/src/tx_byte_pool_delete.c.obj 33e0eeb36e2aa751 -6 99 1788959814999553244 CMakeFiles/threadx.dir/common/src/tx_block_allocate.c.obj d7d226a397e6572f -31 100 1788959815007042494 CMakeFiles/threadx.dir/common/src/tx_byte_pool_info_get.c.obj 2d67f364cfcd6861 -24 101 1788959815007042494 CMakeFiles/threadx.dir/common/src/tx_byte_pool_cleanup.c.obj b25a962a81e80ed3 -43 113 1788959815017115021 CMakeFiles/threadx.dir/common/src/tx_byte_pool_performance_info_get.c.obj 7d06ee00aa77354c -56 117 1788959815023063536 CMakeFiles/threadx.dir/common/src/tx_byte_pool_performance_system_info_get.c.obj 110a033022e7444c -65 123 1788959815030235233 CMakeFiles/threadx.dir/common/src/tx_event_flags_create.c.obj 632222be81dd5d5b -63 125 1788959815028062176 CMakeFiles/threadx.dir/common/src/tx_byte_pool_prioritize.c.obj 38960f2f17ed3440 -64 125 1788959815031448346 CMakeFiles/threadx.dir/common/src/tx_byte_pool_search.c.obj 9a61e94cefd27694 -65 125 1788959815031448346 CMakeFiles/threadx.dir/common/src/tx_event_flags_delete.c.obj 7ef3395284f28880 -66 126 1788959815030235233 CMakeFiles/threadx.dir/common/src/tx_event_flags_get.c.obj 68fc0697aaaedd3 -64 128 1788959815034156190 CMakeFiles/threadx.dir/common/src/tx_event_flags_cleanup.c.obj 60beac5c7fe1b560 -64 128 1788959815033175584 CMakeFiles/threadx.dir/common/src/tx_byte_release.c.obj 19dc4637dc26fd81 -76 143 1788959815050210464 CMakeFiles/threadx.dir/common/src/tx_event_flags_initialize.c.obj 93dde25808b98e6c -88 156 1788959815055834116 CMakeFiles/threadx.dir/common/src/tx_event_flags_set.c.obj 6e231edde5656b7 -83 162 1788959815064768574 CMakeFiles/threadx.dir/common/src/tx_event_flags_performance_info_get.c.obj 337df1037e3d2047 -88 163 1788959815064768574 CMakeFiles/threadx.dir/common/src/tx_event_flags_set_notify.c.obj cdd84434b87875d2 -99 166 1788959815064768574 CMakeFiles/threadx.dir/common/src/tx_initialize_high_level.c.obj a6774cc5db7f561d -86 167 1788959815072735972 CMakeFiles/threadx.dir/common/src/tx_event_flags_performance_system_info_get.c.obj 7ed5e8a80c67c6e1 -101 170 1788959815072735972 CMakeFiles/threadx.dir/common/src/tx_initialize_kernel_setup.c.obj 98c55ef279b6009 -126 177 1788959815068145683 CMakeFiles/threadx.dir/common/src/tx_mutex_initialize.c.obj f2b1d22759155cb2 -67 179 1788959815081237716 CMakeFiles/threadx.dir/common/src/tx_event_flags_info_get.c.obj 66af35295b6da083 -100 179 1788959815084391745 CMakeFiles/threadx.dir/common/src/tx_initialize_kernel_enter.c.obj 3dabae31eb34d8bf -113 182 1788959815074636910 CMakeFiles/threadx.dir/common/src/tx_misra.c.obj 952ce45509eb109d -117 184 1788959815084391745 CMakeFiles/threadx.dir/common/src/tx_mutex_cleanup.c.obj db77a90bbe057cf4 -123 186 1788959815086111687 CMakeFiles/threadx.dir/common/src/tx_mutex_create.c.obj ab26c351648a525 -125 192 1788959815090099418 CMakeFiles/threadx.dir/common/src/tx_mutex_delete.c.obj 710f849a6070536a -125 195 1788959815090099418 CMakeFiles/threadx.dir/common/src/tx_mutex_info_get.c.obj 5233718d3dc46829 -125 200 1788959815088559595 CMakeFiles/threadx.dir/common/src/tx_mutex_get.c.obj ca82c4591c13ae29 -128 203 1788959815097278469 CMakeFiles/threadx.dir/common/src/tx_mutex_performance_system_info_get.c.obj c109f68be8570a2b -143 218 1788959815115990014 CMakeFiles/threadx.dir/common/src/tx_mutex_prioritize.c.obj 998b0f6327c92876 -180 220 1788959815125641279 CMakeFiles/threadx.dir/common/src/tx_queue_initialize.c.obj 42aab2c6a4fe823b -162 222 1788959815129170501 CMakeFiles/threadx.dir/common/src/tx_mutex_put.c.obj e42a3e9d195c8da6 -163 224 1788959815129170501 CMakeFiles/threadx.dir/common/src/tx_queue_cleanup.c.obj f328f5cf950605b7 -156 227 1788959815132953242 CMakeFiles/threadx.dir/common/src/tx_mutex_priority_change.c.obj 25dcd6e0db7d3812 -170 230 1788959815137446946 CMakeFiles/threadx.dir/common/src/tx_queue_flush.c.obj 109743a2367ccfdc -167 231 1788959815137446946 CMakeFiles/threadx.dir/common/src/tx_queue_delete.c.obj b4fd83c9a28a901d -182 243 1788959815150760286 CMakeFiles/threadx.dir/common/src/tx_queue_performance_info_get.c.obj 25b3559a9d843353 -128 244 1788959815147323525 CMakeFiles/threadx.dir/common/src/tx_mutex_performance_info_get.c.obj 90d20e734eb3dd3c -186 248 1788959815152182141 CMakeFiles/threadx.dir/common/src/tx_queue_prioritize.c.obj afa2f28d470b7d89 -203 263 1788959815170362085 CMakeFiles/threadx.dir/common/src/tx_semaphore_ceiling_put.c.obj 768be723db352257 -177 264 1788959815170491256 CMakeFiles/threadx.dir/common/src/tx_queue_front_send.c.obj 7c6d2908e277afb2 -200 264 1788959815170806744 CMakeFiles/threadx.dir/common/src/tx_queue_send_notify.c.obj 11b625a2e85d057f -166 267 1788959815172956498 CMakeFiles/threadx.dir/common/src/tx_queue_create.c.obj 967d69d170ae5594 -230 272 1788959815177013727 CMakeFiles/threadx.dir/common/src/tx_semaphore_initialize.c.obj ddcd20611e889a84 -192 278 1788959815184176113 CMakeFiles/threadx.dir/common/src/tx_queue_receive.c.obj d94d0946f0e1bad2 -220 281 1788959815187074501 CMakeFiles/threadx.dir/common/src/tx_semaphore_create.c.obj a022461d144394b1 -179 284 1788959815186361633 CMakeFiles/threadx.dir/common/src/tx_queue_info_get.c.obj 57649b3d6ff8f773 -224 288 1788959815193722510 CMakeFiles/threadx.dir/common/src/tx_semaphore_get.c.obj 22b016f726279d6b -218 290 1788959815196820379 CMakeFiles/threadx.dir/common/src/tx_semaphore_cleanup.c.obj 8e545190286d87b3 -231 291 1788959815198364074 CMakeFiles/threadx.dir/common/src/tx_semaphore_performance_info_get.c.obj 6c027cdd916a37c6 -227 295 1788959815202207791 CMakeFiles/threadx.dir/common/src/tx_semaphore_info_get.c.obj 25e6391ee40aae7a -184 297 1788959815204531552 CMakeFiles/threadx.dir/common/src/tx_queue_performance_system_info_get.c.obj 8f1132d0a840ae94 -195 300 1788959815207003841 CMakeFiles/threadx.dir/common/src/tx_queue_send.c.obj e7262927a917bdb9 -222 301 1788959815208563845 CMakeFiles/threadx.dir/common/src/tx_semaphore_delete.c.obj 3dd3f8ab254bf87c -248 303 1788959815210625359 CMakeFiles/threadx.dir/common/src/tx_semaphore_put.c.obj 342cdcd34546c48d -243 304 1788959815211938798 CMakeFiles/threadx.dir/common/src/tx_semaphore_performance_system_info_get.c.obj 309b844d40c8454b -244 305 1788959815210625359 CMakeFiles/threadx.dir/common/src/tx_semaphore_prioritize.c.obj 13e6ef6614d8595e -267 317 1788959815224262570 CMakeFiles/threadx.dir/common/src/tx_thread_identify.c.obj f981455e63570649 -263 326 1788959815231811997 CMakeFiles/threadx.dir/common/src/tx_semaphore_put_notify.c.obj 570d831c409c872e -272 334 1788959815239656032 CMakeFiles/threadx.dir/common/src/tx_thread_info_get.c.obj efd705dd1c02b3e5 -281 336 1788959815242148849 CMakeFiles/threadx.dir/common/src/tx_thread_performance_info_get.c.obj 9416e192b5fe2306 -303 336 1788959815242148849 CMakeFiles/threadx.dir/common/src/tx_thread_stack_error_handler.c.obj c7e2d17fb3a714fc -279 338 1788959815244779904 CMakeFiles/threadx.dir/common/src/tx_thread_initialize.c.obj 3726afe17928f7f4 -291 342 1788959815248542021 CMakeFiles/threadx.dir/common/src/tx_thread_priority_change.c.obj 489cf9d756529475 -264 343 1788959815250479045 CMakeFiles/threadx.dir/common/src/tx_thread_entry_exit_notify.c.obj 869a26c327d63e53 -288 347 1788959815251515503 CMakeFiles/threadx.dir/common/src/tx_thread_preemption_change.c.obj 2dd13672b59e0659 -295 348 1788959815255685774 CMakeFiles/threadx.dir/common/src/tx_thread_resume.c.obj 24a748f76813777d -284 349 1788959815255685774 CMakeFiles/threadx.dir/common/src/tx_thread_performance_system_info_get.c.obj 7c1af7efff31e49 -264 366 1788959815266037426 CMakeFiles/threadx.dir/common/src/tx_thread_create.c.obj adce0aa1054309d0 -301 370 1788959815266037426 CMakeFiles/threadx.dir/common/src/tx_thread_stack_analyze.c.obj 89539c8a1590e36a -304 371 1788959815277429974 CMakeFiles/threadx.dir/common/src/tx_thread_stack_error_notify.c.obj 7987bf465b5df827 -300 375 1788959815277429974 CMakeFiles/threadx.dir/common/src/tx_thread_sleep.c.obj 48ccd71ad4cfc88f -317 383 1788959815290317642 CMakeFiles/threadx.dir/common/src/tx_thread_system_preempt_check.c.obj 28834ac3b7165cb -297 384 1788959815290317642 CMakeFiles/threadx.dir/common/src/tx_thread_shell_entry.c.obj 802dc948aedb90eb -337 390 1788959815296833423 CMakeFiles/threadx.dir/common/src/tx_thread_time_slice.c.obj 7a271de98f7774 -291 392 1788959815297438772 CMakeFiles/threadx.dir/common/src/tx_thread_relinquish.c.obj 9a9ab4d3334de311 -305 395 1788959815297438772 CMakeFiles/threadx.dir/common/src/tx_thread_suspend.c.obj 44da4f9f191e827f -336 398 1788959815297438772 CMakeFiles/threadx.dir/common/src/tx_thread_terminate.c.obj e6403e00e325bd74 -342 400 1788959815302161553 CMakeFiles/threadx.dir/common/src/tx_thread_timeout.c.obj 73b35a3ddea852ea -334 403 1788959815310351965 CMakeFiles/threadx.dir/common/src/tx_thread_system_suspend.c.obj 14fd9ec8a9d46e91 -338 404 1788959815305946755 CMakeFiles/threadx.dir/common/src/tx_thread_time_slice_change.c.obj 174461221eab7977 -343 405 1788959815310351965 CMakeFiles/threadx.dir/common/src/tx_thread_wait_abort.c.obj bda57a12055fbd31 -326 411 1788959815310351965 CMakeFiles/threadx.dir/common/src/tx_thread_system_resume.c.obj e4f3fb4824571685 -349 418 1788959815318797822 CMakeFiles/threadx.dir/common/src/tx_timer_activate.c.obj eb2e6658f137087e -347 424 1788959815329103529 CMakeFiles/threadx.dir/common/src/tx_time_get.c.obj cbc97d503eb128de -366 427 1788959815333989328 CMakeFiles/threadx.dir/common/src/tx_timer_change.c.obj 49dd976494ad6969 -370 431 1788959815336949765 CMakeFiles/threadx.dir/common/src/tx_timer_create.c.obj c6866a6d2017df09 -371 432 1788959815336949765 CMakeFiles/threadx.dir/common/src/tx_timer_deactivate.c.obj cd66cf0575ef14fd -375 434 1788959815330118006 CMakeFiles/threadx.dir/common/src/tx_timer_delete.c.obj b21c8d17e88b1844 -348 447 1788959815352059426 CMakeFiles/threadx.dir/common/src/tx_time_set.c.obj b6accfada4ea7ee8 -395 451 1788959815357530209 CMakeFiles/threadx.dir/common/src/tx_timer_performance_system_info_get.c.obj c024628d0644d579 -400 453 1788959815360863970 CMakeFiles/threadx.dir/common/src/tx_timer_system_deactivate.c.obj 10869c004b77eca0 -384 455 1788959815360863970 CMakeFiles/threadx.dir/common/src/tx_timer_info_get.c.obj 28ca652cfa102dff -390 455 1788959815360863970 CMakeFiles/threadx.dir/common/src/tx_timer_initialize.c.obj fcc1fad694d8f6bc -384 459 1788959815360863970 CMakeFiles/threadx.dir/common/src/tx_timer_expiration_process.c.obj eead1c56756c00c8 -392 461 1788959815362797240 CMakeFiles/threadx.dir/common/src/tx_timer_performance_info_get.c.obj 5ff819261cdb89af -404 462 1788959815367982954 CMakeFiles/threadx.dir/common/src/tx_trace_buffer_full_notify.c.obj 64ba5346090e1b63 -411 464 1788959815371067312 CMakeFiles/threadx.dir/common/src/tx_trace_enable.c.obj d6b35df11c0dd4ac -398 468 1788959815373560491 CMakeFiles/threadx.dir/common/src/tx_timer_system_activate.c.obj fb38dda7ea3cffd6 -405 474 1788959815373560491 CMakeFiles/threadx.dir/common/src/tx_trace_disable.c.obj f6b4c28de287dc1d -418 476 1788959815381748108 CMakeFiles/threadx.dir/common/src/tx_trace_event_filter.c.obj 40ca2e165de1d67a -403 480 1788959815381748108 CMakeFiles/threadx.dir/common/src/tx_timer_thread_entry.c.obj 326c9e51f5b1da36 -431 490 1788959815395476473 CMakeFiles/threadx.dir/common/src/tx_trace_interrupt_control.c.obj 50c4772b5d621535 -427 495 1788959815397516708 CMakeFiles/threadx.dir/common/src/tx_trace_initialize.c.obj 683bc07343dc4d2c -434 495 1788959815401113461 CMakeFiles/threadx.dir/common/src/tx_trace_isr_exit_insert.c.obj a9ce0f456d6b5e53 -424 500 1788959815401113461 CMakeFiles/threadx.dir/common/src/tx_trace_event_unfilter.c.obj 151b5420a89df4f6 -432 501 1788959815405328004 CMakeFiles/threadx.dir/common/src/tx_trace_isr_enter_insert.c.obj 9b1aa92002a490db -451 509 1788959815415657321 CMakeFiles/threadx.dir/common/src/tx_trace_object_unregister.c.obj cdd3aa479dc341dd -462 510 1788959815417538805 CMakeFiles/threadx.dir/common/src/txe_block_pool_prioritize.c.obj e86098cdc9612109 -459 514 1788959815421386647 CMakeFiles/threadx.dir/common/src/txe_block_pool_delete.c.obj e9c481ce52eff5fa -455 516 1788959815419389275 CMakeFiles/threadx.dir/common/src/txe_block_pool_create.c.obj 4b5f98b899a08cfe -461 516 1788959815423994468 CMakeFiles/threadx.dir/common/src/txe_block_pool_info_get.c.obj be2c996989bbe3df -448 517 1788959815422952795 CMakeFiles/threadx.dir/common/src/tx_trace_object_register.c.obj 22c12a47cc074d2a -455 518 1788959815425417908 CMakeFiles/threadx.dir/common/src/txe_block_allocate.c.obj f84f7c25917d2182 -453 519 1788959815426778476 CMakeFiles/threadx.dir/common/src/tx_trace_user_event_insert.c.obj 2537e8458f153ffb -464 529 1788959815436249135 CMakeFiles/threadx.dir/common/src/txe_block_release.c.obj 76a412317e1991a -480 535 1788959815442488258 CMakeFiles/threadx.dir/common/src/txe_byte_pool_info_get.c.obj 86b1416cccef300c -476 551 1788959815457404584 CMakeFiles/threadx.dir/common/src/txe_byte_pool_delete.c.obj 6a76087879162c12 -490 560 1788959815457404584 CMakeFiles/threadx.dir/common/src/txe_byte_pool_prioritize.c.obj d620399eb038f01e -495 561 1788959815466741957 CMakeFiles/threadx.dir/common/src/txe_byte_release.c.obj 2f0f0404340da8e5 -468 562 1788959815467888394 CMakeFiles/threadx.dir/common/src/txe_byte_allocate.c.obj e9bcc54954522cfd -474 563 1788959815469084144 CMakeFiles/threadx.dir/common/src/txe_byte_pool_create.c.obj 11863d6f1b3d8142 -500 563 1788959815469084144 CMakeFiles/threadx.dir/common/src/txe_event_flags_delete.c.obj bdb83eee6e23ac07 -509 563 1788959815467888394 CMakeFiles/threadx.dir/common/src/txe_event_flags_info_get.c.obj 3465b2317a7a3f73 -514 565 1788959815469084144 CMakeFiles/threadx.dir/common/src/txe_event_flags_set_notify.c.obj bdcef8369128ddd6 -510 565 1788959815470614586 CMakeFiles/threadx.dir/common/src/txe_event_flags_set.c.obj c038b135c3bd5fde -495 575 1788959815473872735 CMakeFiles/threadx.dir/common/src/txe_event_flags_create.c.obj 68e89ef1bf2a6d81 -501 582 1788959815489573780 CMakeFiles/threadx.dir/common/src/txe_event_flags_get.c.obj 545521f3c11551d6 -516 585 1788959815486862647 CMakeFiles/threadx.dir/common/src/txe_mutex_create.c.obj 7050344f91f5c0a1 -516 585 1788959815492275344 CMakeFiles/threadx.dir/common/src/txe_mutex_delete.c.obj 63df38f752b13e7 -519 586 1788959815489573780 CMakeFiles/threadx.dir/common/src/txe_mutex_prioritize.c.obj 856af1d73ccdb848 -529 592 1788959815497238849 CMakeFiles/threadx.dir/common/src/txe_mutex_put.c.obj 72b7efeb8056daa -518 599 1788959815505465690 CMakeFiles/threadx.dir/common/src/txe_mutex_info_get.c.obj d5c5ecfc54a1cd9f -517 615 1788959815520647387 CMakeFiles/threadx.dir/common/src/txe_mutex_get.c.obj 355c3a9632bebbf3 -551 619 1788959815520647387 CMakeFiles/threadx.dir/common/src/txe_queue_delete.c.obj 3abb5d884f58e9c4 -563 620 1788959815520647387 CMakeFiles/threadx.dir/common/src/txe_queue_receive.c.obj 7f36d4cd58f9fddb -562 620 1788959815524317191 CMakeFiles/threadx.dir/common/src/txe_queue_info_get.c.obj a42e0031a8a47849 -563 622 1788959815524317191 CMakeFiles/threadx.dir/common/src/txe_queue_prioritize.c.obj 84bc4dcc5c3ed399 -565 624 1788959815524317191 CMakeFiles/threadx.dir/common/src/txe_semaphore_ceiling_put.c.obj f3f50c33d5892285 -561 627 1788959815528476091 CMakeFiles/threadx.dir/common/src/txe_queue_front_send.c.obj 2896a1b8bd9aead9 -561 634 1788959815533315516 CMakeFiles/threadx.dir/common/src/txe_queue_flush.c.obj 70ee584c446248de -582 636 1788959815542559384 CMakeFiles/threadx.dir/common/src/txe_semaphore_delete.c.obj 7ccd4b9b5c30c54f -535 639 1788959815545056867 CMakeFiles/threadx.dir/common/src/txe_queue_create.c.obj a77e43cedf87b69a -575 647 1788959815553266661 CMakeFiles/threadx.dir/common/src/txe_semaphore_create.c.obj 71606cfb103e7f51 -586 648 1788959815553266661 CMakeFiles/threadx.dir/common/src/txe_semaphore_prioritize.c.obj 4e05bf9d76f91053 -585 651 1788959815558162261 CMakeFiles/threadx.dir/common/src/txe_semaphore_get.c.obj 6af475949cd3b4cf -585 653 1788959815560987871 CMakeFiles/threadx.dir/common/src/txe_semaphore_info_get.c.obj 8683984653f27803 -565 655 1788959815561777827 CMakeFiles/threadx.dir/common/src/txe_queue_send_notify.c.obj be64c0ca4f55405c -620 676 1788959815582381224 CMakeFiles/threadx.dir/common/src/txe_thread_info_get.c.obj cb5d7e1bbc229060 -599 677 1788959815583417993 CMakeFiles/threadx.dir/common/src/txe_semaphore_put_notify.c.obj a02635f5859b5d2c -592 679 1788959815583901126 CMakeFiles/threadx.dir/common/src/txe_semaphore_put.c.obj 5ba55d0fe8a81f5 -563 687 1788959815586131747 CMakeFiles/threadx.dir/common/src/txe_queue_send.c.obj 3d58854467d61373 -619 687 1788959815593731170 CMakeFiles/threadx.dir/common/src/txe_thread_delete.c.obj e17b227d67f855e0 -620 688 1788959815587503854 CMakeFiles/threadx.dir/common/src/txe_thread_entry_exit_notify.c.obj cdbb2c4171a8d74e -624 698 1788959815598120255 CMakeFiles/threadx.dir/common/src/txe_thread_priority_change.c.obj d6f6c01fcace9654 -639 700 1788959815606484964 CMakeFiles/threadx.dir/common/src/txe_thread_suspend.c.obj 14f03bf866fadf55 -627 703 1788959815600886651 CMakeFiles/threadx.dir/common/src/txe_thread_relinquish.c.obj ff82f22cd0c95db5 -636 703 1788959815609845621 CMakeFiles/threadx.dir/common/src/txe_thread_resume.c.obj cab8d219df477e79 -647 707 1788959815613796384 CMakeFiles/threadx.dir/common/src/txe_thread_terminate.c.obj 5c174ad2c4940e32 -615 707 1788959815613796384 CMakeFiles/threadx.dir/common/src/txe_thread_create.c.obj e0c4166f2b2f276b -622 707 1788959815613796384 CMakeFiles/threadx.dir/common/src/txe_thread_preemption_change.c.obj 7f2f48efb01bb803 -634 708 1788959815613796384 CMakeFiles/threadx.dir/common/src/txe_thread_reset.c.obj dabba2078d434a2c -648 708 1788959815615271046 CMakeFiles/threadx.dir/common/src/txe_thread_time_slice_change.c.obj 813ddb25fc79c35d -651 708 1788959815615271046 CMakeFiles/threadx.dir/common/src/txe_thread_wait_abort.c.obj 50db60f5566dc095 -700 713 1788959815620133766 ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/tx_initialize_low_level.S.obj 1beece3673f7981 -655 722 1788959815629147293 CMakeFiles/threadx.dir/common/src/txe_timer_change.c.obj aa988079e705f37f -653 728 1788959815635848602 CMakeFiles/threadx.dir/common/src/txe_timer_activate.c.obj 727cb3b86a957e3c -677 732 1788959815638446822 CMakeFiles/threadx.dir/common/src/txe_timer_deactivate.c.obj 9f2841ee6b4a52dc -676 732 1788959815640231891 CMakeFiles/threadx.dir/common/src/txe_timer_create.c.obj 184a61b49fd88e68 -679 735 1788959815642405182 CMakeFiles/threadx.dir/common/src/txe_timer_delete.c.obj 15f20bf94ae8e255 -688 744 1788959815650766415 ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/hwtimer.c.obj c74642f511df35fe -698 744 1788959815650766415 ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/trap.c.obj 33362e38797d81bc -687 746 1788959815653912749 CMakeFiles/threadx.dir/common/src/txe_timer_info_get.c.obj ec3843e84a6e6a6a -688 755 1788959815662129768 ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/demo_threadx.c.obj d23c7052f7b75543 -746 791 1788959815693736239 libthreadx.a f7365c202adc57c6 -791 909 1788959815812226206 ports/risc-v64/gnu/example_build/qemu_virt/kernel.elf 87866ac7df6584e7 -4 226 0 ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/check-functional-riscv64 5d05461e8e889612 -4 226 0 /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/check-functional-riscv64 5d05461e8e889612 diff --git a/build-rv64/CPackConfig.cmake b/build-rv64/CPackConfig.cmake deleted file mode 100644 index 128314f29..000000000 --- a/build-rv64/CPackConfig.cmake +++ /dev/null @@ -1,76 +0,0 @@ -# This file will be configured to contain variables for CPack. These variables -# should be set in the CMake list file of the project before CPack module is -# included. The list of available CPACK_xxx variables and their associated -# documentation may be obtained using -# cpack --help-variable-list -# -# Some variables are common to all generators (e.g. CPACK_PACKAGE_NAME) -# and some are specific to a generator -# (e.g. CPACK_NSIS_EXTRA_INSTALL_COMMANDS). The generator specific variables -# usually begin with CPACK__xxxx. - - -set(CPACK_ARCHIVE_GID "-1") -set(CPACK_ARCHIVE_UID "-1") -set(CPACK_BINARY_7Z "OFF") -set(CPACK_BINARY_IFW "OFF") -set(CPACK_BINARY_INNOSETUP "OFF") -set(CPACK_BINARY_NSIS "ON") -set(CPACK_BINARY_NUGET "OFF") -set(CPACK_BINARY_WIX "OFF") -set(CPACK_BINARY_ZIP "OFF") -set(CPACK_BUILD_SOURCE_DIRS "/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698;/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64") -set(CPACK_CMAKE_GENERATOR "Ninja") -set(CPACK_COMPONENTS_ALL "") -set(CPACK_COMPONENT_UNSPECIFIED_HIDDEN "TRUE") -set(CPACK_COMPONENT_UNSPECIFIED_REQUIRED "TRUE") -set(CPACK_DEFAULT_PACKAGE_DESCRIPTION_FILE "/usr/share/cmake-4.4/Templates/CPack.GenericDescription.txt") -set(CPACK_DEFAULT_PACKAGE_DESCRIPTION_SUMMARY "threadx built using CMake") -set(CPACK_GENERATOR "NSIS") -set(CPACK_INNOSETUP_ARCHITECTURE "x64") -set(CPACK_INSTALL_CMAKE_PROJECTS "/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64;threadx;ALL;/") -set(CPACK_INSTALL_PREFIX "/usr/local") -set(CPACK_MODULE_PATH "") -set(CPACK_NSIS_DISPLAY_NAME "threadx 0.1.1") -set(CPACK_NSIS_INSTALLER_ICON_CODE "") -set(CPACK_NSIS_INSTALLER_MUI_ICON_CODE "") -set(CPACK_NSIS_INSTALL_ROOT "\$PROGRAMFILES") -set(CPACK_NSIS_PACKAGE_NAME "threadx 0.1.1") -set(CPACK_NSIS_UNINSTALL_NAME "Uninstall") -set(CPACK_OBJCOPY_EXECUTABLE "/opt/riscv/bin/riscv64-unknown-elf-objcopy") -set(CPACK_OBJDUMP_EXECUTABLE "/opt/riscv/bin/riscv64-unknown-elf-objdump") -set(CPACK_OUTPUT_CONFIG_FILE "/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/CPackConfig.cmake") -set(CPACK_PACKAGE_DEFAULT_LOCATION "/") -set(CPACK_PACKAGE_DESCRIPTION_FILE "/usr/share/cmake-4.4/Templates/CPack.GenericDescription.txt") -set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "threadx built using CMake") -set(CPACK_PACKAGE_FILE_NAME "threadx-0.1.1-Generic") -set(CPACK_PACKAGE_INSTALL_DIRECTORY "threadx 0.1.1") -set(CPACK_PACKAGE_INSTALL_REGISTRY_KEY "threadx 0.1.1") -set(CPACK_PACKAGE_NAME "threadx") -set(CPACK_PACKAGE_RELOCATABLE "true") -set(CPACK_PACKAGE_VENDOR "Humanity") -set(CPACK_PACKAGE_VERSION "0.1.1") -set(CPACK_PACKAGE_VERSION_MAJOR "0") -set(CPACK_PACKAGE_VERSION_MINOR "1") -set(CPACK_PACKAGE_VERSION_PATCH "1") -set(CPACK_READELF_EXECUTABLE "/opt/riscv/bin/riscv64-unknown-elf-readelf") -set(CPACK_RESOURCE_FILE_LICENSE "/usr/share/cmake-4.4/Templates/CPack.GenericLicense.txt") -set(CPACK_RESOURCE_FILE_README "/usr/share/cmake-4.4/Templates/CPack.GenericDescription.txt") -set(CPACK_RESOURCE_FILE_WELCOME "/usr/share/cmake-4.4/Templates/CPack.GenericWelcome.txt") -set(CPACK_SET_DESTDIR "OFF") -set(CPACK_SOURCE_GENERATOR "ZIP") -set(CPACK_SOURCE_IGNORE_FILES "\\.git/;\\.github/;_build/;\\.git;\\.gitattributes;\\.gitignore;.*~\$") -set(CPACK_SOURCE_OUTPUT_CONFIG_FILE "/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/CPackSourceConfig.cmake") -set(CPACK_SYSTEM_NAME "Generic") -set(CPACK_THREADS "1") -set(CPACK_TOPLEVEL_TAG "Generic") -set(CPACK_VERBATIM_VARIABLES "YES") -set(CPACK_WIX_SIZEOF_VOID_P "8") - -if(NOT CPACK_PROPERTIES_FILE) - set(CPACK_PROPERTIES_FILE "/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/CPackProperties.cmake") -endif() - -if(EXISTS ${CPACK_PROPERTIES_FILE}) - include(${CPACK_PROPERTIES_FILE}) -endif() diff --git a/build-rv64/CPackSourceConfig.cmake b/build-rv64/CPackSourceConfig.cmake deleted file mode 100644 index c858219c0..000000000 --- a/build-rv64/CPackSourceConfig.cmake +++ /dev/null @@ -1,83 +0,0 @@ -# This file will be configured to contain variables for CPack. These variables -# should be set in the CMake list file of the project before CPack module is -# included. The list of available CPACK_xxx variables and their associated -# documentation may be obtained using -# cpack --help-variable-list -# -# Some variables are common to all generators (e.g. CPACK_PACKAGE_NAME) -# and some are specific to a generator -# (e.g. CPACK_NSIS_EXTRA_INSTALL_COMMANDS). The generator specific variables -# usually begin with CPACK__xxxx. - - -set(CPACK_ARCHIVE_GID "-1") -set(CPACK_ARCHIVE_UID "-1") -set(CPACK_BINARY_7Z "OFF") -set(CPACK_BINARY_IFW "OFF") -set(CPACK_BINARY_INNOSETUP "OFF") -set(CPACK_BINARY_NSIS "ON") -set(CPACK_BINARY_NUGET "OFF") -set(CPACK_BINARY_WIX "OFF") -set(CPACK_BINARY_ZIP "OFF") -set(CPACK_BUILD_SOURCE_DIRS "/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698;/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64") -set(CPACK_CMAKE_GENERATOR "Ninja") -set(CPACK_COMPONENTS_ALL "") -set(CPACK_COMPONENT_UNSPECIFIED_HIDDEN "TRUE") -set(CPACK_COMPONENT_UNSPECIFIED_REQUIRED "TRUE") -set(CPACK_DEFAULT_PACKAGE_DESCRIPTION_FILE "/usr/share/cmake-4.4/Templates/CPack.GenericDescription.txt") -set(CPACK_DEFAULT_PACKAGE_DESCRIPTION_SUMMARY "threadx built using CMake") -set(CPACK_GENERATOR "ZIP") -set(CPACK_IGNORE_FILES "\\.git/;\\.github/;_build/;\\.git;\\.gitattributes;\\.gitignore;.*~\$") -set(CPACK_INNOSETUP_ARCHITECTURE "x64") -set(CPACK_INSTALLED_DIRECTORIES "/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698;/") -set(CPACK_INSTALL_CMAKE_PROJECTS "") -set(CPACK_INSTALL_PREFIX "/usr/local") -set(CPACK_MODULE_PATH "") -set(CPACK_NSIS_DISPLAY_NAME "threadx 0.1.1") -set(CPACK_NSIS_INSTALLER_ICON_CODE "") -set(CPACK_NSIS_INSTALLER_MUI_ICON_CODE "") -set(CPACK_NSIS_INSTALL_ROOT "\$PROGRAMFILES") -set(CPACK_NSIS_PACKAGE_NAME "threadx 0.1.1") -set(CPACK_NSIS_UNINSTALL_NAME "Uninstall") -set(CPACK_OBJCOPY_EXECUTABLE "/opt/riscv/bin/riscv64-unknown-elf-objcopy") -set(CPACK_OBJDUMP_EXECUTABLE "/opt/riscv/bin/riscv64-unknown-elf-objdump") -set(CPACK_OUTPUT_CONFIG_FILE "/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/CPackConfig.cmake") -set(CPACK_PACKAGE_DEFAULT_LOCATION "/") -set(CPACK_PACKAGE_DESCRIPTION_FILE "/usr/share/cmake-4.4/Templates/CPack.GenericDescription.txt") -set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "threadx built using CMake") -set(CPACK_PACKAGE_FILE_NAME "threadx-0.1.1-Source") -set(CPACK_PACKAGE_INSTALL_DIRECTORY "threadx 0.1.1") -set(CPACK_PACKAGE_INSTALL_REGISTRY_KEY "threadx 0.1.1") -set(CPACK_PACKAGE_NAME "threadx") -set(CPACK_PACKAGE_RELOCATABLE "true") -set(CPACK_PACKAGE_VENDOR "Humanity") -set(CPACK_PACKAGE_VERSION "0.1.1") -set(CPACK_PACKAGE_VERSION_MAJOR "0") -set(CPACK_PACKAGE_VERSION_MINOR "1") -set(CPACK_PACKAGE_VERSION_PATCH "1") -set(CPACK_READELF_EXECUTABLE "/opt/riscv/bin/riscv64-unknown-elf-readelf") -set(CPACK_RESOURCE_FILE_LICENSE "/usr/share/cmake-4.4/Templates/CPack.GenericLicense.txt") -set(CPACK_RESOURCE_FILE_README "/usr/share/cmake-4.4/Templates/CPack.GenericDescription.txt") -set(CPACK_RESOURCE_FILE_WELCOME "/usr/share/cmake-4.4/Templates/CPack.GenericWelcome.txt") -set(CPACK_RPM_PACKAGE_SOURCES "ON") -set(CPACK_SET_DESTDIR "OFF") -set(CPACK_SOURCE_GENERATOR "ZIP") -set(CPACK_SOURCE_IGNORE_FILES "\\.git/;\\.github/;_build/;\\.git;\\.gitattributes;\\.gitignore;.*~\$") -set(CPACK_SOURCE_INSTALLED_DIRECTORIES "/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698;/") -set(CPACK_SOURCE_OUTPUT_CONFIG_FILE "/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/CPackSourceConfig.cmake") -set(CPACK_SOURCE_PACKAGE_FILE_NAME "threadx-0.1.1-Source") -set(CPACK_SOURCE_TOPLEVEL_TAG "Generic-Source") -set(CPACK_STRIP_FILES "") -set(CPACK_SYSTEM_NAME "Generic") -set(CPACK_THREADS "1") -set(CPACK_TOPLEVEL_TAG "Generic-Source") -set(CPACK_VERBATIM_VARIABLES "YES") -set(CPACK_WIX_SIZEOF_VOID_P "8") - -if(NOT CPACK_PROPERTIES_FILE) - set(CPACK_PROPERTIES_FILE "/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/CPackProperties.cmake") -endif() - -if(EXISTS ${CPACK_PROPERTIES_FILE}) - include(${CPACK_PROPERTIES_FILE}) -endif() diff --git a/build-rv64/build.ninja b/build-rv64/build.ninja deleted file mode 100644 index 28cff4b75..000000000 --- a/build-rv64/build.ninja +++ /dev/null @@ -1,3950 +0,0 @@ -# CMAKE generated file: DO NOT EDIT! -# Generated by "Ninja" Generator, CMake Version 4.4 - -# This file contains all the build statements describing the -# compilation DAG. - -# ============================================================================= -# Write statements declared in CMakeLists.txt: -# -# Which is the root file. -# ============================================================================= - -# ============================================================================= -# Project: threadx -# Configurations: -# ============================================================================= - -############################################# -# Minimal version of Ninja required by this file - -ninja_required_version = 1.5 - -# ============================================================================= -# Include auxiliary files. - - -############################################# -# Include rules file. - -include CMakeFiles/rules.ninja - -# ============================================================================= - -############################################# -# Logical path to working directory; prefix for absolute paths. - -cmake_ninja_workdir = /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/ -# ============================================================================= -# Object build statements for STATIC_LIBRARY target threadx - - -############################################# -# Order-only phony target for threadx - -build cmake_object_order_depends_target_threadx: phony || . - -build CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_initialize_low_level.S.obj: ASM_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/src/tx_initialize_low_level.S || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_initialize_low_level.S.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany -D__ASSEMBLER__ - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/ports/risc-v64/gnu/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_context_restore.S.obj: ASM_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/src/tx_thread_context_restore.S || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_context_restore.S.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany -D__ASSEMBLER__ - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/ports/risc-v64/gnu/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_context_save.S.obj: ASM_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/src/tx_thread_context_save.S || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_context_save.S.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany -D__ASSEMBLER__ - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/ports/risc-v64/gnu/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_interrupt_control.S.obj: ASM_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/src/tx_thread_interrupt_control.S || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_interrupt_control.S.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany -D__ASSEMBLER__ - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/ports/risc-v64/gnu/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_schedule.S.obj: ASM_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/src/tx_thread_schedule.S || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_schedule.S.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany -D__ASSEMBLER__ - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/ports/risc-v64/gnu/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_stack_build.S.obj: ASM_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/src/tx_thread_stack_build.S || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_stack_build.S.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany -D__ASSEMBLER__ - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/ports/risc-v64/gnu/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_system_return.S.obj: ASM_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/src/tx_thread_system_return.S || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_system_return.S.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany -D__ASSEMBLER__ - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/ports/risc-v64/gnu/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_timer_interrupt.S.obj: ASM_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/src/tx_timer_interrupt.S || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_timer_interrupt.S.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany -D__ASSEMBLER__ - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/ports/risc-v64/gnu/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_thread_delete.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_delete.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_delete.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_thread_reset.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_reset.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_reset.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_block_allocate.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_block_allocate.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_block_allocate.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_block_pool_cleanup.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_block_pool_cleanup.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_block_pool_cleanup.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_block_pool_create.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_block_pool_create.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_block_pool_create.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_block_pool_delete.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_block_pool_delete.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_block_pool_delete.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_block_pool_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_block_pool_info_get.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_block_pool_info_get.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_block_pool_initialize.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_block_pool_initialize.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_block_pool_initialize.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_block_pool_performance_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_block_pool_performance_info_get.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_block_pool_performance_info_get.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_block_pool_performance_system_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_block_pool_performance_system_info_get.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_block_pool_performance_system_info_get.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_block_pool_prioritize.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_block_pool_prioritize.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_block_pool_prioritize.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_block_release.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_block_release.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_block_release.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_byte_allocate.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_byte_allocate.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_byte_allocate.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_byte_pool_cleanup.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_byte_pool_cleanup.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_byte_pool_cleanup.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_byte_pool_create.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_byte_pool_create.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_byte_pool_create.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_byte_pool_delete.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_byte_pool_delete.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_byte_pool_delete.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_byte_pool_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_byte_pool_info_get.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_byte_pool_info_get.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_byte_pool_initialize.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_byte_pool_initialize.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_byte_pool_initialize.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_byte_pool_performance_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_byte_pool_performance_info_get.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_byte_pool_performance_info_get.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_byte_pool_performance_system_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_byte_pool_performance_system_info_get.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_byte_pool_performance_system_info_get.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_byte_pool_prioritize.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_byte_pool_prioritize.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_byte_pool_prioritize.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_byte_pool_search.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_byte_pool_search.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_byte_pool_search.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_byte_release.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_byte_release.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_byte_release.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_event_flags_cleanup.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_event_flags_cleanup.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_event_flags_cleanup.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_event_flags_create.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_event_flags_create.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_event_flags_create.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_event_flags_delete.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_event_flags_delete.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_event_flags_delete.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_event_flags_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_event_flags_get.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_event_flags_get.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_event_flags_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_event_flags_info_get.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_event_flags_info_get.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_event_flags_initialize.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_event_flags_initialize.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_event_flags_initialize.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_event_flags_performance_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_event_flags_performance_info_get.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_event_flags_performance_info_get.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_event_flags_performance_system_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_event_flags_performance_system_info_get.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_event_flags_performance_system_info_get.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_event_flags_set.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_event_flags_set.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_event_flags_set.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_event_flags_set_notify.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_event_flags_set_notify.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_event_flags_set_notify.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_initialize_high_level.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_initialize_high_level.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_initialize_high_level.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_initialize_kernel_enter.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_initialize_kernel_enter.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_initialize_kernel_enter.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_initialize_kernel_setup.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_initialize_kernel_setup.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_initialize_kernel_setup.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_misra.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_misra.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_misra.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_mutex_cleanup.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_mutex_cleanup.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_mutex_cleanup.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_mutex_create.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_mutex_create.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_mutex_create.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_mutex_delete.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_mutex_delete.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_mutex_delete.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_mutex_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_mutex_get.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_mutex_get.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_mutex_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_mutex_info_get.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_mutex_info_get.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_mutex_initialize.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_mutex_initialize.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_mutex_initialize.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_mutex_performance_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_mutex_performance_info_get.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_mutex_performance_info_get.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_mutex_performance_system_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_mutex_performance_system_info_get.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_mutex_performance_system_info_get.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_mutex_prioritize.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_mutex_prioritize.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_mutex_prioritize.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_mutex_priority_change.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_mutex_priority_change.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_mutex_priority_change.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_mutex_put.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_mutex_put.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_mutex_put.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_queue_cleanup.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_queue_cleanup.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_queue_cleanup.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_queue_create.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_queue_create.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_queue_create.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_queue_delete.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_queue_delete.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_queue_delete.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_queue_flush.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_queue_flush.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_queue_flush.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_queue_front_send.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_queue_front_send.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_queue_front_send.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_queue_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_queue_info_get.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_queue_info_get.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_queue_initialize.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_queue_initialize.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_queue_initialize.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_queue_performance_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_queue_performance_info_get.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_queue_performance_info_get.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_queue_performance_system_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_queue_performance_system_info_get.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_queue_performance_system_info_get.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_queue_prioritize.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_queue_prioritize.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_queue_prioritize.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_queue_receive.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_queue_receive.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_queue_receive.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_queue_send.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_queue_send.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_queue_send.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_queue_send_notify.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_queue_send_notify.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_queue_send_notify.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_semaphore_ceiling_put.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_semaphore_ceiling_put.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_semaphore_ceiling_put.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_semaphore_cleanup.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_semaphore_cleanup.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_semaphore_cleanup.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_semaphore_create.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_semaphore_create.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_semaphore_create.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_semaphore_delete.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_semaphore_delete.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_semaphore_delete.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_semaphore_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_semaphore_get.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_semaphore_get.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_semaphore_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_semaphore_info_get.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_semaphore_info_get.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_semaphore_initialize.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_semaphore_initialize.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_semaphore_initialize.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_semaphore_performance_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_semaphore_performance_info_get.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_semaphore_performance_info_get.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_semaphore_performance_system_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_semaphore_performance_system_info_get.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_semaphore_performance_system_info_get.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_semaphore_prioritize.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_semaphore_prioritize.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_semaphore_prioritize.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_semaphore_put.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_semaphore_put.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_semaphore_put.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_semaphore_put_notify.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_semaphore_put_notify.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_semaphore_put_notify.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_thread_create.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_create.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_create.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_thread_entry_exit_notify.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_entry_exit_notify.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_entry_exit_notify.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_thread_identify.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_identify.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_identify.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_thread_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_info_get.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_info_get.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_thread_initialize.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_initialize.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_initialize.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_thread_performance_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_performance_info_get.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_performance_info_get.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_thread_performance_system_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_performance_system_info_get.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_performance_system_info_get.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_thread_preemption_change.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_preemption_change.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_preemption_change.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_thread_priority_change.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_priority_change.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_priority_change.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_thread_relinquish.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_relinquish.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_relinquish.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_thread_resume.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_resume.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_resume.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_thread_shell_entry.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_shell_entry.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_shell_entry.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_thread_sleep.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_sleep.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_sleep.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_thread_stack_analyze.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_stack_analyze.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_stack_analyze.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_thread_stack_error_handler.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_stack_error_handler.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_stack_error_handler.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_thread_stack_error_notify.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_stack_error_notify.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_stack_error_notify.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_thread_suspend.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_suspend.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_suspend.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_thread_system_preempt_check.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_system_preempt_check.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_system_preempt_check.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_thread_system_resume.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_system_resume.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_system_resume.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_thread_system_suspend.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_system_suspend.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_system_suspend.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_thread_terminate.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_terminate.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_terminate.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_thread_time_slice.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_time_slice.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_time_slice.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_thread_time_slice_change.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_time_slice_change.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_time_slice_change.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_thread_timeout.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_timeout.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_timeout.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_thread_wait_abort.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_thread_wait_abort.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_thread_wait_abort.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_time_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_time_get.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_time_get.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_time_set.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_time_set.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_time_set.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_timer_activate.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_timer_activate.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_timer_activate.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_timer_change.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_timer_change.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_timer_change.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_timer_create.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_timer_create.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_timer_create.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_timer_deactivate.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_timer_deactivate.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_timer_deactivate.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_timer_delete.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_timer_delete.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_timer_delete.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_timer_expiration_process.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_timer_expiration_process.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_timer_expiration_process.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_timer_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_timer_info_get.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_timer_info_get.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_timer_initialize.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_timer_initialize.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_timer_initialize.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_timer_performance_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_timer_performance_info_get.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_timer_performance_info_get.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_timer_performance_system_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_timer_performance_system_info_get.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_timer_performance_system_info_get.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_timer_system_activate.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_timer_system_activate.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_timer_system_activate.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_timer_system_deactivate.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_timer_system_deactivate.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_timer_system_deactivate.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_timer_thread_entry.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_timer_thread_entry.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_timer_thread_entry.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_trace_buffer_full_notify.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_trace_buffer_full_notify.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_trace_buffer_full_notify.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_trace_disable.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_trace_disable.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_trace_disable.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_trace_enable.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_trace_enable.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_trace_enable.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_trace_event_filter.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_trace_event_filter.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_trace_event_filter.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_trace_event_unfilter.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_trace_event_unfilter.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_trace_event_unfilter.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_trace_initialize.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_trace_initialize.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_trace_initialize.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_trace_interrupt_control.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_trace_interrupt_control.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_trace_interrupt_control.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_trace_isr_enter_insert.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_trace_isr_enter_insert.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_trace_isr_enter_insert.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_trace_isr_exit_insert.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_trace_isr_exit_insert.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_trace_isr_exit_insert.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_trace_object_register.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_trace_object_register.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_trace_object_register.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_trace_object_unregister.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_trace_object_unregister.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_trace_object_unregister.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/tx_trace_user_event_insert.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/tx_trace_user_event_insert.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/tx_trace_user_event_insert.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_block_allocate.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_block_allocate.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_block_allocate.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_block_pool_create.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_block_pool_create.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_block_pool_create.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_block_pool_delete.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_block_pool_delete.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_block_pool_delete.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_block_pool_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_block_pool_info_get.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_block_pool_info_get.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_block_pool_prioritize.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_block_pool_prioritize.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_block_pool_prioritize.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_block_release.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_block_release.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_block_release.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_byte_allocate.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_byte_allocate.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_byte_allocate.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_byte_pool_create.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_byte_pool_create.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_byte_pool_create.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_byte_pool_delete.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_byte_pool_delete.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_byte_pool_delete.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_byte_pool_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_byte_pool_info_get.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_byte_pool_info_get.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_byte_pool_prioritize.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_byte_pool_prioritize.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_byte_pool_prioritize.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_byte_release.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_byte_release.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_byte_release.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_event_flags_create.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_event_flags_create.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_event_flags_create.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_event_flags_delete.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_event_flags_delete.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_event_flags_delete.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_event_flags_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_event_flags_get.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_event_flags_get.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_event_flags_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_event_flags_info_get.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_event_flags_info_get.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_event_flags_set.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_event_flags_set.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_event_flags_set.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_event_flags_set_notify.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_event_flags_set_notify.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_event_flags_set_notify.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_mutex_create.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_mutex_create.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_mutex_create.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_mutex_delete.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_mutex_delete.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_mutex_delete.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_mutex_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_mutex_get.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_mutex_get.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_mutex_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_mutex_info_get.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_mutex_info_get.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_mutex_prioritize.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_mutex_prioritize.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_mutex_prioritize.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_mutex_put.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_mutex_put.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_mutex_put.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_queue_create.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_queue_create.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_queue_create.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_queue_delete.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_queue_delete.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_queue_delete.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_queue_flush.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_queue_flush.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_queue_flush.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_queue_front_send.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_queue_front_send.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_queue_front_send.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_queue_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_queue_info_get.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_queue_info_get.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_queue_prioritize.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_queue_prioritize.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_queue_prioritize.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_queue_receive.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_queue_receive.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_queue_receive.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_queue_send.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_queue_send.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_queue_send.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_queue_send_notify.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_queue_send_notify.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_queue_send_notify.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_semaphore_ceiling_put.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_semaphore_ceiling_put.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_semaphore_ceiling_put.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_semaphore_create.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_semaphore_create.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_semaphore_create.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_semaphore_delete.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_semaphore_delete.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_semaphore_delete.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_semaphore_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_semaphore_get.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_semaphore_get.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_semaphore_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_semaphore_info_get.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_semaphore_info_get.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_semaphore_prioritize.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_semaphore_prioritize.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_semaphore_prioritize.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_semaphore_put.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_semaphore_put.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_semaphore_put.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_semaphore_put_notify.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_semaphore_put_notify.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_semaphore_put_notify.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_thread_create.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_thread_create.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_thread_create.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_thread_delete.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_thread_delete.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_thread_delete.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_thread_entry_exit_notify.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_thread_entry_exit_notify.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_thread_entry_exit_notify.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_thread_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_thread_info_get.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_thread_info_get.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_thread_preemption_change.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_thread_preemption_change.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_thread_preemption_change.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_thread_priority_change.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_thread_priority_change.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_thread_priority_change.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_thread_relinquish.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_thread_relinquish.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_thread_relinquish.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_thread_reset.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_thread_reset.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_thread_reset.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_thread_resume.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_thread_resume.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_thread_resume.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_thread_suspend.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_thread_suspend.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_thread_suspend.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_thread_terminate.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_thread_terminate.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_thread_terminate.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_thread_time_slice_change.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_thread_time_slice_change.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_thread_time_slice_change.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_thread_wait_abort.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_thread_wait_abort.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_thread_wait_abort.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_timer_activate.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_timer_activate.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_timer_activate.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_timer_change.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_timer_change.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_timer_change.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_timer_create.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_timer_create.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_timer_create.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_timer_deactivate.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_timer_deactivate.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_timer_deactivate.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_timer_delete.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_timer_delete.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_timer_delete.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -build CMakeFiles/threadx.dir/common/src/txe_timer_info_get.c.obj: C_COMPILER__threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/src/txe_timer_info_get.c || cmake_object_order_depends_target_threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/threadx.dir/common/src/txe_timer_info_get.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/threadx.dir - OBJECT_FILE_DIR = CMakeFiles/threadx.dir/common/src - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - - -# ============================================================================= -# Link build statements for STATIC_LIBRARY target threadx - - -############################################# -# Link the static library libthreadx.a - -build libthreadx.a: C_STATIC_LIBRARY_LINKER__threadx_ CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_initialize_low_level.S.obj CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_context_restore.S.obj CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_context_save.S.obj CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_interrupt_control.S.obj CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_schedule.S.obj CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_stack_build.S.obj CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_thread_system_return.S.obj CMakeFiles/threadx.dir/ports/risc-v64/gnu/src/tx_timer_interrupt.S.obj CMakeFiles/threadx.dir/common/src/tx_thread_delete.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_reset.c.obj CMakeFiles/threadx.dir/common/src/tx_block_allocate.c.obj CMakeFiles/threadx.dir/common/src/tx_block_pool_cleanup.c.obj CMakeFiles/threadx.dir/common/src/tx_block_pool_create.c.obj CMakeFiles/threadx.dir/common/src/tx_block_pool_delete.c.obj CMakeFiles/threadx.dir/common/src/tx_block_pool_info_get.c.obj CMakeFiles/threadx.dir/common/src/tx_block_pool_initialize.c.obj CMakeFiles/threadx.dir/common/src/tx_block_pool_performance_info_get.c.obj CMakeFiles/threadx.dir/common/src/tx_block_pool_performance_system_info_get.c.obj CMakeFiles/threadx.dir/common/src/tx_block_pool_prioritize.c.obj CMakeFiles/threadx.dir/common/src/tx_block_release.c.obj CMakeFiles/threadx.dir/common/src/tx_byte_allocate.c.obj CMakeFiles/threadx.dir/common/src/tx_byte_pool_cleanup.c.obj CMakeFiles/threadx.dir/common/src/tx_byte_pool_create.c.obj CMakeFiles/threadx.dir/common/src/tx_byte_pool_delete.c.obj CMakeFiles/threadx.dir/common/src/tx_byte_pool_info_get.c.obj CMakeFiles/threadx.dir/common/src/tx_byte_pool_initialize.c.obj CMakeFiles/threadx.dir/common/src/tx_byte_pool_performance_info_get.c.obj CMakeFiles/threadx.dir/common/src/tx_byte_pool_performance_system_info_get.c.obj CMakeFiles/threadx.dir/common/src/tx_byte_pool_prioritize.c.obj CMakeFiles/threadx.dir/common/src/tx_byte_pool_search.c.obj CMakeFiles/threadx.dir/common/src/tx_byte_release.c.obj CMakeFiles/threadx.dir/common/src/tx_event_flags_cleanup.c.obj CMakeFiles/threadx.dir/common/src/tx_event_flags_create.c.obj CMakeFiles/threadx.dir/common/src/tx_event_flags_delete.c.obj CMakeFiles/threadx.dir/common/src/tx_event_flags_get.c.obj CMakeFiles/threadx.dir/common/src/tx_event_flags_info_get.c.obj CMakeFiles/threadx.dir/common/src/tx_event_flags_initialize.c.obj CMakeFiles/threadx.dir/common/src/tx_event_flags_performance_info_get.c.obj CMakeFiles/threadx.dir/common/src/tx_event_flags_performance_system_info_get.c.obj CMakeFiles/threadx.dir/common/src/tx_event_flags_set.c.obj CMakeFiles/threadx.dir/common/src/tx_event_flags_set_notify.c.obj CMakeFiles/threadx.dir/common/src/tx_initialize_high_level.c.obj CMakeFiles/threadx.dir/common/src/tx_initialize_kernel_enter.c.obj CMakeFiles/threadx.dir/common/src/tx_initialize_kernel_setup.c.obj CMakeFiles/threadx.dir/common/src/tx_misra.c.obj CMakeFiles/threadx.dir/common/src/tx_mutex_cleanup.c.obj CMakeFiles/threadx.dir/common/src/tx_mutex_create.c.obj CMakeFiles/threadx.dir/common/src/tx_mutex_delete.c.obj CMakeFiles/threadx.dir/common/src/tx_mutex_get.c.obj CMakeFiles/threadx.dir/common/src/tx_mutex_info_get.c.obj CMakeFiles/threadx.dir/common/src/tx_mutex_initialize.c.obj CMakeFiles/threadx.dir/common/src/tx_mutex_performance_info_get.c.obj CMakeFiles/threadx.dir/common/src/tx_mutex_performance_system_info_get.c.obj CMakeFiles/threadx.dir/common/src/tx_mutex_prioritize.c.obj CMakeFiles/threadx.dir/common/src/tx_mutex_priority_change.c.obj CMakeFiles/threadx.dir/common/src/tx_mutex_put.c.obj CMakeFiles/threadx.dir/common/src/tx_queue_cleanup.c.obj CMakeFiles/threadx.dir/common/src/tx_queue_create.c.obj CMakeFiles/threadx.dir/common/src/tx_queue_delete.c.obj CMakeFiles/threadx.dir/common/src/tx_queue_flush.c.obj CMakeFiles/threadx.dir/common/src/tx_queue_front_send.c.obj CMakeFiles/threadx.dir/common/src/tx_queue_info_get.c.obj CMakeFiles/threadx.dir/common/src/tx_queue_initialize.c.obj CMakeFiles/threadx.dir/common/src/tx_queue_performance_info_get.c.obj CMakeFiles/threadx.dir/common/src/tx_queue_performance_system_info_get.c.obj CMakeFiles/threadx.dir/common/src/tx_queue_prioritize.c.obj CMakeFiles/threadx.dir/common/src/tx_queue_receive.c.obj CMakeFiles/threadx.dir/common/src/tx_queue_send.c.obj CMakeFiles/threadx.dir/common/src/tx_queue_send_notify.c.obj CMakeFiles/threadx.dir/common/src/tx_semaphore_ceiling_put.c.obj CMakeFiles/threadx.dir/common/src/tx_semaphore_cleanup.c.obj CMakeFiles/threadx.dir/common/src/tx_semaphore_create.c.obj CMakeFiles/threadx.dir/common/src/tx_semaphore_delete.c.obj CMakeFiles/threadx.dir/common/src/tx_semaphore_get.c.obj CMakeFiles/threadx.dir/common/src/tx_semaphore_info_get.c.obj CMakeFiles/threadx.dir/common/src/tx_semaphore_initialize.c.obj CMakeFiles/threadx.dir/common/src/tx_semaphore_performance_info_get.c.obj CMakeFiles/threadx.dir/common/src/tx_semaphore_performance_system_info_get.c.obj CMakeFiles/threadx.dir/common/src/tx_semaphore_prioritize.c.obj CMakeFiles/threadx.dir/common/src/tx_semaphore_put.c.obj CMakeFiles/threadx.dir/common/src/tx_semaphore_put_notify.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_create.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_entry_exit_notify.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_identify.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_info_get.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_initialize.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_performance_info_get.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_performance_system_info_get.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_preemption_change.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_priority_change.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_relinquish.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_resume.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_shell_entry.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_sleep.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_stack_analyze.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_stack_error_handler.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_stack_error_notify.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_suspend.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_system_preempt_check.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_system_resume.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_system_suspend.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_terminate.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_time_slice.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_time_slice_change.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_timeout.c.obj CMakeFiles/threadx.dir/common/src/tx_thread_wait_abort.c.obj CMakeFiles/threadx.dir/common/src/tx_time_get.c.obj CMakeFiles/threadx.dir/common/src/tx_time_set.c.obj CMakeFiles/threadx.dir/common/src/tx_timer_activate.c.obj CMakeFiles/threadx.dir/common/src/tx_timer_change.c.obj CMakeFiles/threadx.dir/common/src/tx_timer_create.c.obj CMakeFiles/threadx.dir/common/src/tx_timer_deactivate.c.obj CMakeFiles/threadx.dir/common/src/tx_timer_delete.c.obj CMakeFiles/threadx.dir/common/src/tx_timer_expiration_process.c.obj CMakeFiles/threadx.dir/common/src/tx_timer_info_get.c.obj CMakeFiles/threadx.dir/common/src/tx_timer_initialize.c.obj CMakeFiles/threadx.dir/common/src/tx_timer_performance_info_get.c.obj CMakeFiles/threadx.dir/common/src/tx_timer_performance_system_info_get.c.obj CMakeFiles/threadx.dir/common/src/tx_timer_system_activate.c.obj CMakeFiles/threadx.dir/common/src/tx_timer_system_deactivate.c.obj CMakeFiles/threadx.dir/common/src/tx_timer_thread_entry.c.obj CMakeFiles/threadx.dir/common/src/tx_trace_buffer_full_notify.c.obj CMakeFiles/threadx.dir/common/src/tx_trace_disable.c.obj CMakeFiles/threadx.dir/common/src/tx_trace_enable.c.obj CMakeFiles/threadx.dir/common/src/tx_trace_event_filter.c.obj CMakeFiles/threadx.dir/common/src/tx_trace_event_unfilter.c.obj CMakeFiles/threadx.dir/common/src/tx_trace_initialize.c.obj CMakeFiles/threadx.dir/common/src/tx_trace_interrupt_control.c.obj CMakeFiles/threadx.dir/common/src/tx_trace_isr_enter_insert.c.obj CMakeFiles/threadx.dir/common/src/tx_trace_isr_exit_insert.c.obj CMakeFiles/threadx.dir/common/src/tx_trace_object_register.c.obj CMakeFiles/threadx.dir/common/src/tx_trace_object_unregister.c.obj CMakeFiles/threadx.dir/common/src/tx_trace_user_event_insert.c.obj CMakeFiles/threadx.dir/common/src/txe_block_allocate.c.obj CMakeFiles/threadx.dir/common/src/txe_block_pool_create.c.obj CMakeFiles/threadx.dir/common/src/txe_block_pool_delete.c.obj CMakeFiles/threadx.dir/common/src/txe_block_pool_info_get.c.obj CMakeFiles/threadx.dir/common/src/txe_block_pool_prioritize.c.obj CMakeFiles/threadx.dir/common/src/txe_block_release.c.obj CMakeFiles/threadx.dir/common/src/txe_byte_allocate.c.obj CMakeFiles/threadx.dir/common/src/txe_byte_pool_create.c.obj CMakeFiles/threadx.dir/common/src/txe_byte_pool_delete.c.obj CMakeFiles/threadx.dir/common/src/txe_byte_pool_info_get.c.obj CMakeFiles/threadx.dir/common/src/txe_byte_pool_prioritize.c.obj CMakeFiles/threadx.dir/common/src/txe_byte_release.c.obj CMakeFiles/threadx.dir/common/src/txe_event_flags_create.c.obj CMakeFiles/threadx.dir/common/src/txe_event_flags_delete.c.obj CMakeFiles/threadx.dir/common/src/txe_event_flags_get.c.obj CMakeFiles/threadx.dir/common/src/txe_event_flags_info_get.c.obj CMakeFiles/threadx.dir/common/src/txe_event_flags_set.c.obj CMakeFiles/threadx.dir/common/src/txe_event_flags_set_notify.c.obj CMakeFiles/threadx.dir/common/src/txe_mutex_create.c.obj CMakeFiles/threadx.dir/common/src/txe_mutex_delete.c.obj CMakeFiles/threadx.dir/common/src/txe_mutex_get.c.obj CMakeFiles/threadx.dir/common/src/txe_mutex_info_get.c.obj CMakeFiles/threadx.dir/common/src/txe_mutex_prioritize.c.obj CMakeFiles/threadx.dir/common/src/txe_mutex_put.c.obj CMakeFiles/threadx.dir/common/src/txe_queue_create.c.obj CMakeFiles/threadx.dir/common/src/txe_queue_delete.c.obj CMakeFiles/threadx.dir/common/src/txe_queue_flush.c.obj CMakeFiles/threadx.dir/common/src/txe_queue_front_send.c.obj CMakeFiles/threadx.dir/common/src/txe_queue_info_get.c.obj CMakeFiles/threadx.dir/common/src/txe_queue_prioritize.c.obj CMakeFiles/threadx.dir/common/src/txe_queue_receive.c.obj CMakeFiles/threadx.dir/common/src/txe_queue_send.c.obj CMakeFiles/threadx.dir/common/src/txe_queue_send_notify.c.obj CMakeFiles/threadx.dir/common/src/txe_semaphore_ceiling_put.c.obj CMakeFiles/threadx.dir/common/src/txe_semaphore_create.c.obj CMakeFiles/threadx.dir/common/src/txe_semaphore_delete.c.obj CMakeFiles/threadx.dir/common/src/txe_semaphore_get.c.obj CMakeFiles/threadx.dir/common/src/txe_semaphore_info_get.c.obj CMakeFiles/threadx.dir/common/src/txe_semaphore_prioritize.c.obj CMakeFiles/threadx.dir/common/src/txe_semaphore_put.c.obj CMakeFiles/threadx.dir/common/src/txe_semaphore_put_notify.c.obj CMakeFiles/threadx.dir/common/src/txe_thread_create.c.obj CMakeFiles/threadx.dir/common/src/txe_thread_delete.c.obj CMakeFiles/threadx.dir/common/src/txe_thread_entry_exit_notify.c.obj CMakeFiles/threadx.dir/common/src/txe_thread_info_get.c.obj CMakeFiles/threadx.dir/common/src/txe_thread_preemption_change.c.obj CMakeFiles/threadx.dir/common/src/txe_thread_priority_change.c.obj CMakeFiles/threadx.dir/common/src/txe_thread_relinquish.c.obj CMakeFiles/threadx.dir/common/src/txe_thread_reset.c.obj CMakeFiles/threadx.dir/common/src/txe_thread_resume.c.obj CMakeFiles/threadx.dir/common/src/txe_thread_suspend.c.obj CMakeFiles/threadx.dir/common/src/txe_thread_terminate.c.obj CMakeFiles/threadx.dir/common/src/txe_thread_time_slice_change.c.obj CMakeFiles/threadx.dir/common/src/txe_thread_wait_abort.c.obj CMakeFiles/threadx.dir/common/src/txe_timer_activate.c.obj CMakeFiles/threadx.dir/common/src/txe_timer_change.c.obj CMakeFiles/threadx.dir/common/src/txe_timer_create.c.obj CMakeFiles/threadx.dir/common/src/txe_timer_deactivate.c.obj CMakeFiles/threadx.dir/common/src/txe_timer_delete.c.obj CMakeFiles/threadx.dir/common/src/txe_timer_info_get.c.obj - LANGUAGE_COMPILE_FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - OBJECT_DIR = CMakeFiles/threadx.dir - POST_BUILD = : - PRE_LINK = : - TARGET_COMPILE_PDB = CMakeFiles/threadx.dir/threadx.pdb - TARGET_FILE = libthreadx.a - TARGET_PDB = libthreadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/threadx.dir - -# ============================================================================= -# Object build statements for STATIC_LIBRARY target freertos-threadx - - -############################################# -# Order-only phony target for freertos-threadx - -build cmake_object_order_depends_target_freertos-threadx: phony || cmake_object_order_depends_target_threadx - -build CMakeFiles/freertos-threadx.dir/utility/rtos_compatibility_layers/FreeRTOS/tx_freertos.c.obj: C_COMPILER__freertos-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/FreeRTOS/tx_freertos.c || cmake_object_order_depends_target_freertos-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = CMakeFiles/freertos-threadx.dir/utility/rtos_compatibility_layers/FreeRTOS/tx_freertos.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/FreeRTOS -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = CMakeFiles/freertos-threadx.dir - OBJECT_FILE_DIR = CMakeFiles/freertos-threadx.dir/utility/rtos_compatibility_layers/FreeRTOS - TARGET_COMPILE_PDB = CMakeFiles/freertos-threadx.dir/freertos-threadx.pdb - TARGET_PDB = libfreertos-threadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/freertos-threadx.dir - - -# ============================================================================= -# Link build statements for STATIC_LIBRARY target freertos-threadx - - -############################################# -# Link the static library libfreertos-threadx.a - -build libfreertos-threadx.a: C_STATIC_LIBRARY_LINKER__freertos-threadx_ CMakeFiles/freertos-threadx.dir/utility/rtos_compatibility_layers/FreeRTOS/tx_freertos.c.obj || libthreadx.a - LANGUAGE_COMPILE_FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - OBJECT_DIR = CMakeFiles/freertos-threadx.dir - POST_BUILD = : - PRE_LINK = : - TARGET_COMPILE_PDB = CMakeFiles/freertos-threadx.dir/freertos-threadx.pdb - TARGET_FILE = libfreertos-threadx.a - TARGET_PDB = libfreertos-threadx.pdb - TARGET_SUPPORT_DIR = CMakeFiles/freertos-threadx.dir - - -############################################# -# Utility command for package - -build CMakeFiles/package.util: CUSTOM_COMMAND all - COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64 && /usr/bin/cpack --config ./CPackConfig.cmake - DESC = Run CPack packaging tool... - pool = console - restat = 1 - -build package: phony CMakeFiles/package.util - - -############################################# -# Utility command for package_source - -build CMakeFiles/package_source.util: CUSTOM_COMMAND - COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64 && /usr/bin/cpack --config ./CPackSourceConfig.cmake - DESC = Run CPack packaging tool for source... - pool = console - restat = 1 - -build package_source: phony CMakeFiles/package_source.util - - -############################################# -# Utility command for test - -build CMakeFiles/test.util: CUSTOM_COMMAND - COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64 && /usr/bin/ctest - DESC = Running tests... - pool = console - restat = 1 - -build test: phony CMakeFiles/test.util - - -############################################# -# Utility command for edit_cache - -build CMakeFiles/edit_cache.util: CUSTOM_COMMAND - COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64 && /usr/bin/cmake -E echo No\ interactive\ CMake\ dialog\ available. - DESC = No interactive CMake dialog available... - restat = 1 - -build edit_cache: phony CMakeFiles/edit_cache.util - - -############################################# -# Utility command for rebuild_cache - -build CMakeFiles/rebuild_cache.util: CUSTOM_COMMAND - COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64 && /usr/bin/cmake --regenerate-during-build -S/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698 -B/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64 - DESC = Running CMake to regenerate build system... - pool = console - restat = 1 - -build rebuild_cache: phony CMakeFiles/rebuild_cache.util - -# ============================================================================= -# Write statements declared in CMakeLists.txt: -# /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/CMakeLists.txt -# ============================================================================= - - -############################################# -# Utility command for package - -build ports/risc-v64/gnu/CMakeFiles/package.util: CUSTOM_COMMAND ports/risc-v64/gnu/all - COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64 && /usr/bin/cpack --config ./CPackConfig.cmake - DESC = Run CPack packaging tool... - pool = console - restat = 1 - -build ports/risc-v64/gnu/package: phony ports/risc-v64/gnu/CMakeFiles/package.util - - -############################################# -# Utility command for package_source - -build ports/risc-v64/gnu/CMakeFiles/package_source.util: CUSTOM_COMMAND - COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64 && /usr/bin/cpack --config ./CPackSourceConfig.cmake - DESC = Run CPack packaging tool for source... - pool = console - restat = 1 - -build ports/risc-v64/gnu/package_source: phony ports/risc-v64/gnu/CMakeFiles/package_source.util - - -############################################# -# Utility command for test - -build ports/risc-v64/gnu/CMakeFiles/test.util: CUSTOM_COMMAND - COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/ports/risc-v64/gnu && /usr/bin/ctest - DESC = Running tests... - pool = console - restat = 1 - -build ports/risc-v64/gnu/test: phony ports/risc-v64/gnu/CMakeFiles/test.util - - -############################################# -# Utility command for edit_cache - -build ports/risc-v64/gnu/CMakeFiles/edit_cache.util: CUSTOM_COMMAND - COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/ports/risc-v64/gnu && /usr/bin/cmake -E echo No\ interactive\ CMake\ dialog\ available. - DESC = No interactive CMake dialog available... - restat = 1 - -build ports/risc-v64/gnu/edit_cache: phony ports/risc-v64/gnu/CMakeFiles/edit_cache.util - - -############################################# -# Utility command for rebuild_cache - -build ports/risc-v64/gnu/CMakeFiles/rebuild_cache.util: CUSTOM_COMMAND - COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/ports/risc-v64/gnu && /usr/bin/cmake --regenerate-during-build -S/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698 -B/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64 - DESC = Running CMake to regenerate build system... - pool = console - restat = 1 - -build ports/risc-v64/gnu/rebuild_cache: phony ports/risc-v64/gnu/CMakeFiles/rebuild_cache.util - -# ============================================================================= -# Write statements declared in CMakeLists.txt: -# /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/CMakeLists.txt -# ============================================================================= - -# ============================================================================= -# Object build statements for EXECUTABLE target kernel.elf - - -############################################# -# Order-only phony target for kernel.elf - -build cmake_object_order_depends_target_kernel.elf: phony || cmake_object_order_depends_target_threadx - -build ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/demo_threadx.c.obj: C_COMPILER__kernel.2eelf_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/example_build/qemu_virt/demo_threadx.c || cmake_object_order_depends_target_kernel.elf - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/demo_threadx.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/example_build/qemu_virt -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir - OBJECT_FILE_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir - TARGET_COMPILE_PDB = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/ - TARGET_PDB = ports/risc-v64/gnu/example_build/qemu_virt/kernel.elf.pdb - TARGET_SUPPORT_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir - -build ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/entry.S.obj: ASM_COMPILER__kernel.2eelf_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/example_build/qemu_virt/entry.S || cmake_object_order_depends_target_kernel.elf - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/entry.S.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany -D__ASSEMBLER__ - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/example_build/qemu_virt -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir - OBJECT_FILE_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir - TARGET_COMPILE_PDB = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/ - TARGET_PDB = ports/risc-v64/gnu/example_build/qemu_virt/kernel.elf.pdb - TARGET_SUPPORT_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir - -build ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/uart.c.obj: C_COMPILER__kernel.2eelf_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/example_build/qemu_virt/uart.c || cmake_object_order_depends_target_kernel.elf - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/uart.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/example_build/qemu_virt -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir - OBJECT_FILE_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir - TARGET_COMPILE_PDB = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/ - TARGET_PDB = ports/risc-v64/gnu/example_build/qemu_virt/kernel.elf.pdb - TARGET_SUPPORT_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir - -build ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/plic.c.obj: C_COMPILER__kernel.2eelf_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/example_build/qemu_virt/plic.c || cmake_object_order_depends_target_kernel.elf - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/plic.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/example_build/qemu_virt -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir - OBJECT_FILE_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir - TARGET_COMPILE_PDB = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/ - TARGET_PDB = ports/risc-v64/gnu/example_build/qemu_virt/kernel.elf.pdb - TARGET_SUPPORT_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir - -build ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/hwtimer.c.obj: C_COMPILER__kernel.2eelf_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/example_build/qemu_virt/hwtimer.c || cmake_object_order_depends_target_kernel.elf - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/hwtimer.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/example_build/qemu_virt -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir - OBJECT_FILE_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir - TARGET_COMPILE_PDB = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/ - TARGET_PDB = ports/risc-v64/gnu/example_build/qemu_virt/kernel.elf.pdb - TARGET_SUPPORT_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir - -build ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/trap.c.obj: C_COMPILER__kernel.2eelf_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/example_build/qemu_virt/trap.c || cmake_object_order_depends_target_kernel.elf - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/trap.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/example_build/qemu_virt -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir - OBJECT_FILE_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir - TARGET_COMPILE_PDB = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/ - TARGET_PDB = ports/risc-v64/gnu/example_build/qemu_virt/kernel.elf.pdb - TARGET_SUPPORT_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir - -build ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/board.c.obj: C_COMPILER__kernel.2eelf_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/example_build/qemu_virt/board.c || cmake_object_order_depends_target_kernel.elf - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/board.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/example_build/qemu_virt -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir - OBJECT_FILE_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir - TARGET_COMPILE_PDB = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/ - TARGET_PDB = ports/risc-v64/gnu/example_build/qemu_virt/kernel.elf.pdb - TARGET_SUPPORT_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir - -build ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/tx_initialize_low_level.S.obj: ASM_COMPILER__kernel.2eelf_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/example_build/qemu_virt/tx_initialize_low_level.S || cmake_object_order_depends_target_kernel.elf - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/tx_initialize_low_level.S.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany -D__ASSEMBLER__ - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/example_build/qemu_virt -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir - OBJECT_FILE_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir - TARGET_COMPILE_PDB = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/ - TARGET_PDB = ports/risc-v64/gnu/example_build/qemu_virt/kernel.elf.pdb - TARGET_SUPPORT_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir - - -# ============================================================================= -# Link build statements for EXECUTABLE target kernel.elf - - -############################################# -# Link the executable ports/risc-v64/gnu/example_build/qemu_virt/kernel.elf - -build ports/risc-v64/gnu/example_build/qemu_virt/kernel.elf: C_EXECUTABLE_LINKER__kernel.2eelf_ ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/demo_threadx.c.obj ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/entry.S.obj ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/uart.c.obj ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/plic.c.obj ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/hwtimer.c.obj ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/trap.c.obj ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/board.c.obj ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/tx_initialize_low_level.S.obj | libthreadx.a || libthreadx.a - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - LINK_FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany -T/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/example_build/qemu_virt/link.lds -nostartfiles -Wl,-Map=kernel.map - LINK_LIBRARIES = libthreadx.a -lgcc - OBJECT_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir - POST_BUILD = : - PRE_LINK = : - TARGET_COMPILE_PDB = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir/ - TARGET_FILE = ports/risc-v64/gnu/example_build/qemu_virt/kernel.elf - TARGET_PDB = ports/risc-v64/gnu/example_build/qemu_virt/kernel.elf.pdb - TARGET_SUPPORT_DIR = ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/kernel.elf.dir - - -############################################# -# Utility command for check-functional-riscv64 - -build ports/risc-v64/gnu/example_build/qemu_virt/check-functional-riscv64: phony ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/check-functional-riscv64 ports/risc-v64/gnu/example_build/qemu_virt/kernel.elf - - -############################################# -# Utility command for package - -build ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/package.util: CUSTOM_COMMAND ports/risc-v64/gnu/example_build/qemu_virt/all - COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64 && /usr/bin/cpack --config ./CPackConfig.cmake - DESC = Run CPack packaging tool... - pool = console - restat = 1 - -build ports/risc-v64/gnu/example_build/qemu_virt/package: phony ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/package.util - - -############################################# -# Utility command for package_source - -build ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/package_source.util: CUSTOM_COMMAND - COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64 && /usr/bin/cpack --config ./CPackSourceConfig.cmake - DESC = Run CPack packaging tool for source... - pool = console - restat = 1 - -build ports/risc-v64/gnu/example_build/qemu_virt/package_source: phony ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/package_source.util - - -############################################# -# Utility command for test - -build ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/test.util: CUSTOM_COMMAND - COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/ports/risc-v64/gnu/example_build/qemu_virt && /usr/bin/ctest - DESC = Running tests... - pool = console - restat = 1 - -build ports/risc-v64/gnu/example_build/qemu_virt/test: phony ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/test.util - - -############################################# -# Utility command for edit_cache - -build ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/edit_cache.util: CUSTOM_COMMAND - COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/ports/risc-v64/gnu/example_build/qemu_virt && /usr/bin/cmake -E echo No\ interactive\ CMake\ dialog\ available. - DESC = No interactive CMake dialog available... - restat = 1 - -build ports/risc-v64/gnu/example_build/qemu_virt/edit_cache: phony ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/edit_cache.util - - -############################################# -# Utility command for rebuild_cache - -build ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/rebuild_cache.util: CUSTOM_COMMAND - COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/ports/risc-v64/gnu/example_build/qemu_virt && /usr/bin/cmake --regenerate-during-build -S/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698 -B/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64 - DESC = Running CMake to regenerate build system... - pool = console - restat = 1 - -build ports/risc-v64/gnu/example_build/qemu_virt/rebuild_cache: phony ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/rebuild_cache.util - - -############################################# -# Custom command for ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/check-functional-riscv64 - -build ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/check-functional-riscv64 | ${cmake_ninja_workdir}ports/risc-v64/gnu/example_build/qemu_virt/CMakeFiles/check-functional-riscv64: CUSTOM_COMMAND ports/risc-v64/gnu/example_build/qemu_virt/kernel.elf || libthreadx.a ports/risc-v64/gnu/example_build/qemu_virt/kernel.elf - COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/ports/risc-v64/gnu/example_build/qemu_virt && /usr/bin/python3.12 /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/example_build/qemu_virt/test/threadx_test_tx_gnu_riscv64_qemu.py --elf /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/ports/risc-v64/gnu/example_build/qemu_virt/kernel.elf --qemu /usr/bin/qemu-system-riscv64 --gdb /opt/riscv/bin/riscv64-unknown-elf-gdb - DESC = Running RISC-V64 QEMU/GDB functional test runner... - -# ============================================================================= -# Write statements declared in CMakeLists.txt: -# /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/CMakeLists.txt -# ============================================================================= - - -############################################# -# Utility command for package - -build common/CMakeFiles/package.util: CUSTOM_COMMAND common/all - COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64 && /usr/bin/cpack --config ./CPackConfig.cmake - DESC = Run CPack packaging tool... - pool = console - restat = 1 - -build common/package: phony common/CMakeFiles/package.util - - -############################################# -# Utility command for package_source - -build common/CMakeFiles/package_source.util: CUSTOM_COMMAND - COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64 && /usr/bin/cpack --config ./CPackSourceConfig.cmake - DESC = Run CPack packaging tool for source... - pool = console - restat = 1 - -build common/package_source: phony common/CMakeFiles/package_source.util - - -############################################# -# Utility command for test - -build common/CMakeFiles/test.util: CUSTOM_COMMAND - COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/common && /usr/bin/ctest - DESC = Running tests... - pool = console - restat = 1 - -build common/test: phony common/CMakeFiles/test.util - - -############################################# -# Utility command for edit_cache - -build common/CMakeFiles/edit_cache.util: CUSTOM_COMMAND - COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/common && /usr/bin/cmake -E echo No\ interactive\ CMake\ dialog\ available. - DESC = No interactive CMake dialog available... - restat = 1 - -build common/edit_cache: phony common/CMakeFiles/edit_cache.util - - -############################################# -# Utility command for rebuild_cache - -build common/CMakeFiles/rebuild_cache.util: CUSTOM_COMMAND - COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/common && /usr/bin/cmake --regenerate-during-build -S/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698 -B/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64 - DESC = Running CMake to regenerate build system... - pool = console - restat = 1 - -build common/rebuild_cache: phony common/CMakeFiles/rebuild_cache.util - -# ============================================================================= -# Write statements declared in CMakeLists.txt: -# /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/CMakeLists.txt -# ============================================================================= - -# ============================================================================= -# Object build statements for STATIC_LIBRARY target posix-threadx - - -############################################# -# Order-only phony target for posix-threadx - -build cmake_object_order_depends_target_posix-threadx: phony || cmake_object_order_depends_target_threadx - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_abs_time_to_rel_ticks.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_abs_time_to_rel_ticks.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_abs_time_to_rel_ticks.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_clock_getres.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_clock_getres.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_clock_getres.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_clock_gettime.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_clock_gettime.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_clock_gettime.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_clock_settime.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_clock_settime.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_clock_settime.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_cond_broadcast.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_cond_broadcast.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_cond_broadcast.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_cond_destroy.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_cond_destroy.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_cond_destroy.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_cond_init.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_cond_init.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_cond_init.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_cond_signal.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_cond_signal.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_cond_signal.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_cond_timedwait.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_cond_timedwait.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_cond_timedwait.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_cond_wait.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_cond_wait.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_cond_wait.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_error.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_error.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_error.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_in_thread_context.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_in_thread_context.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_in_thread_context.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_internal_signal_dispatch.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_internal_signal_dispatch.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_internal_signal_dispatch.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_memory_allocate.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_memory_allocate.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_memory_allocate.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_memory_release.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_memory_release.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_memory_release.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_arrange_msg.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mq_arrange_msg.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_arrange_msg.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_attr_init.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mq_attr_init.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_attr_init.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_close.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mq_close.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_close.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_create.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mq_create.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_create.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_find_queue.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mq_find_queue.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_find_queue.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_get_new_queue.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mq_get_new_queue.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_get_new_queue.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_get_queue_desc.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mq_get_queue_desc.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_get_queue_desc.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_open.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mq_open.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_open.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_priority_search.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mq_priority_search.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_priority_search.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_putback_queue.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mq_putback_queue.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_putback_queue.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_queue_delete.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mq_queue_delete.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_queue_delete.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_queue_init.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mq_queue_init.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_queue_init.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_receive.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mq_receive.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_receive.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_reset_queue.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mq_reset_queue.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_reset_queue.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_send.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mq_send.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_send.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_unlink.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mq_unlink.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_unlink.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_attr_destroy.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mx_attr_destroy.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_attr_destroy.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_attr_getprotocol.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mx_attr_getprotocol.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_attr_getprotocol.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_attr_getpshared.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mx_attr_getpshared.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_attr_getpshared.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_attr_gettype.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mx_attr_gettype.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_attr_gettype.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_attr_initi.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mx_attr_initi.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_attr_initi.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_attr_setprotocol.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mx_attr_setprotocol.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_attr_setprotocol.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_attr_setpshared.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mx_attr_setpshared.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_attr_setpshared.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_attr_settype.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mx_attr_settype.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_attr_settype.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_destroy.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mx_destroy.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_destroy.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_init.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mx_init.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_init.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_lock.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mx_lock.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_lock.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_set_default_mutexattr.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mx_set_default_mutexattr.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_set_default_mutexattr.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_timedlock.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mx_timedlock.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_timedlock.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_trylock.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mx_trylock.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_trylock.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_unlock.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_mx_unlock.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_unlock.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_nanosleep.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_nanosleep.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_nanosleep.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_destroy.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_attr_destroy.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_destroy.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_getdetachstate.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_attr_getdetachstate.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_getdetachstate.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_getinheritsched.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_attr_getinheritsched.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_getinheritsched.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_getschedparam.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_attr_getschedparam.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_getschedparam.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_getschedpolicy.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_attr_getschedpolicy.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_getschedpolicy.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_getstack.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_attr_getstack.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_getstack.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_getstackaddr.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_attr_getstackaddr.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_getstackaddr.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_getstacksize.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_attr_getstacksize.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_getstacksize.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_init.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_attr_init.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_init.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_setdetachstate.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_attr_setdetachstate.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_setdetachstate.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_setinheritsched.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_attr_setinheritsched.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_setinheritsched.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_setschedparam.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_attr_setschedparam.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_setschedparam.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_setschedpolicyl.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_attr_setschedpolicyl.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_setschedpolicyl.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_setstack.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_attr_setstack.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_setstack.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_setstackaddr.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_attr_setstackaddr.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_setstackaddr.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_setstacksize.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_attr_setstacksize.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_setstacksize.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_cancel.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_cancel.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_cancel.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_create.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_create.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_create.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_detach.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_detach.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_detach.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_equal.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_equal.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_equal.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_exit.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_exit.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_exit.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_getcanceltype.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_getcanceltype.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_getcanceltype.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_getschedparam.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_getschedparam.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_getschedparam.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_init.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_init.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_init.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_join.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_join.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_join.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_kill.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_kill.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_kill.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_once.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_once.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_once.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_self.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_self.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_self.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_set_default_pthread_attr.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_set_default_pthread_attr.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_set_default_pthread_attr.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_setcancelstate.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_setcancelstate.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_setcancelstate.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_setcanceltype.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_setcanceltype.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_setcanceltype.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_setschedparam.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_setschedparam.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_setschedparam.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_sigmask.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_sigmask.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_sigmask.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_testcancel.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_testcancel.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_testcancel.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_yield.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_pth_yield.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_yield.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_px_initialize.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_px_initialize.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_px_initialize.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sched_get_prio.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_sched_get_prio.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sched_get_prio.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sched_yield.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_sched_yield.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sched_yield.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_close.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_sem_close.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_close.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_destroy.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_sem_destroy.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_destroy.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_find_sem.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_sem_find_sem.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_find_sem.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_get_new_sem.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_sem_get_new_sem.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_get_new_sem.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_getvalue.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_sem_getvalue.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_getvalue.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_init.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_sem_init.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_init.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_open.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_sem_open.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_open.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_post.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_sem_post.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_post.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_reset.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_sem_reset.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_reset.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_set_sem_name.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_sem_set_sem_name.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_set_sem_name.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_trywait.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_sem_trywait.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_trywait.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_unlink.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_sem_unlink.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_unlink.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_wait.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_sem_wait.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_wait.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sig_addset.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_sig_addset.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sig_addset.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sig_delset.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_sig_delset.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sig_delset.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sig_emptyset.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_sig_emptyset.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sig_emptyset.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sig_fillset.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_sig_fillset.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sig_fillset.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sig_signal.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_sig_signal.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sig_signal.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sig_wait.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_sig_wait.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sig_wait.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sleep.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_sleep.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sleep.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - -build utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_system_manager.c.obj: C_COMPILER__posix-threadx_unscanned_ /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/px_system_manager.c || cmake_object_order_depends_target_posix-threadx - DEFINES = -DTX_INCLUDE_USER_DEFINE_FILE - DEP_FILE = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_system_manager.c.obj.d - FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - INCLUDES = -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/inc -I/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/custom_inc -isystem /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - OBJECT_FILE_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - - -# ============================================================================= -# Link build statements for STATIC_LIBRARY target posix-threadx - - -############################################# -# Link the static library utility/rtos_compatibility_layers/posix/libposix-threadx.a - -build utility/rtos_compatibility_layers/posix/libposix-threadx.a: C_STATIC_LIBRARY_LINKER__posix-threadx_ utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_abs_time_to_rel_ticks.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_clock_getres.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_clock_gettime.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_clock_settime.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_cond_broadcast.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_cond_destroy.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_cond_init.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_cond_signal.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_cond_timedwait.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_cond_wait.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_error.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_in_thread_context.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_internal_signal_dispatch.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_memory_allocate.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_memory_release.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_arrange_msg.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_attr_init.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_close.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_create.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_find_queue.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_get_new_queue.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_get_queue_desc.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_open.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_priority_search.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_putback_queue.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_queue_delete.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_queue_init.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_receive.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_reset_queue.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_send.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mq_unlink.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_attr_destroy.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_attr_getprotocol.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_attr_getpshared.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_attr_gettype.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_attr_initi.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_attr_setprotocol.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_attr_setpshared.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_attr_settype.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_destroy.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_init.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_lock.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_set_default_mutexattr.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_timedlock.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_trylock.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_mx_unlock.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_nanosleep.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_destroy.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_getdetachstate.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_getinheritsched.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_getschedparam.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_getschedpolicy.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_getstack.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_getstackaddr.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_getstacksize.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_init.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_setdetachstate.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_setinheritsched.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_setschedparam.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_setschedpolicyl.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_setstack.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_setstackaddr.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_attr_setstacksize.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_cancel.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_create.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_detach.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_equal.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_exit.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_getcanceltype.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_getschedparam.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_init.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_join.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_kill.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_once.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_self.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_set_default_pthread_attr.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_setcancelstate.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_setcanceltype.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_setschedparam.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_sigmask.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_testcancel.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_pth_yield.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_px_initialize.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sched_get_prio.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sched_yield.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_close.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_destroy.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_find_sem.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_get_new_sem.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_getvalue.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_init.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_open.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_post.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_reset.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_set_sem_name.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_trywait.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_unlink.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sem_wait.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sig_addset.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sig_delset.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sig_emptyset.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sig_fillset.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sig_signal.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sig_wait.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_sleep.c.obj utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/px_system_manager.c.obj || libthreadx.a - LANGUAGE_COMPILE_FLAGS = -g -march=rv64gc -mabi=lp64d -mcmodel=medany - OBJECT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - POST_BUILD = : - PRE_LINK = : - TARGET_COMPILE_PDB = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir/posix-threadx.pdb - TARGET_FILE = utility/rtos_compatibility_layers/posix/libposix-threadx.a - TARGET_PDB = utility/rtos_compatibility_layers/posix/libposix-threadx.pdb - TARGET_SUPPORT_DIR = utility/rtos_compatibility_layers/posix/CMakeFiles/posix-threadx.dir - - -############################################# -# Utility command for package - -build utility/rtos_compatibility_layers/posix/CMakeFiles/package.util: CUSTOM_COMMAND utility/rtos_compatibility_layers/posix/all - COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64 && /usr/bin/cpack --config ./CPackConfig.cmake - DESC = Run CPack packaging tool... - pool = console - restat = 1 - -build utility/rtos_compatibility_layers/posix/package: phony utility/rtos_compatibility_layers/posix/CMakeFiles/package.util - - -############################################# -# Utility command for package_source - -build utility/rtos_compatibility_layers/posix/CMakeFiles/package_source.util: CUSTOM_COMMAND - COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64 && /usr/bin/cpack --config ./CPackSourceConfig.cmake - DESC = Run CPack packaging tool for source... - pool = console - restat = 1 - -build utility/rtos_compatibility_layers/posix/package_source: phony utility/rtos_compatibility_layers/posix/CMakeFiles/package_source.util - - -############################################# -# Utility command for test - -build utility/rtos_compatibility_layers/posix/CMakeFiles/test.util: CUSTOM_COMMAND - COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/utility/rtos_compatibility_layers/posix && /usr/bin/ctest - DESC = Running tests... - pool = console - restat = 1 - -build utility/rtos_compatibility_layers/posix/test: phony utility/rtos_compatibility_layers/posix/CMakeFiles/test.util - - -############################################# -# Utility command for edit_cache - -build utility/rtos_compatibility_layers/posix/CMakeFiles/edit_cache.util: CUSTOM_COMMAND - COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/utility/rtos_compatibility_layers/posix && /usr/bin/cmake -E echo No\ interactive\ CMake\ dialog\ available. - DESC = No interactive CMake dialog available... - restat = 1 - -build utility/rtos_compatibility_layers/posix/edit_cache: phony utility/rtos_compatibility_layers/posix/CMakeFiles/edit_cache.util - - -############################################# -# Utility command for rebuild_cache - -build utility/rtos_compatibility_layers/posix/CMakeFiles/rebuild_cache.util: CUSTOM_COMMAND - COMMAND = cd /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/utility/rtos_compatibility_layers/posix && /usr/bin/cmake --regenerate-during-build -S/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698 -B/tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64 - DESC = Running CMake to regenerate build system... - pool = console - restat = 1 - -build utility/rtos_compatibility_layers/posix/rebuild_cache: phony utility/rtos_compatibility_layers/posix/CMakeFiles/rebuild_cache.util - -# ============================================================================= -# Target aliases. - -build check-functional-riscv64: phony ports/risc-v64/gnu/example_build/qemu_virt/check-functional-riscv64 - -build freertos-threadx: phony libfreertos-threadx.a - -build kernel.elf: phony ports/risc-v64/gnu/example_build/qemu_virt/kernel.elf - -build libposix-threadx.a: phony utility/rtos_compatibility_layers/posix/libposix-threadx.a - -build posix-threadx: phony utility/rtos_compatibility_layers/posix/libposix-threadx.a - -build threadx: phony libthreadx.a - -# ============================================================================= -# Folder targets. - -# ============================================================================= - -############################################# -# Folder: /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64 - -build all: phony libthreadx.a ports/risc-v64/gnu/all common/all utility/rtos_compatibility_layers/posix/all - -# ============================================================================= - -############################################# -# Folder: /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/common - -build common/all: phony - -# ============================================================================= - -############################################# -# Folder: /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/ports/risc-v64/gnu - -build ports/risc-v64/gnu/all: phony ports/risc-v64/gnu/example_build/qemu_virt/all - -# ============================================================================= - -############################################# -# Folder: /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/ports/risc-v64/gnu/example_build/qemu_virt - -build ports/risc-v64/gnu/example_build/qemu_virt/all: phony - -# ============================================================================= - -############################################# -# Folder: /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/utility/rtos_compatibility_layers/posix - -build utility/rtos_compatibility_layers/posix/all: phony - -# ============================================================================= -# Built-in targets - - -############################################# -# Re-run CMake if any of its inputs changed. - -build build.ninja /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/cmake_install.cmake /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/ports/risc-v64/gnu/cmake_install.cmake /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/ports/risc-v64/gnu/example_build/qemu_virt/cmake_install.cmake /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/common/cmake_install.cmake /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/utility/rtos_compatibility_layers/posix/cmake_install.cmake /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/CTestTestfile.cmake /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/ports/risc-v64/gnu/CTestTestfile.cmake /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/ports/risc-v64/gnu/example_build/qemu_virt/CTestTestfile.cmake /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/common/CTestTestfile.cmake /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/build-rv64/utility/rtos_compatibility_layers/posix/CTestTestfile.cmake: RERUN_CMAKE | /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/CMakeLists.txt /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/cmake/riscv64-unknown-elf.cmake /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/cmake/riscv64_gnu.cmake /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/cmake/threadx_riscv_port.cmake /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/CMakeLists.txt /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc/tx_user_sample.h /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/CMakeLists.txt /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/example_build/qemu_virt/CMakeLists.txt /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/CMakeLists.txt /usr/share/cmake-4.4/Modules/CMakeASMCompiler.cmake.in /usr/share/cmake-4.4/Modules/CMakeASMInformation.cmake /usr/share/cmake-4.4/Modules/CMakeCCompiler.cmake.in /usr/share/cmake-4.4/Modules/CMakeCCompilerABI.c /usr/share/cmake-4.4/Modules/CMakeCInformation.cmake /usr/share/cmake-4.4/Modules/CMakeCommonLanguageInclude.cmake /usr/share/cmake-4.4/Modules/CMakeCompilerIdDetection.cmake /usr/share/cmake-4.4/Modules/CMakeDetermineASMCompiler.cmake /usr/share/cmake-4.4/Modules/CMakeDetermineCCompiler.cmake /usr/share/cmake-4.4/Modules/CMakeDetermineCompiler.cmake /usr/share/cmake-4.4/Modules/CMakeDetermineCompilerABI.cmake /usr/share/cmake-4.4/Modules/CMakeDetermineCompilerId.cmake /usr/share/cmake-4.4/Modules/CMakeDetermineCompilerSupport.cmake /usr/share/cmake-4.4/Modules/CMakeDetermineSystem.cmake /usr/share/cmake-4.4/Modules/CMakeFindBinUtils.cmake /usr/share/cmake-4.4/Modules/CMakeGenericSystem.cmake /usr/share/cmake-4.4/Modules/CMakeInitializeConfigs.cmake /usr/share/cmake-4.4/Modules/CMakeLanguageInformation.cmake /usr/share/cmake-4.4/Modules/CMakeNinjaFindMake.cmake /usr/share/cmake-4.4/Modules/CMakeParseImplicitIncludeInfo.cmake /usr/share/cmake-4.4/Modules/CMakeParseImplicitLinkInfo.cmake /usr/share/cmake-4.4/Modules/CMakeParseLibraryArchitecture.cmake /usr/share/cmake-4.4/Modules/CMakeSystem.cmake.in /usr/share/cmake-4.4/Modules/CMakeSystemSpecificInformation.cmake /usr/share/cmake-4.4/Modules/CMakeSystemSpecificInitialize.cmake /usr/share/cmake-4.4/Modules/CMakeTestASMCompiler.cmake /usr/share/cmake-4.4/Modules/CMakeTestCCompiler.cmake /usr/share/cmake-4.4/Modules/CMakeTestCompilerCommon.cmake /usr/share/cmake-4.4/Modules/CPack.cmake /usr/share/cmake-4.4/Modules/CPackComponent.cmake /usr/share/cmake-4.4/Modules/Compiler/ADSP-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/ARMCC-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/ARMClang-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/AppleClang-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/Borland-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/Bruce-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/CMakeCommonCompilerMacros.cmake /usr/share/cmake-4.4/Modules/Compiler/Clang-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/Clang-DetermineCompilerInternal.cmake /usr/share/cmake-4.4/Modules/Compiler/Compaq-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/Cray-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/CrayClang-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/Diab-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/Embarcadero-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/Fujitsu-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/GHS-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/GNU-ASM.cmake /usr/share/cmake-4.4/Modules/Compiler/GNU-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/GNU-C.cmake /usr/share/cmake-4.4/Modules/Compiler/GNU-FindBinUtils.cmake /usr/share/cmake-4.4/Modules/Compiler/GNU.cmake /usr/share/cmake-4.4/Modules/Compiler/HP-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/IAR-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake /usr/share/cmake-4.4/Modules/Compiler/IBMClang-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/Intel-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/LCC-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/MSVC-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/NVHPC-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/NVIDIA-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/OrangeC-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/PGI-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/PathScale-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/PellesC-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/Renesas-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/SCO-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/SDCC-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/SunPro-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/TI-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/TIClang-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/Tasking-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/Watcom-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/XL-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/XLClang-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/zOS-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/FindPackageHandleStandardArgs.cmake /usr/share/cmake-4.4/Modules/FindPackageMessage.cmake /usr/share/cmake-4.4/Modules/FindPython/Support.cmake /usr/share/cmake-4.4/Modules/FindPython3.cmake /usr/share/cmake-4.4/Modules/Internal/CMakeASMLinkerInformation.cmake /usr/share/cmake-4.4/Modules/Internal/CMakeCLinkerInformation.cmake /usr/share/cmake-4.4/Modules/Internal/CMakeCommonLinkerInformation.cmake /usr/share/cmake-4.4/Modules/Internal/CMakeDetermineLinkerId.cmake /usr/share/cmake-4.4/Modules/Internal/CMakeInspectASMLinker.cmake /usr/share/cmake-4.4/Modules/Internal/CMakeInspectCLinker.cmake /usr/share/cmake-4.4/Modules/Internal/FeatureTesting.cmake /usr/share/cmake-4.4/Modules/Platform/Generic.cmake /usr/share/cmake-4.4/Templates/CPackConfig.cmake.in CMakeCache.txt CMakeFiles/4.4.3/CMakeASMCompiler.cmake CMakeFiles/4.4.3/CMakeCCompiler.cmake CMakeFiles/4.4.3/CMakeSystem.cmake - pool = console - - -############################################# -# A missing CMake input file is not an error. - -build /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/CMakeLists.txt /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/cmake/riscv64-unknown-elf.cmake /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/cmake/riscv64_gnu.cmake /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/cmake/threadx_riscv_port.cmake /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/CMakeLists.txt /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/common/inc/tx_user_sample.h /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/CMakeLists.txt /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/ports/risc-v64/gnu/example_build/qemu_virt/CMakeLists.txt /tmp/claude-1000/-home-fdesbiens-652-threadx/3e4a51a5-e5ba-416c-90fd-fe90ff96f461/scratchpad/wt698/utility/rtos_compatibility_layers/posix/CMakeLists.txt /usr/share/cmake-4.4/Modules/CMakeASMCompiler.cmake.in /usr/share/cmake-4.4/Modules/CMakeASMInformation.cmake /usr/share/cmake-4.4/Modules/CMakeCCompiler.cmake.in /usr/share/cmake-4.4/Modules/CMakeCCompilerABI.c /usr/share/cmake-4.4/Modules/CMakeCInformation.cmake /usr/share/cmake-4.4/Modules/CMakeCommonLanguageInclude.cmake /usr/share/cmake-4.4/Modules/CMakeCompilerIdDetection.cmake /usr/share/cmake-4.4/Modules/CMakeDetermineASMCompiler.cmake /usr/share/cmake-4.4/Modules/CMakeDetermineCCompiler.cmake /usr/share/cmake-4.4/Modules/CMakeDetermineCompiler.cmake /usr/share/cmake-4.4/Modules/CMakeDetermineCompilerABI.cmake /usr/share/cmake-4.4/Modules/CMakeDetermineCompilerId.cmake /usr/share/cmake-4.4/Modules/CMakeDetermineCompilerSupport.cmake /usr/share/cmake-4.4/Modules/CMakeDetermineSystem.cmake /usr/share/cmake-4.4/Modules/CMakeFindBinUtils.cmake /usr/share/cmake-4.4/Modules/CMakeGenericSystem.cmake /usr/share/cmake-4.4/Modules/CMakeInitializeConfigs.cmake /usr/share/cmake-4.4/Modules/CMakeLanguageInformation.cmake /usr/share/cmake-4.4/Modules/CMakeNinjaFindMake.cmake /usr/share/cmake-4.4/Modules/CMakeParseImplicitIncludeInfo.cmake /usr/share/cmake-4.4/Modules/CMakeParseImplicitLinkInfo.cmake /usr/share/cmake-4.4/Modules/CMakeParseLibraryArchitecture.cmake /usr/share/cmake-4.4/Modules/CMakeSystem.cmake.in /usr/share/cmake-4.4/Modules/CMakeSystemSpecificInformation.cmake /usr/share/cmake-4.4/Modules/CMakeSystemSpecificInitialize.cmake /usr/share/cmake-4.4/Modules/CMakeTestASMCompiler.cmake /usr/share/cmake-4.4/Modules/CMakeTestCCompiler.cmake /usr/share/cmake-4.4/Modules/CMakeTestCompilerCommon.cmake /usr/share/cmake-4.4/Modules/CPack.cmake /usr/share/cmake-4.4/Modules/CPackComponent.cmake /usr/share/cmake-4.4/Modules/Compiler/ADSP-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/ARMCC-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/ARMClang-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/AppleClang-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/Borland-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/Bruce-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/CMakeCommonCompilerMacros.cmake /usr/share/cmake-4.4/Modules/Compiler/Clang-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/Clang-DetermineCompilerInternal.cmake /usr/share/cmake-4.4/Modules/Compiler/Compaq-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/Cray-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/CrayClang-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/Diab-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/Embarcadero-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/Fujitsu-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/FujitsuClang-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/GHS-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/GNU-ASM.cmake /usr/share/cmake-4.4/Modules/Compiler/GNU-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/GNU-C.cmake /usr/share/cmake-4.4/Modules/Compiler/GNU-FindBinUtils.cmake /usr/share/cmake-4.4/Modules/Compiler/GNU.cmake /usr/share/cmake-4.4/Modules/Compiler/HP-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/IAR-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/IBMCPP-C-DetermineVersionInternal.cmake /usr/share/cmake-4.4/Modules/Compiler/IBMClang-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/Intel-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/IntelLLVM-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/LCC-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/MSVC-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/NVHPC-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/NVIDIA-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/OpenWatcom-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/OrangeC-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/PGI-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/PathScale-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/PellesC-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/Renesas-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/SCO-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/SDCC-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/SunPro-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/TI-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/TIClang-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/Tasking-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/TinyCC-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/VisualAge-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/Watcom-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/XL-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/XLClang-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/Compiler/zOS-C-DetermineCompiler.cmake /usr/share/cmake-4.4/Modules/FindPackageHandleStandardArgs.cmake /usr/share/cmake-4.4/Modules/FindPackageMessage.cmake /usr/share/cmake-4.4/Modules/FindPython/Support.cmake /usr/share/cmake-4.4/Modules/FindPython3.cmake /usr/share/cmake-4.4/Modules/Internal/CMakeASMLinkerInformation.cmake /usr/share/cmake-4.4/Modules/Internal/CMakeCLinkerInformation.cmake /usr/share/cmake-4.4/Modules/Internal/CMakeCommonLinkerInformation.cmake /usr/share/cmake-4.4/Modules/Internal/CMakeDetermineLinkerId.cmake /usr/share/cmake-4.4/Modules/Internal/CMakeInspectASMLinker.cmake /usr/share/cmake-4.4/Modules/Internal/CMakeInspectCLinker.cmake /usr/share/cmake-4.4/Modules/Internal/FeatureTesting.cmake /usr/share/cmake-4.4/Modules/Platform/Generic.cmake /usr/share/cmake-4.4/Templates/CPackConfig.cmake.in CMakeCache.txt CMakeFiles/4.4.3/CMakeASMCompiler.cmake CMakeFiles/4.4.3/CMakeCCompiler.cmake CMakeFiles/4.4.3/CMakeSystem.cmake: phony - - -############################################# -# Clean all the built files. - -build clean: CLEAN - - -############################################# -# Print all primary targets available. - -build help: HELP - - -############################################# -# Make the all target the default. - -default all diff --git a/build-rv64/custom_inc/tx_user.h b/build-rv64/custom_inc/tx_user.h deleted file mode 100644 index 0733c16c4..000000000 --- a/build-rv64/custom_inc/tx_user.h +++ /dev/null @@ -1,298 +0,0 @@ -/*************************************************************************** - * Copyright (c) 2024 Microsoft Corporation - * Copyright (c) 2026-present 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 - **************************************************************************/ - - -/**************************************************************************/ -/**************************************************************************/ -/** */ -/** ThreadX Component */ -/** */ -/** User Specific */ -/** */ -/**************************************************************************/ -/**************************************************************************/ - - -/**************************************************************************/ -/* */ -/* PORT SPECIFIC C INFORMATION RELEASE */ -/* */ -/* tx_user.h PORTABLE C */ -/* 6.3.0 */ -/* */ -/* AUTHOR */ -/* */ -/* William E. Lamie, Microsoft Corporation */ -/* */ -/* DESCRIPTION */ -/* */ -/* This file contains user defines for configuring ThreadX in specific */ -/* ways. This file will have an effect only if the application and */ -/* ThreadX library are built with TX_INCLUDE_USER_DEFINE_FILE defined. */ -/* Note that all the defines in this file may also be made on the */ -/* command line when building ThreadX library and application objects. */ -/* */ -/**************************************************************************/ - -#ifndef TX_USER_H -#define TX_USER_H - - -/* Define various build options for the ThreadX port. The application should either make changes - here by commenting or un-commenting the conditional compilation defined OR supply the defines - though the compiler's equivalent of the -D option. - - For maximum speed, the following should be defined: - - TX_MAX_PRIORITIES 32 - TX_DISABLE_PREEMPTION_THRESHOLD - TX_DISABLE_REDUNDANT_CLEARING - TX_DISABLE_NOTIFY_CALLBACKS - TX_NOT_INTERRUPTABLE - TX_TIMER_PROCESS_IN_ISR - TX_REACTIVATE_INLINE - TX_DISABLE_STACK_FILLING - TX_INLINE_THREAD_RESUME_SUSPEND - - For minimum size, the following should be defined: - - TX_MAX_PRIORITIES 32 - TX_DISABLE_PREEMPTION_THRESHOLD - TX_DISABLE_REDUNDANT_CLEARING - TX_DISABLE_NOTIFY_CALLBACKS - TX_NO_FILEX_POINTER - TX_NOT_INTERRUPTABLE - TX_TIMER_PROCESS_IN_ISR - - Of course, many of these defines reduce functionality and/or change the behavior of the - system in ways that may not be worth the trade-off. For example, the TX_TIMER_PROCESS_IN_ISR - results in faster and smaller code, however, it increases the amount of processing in the ISR. - In addition, some services that are available in timers are not available from ISRs and will - therefore return an error if this option is used. This may or may not be desirable for a - given application. */ - - -/* Override various options with default values already assigned in tx_port.h. Please also refer - to tx_port.h for descriptions on each of these options. */ - -/* -#define TX_MAX_PRIORITIES 32 -#define TX_MINIMUM_STACK ???? -#define TX_THREAD_USER_EXTENSION ???? -#define TX_TIMER_THREAD_STACK_SIZE ???? -#define TX_TIMER_THREAD_PRIORITY ???? -*/ - -/* Define the maximum size of a message in the a queue. the Default value is TX_ULONG_16. - the new value must be a multiple of ULONG. */ - -/* -#define TX_QUEUE_MESSAGE_MAX_SIZE TX_16_ULONG -*/ - -/* Define the common timer tick reference for use by other middleware components. The default - value is 10ms (i.e. 100 ticks, defined in tx_api.h), but may be replaced by a port-specific - version in tx_port.h or here. - Note: the actual hardware timer value may need to be changed (usually in tx_initialize_low_level). */ - -/* -#define TX_TIMER_TICKS_PER_SECOND (100UL) -*/ - -/* Determine if there is a FileX pointer in the thread control block. - By default, the pointer is there for legacy/backwards compatibility. - The pointer must also be there for applications using FileX. - Define this to save space in the thread control block. -*/ - -/* -#define TX_NO_FILEX_POINTER -*/ - -/* Determine if timer expirations (application timers, timeouts, and tx_thread_sleep calls - should be processed within the a system timer thread or directly in the timer ISR. - By default, the timer thread is used. When the following is defined, the timer expiration - processing is done directly from the timer ISR, thereby eliminating the timer thread control - block, stack, and context switching to activate it. */ - -/* -#define TX_TIMER_PROCESS_IN_ISR -*/ - -/* Determine if in-line timer reactivation should be used within the timer expiration processing. - By default, this is disabled and a function call is used. When the following is defined, - reactivating is performed in-line resulting in faster timer processing but slightly larger - code size. */ - -/* -#define TX_REACTIVATE_INLINE -*/ - -/* Determine is stack filling is enabled. By default, ThreadX stack filling is enabled, - which places an 0xEF pattern in each byte of each thread's stack. This is used by - debuggers with ThreadX-awareness and by the ThreadX run-time stack checking feature. */ - -/* -#define TX_DISABLE_STACK_FILLING -*/ - -/* Determine whether or not stack checking is enabled. By default, ThreadX stack checking is - disabled. When the following is defined, ThreadX thread stack checking is enabled. If stack - checking is enabled (TX_ENABLE_STACK_CHECKING is defined), the TX_DISABLE_STACK_FILLING - define is negated, thereby forcing the stack fill which is necessary for the stack checking - logic. */ - -/* -#define TX_ENABLE_STACK_CHECKING -*/ - -/* Determine if random number is used for stack filling. By default, ThreadX uses a fixed - pattern for stack filling. When the following is defined, ThreadX uses a random number - for stack filling. This is effective only when TX_ENABLE_STACK_CHECKING is defined. */ - -/* -#define TX_ENABLE_RANDOM_NUMBER_STACK_FILLING -*/ - -/* Determine if preemption-threshold should be disabled. By default, preemption-threshold is - enabled. If the application does not use preemption-threshold, it may be disabled to reduce - code size and improve performance. */ - -/* -#define TX_DISABLE_PREEMPTION_THRESHOLD -*/ - -/* Determine if global ThreadX variables should be cleared. If the compiler startup code clears - the .bss section prior to ThreadX running, the define can be used to eliminate unnecessary - clearing of ThreadX global variables. */ - -/* -#define TX_DISABLE_REDUNDANT_CLEARING -*/ - -/* Determine if no timer processing is required. This option will help eliminate the timer - processing when not needed. The user will also have to comment out the call to - tx_timer_interrupt, which is typically made from assembly language in - tx_initialize_low_level. Note: if TX_NO_TIMER is used, the define TX_TIMER_PROCESS_IN_ISR - must also be used and tx_timer_initialize must be removed from ThreadX library. */ - -/* -#define TX_NO_TIMER -#ifndef TX_TIMER_PROCESS_IN_ISR -#define TX_TIMER_PROCESS_IN_ISR -#endif -*/ - -/* Determine if the notify callback option should be disabled. By default, notify callbacks are - enabled. If the application does not use notify callbacks, they may be disabled to reduce - code size and improve performance. */ - -/* -#define TX_DISABLE_NOTIFY_CALLBACKS -*/ - - -/* Determine if the tx_thread_resume and tx_thread_suspend services should have their internal - code in-line. This results in a larger image, but improves the performance of the thread - resume and suspend services. */ - -/* -#define TX_INLINE_THREAD_RESUME_SUSPEND -*/ - - -/* Determine if the internal ThreadX code is non-interruptable. This results in smaller code - size and less processing overhead, but increases the interrupt lockout time. */ - -/* -#define TX_NOT_INTERRUPTABLE -*/ - - -/* Determine if the trace event logging code should be enabled. This causes slight increases in - code size and overhead, but provides the ability to generate system trace information which - is available for viewing in TraceX. */ - -/* -#define TX_ENABLE_EVENT_TRACE -*/ - - -/* Determine if block pool performance gathering is required by the application. When the following is - defined, ThreadX gathers various block pool performance information. */ - -/* -#define TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO -*/ - -/* Determine if byte pool performance gathering is required by the application. When the following is - defined, ThreadX gathers various byte pool performance information. */ - -/* -#define TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO -*/ - -/* Determine if event flags performance gathering is required by the application. When the following is - defined, ThreadX gathers various event flags performance information. */ - -/* -#define TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO -*/ - -/* Determine if mutex performance gathering is required by the application. When the following is - defined, ThreadX gathers various mutex performance information. */ - -/* -#define TX_MUTEX_ENABLE_PERFORMANCE_INFO -*/ - -/* Determine if queue performance gathering is required by the application. When the following is - defined, ThreadX gathers various queue performance information. */ - -/* -#define TX_QUEUE_ENABLE_PERFORMANCE_INFO -*/ - -/* Determine if semaphore performance gathering is required by the application. When the following is - defined, ThreadX gathers various semaphore performance information. */ - -/* -#define TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO -*/ - -/* Determine if thread performance gathering is required by the application. When the following is - defined, ThreadX gathers various thread performance information. */ - -/* -#define TX_THREAD_ENABLE_PERFORMANCE_INFO -*/ - -/* Determine if timer performance gathering is required by the application. When the following is - defined, ThreadX gathers various timer performance information. */ - -/* -#define TX_TIMER_ENABLE_PERFORMANCE_INFO -*/ - -/* Override options for byte pool searches of multiple blocks. */ - -/* -#define TX_BYTE_POOL_MULTIPLE_BLOCK_SEARCH 20 -*/ - -/* Override options for byte pool search delay to avoid thrashing. */ - -/* -#define TX_BYTE_POOL_DELAY_VALUE 3 -*/ - -#endif - diff --git a/build-rv64/ports/risc-v64/gnu/example_build/qemu_virt/kernel.elf b/build-rv64/ports/risc-v64/gnu/example_build/qemu_virt/kernel.elf deleted file mode 100755 index b9e83bcc83bb84f3954a023df8d70185ac937184..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 239112 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 1 && $fpu_err > -0.01 && $fpu_err < 0.01 - printf "FPU_VERIFIED_OK value=%f adds=%d\n", fpu_test_val, $fpu_n - else - printf "FPU_VERIFIED_FAIL value=%f adds=%d passes=%d\n", fpu_test_val, $fpu_n, $fpu_iter - end -end - -# Await Timer Interrupt. Arm only the timer breakpoint, so this stop is -# _tx_timer_interrupt and $ra below really is the ISR return address. -disable 1 -disable 2 -disable 3 -enable 4 -continue -print "Hit Timer Interrupt" - -# Verify MEPC Integrity - Save State -print/x $mepc -set $saved_pc = $mepc - -# Verify System Timer Before ISR -set $clock_before = _tx_timer_system_clock -print $clock_before - -# Configure Time-Slice Test Conditions -set _tx_timer_time_slice = 1 -set _tx_timer_expired_time_slice = 0 -set $ts_handler_called = 0 - -# Set Breakpoint at Time-Slice Handler with Auto-Continue -tbreak _tx_thread_time_slice -commands - set $ts_handler_called = 1 - continue -end - -# Set Breakpoint at ISR Return Address. Disable the timer breakpoint for -# this window, so the next tick cannot stop us short of the return. -set $ret_addr = $ra -disable 4 -tbreak *$ret_addr -continue - -# Verify that the live CSR and saved frame still contain the interrupted PC. -set $frame_pc = ((unsigned long *)_tx_thread_current_ptr->tx_thread_stack_ptr)[30] -if $mepc == $saved_pc && $frame_pc == $saved_pc - printf "MEPC_VERIFIED_OK mepc=0x%lx frame_pc=0x%lx\n", $mepc, $frame_pc -else - printf "MEPC_VERIFIED_FAIL saved=0x%lx mepc=0x%lx frame_pc=0x%lx\n", $saved_pc, $mepc, $frame_pc -end - -# Verify Time-Slice Handler Was Called -if $ts_handler_called == 1 - print "SUCCESS: Time-slice handler called." -else - print "FAILURE: Time-slice handler NOT called." -end - -# Verify System Timer Increment (Monotonicity) -set $clock_after = _tx_timer_system_clock -print $clock_after - -if $clock_after > $clock_before - print "SUCCESS: System timer incremented." -else - print "FAILURE: System timer did not increment." -end - -# Verify Preemption Logic (Thread Priority) -# -# We are now stopped at the return address from _tx_timer_interrupt, -# after _tx_thread_time_slice and the timer expiration processing have had -# a chance to update _tx_thread_execute_ptr but before trap_handler -# returns into _tx_thread_context_restore. -# -# Whether any ONE tick lands inside a preemption window depends on -# scheduling phase, not on the tick rate, so poll consecutive ticks at -# this same sample point until the priority relation holds. Each retry -# re-arms the time slice and re-derives the return address from $ra, so -# the sample point is identical every iteration. The cap bounds ticks and -# fails loudly on exhaustion; it never passes the check. -set $preempt_ok = 0 -set $preempt_null = 0 -set $preempt_iter = 0 -while $preempt_iter < 250 && $preempt_ok == 0 - set $curr_ptr = _tx_thread_current_ptr - set $exec_ptr = _tx_thread_execute_ptr - if $curr_ptr == 0 || $exec_ptr == 0 - set $preempt_null = $preempt_null + 1 - else - set $curr_prio = $curr_ptr->tx_thread_priority - set $exec_prio = $exec_ptr->tx_thread_priority - if $exec_prio < $curr_prio - printf "PREEMPT_CHECK current_prio=%d execute_prio=%d\n", $curr_prio, $exec_prio - set $preempt_ok = 1 - end - end - if $preempt_ok == 0 - set $preempt_iter = $preempt_iter + 1 - enable 4 - continue - set _tx_timer_time_slice = 1 - set _tx_timer_expired_time_slice = 0 - set $ret_addr = $ra - disable 4 - tbreak *$ret_addr - continue - end -end - -if $preempt_ok == 1 - printf "PREEMPT_VERIFIED_OK ticks=%d\n", $preempt_iter -else - if $preempt_null == $preempt_iter - printf "PREEMPT_VERIFIED_FAIL_NULL\n" - else - printf "PREEMPT_VERIFIED_FAIL_NOT_OBSERVED ticks=%d\n", $preempt_iter - end -end - -quit From d3fb72b6dd2710bab1f1c6b5dfa28a36fdbdedd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Wed, 9 Sep 2026 09:34:33 -0400 Subject: [PATCH 109/181] Aligned the simulator ports' fake stack pointer so ThreadX no longer performs misaligned ULONG accesses (#705) The Linux, Win32 and Win64 simulation ports build a fake initial stack pointer by subtracting a fixed 8 bytes from tx_thread_stack_end. That field addresses the last byte of the thread's stack area, so it is one less than an aligned address and the resulting pointer is misaligned by construction, no matter how well aligned the stack the application supplied was. Two ULONG accesses then use that pointer. _tx_thread_stack_build() itself clears the word below it, and _tx_thread_create() copies it into tx_thread_stack_highest_ptr, which TX_THREAD_STACK_CHECK dereferences on every suspend and resume when TX_ENABLE_STACK_CHECKING is defined. Both are undefined behaviour. They happen to work on x86 but are reported by GCC's undefined behaviour sanitizer, and would fault on a host that requires natural alignment. The fake stack pointer is now rounded down to a ULONG boundary, which leaves it inside the stack area and makes both accesses aligned. Verified by building the Linux port with -fsanitize=undefined and running the demo: the two reported diagnostics are produced before the change and neither appears after it. The tx and smp regression suites pass, 98 and 114 tests respectively. Fixes #218 Assisted-by: Copilot (Opus 5) --- ports/linux/gnu/src/tx_thread_stack_build.c | 12 ++++++++++-- ports/win32/vs_2019/src/tx_thread_stack_build.c | 12 ++++++++++-- ports/win64/vs_2022/src/tx_thread_stack_build.c | 12 ++++++++++-- ports_smp/linux/gnu/src/tx_thread_stack_build.c | 12 ++++++++++-- 4 files changed, 40 insertions(+), 8 deletions(-) diff --git a/ports/linux/gnu/src/tx_thread_stack_build.c b/ports/linux/gnu/src/tx_thread_stack_build.c index cdadba6c2..98c1ca716 100644 --- a/ports/linux/gnu/src/tx_thread_stack_build.c +++ b/ports/linux/gnu/src/tx_thread_stack_build.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -79,6 +81,7 @@ void *_tx_linux_thread_entry(void *ptr); /**************************************************************************/ VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID)) { +ALIGN_TYPE fake_stack_ptr; struct sched_param sp; (VOID)function_ptr; @@ -118,8 +121,13 @@ struct sched_param sp; tx_interrupt_control nesting. */ thread_ptr -> tx_thread_linux_int_disabled_flag = 0; - /* Setup a fake thread stack pointer. */ - thread_ptr -> tx_thread_stack_ptr = (VOID *) (((CHAR *) thread_ptr -> tx_thread_stack_end) - 8); + /* Setup a fake thread stack pointer. The stack end points at the last byte of the + thread's stack area and is therefore not necessarily aligned, so round the result + down to a ULONG boundary. This pointer is dereferenced as a ULONG below and is + also the starting value of the stack checking logic's highest used pointer. */ + fake_stack_ptr = TX_POINTER_TO_ALIGN_TYPE_CONVERT(((CHAR *) thread_ptr -> tx_thread_stack_end) - 8); + fake_stack_ptr = fake_stack_ptr & (~((ALIGN_TYPE) (sizeof(ULONG) - 1))); + thread_ptr -> tx_thread_stack_ptr = TX_ALIGN_TYPE_TO_POINTER_CONVERT(fake_stack_ptr); /* Clear the first word of the stack. */ *(((ULONG *) thread_ptr -> tx_thread_stack_ptr) - 1) = 0; diff --git a/ports/win32/vs_2019/src/tx_thread_stack_build.c b/ports/win32/vs_2019/src/tx_thread_stack_build.c index da51e7c4d..ccbabefd1 100644 --- a/ports/win32/vs_2019/src/tx_thread_stack_build.c +++ b/ports/win32/vs_2019/src/tx_thread_stack_build.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -75,6 +77,7 @@ DWORD WINAPI _tx_win32_thread_entry(LPVOID p); /**************************************************************************/ VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID)) { +ALIGN_TYPE fake_stack_ptr; /* Create a Win32 thread for the application thread. */ thread_ptr -> tx_thread_win32_thread_handle = @@ -119,8 +122,13 @@ VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID)) tx_interrupt_control nesting. */ thread_ptr -> tx_thread_win32_int_disabled_flag = 0; - /* Setup a fake thread stack pointer. */ - thread_ptr -> tx_thread_stack_ptr = (VOID *) (((CHAR *) thread_ptr -> tx_thread_stack_end) - 8); + /* Setup a fake thread stack pointer. The stack end points at the last byte of the + thread's stack area and is therefore not necessarily aligned, so round the result + down to a ULONG boundary. This pointer is dereferenced as a ULONG below and is + also the starting value of the stack checking logic's highest used pointer. */ + fake_stack_ptr = TX_POINTER_TO_ALIGN_TYPE_CONVERT(((CHAR *) thread_ptr -> tx_thread_stack_end) - 8); + fake_stack_ptr = fake_stack_ptr & (~((ALIGN_TYPE) (sizeof(ULONG) - 1))); + thread_ptr -> tx_thread_stack_ptr = TX_ALIGN_TYPE_TO_POINTER_CONVERT(fake_stack_ptr); /* Clear the first word of the stack. */ *(((ULONG *) thread_ptr -> tx_thread_stack_ptr) - 1) = 0; diff --git a/ports/win64/vs_2022/src/tx_thread_stack_build.c b/ports/win64/vs_2022/src/tx_thread_stack_build.c index c50f7754d..d48a8f061 100644 --- a/ports/win64/vs_2022/src/tx_thread_stack_build.c +++ b/ports/win64/vs_2022/src/tx_thread_stack_build.c @@ -13,6 +13,8 @@ * SPDX-License-Identifier: MIT and CC0-1.0 **************************************************************************/ +// Some portions generated by Copilot (Opus 5). + // Some portions generated by Codex (gpt 5.4). /**************************************************************************/ @@ -80,6 +82,7 @@ DWORD WINAPI _tx_win32_thread_entry(LPVOID p); /**************************************************************************/ VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID)) { +ALIGN_TYPE fake_stack_ptr; /* Create a Win32 thread for the application thread. */ thread_ptr -> tx_thread_win32_thread_handle = @@ -138,8 +141,13 @@ VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID)) tx_interrupt_control nesting. */ thread_ptr -> tx_thread_win32_int_disabled_flag = 0; - /* Setup a fake thread stack pointer. */ - thread_ptr -> tx_thread_stack_ptr = (VOID *) (((CHAR *) thread_ptr -> tx_thread_stack_end) - 8); + /* Setup a fake thread stack pointer. The stack end points at the last byte of the + thread's stack area and is therefore not necessarily aligned, so round the result + down to a ULONG boundary. This pointer is dereferenced as a ULONG below and is + also the starting value of the stack checking logic's highest used pointer. */ + fake_stack_ptr = TX_POINTER_TO_ALIGN_TYPE_CONVERT(((CHAR *) thread_ptr -> tx_thread_stack_end) - 8); + fake_stack_ptr = fake_stack_ptr & (~((ALIGN_TYPE) (sizeof(ULONG) - 1))); + thread_ptr -> tx_thread_stack_ptr = TX_ALIGN_TYPE_TO_POINTER_CONVERT(fake_stack_ptr); /* Clear the first word of the stack. */ *(((ULONG *) thread_ptr -> tx_thread_stack_ptr) - 1) = 0; diff --git a/ports_smp/linux/gnu/src/tx_thread_stack_build.c b/ports_smp/linux/gnu/src/tx_thread_stack_build.c index 1b491a3a0..787d07d47 100644 --- a/ports_smp/linux/gnu/src/tx_thread_stack_build.c +++ b/ports_smp/linux/gnu/src/tx_thread_stack_build.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -80,6 +82,7 @@ void *_tx_linux_thread_entry(void *ptr); /**************************************************************************/ VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID)) { +ALIGN_TYPE fake_stack_ptr; struct sched_param sp; pthread_attr_t attrs; @@ -120,8 +123,13 @@ pthread_attr_t attrs; tx_interrupt_control nesting. */ thread_ptr -> tx_thread_linux_mutex_access = TX_FALSE; - /* Setup a fake thread stack pointer. */ - thread_ptr -> tx_thread_stack_ptr = (VOID *) (((CHAR *) thread_ptr -> tx_thread_stack_end) - 8); + /* Setup a fake thread stack pointer. The stack end points at the last byte of the + thread's stack area and is therefore not necessarily aligned, so round the result + down to a ULONG boundary. This pointer is dereferenced as a ULONG below and is + also the starting value of the stack checking logic's highest used pointer. */ + fake_stack_ptr = TX_POINTER_TO_ALIGN_TYPE_CONVERT(((CHAR *) thread_ptr -> tx_thread_stack_end) - 8); + fake_stack_ptr = fake_stack_ptr & (~((ALIGN_TYPE) (sizeof(ULONG) - 1))); + thread_ptr -> tx_thread_stack_ptr = TX_ALIGN_TYPE_TO_POINTER_CONVERT(fake_stack_ptr); /* Clear the first word of the stack. */ *(((ULONG *) thread_ptr -> tx_thread_stack_ptr) - 1) = 0; From 37f48fa83c0d55428ca58c98ce36d314356d5e14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Wed, 9 Sep 2026 10:29:51 -0400 Subject: [PATCH 110/181] Removed FIFO queueing from the ARMv7-A SMP ports so an ISR can no longer deadlock waiting for protection (#707) The Cortex-A5, A7 and A9 SMP ports guarded the inter-core protection with a FIFO wait list: a core that could not take the lock added itself to a queue, incremented _tx_thread_smp_protect_wait_counts[core], and only the core at the head of the queue was allowed to acquire. Two parts of that scheme require the waiting core to be interruptible. _tx_thread_smp_unprotect() refuses to release the protection while the releasing core's own wait count is non-zero, and a queued core is taken back out of the list by _tx_thread_context_restore() when it is preempted. Neither can happen on a core that is spinning inside an ISR with interrupts already masked, because the spin loop restores the caller's interrupt posture rather than enabling interrupts. The core stays in the list forever and the system deadlocks with cores stuck in the wait loop. This is the deadlock Microsoft removed from the ARMv8-A SMP ports in 6.1.11, by dropping the wait list and using a plain LDAXR/STXR spinlock. The same removal was announced for the ARMv7-A ports at the time but was never made, so those three ports have carried the deadlock ever since. The FIFO queueing is now removed from the ARMv7-A SMP ports as well. _tx_thread_smp_protect() becomes an LDREX/STREX spinlock that releases interrupts between attempts, matching the sequence already used by the Cortex-R8 SMP port; _tx_thread_smp_unprotect() no longer consults the wait counts; and _tx_thread_context_restore() no longer has to unqueue a preempted core. The now unreferenced wait list macro headers are deleted. Verified by assembling all three GNU ports with arm-none-eabi-gcc for cortex-a5, cortex-a7 and cortex-a9, with and without TX_ENABLE_FIQ_SUPPORT, TX_ENABLE_WFE and TX_MPCORE_DEBUG_ENABLE, and by reading back the disassembly of the new protect sequence. The port consistency checks pass. Fixes #219 Assisted-by: Copilot (Opus 5) --- .../ac5/src/tx_thread_context_restore.s | 80 +---- .../ac5/src/tx_thread_smp_protect.s | 292 ++++------------ ...x_thread_smp_protection_wait_list_macros.h | 314 ------------------ .../ac5/src/tx_thread_smp_unprotect.s | 7 +- .../gnu/src/tx_thread_context_restore.S | 80 +---- .../gnu/src/tx_thread_smp_protect.S | 292 ++++------------ ...x_thread_smp_protection_wait_list_macros.h | 309 ----------------- .../gnu/src/tx_thread_smp_unprotect.S | 7 +- .../ac5/src/tx_thread_context_restore.s | 79 +---- .../ac5/src/tx_thread_smp_protect.s | 290 +++------------- ...x_thread_smp_protection_wait_list_macros.h | 312 ----------------- .../ac5/src/tx_thread_smp_unprotect.s | 7 +- .../gnu/src/tx_thread_context_restore.S | 79 +---- .../gnu/src/tx_thread_smp_protect.S | 289 +++------------- ...x_thread_smp_protection_wait_list_macros.h | 308 ----------------- .../gnu/src/tx_thread_smp_unprotect.S | 7 +- .../ac5/src/tx_thread_context_restore.s | 80 +---- .../ac5/src/tx_thread_smp_protect.s | 290 +++------------- ...x_thread_smp_protection_wait_list_macros.h | 314 ------------------ .../ac5/src/tx_thread_smp_unprotect.s | 7 +- .../gnu/src/tx_thread_context_restore.S | 80 +---- .../gnu/src/tx_thread_smp_protect.S | 290 +++------------- ...x_thread_smp_protection_wait_list_macros.h | 309 ----------------- .../gnu/src/tx_thread_smp_unprotect.S | 7 +- 24 files changed, 352 insertions(+), 3777 deletions(-) delete mode 100644 ports_smp/cortex_a5_smp/ac5/src/tx_thread_smp_protection_wait_list_macros.h delete mode 100644 ports_smp/cortex_a5_smp/gnu/src/tx_thread_smp_protection_wait_list_macros.h delete mode 100644 ports_smp/cortex_a7_smp/ac5/src/tx_thread_smp_protection_wait_list_macros.h delete mode 100644 ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_protection_wait_list_macros.h delete mode 100644 ports_smp/cortex_a9_smp/ac5/src/tx_thread_smp_protection_wait_list_macros.h delete mode 100644 ports_smp/cortex_a9_smp/gnu/src/tx_thread_smp_protection_wait_list_macros.h diff --git a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_context_restore.s b/ports_smp/cortex_a5_smp/ac5/src/tx_thread_context_restore.s index 21d63d056..c639983bf 100644 --- a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_context_restore.s +++ b/ports_smp/cortex_a5_smp/ac5/src/tx_thread_context_restore.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * 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 @@ -7,6 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ +; Some portions generated by Copilot (Opus 5). ; ; ;/**************************************************************************/ @@ -29,8 +31,6 @@ ;#include "tx_thread.h" ;#include "tx_timer.h" ; -;/* Include macros for modifying the wait list. */ -#include "tx_thread_smp_protection_wait_list_macros.h" IF :DEF:TX_ENABLE_FIQ_SUPPORT DISABLE_INTS EQU 0xC0 ; Disable IRQ & FIQ interrupts @@ -51,11 +51,6 @@ SVC_MODE EQU 0x93 ; SVC mode IMPORT _tx_thread_preempt_disable IMPORT _tx_timer_interrupt_active IMPORT _tx_thread_smp_protection - IMPORT _tx_thread_smp_protect_wait_counts - IMPORT _tx_thread_smp_protect_wait_list - IMPORT _tx_thread_smp_protect_wait_list_lock_protect_in_force - IMPORT _tx_thread_smp_protect_wait_list_tail - IMPORT _tx_thread_smp_protect_wait_list_size IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY IMPORT _tx_execution_isr_exit ENDIF @@ -196,77 +191,6 @@ __tx_thread_no_preempt_restore ; { ; __tx_thread_preempt_restore -; -; /* Was the thread being preempted waiting for the lock? */ -; if (_tx_thread_smp_protect_wait_counts[this_core] != 0) -; { -; - LDR r1, =_tx_thread_smp_protect_wait_counts ; Load waiting count list - LDR r2, [r1, r10, LSL #2] ; Load waiting value for this core - CMP r2, #0 - BEQ _nobody_waiting_for_lock ; Is the core waiting for the lock? -; -; /* Do we not have the lock? This means the ISR never got the inter-core lock. */ -; if (_tx_thread_smp_protection.tx_thread_smp_protect_owned != this_core) -; { -; - LDR r1, =_tx_thread_smp_protection ; Load address of protection structure - LDR r2, [r1, #8] ; Pickup the owning core - CMP r10, r2 ; Compare our core to the owning core - BEQ _this_core_has_lock ; Do we have the lock? -; -; /* We don't have the lock. This core should be in the list. Remove it. */ -; _tx_thread_smp_protect_wait_list_remove(this_core); -; - MOV r0, r10 ; Move the core ID to r0 for the macro -macro_call0 _tx_thread_smp_protect_wait_list_remove ; Call macro to remove core from the list - B _nobody_waiting_for_lock ; Leave -; -; } -; else -; { -; /* We have the lock. This means the ISR got the inter-core lock, but -; never released it because it saw that there was someone waiting. -; Note this core is not in the list. */ -; -_this_core_has_lock -; -; /* We're no longer waiting. Note that this should be zero since this happens during thread preemption. */ -; _tx_thread_smp_protect_wait_counts[core]--; -; - LDR r1, =_tx_thread_smp_protect_wait_counts ; Load waiting count list - LDR r2, [r1, r10, LSL #2] ; Load waiting value for this core - SUB r2, r2, #1 ; Decrement waiting value. Should be zero now - STR r2, [r1, r10, LSL #2] ; Store new waiting value -; -; /* Now release the inter-core lock. */ -; -; /* Set protected core as invalid. */ -; _tx_thread_smp_protection.tx_thread_smp_protect_core = 0xFFFFFFFF; -; - LDR r1, =_tx_thread_smp_protection ; Load address of protection structure - MOV r2, #0xFFFFFFFF ; Build invalid value - STR r2, [r1, #8] ; Mark the protected core as invalid - DMB ; Ensure that accesses to shared resource have completed -; -; /* Release protection. */ -; _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 0; -; - MOV r2, #0 ; Build release protection value - STR r2, [r1, #0] ; Release the protection - DSB ISH ; To ensure update of the protection occurs before other CPUs awake -; -; /* Wake up waiting processors. Note interrupts are already enabled. */ -; - IF :DEF:TX_ENABLE_WFE - SEV ; Send event to other CPUs - ENDIF -; -; } -; } -; - -_nobody_waiting_for_lock LDMIA sp!, {r3, r10, r12, lr} ; Recover temporarily saved registers MOV r1, lr ; Save lr (point of interrupt) diff --git a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_smp_protect.s b/ports_smp/cortex_a5_smp/ac5/src/tx_thread_smp_protect.s index a7419c10a..a1bb8b2fb 100644 --- a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_smp_protect.s +++ b/ports_smp/cortex_a5_smp/ac5/src/tx_thread_smp_protect.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * 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 @@ -7,6 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ +; Some portions generated by Copilot (Opus 5). ; ; ;/**************************************************************************/ @@ -31,17 +33,9 @@ ; ; -;/* Include macros for modifying the wait list. */ -#include "tx_thread_smp_protection_wait_list_macros.h" IMPORT _tx_thread_current_ptr IMPORT _tx_thread_smp_protection - IMPORT _tx_thread_smp_protect_wait_counts - IMPORT _tx_thread_smp_protect_wait_list - IMPORT _tx_thread_smp_protect_wait_list_lock_protect_in_force - IMPORT _tx_thread_smp_protect_wait_list_head - IMPORT _tx_thread_smp_protect_wait_list_tail - IMPORT _tx_thread_smp_protect_wait_list_size AREA ||.text||, CODE, READONLY PRESERVE8 @@ -80,12 +74,12 @@ ;/**************************************************************************/ EXPORT _tx_thread_smp_protect _tx_thread_smp_protect - - PUSH {r4-r6} ; Save registers we'll be using +;VOID _tx_thread_smp_protect(VOID) +;{ ; ; /* Disable interrupts so we don't get preempted. */ ; - MRS r0, CPSR ; Pickup current CPSR + MRS r3, CPSR ; Pickup current CPSR IF :DEF:TX_ENABLE_FIQ_SUPPORT CPSID if ; Disable IRQ and FIQ interrupts @@ -93,266 +87,93 @@ _tx_thread_smp_protect CPSID i ; Disable IRQ interrupts ENDIF ; +; /* Pickup the CPU ID. */ +; + MRC p15, 0, r2, c0, c0, 5 ; Read CPU ID register + AND r2, r2, #0x03 ; Mask off, leaving the CPU ID field +; ; /* Do we already have protection? */ ; if (this_core == _tx_thread_smp_protection.tx_thread_smp_protect_core) ; { ; - MRC p15, 0, r1, c0, c0, 5 ; Read CPU ID register - AND r1, r1, #0x03 ; Mask off, leaving the CPU ID field - LDR r2, =_tx_thread_smp_protection ; Build address to protection structure - LDR r3, [r2, #8] ; Pickup the owning core - CMP r1, r3 ; Is it not this core? - BNE _protection_not_owned ; No, the protection is not already owned -; -; /* We already have protection. */ -; -; /* Increment the protection count. */ -; _tx_thread_smp_protection.tx_thread_smp_protect_count++; + LDR r0, =_tx_thread_smp_protection ; Build address to protection structure + LDR r1, [r0, #8] ; Pickup the owning core + CMP r1, r2 ; Is it this core? + BEQ _owned ; Yes, the protection is already owned ; - LDR r3, [r2, #12] ; Pickup ownership count - ADD r3, r3, #1 ; Increment ownership count - STR r3, [r2, #12] ; Store ownership count - DMB - - B _return - -_protection_not_owned +; } ; ; /* Is the lock available? */ ; if (_tx_thread_smp_protection.tx_thread_smp_protect_in_force == 0) ; { ; - LDREX r3, [r2, #0] ; Pickup the protection flag - CMP r3, #0 - BNE _start_waiting ; No, protection not available -; -; /* Is the list empty? */ -; if (_tx_thread_smp_protect_wait_list_head == _tx_thread_smp_protect_wait_list_tail) -; { -; - LDR r3, =_tx_thread_smp_protect_wait_list_head - LDR r3, [r3] - LDR r4, =_tx_thread_smp_protect_wait_list_tail - LDR r4, [r4] - CMP r3, r4 - BNE _list_not_empty -; -; /* Try to get the lock. */ -; if (write_exclusive(&_tx_thread_smp_protection.tx_thread_smp_protect_in_force, 1) == SUCCESS) -; { -; - MOV r3, #1 ; Build lock value - STREX r4, r3, [r2, #0] ; Attempt to get the protection - CMP r4, #0 - BNE _start_waiting ; Did it fail? -; -; /* We got the lock! */ -; _tx_thread_smp_protect_lock_got(); -; - DMB ; Ensure write to protection finishes -macro_call0 _tx_thread_smp_protect_lock_got ; Call the lock got function - - B _return - -_list_not_empty -; -; /* Are we at the front of the list? */ -; if (this_core == _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_head]) -; { -; - LDR r3, =_tx_thread_smp_protect_wait_list_head ; Get the address of the head - LDR r3, [r3] ; Get the value of the head - LDR r4, =_tx_thread_smp_protect_wait_list ; Get the address of the list - LDR r4, [r4, r3, LSL #2] ; Get the value at the head index - - CMP r1, r4 - BNE _start_waiting -; -; /* Is the lock still available? */ -; if (_tx_thread_smp_protection.tx_thread_smp_protect_in_force == 0) -; { -; - LDR r3, [r2, #0] ; Pickup the protection flag - CMP r3, #0 - BNE _start_waiting ; No, protection not available -; -; /* Get the lock. */ -; _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 1; -; - MOV r3, #1 ; Build lock value - STR r3, [r2, #0] ; Store lock value - DMB ; -; -; /* Got the lock. */ -; _tx_thread_smp_protect_lock_got(); -; -macro_call1 _tx_thread_smp_protect_lock_got -; -; /* Remove this core from the wait list. */ -; _tx_thread_smp_protect_remove_from_front_of_list(); -; -macro_call2 _tx_thread_smp_protect_remove_from_front_of_list - - B _return - -_start_waiting -; -; /* For one reason or another, we didn't get the lock. */ -; -; /* Increment wait count. */ -; _tx_thread_smp_protect_wait_counts[this_core]++; -; - LDR r3, =_tx_thread_smp_protect_wait_counts ; Load wait list counts - LDR r4, [r3, r1, LSL #2] ; Load waiting value for this core - ADD r4, r4, #1 ; Increment wait value - STR r4, [r3, r1, LSL #2] ; Store new wait value -; -; /* Have we not added ourselves to the list yet? */ -; if (_tx_thread_smp_protect_wait_counts[this_core] == 1) -; { -; - CMP r4, #1 - BNE _already_in_list0 ; Is this core already waiting? -; -; /* Add ourselves to the list. */ -; _tx_thread_smp_protect_wait_list_add(this_core); -; -macro_call3 _tx_thread_smp_protect_wait_list_add ; Call macro to add ourselves to the list + LDREX r1, [r0] ; Pickup the protection flag + CMP r1, #0 ; Is it available? + BEQ _get_protection ; Yes, attempt to get the protection ; ; } ; -_already_in_list0 -; -; /* Restore interrupts. */ +; /* The protection is held elsewhere. Restore interrupts so this core can be +; preempted while it waits, then try the whole sequence again. */ ; - MSR CPSR_c, r0 ; Restore CPSR + MSR CPSR_c, r3 ; Restore CPSR IF :DEF:TX_ENABLE_WFE WFE ; Go into standby ENDIF -; -; /* We do this until we have the lock. */ -; while (1) -; { -; -_try_to_get_lock -; -; /* Disable interrupts so we don't get preempted. */ -; - IF :DEF:TX_ENABLE_FIQ_SUPPORT - CPSID if ; Disable IRQ and FIQ interrupts - ELSE - CPSID i ; Disable IRQ interrupts - ENDIF + B _tx_thread_smp_protect ; On waking, restart the protection attempt - MRC p15, 0, r1, c0, c0, 5 ; Read CPU ID register - AND r1, r1, #0x03 ; Mask off, leaving the CPU ID field +_get_protection ; -; /* Do we already have protection? */ -; if (this_core == _tx_thread_smp_protection.tx_thread_smp_protect_core) +; /* Try to get the lock. */ +; if (write_exclusive(&_tx_thread_smp_protection.tx_thread_smp_protect_in_force, 1) == SUCCESS) ; { ; - LDR r3, [r2, #8] ; Pickup the owning core - CMP r3, r1 ; Is it this core? - BEQ _got_lock_after_waiting ; Yes, the protection is already owned. This means - ; an ISR preempted us and got protection + MOV r1, #1 ; Build lock value + STREX r2, r1, [r0] ; Attempt to get the protection + CMP r2, #0 ; Check whether the store succeeded (0 = success) + BEQ _got_protection ; Yes, we have the protection ; ; } ; -; /* Are we at the front of the list? */ -; if (this_core == _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_head]) -; { +; /* Another core beat us to it. Restore interrupts and try again. */ ; - LDR r3, =_tx_thread_smp_protect_wait_list_head ; Get the address of the head - LDR r3, [r3] ; Get the value of the head - LDR r4, =_tx_thread_smp_protect_wait_list ; Get the address of the list - LDR r4, [r4, r3, LSL #2] ; Get the value at the head index + MSR CPSR_c, r3 ; Restore CPSR + B _tx_thread_smp_protect ; Try the whole process again - CMP r1, r4 - BNE _did_not_get_lock -; -; /* Is the lock still available? */ -; if (_tx_thread_smp_protection.tx_thread_smp_protect_in_force == 0) -; { -; - LDR r3, [r2, #0] ; Pickup the protection flag - CMP r3, #0 - BNE _did_not_get_lock ; No, protection not available -; -; /* Get the lock. */ -; _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 1; -; - MOV r3, #1 ; Build lock value - STR r3, [r2, #0] ; Store lock value - DMB ; +_got_protection ; -; /* Got the lock. */ -; _tx_thread_smp_protect_lock_got(); +; /* Got the lock. Record the owning core. */ +; _tx_thread_smp_protection.tx_thread_smp_protect_core = this_core; ; -macro_call4 _tx_thread_smp_protect_lock_got -; -; /* Remove this core from the wait list. */ -; _tx_thread_smp_protect_remove_from_front_of_list(); -; -macro_call5 _tx_thread_smp_protect_remove_from_front_of_list - - B _got_lock_after_waiting + DMB ; Ensure the protection write completes before it is used + MRC p15, 0, r2, c0, c0, 5 ; Read CPU ID register + AND r2, r2, #0x03 ; Mask off, leaving the CPU ID field + STR r2, [r0, #8] ; Save the owning core -_did_not_get_lock -; -; /* For one reason or another, we didn't get the lock. */ -; -; /* Were we removed from the list? This can happen if we're a thread -; and we got preempted. */ -; if (_tx_thread_smp_protect_wait_counts[this_core] == 0) -; { -; - LDR r3, =_tx_thread_smp_protect_wait_counts ; Load wait list counts - LDR r4, [r3, r1, LSL #2] ; Load waiting value for this core - CMP r4, #0 - BNE _already_in_list1 ; Is this core already in the list? -; -; /* Add ourselves to the list. */ -; _tx_thread_smp_protect_wait_list_add(this_core); -; -macro_call6 _tx_thread_smp_protect_wait_list_add ; Call macro to add ourselves to the list -; -; /* Our waiting count was also reset when we were preempted. Increment it again. */ -; _tx_thread_smp_protect_wait_counts[this_core]++; -; - LDR r3, =_tx_thread_smp_protect_wait_counts ; Load wait list counts - LDR r4, [r3, r1, LSL #2] ; Load waiting value for this core - ADD r4, r4, #1 ; Increment wait value - STR r4, [r3, r1, LSL #2] ; Store new wait value value -; -; } -; -_already_in_list1 -; -; /* Restore interrupts and try again. */ -; - MSR CPSR_c, r0 ; Restore CPSR - IF :DEF:TX_ENABLE_WFE - WFE ; Go into standby + IF :DEF:TX_MPCORE_DEBUG_ENABLE + LSL r2, r2, #2 ; Build offset to array indexes + LDR r1, =_tx_thread_current_ptr ; Pickup start of the current thread array + ADD r1, r1, r2 ; Build index into the current thread array + LDR r2, [r1] ; Pickup current thread for this core + STR r2, [r0, #4] ; Save current thread pointer + STR LR, [r0, #16] ; Save caller's return address + STR r3, [r0, #20] ; Save CPSR ENDIF - B _try_to_get_lock ; On waking, restart the protection attempt -_got_lock_after_waiting +_owned ; -; /* We're no longer waiting. */ -; _tx_thread_smp_protect_wait_counts[this_core]--; +; /* Increment the protection count. */ +; _tx_thread_smp_protection.tx_thread_smp_protect_count++; ; - LDR r3, =_tx_thread_smp_protect_wait_counts ; Load waiting list - LDR r4, [r3, r1, LSL #2] ; Load current wait value - SUB r4, r4, #1 ; Decrement wait value - STR r4, [r3, r1, LSL #2] ; Store new wait value value + LDR r1, [r0, #12] ; Pickup ownership count + ADD r1, r1, #1 ; Increment ownership count + STR r1, [r0, #12] ; Store new ownership count + DMB ; + MOV r0, r3 ; Return the previous CPSR ; -; /* Restore link register and return. */ +;} ; -_return - - POP {r4-r6} ; Restore registers - IF {INTER} = {TRUE} BX lr ; Return to caller ELSE @@ -360,4 +181,3 @@ _return ENDIF END - diff --git a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_smp_protection_wait_list_macros.h b/ports_smp/cortex_a5_smp/ac5/src/tx_thread_smp_protection_wait_list_macros.h deleted file mode 100644 index fec515810..000000000 --- a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_smp_protection_wait_list_macros.h +++ /dev/null @@ -1,314 +0,0 @@ -;/*************************************************************************** -; * Copyright (c) 2024 Microsoft Corporation -; * -; * This program and the accompanying materials are made available under the -; * terms of the MIT License which is available at -; * https://opensource.org/licenses/MIT. -; * -; * SPDX-License-Identifier: MIT -; **************************************************************************/ -; -; -;/**************************************************************************/ -;/**************************************************************************/ -;/** */ -;/** ThreadX Component */ -;/** */ -;/** Thread - Low Level SMP Support */ -;/** */ -;/**************************************************************************/ -;/**************************************************************************/ - - MACRO -$label _tx_thread_smp_protect_lock_got -; -; /* Set the currently owned core. */ -; _tx_thread_smp_protection.tx_thread_smp_protect_core = this_core; -; - STR r1, [r2, #8] ; Store this core -; -; /* Increment the protection count. */ -; _tx_thread_smp_protection.tx_thread_smp_protect_count++; -; - LDR r3, [r2, #12] ; Pickup ownership count - ADD r3, r3, #1 ; Increment ownership count - STR r3, [r2, #12] ; Store ownership count - DMB - - IF :DEF:TX_MPCORE_DEBUG_ENABLE - LSL r3, r1, #2 ; Build offset to array indexes - LDR r4, =_tx_thread_current_ptr ; Pickup start of the current thread array - ADD r4, r3, r4 ; Build index into the current thread array - LDR r3, [r4] ; Pickup current thread for this core - STR r3, [r2, #4] ; Save current thread pointer - STR LR, [r2, #16] ; Save caller's return address - STR r0, [r2, #20] ; Save CPSR - ENDIF - - MEND - - MACRO -$label _tx_thread_smp_protect_remove_from_front_of_list -; -; /* Remove ourselves from the list. */ -; _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_head++] = 0xFFFFFFFF; -; - MOV r3, #0xFFFFFFFF ; Build the invalid core value - LDR r4, =_tx_thread_smp_protect_wait_list_head ; Get the address of the head - LDR r5, [r4] ; Get the value of the head - LDR r6, =_tx_thread_smp_protect_wait_list ; Get the address of the list - STR r3, [r6, r5, LSL #2] ; Store the invalid core value - ADD r5, r5, #1 ; Increment the head -; -; /* Did we wrap? */ -; if (_tx_thread_smp_protect_wait_list_head == TX_THREAD_SMP_MAX_CORES + 1) -; { -; - LDR r3, =_tx_thread_smp_protect_wait_list_size ; Load address of core list size - LDR r3, [r3] ; Load the max cores value - CMP r5, r3 ; Compare the head to it - BNE $label._store_new_head ; Are we at the max? -; -; _tx_thread_smp_protect_wait_list_head = 0; -; - EOR r5, r5, r5 ; We're at the max. Set it to zero -; -; } -; -$label._store_new_head - - STR r5, [r4] ; Store the new head -; -; /* We have the lock! */ -; return; -; - MEND - - - MACRO -$label _tx_thread_smp_protect_wait_list_lock_get -;VOID _tx_thread_smp_protect_wait_list_lock_get() -;{ -; /* We do this until we have the lock. */ -; while (1) -; { -; -$label._tx_thread_smp_protect_wait_list_lock_get__try_to_get_lock -; -; /* Is the list lock available? */ -; _tx_thread_smp_protect_wait_list_lock_protect_in_force = load_exclusive(&_tx_thread_smp_protect_wait_list_lock_protect_in_force); -; - LDR r1, =_tx_thread_smp_protect_wait_list_lock_protect_in_force - LDREX r2, [r1] ; Pickup the protection flag -; -; if (protect_in_force == 0) -; { -; - CMP r2, #0 - BNE $label._tx_thread_smp_protect_wait_list_lock_get__try_to_get_lock ; No, protection not available -; -; /* Try to get the list. */ -; int status = store_exclusive(&_tx_thread_smp_protect_wait_list_lock_protect_in_force, 1); -; - MOV r2, #1 ; Build lock value - STREX r3, r2, [r1] ; Attempt to get the protection -; -; if (status == SUCCESS) -; - CMP r3, #0 - BNE $label._tx_thread_smp_protect_wait_list_lock_get__try_to_get_lock ; Did it fail? If so, try again. -; -; /* We have the lock! */ -; return; -; - MEND - - - MACRO -$label _tx_thread_smp_protect_wait_list_add -;VOID _tx_thread_smp_protect_wait_list_add(UINT new_core) -;{ -; -; /* We're about to modify the list, so get the list lock. */ -; _tx_thread_smp_protect_wait_list_lock_get(); -; - PUSH {r1-r2} - -$label _tx_thread_smp_protect_wait_list_lock_get - - POP {r1-r2} -; -; /* Add this core. */ -; _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_tail++] = new_core; -; - LDR r3, =_tx_thread_smp_protect_wait_list_tail ; Get the address of the tail - LDR r4, [r3] ; Get the value of tail - LDR r5, =_tx_thread_smp_protect_wait_list ; Get the address of the list - STR r1, [r5, r4, LSL #2] ; Store the new core value - ADD r4, r4, #1 ; Increment the tail -; -; /* Did we wrap? */ -; if (_tx_thread_smp_protect_wait_list_tail == _tx_thread_smp_protect_wait_list_size) -; { -; - LDR r5, =_tx_thread_smp_protect_wait_list_size ; Load max cores address - LDR r5, [r5] ; Load max cores value - CMP r4, r5 ; Compare max cores to tail - BNE $label._tx_thread_smp_protect_wait_list_add__no_wrap ; Did we wrap? -; -; _tx_thread_smp_protect_wait_list_tail = 0; -; - MOV r4, #0 -; -; } -; -$label._tx_thread_smp_protect_wait_list_add__no_wrap - - STR r4, [r3] ; Store the new tail value. -; -; /* Release the list lock. */ -; _tx_thread_smp_protect_wait_list_lock_protect_in_force = 0; -; - MOV r3, #0 ; Build lock value - LDR r4, =_tx_thread_smp_protect_wait_list_lock_protect_in_force - STR r3, [r4] ; Store the new value - - MEND - - - MACRO -$label _tx_thread_smp_protect_wait_list_remove -;VOID _tx_thread_smp_protect_wait_list_remove(UINT core) -;{ -; -; /* Get the core index. */ -; UINT core_index; -; for (core_index = 0;; core_index++) -; - EOR r1, r1, r1 ; Clear for 'core_index' - LDR r2, =_tx_thread_smp_protect_wait_list ; Get the address of the list -; -; { -; -$label._tx_thread_smp_protect_wait_list_remove__check_cur_core -; -; /* Is this the core? */ -; if (_tx_thread_smp_protect_wait_list[core_index] == core) -; { -; break; -; - LDR r3, [r2, r1, LSL #2] ; Get the value at the current index - CMP r3, r0 ; Did we find the core? - BEQ $label._tx_thread_smp_protect_wait_list_remove__found_core -; -; } -; - ADD r1, r1, #1 ; Increment cur index - B $label._tx_thread_smp_protect_wait_list_remove__check_cur_core ; Restart the loop -; -; } -; -$label._tx_thread_smp_protect_wait_list_remove__found_core -; -; /* We're about to modify the list. Get the lock. We need the lock because another -; core could be simultaneously adding (a core is simultaneously trying to get -; the inter-core lock) or removing (a core is simultaneously being preempted, -; like what is currently happening). */ -; _tx_thread_smp_protect_wait_list_lock_get(); -; - PUSH {r1} - -$label _tx_thread_smp_protect_wait_list_lock_get - - POP {r1} -; -; /* We remove by shifting. */ -; while (core_index != _tx_thread_smp_protect_wait_list_tail) -; { -; -$label._tx_thread_smp_protect_wait_list_remove__compare_index_to_tail - - LDR r2, =_tx_thread_smp_protect_wait_list_tail ; Load tail address - LDR r2, [r2] ; Load tail value - CMP r1, r2 ; Compare cur index and tail - BEQ $label._tx_thread_smp_protect_wait_list_remove__removed -; -; UINT next_index = core_index + 1; -; - MOV r2, r1 ; Move current index to next index register - ADD r2, r2, #1 ; Add 1 -; -; if (next_index == _tx_thread_smp_protect_wait_list_size) -; { -; - LDR r3, =_tx_thread_smp_protect_wait_list_size - LDR r3, [r3] - CMP r2, r3 - BNE $label._tx_thread_smp_protect_wait_list_remove__next_index_no_wrap -; -; next_index = 0; -; - MOV r2, #0 -; -; } -; -$label._tx_thread_smp_protect_wait_list_remove__next_index_no_wrap -; -; list_cores[core_index] = list_cores[next_index]; -; - LDR r0, =_tx_thread_smp_protect_wait_list ; Get the address of the list - LDR r3, [r0, r2, LSL #2] ; Get the value at the next index - STR r3, [r0, r1, LSL #2] ; Store the value at the current index -; -; core_index = next_index; -; - MOV r1, r2 - - B $label._tx_thread_smp_protect_wait_list_remove__compare_index_to_tail -; -; } -; -$label._tx_thread_smp_protect_wait_list_remove__removed -; -; /* Now update the tail. */ -; if (_tx_thread_smp_protect_wait_list_tail == 0) -; { -; - LDR r0, =_tx_thread_smp_protect_wait_list_tail ; Load tail address - LDR r1, [r0] ; Load tail value - CMP r1, #0 - BNE $label._tx_thread_smp_protect_wait_list_remove__tail_not_zero -; -; _tx_thread_smp_protect_wait_list_tail = _tx_thread_smp_protect_wait_list_size; -; - LDR r2, =_tx_thread_smp_protect_wait_list_size - LDR r1, [r2] -; -; } -; -$label._tx_thread_smp_protect_wait_list_remove__tail_not_zero -; -; _tx_thread_smp_protect_wait_list_tail--; -; - SUB r1, r1, #1 - STR r1, [r0] ; Store new tail value -; -; /* Release the list lock. */ -; _tx_thread_smp_protect_wait_list_lock_protect_in_force = 0; -; - MOV r0, #0 ; Build lock value - LDR r1, =_tx_thread_smp_protect_wait_list_lock_protect_in_force ; Load lock address - STR r0, [r1] ; Store the new value -; -; /* We're no longer waiting. Note that this should be zero since, again, -; this function is only called when a thread preemption is occurring. */ -; _tx_thread_smp_protect_wait_counts[core]--; -; - MRC p15, 0, r0, c0, c0, 5 ; Read CPU ID register - AND r0, r0, #0x03 ; Mask off, leaving the CPU ID field - LDR r1, =_tx_thread_smp_protect_wait_counts ; Load wait list counts - LDR r2, [r1, r0, LSL #2] ; Load waiting value - SUB r2, r2, #1 ; Subtract 1 - STR r2, [r1, r0, LSL #2] ; Store new waiting value - MEND - diff --git a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_smp_unprotect.s b/ports_smp/cortex_a5_smp/ac5/src/tx_thread_smp_unprotect.s index 61645b3e4..f19723e2c 100644 --- a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_smp_unprotect.s +++ b/ports_smp/cortex_a5_smp/ac5/src/tx_thread_smp_unprotect.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * 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 @@ -7,6 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ +; Some portions generated by Copilot (Opus 5). ; ; ;/**************************************************************************/ @@ -33,7 +35,6 @@ IMPORT _tx_thread_current_ptr IMPORT _tx_thread_smp_protection IMPORT _tx_thread_preempt_disable - IMPORT _tx_thread_smp_protect_wait_counts AREA ||.text||, CODE, READONLY PRESERVE8 @@ -103,10 +104,6 @@ _tx_thread_smp_unprotect CMP r3, #0 ; Is the preempt disable flag set? BNE _still_protected ; Yes, skip the protection release - LDR r2,=_tx_thread_smp_protect_wait_counts ; Build build address of wait counts - LDR r3, [r2, r1, LSL #2] ; Pickup wait list value - CMP r3, #0 ; Are any entities on this core waiting? - BNE _still_protected ; Yes, skip the protection release LDR r2,=_tx_thread_smp_protection ; Build address of protection structure MOV r3, #0xFFFFFFFF ; Build invalid value diff --git a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_context_restore.S b/ports_smp/cortex_a5_smp/gnu/src/tx_thread_context_restore.S index 53ca2cc21..bd1b08ec8 100644 --- a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_context_restore.S +++ b/ports_smp/cortex_a5_smp/gnu/src/tx_thread_context_restore.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * 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 @@ -7,6 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ +@ Some portions generated by Copilot (Opus 5). @ @ @/**************************************************************************/ @@ -29,8 +31,6 @@ @#include "tx_thread.h" @#include "tx_timer.h" @ -@/* Include macros for modifying the wait list. */ -#include "tx_thread_smp_protection_wait_list_macros.h" #ifdef TX_ENABLE_FIQ_SUPPORT DISABLE_INTS = 0xC0 @ Disable IRQ & FIQ interrupts @@ -51,11 +51,6 @@ SVC_MODE = 0x93 @ SVC mode .global _tx_thread_preempt_disable .global _tx_timer_interrupt_active .global _tx_thread_smp_protection - .global _tx_thread_smp_protect_wait_counts - .global _tx_thread_smp_protect_wait_list - .global _tx_thread_smp_protect_wait_list_lock_protect_in_force - .global _tx_thread_smp_protect_wait_list_tail - .global _tx_thread_smp_protect_wait_list_size #ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY .global _tx_execution_isr_exit #endif @@ -198,77 +193,6 @@ __tx_thread_no_preempt_restore: @ { @ __tx_thread_preempt_restore: -@ -@ /* Was the thread being preempted waiting for the lock? */ -@ if (_tx_thread_smp_protect_wait_counts[this_core] != 0) -@ { -@ - LDR r1, =_tx_thread_smp_protect_wait_counts @ Load waiting count list - LDR r2, [r1, r10, LSL #2] @ Load waiting value for this core - CMP r2, #0 - BEQ _nobody_waiting_for_lock @ Is the core waiting for the lock? -@ -@ /* Do we not have the lock? This means the ISR never got the inter-core lock. */ -@ if (_tx_thread_smp_protection.tx_thread_smp_protect_owned != this_core) -@ { -@ - LDR r1, =_tx_thread_smp_protection @ Load address of protection structure - LDR r2, [r1, #8] @ Pickup the owning core - CMP r10, r2 @ Compare our core to the owning core - BEQ _this_core_has_lock @ Do we have the lock? -@ -@ /* We don't have the lock. This core should be in the list. Remove it. */ -@ _tx_thread_smp_protect_wait_list_remove(this_core); -@ - MOV r0, r10 @ Move the core ID to r0 for the macro - _tx_thread_smp_protect_wait_list_remove @ Call macro to remove core from the list - B _nobody_waiting_for_lock @ Leave -@ -@ } -@ else -@ { -@ /* We have the lock. This means the ISR got the inter-core lock, but -@ never released it because it saw that there was someone waiting. -@ Note this core is not in the list. */ -@ -_this_core_has_lock: -@ -@ /* We're no longer waiting. Note that this should be zero since this happens during thread preemption. */ -@ _tx_thread_smp_protect_wait_counts[core]--; -@ - LDR r1, =_tx_thread_smp_protect_wait_counts @ Load waiting count list - LDR r2, [r1, r10, LSL #2] @ Load waiting value for this core - SUB r2, r2, #1 @ Decrement waiting value. Should be zero now - STR r2, [r1, r10, LSL #2] @ Store new waiting value -@ -@ /* Now release the inter-core lock. */ -@ -@ /* Set protected core as invalid. */ -@ _tx_thread_smp_protection.tx_thread_smp_protect_core = 0xFFFFFFFF; -@ - LDR r1, =_tx_thread_smp_protection @ Load address of protection structure - MOV r2, #0xFFFFFFFF @ Build invalid value - STR r2, [r1, #8] @ Mark the protected core as invalid - DMB @ Ensure that accesses to shared resource have completed -@ -@ /* Release protection. */ -@ _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 0; -@ - MOV r2, #0 @ Build release protection value - STR r2, [r1, #0] @ Release the protection - DSB ISH @ To ensure update of the protection occurs before other CPUs awake -@ -@ /* Wake up waiting processors. Note interrupts are already enabled. */ -@ -#ifdef TX_ENABLE_WFE - SEV @ Send event to other CPUs -#endif -@ -@ } -@ } -@ - -_nobody_waiting_for_lock: LDMIA sp!, {r3, r10, r12, lr} @ Recover temporarily saved registers MOV r1, lr @ Save lr (point of interrupt) diff --git a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_smp_protect.S b/ports_smp/cortex_a5_smp/gnu/src/tx_thread_smp_protect.S index 103dcd71c..0a5373181 100644 --- a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_smp_protect.S +++ b/ports_smp/cortex_a5_smp/gnu/src/tx_thread_smp_protect.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * 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 @@ -7,6 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ +@ Some portions generated by Copilot (Opus 5). @ @ @/**************************************************************************/ @@ -31,17 +33,9 @@ @ @ -@/* Include macros for modifying the wait list. */ -#include "tx_thread_smp_protection_wait_list_macros.h" .global _tx_thread_current_ptr .global _tx_thread_smp_protection - .global _tx_thread_smp_protect_wait_counts - .global _tx_thread_smp_protect_wait_list - .global _tx_thread_smp_protect_wait_list_lock_protect_in_force - .global _tx_thread_smp_protect_wait_list_head - .global _tx_thread_smp_protect_wait_list_tail - .global _tx_thread_smp_protect_wait_list_size .arm .text @@ -82,12 +76,12 @@ .global _tx_thread_smp_protect .type _tx_thread_smp_protect,function _tx_thread_smp_protect: - - PUSH {r4-r6} @ Save registers we'll be using +@VOID _tx_thread_smp_protect(VOID) +@{ @ @ /* Disable interrupts so we don't get preempted. */ @ - MRS r0, CPSR @ Pickup current CPSR + MRS r3, CPSR @ Pickup current CPSR #ifdef TX_ENABLE_FIQ_SUPPORT CPSID if @ Disable IRQ and FIQ interrupts @@ -95,270 +89,96 @@ _tx_thread_smp_protect: CPSID i @ Disable IRQ interrupts #endif @ +@ /* Pickup the CPU ID. */ +@ + MRC p15, 0, r2, c0, c0, 5 @ Read CPU ID register + AND r2, r2, #0x03 @ Mask off, leaving the CPU ID field +@ @ /* Do we already have protection? */ @ if (this_core == _tx_thread_smp_protection.tx_thread_smp_protect_core) @ { @ - MRC p15, 0, r1, c0, c0, 5 @ Read CPU ID register - AND r1, r1, #0x03 @ Mask off, leaving the CPU ID field - LDR r2, =_tx_thread_smp_protection @ Build address to protection structure - LDR r3, [r2, #8] @ Pickup the owning core - CMP r1, r3 @ Is it not this core? - BNE _protection_not_owned @ No, the protection is not already owned -@ -@ /* We already have protection. */ -@ -@ /* Increment the protection count. */ -@ _tx_thread_smp_protection.tx_thread_smp_protect_count++; + LDR r0, =_tx_thread_smp_protection @ Build address to protection structure + LDR r1, [r0, #8] @ Pickup the owning core + CMP r1, r2 @ Is it this core? + BEQ _owned @ Yes, the protection is already owned @ - LDR r3, [r2, #12] @ Pickup ownership count - ADD r3, r3, #1 @ Increment ownership count - STR r3, [r2, #12] @ Store ownership count - DMB - - B _return - -_protection_not_owned: +@ } @ @ /* Is the lock available? */ @ if (_tx_thread_smp_protection.tx_thread_smp_protect_in_force == 0) @ { @ - LDREX r3, [r2] @ Pickup the protection flag - CMP r3, #0 - BNE _start_waiting @ No, protection not available -@ -@ /* Is the list empty? */ -@ if (_tx_thread_smp_protect_wait_list_head == _tx_thread_smp_protect_wait_list_tail) -@ { -@ - LDR r3, =_tx_thread_smp_protect_wait_list_head - LDR r3, [r3] - LDR r4, =_tx_thread_smp_protect_wait_list_tail - LDR r4, [r4] - CMP r3, r4 - BNE _list_not_empty -@ -@ /* Try to get the lock. */ -@ if (write_exclusive(&_tx_thread_smp_protection.tx_thread_smp_protect_in_force, 1) == SUCCESS) -@ { -@ - MOV r3, #1 @ Build lock value - STREX r4, r3, [r2] @ Attempt to get the protection - CMP r4, #0 - BNE _start_waiting @ Did it fail? -@ -@ /* We got the lock! */ -@ _tx_thread_smp_protect_lock_got(); -@ - DMB @ Ensure write to protection finishes - _tx_thread_smp_protect_lock_got @ Call the lock got function - - B _return - -_list_not_empty: -@ -@ /* Are we at the front of the list? */ -@ if (this_core == _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_head]) -@ { -@ - LDR r3, =_tx_thread_smp_protect_wait_list_head @ Get the address of the head - LDR r3, [r3] @ Get the value of the head - LDR r4, =_tx_thread_smp_protect_wait_list @ Get the address of the list - LDR r4, [r4, r3, LSL #2] @ Get the value at the head index - - CMP r1, r4 - BNE _start_waiting -@ -@ /* Is the lock still available? */ -@ if (_tx_thread_smp_protection.tx_thread_smp_protect_in_force == 0) -@ { -@ - LDR r3, [r2, #0] @ Pickup the protection flag - CMP r3, #0 - BNE _start_waiting @ No, protection not available -@ -@ /* Get the lock. */ -@ _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 1; -@ - MOV r3, #1 @ Build lock value - STR r3, [r2, #0] @ Store lock value - DMB @ -@ -@ /* Got the lock. */ -@ _tx_thread_smp_protect_lock_got(); -@ - _tx_thread_smp_protect_lock_got -@ -@ /* Remove this core from the wait list. */ -@ _tx_thread_smp_protect_remove_from_front_of_list(); -@ - _tx_thread_smp_protect_remove_from_front_of_list - - B _return - -_start_waiting: -@ -@ /* For one reason or another, we didn't get the lock. */ -@ -@ /* Increment wait count. */ -@ _tx_thread_smp_protect_wait_counts[this_core]++; -@ - LDR r3, =_tx_thread_smp_protect_wait_counts @ Load wait list counts - LDR r4, [r3, r1, LSL #2] @ Load waiting value for this core - ADD r4, r4, #1 @ Increment wait value - STR r4, [r3, r1, LSL #2] @ Store new wait value -@ -@ /* Have we not added ourselves to the list yet? */ -@ if (_tx_thread_smp_protect_wait_counts[this_core] == 1) -@ { -@ - CMP r4, #1 - BNE _already_in_list0 @ Is this core already waiting? -@ -@ /* Add ourselves to the list. */ -@ _tx_thread_smp_protect_wait_list_add(this_core); -@ - _tx_thread_smp_protect_wait_list_add @ Call macro to add ourselves to the list + LDREX r1, [r0] @ Pickup the protection flag + CMP r1, #0 @ Is it available? + BEQ _get_protection @ Yes, attempt to get the protection @ @ } @ -_already_in_list0: -@ -@ /* Restore interrupts. */ +@ /* The protection is held elsewhere. Restore interrupts so this core can be +@ preempted while it waits, then try the whole sequence again. */ @ - MSR CPSR_c, r0 @ Restore CPSR + MSR CPSR_c, r3 @ Restore CPSR #ifdef TX_ENABLE_WFE WFE @ Go into standby #endif -@ -@ /* We do this until we have the lock. */ -@ while (1) -@ { -@ -_try_to_get_lock: -@ -@ /* Disable interrupts so we don't get preempted. */ -@ -#ifdef TX_ENABLE_FIQ_SUPPORT - CPSID if @ Disable IRQ and FIQ interrupts -#else - CPSID i @ Disable IRQ interrupts -#endif + B _tx_thread_smp_protect @ On waking, restart the protection attempt - MRC p15, 0, r1, c0, c0, 5 @ Read CPU ID register - AND r1, r1, #0x03 @ Mask off, leaving the CPU ID field +_get_protection: @ -@ /* Do we already have protection? */ -@ if (this_core == _tx_thread_smp_protection.tx_thread_smp_protect_core) +@ /* Try to get the lock. */ +@ if (write_exclusive(&_tx_thread_smp_protection.tx_thread_smp_protect_in_force, 1) == SUCCESS) @ { @ - LDR r3, [r2, #8] @ Pickup the owning core - CMP r3, r1 @ Is it this core? - BEQ _got_lock_after_waiting @ Yes, the protection is already owned. This means - @ an ISR preempted us and got protection + MOV r1, #1 @ Build lock value + STREX r2, r1, [r0] @ Attempt to get the protection + CMP r2, #0 @ Check whether the store succeeded (0 = success) + BEQ _got_protection @ Yes, we have the protection @ @ } @ -@ /* Are we at the front of the list? */ -@ if (this_core == _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_head]) -@ { +@ /* Another core beat us to it. Restore interrupts and try again. */ @ - LDR r3, =_tx_thread_smp_protect_wait_list_head @ Get the address of the head - LDR r3, [r3] @ Get the value of the head - LDR r4, =_tx_thread_smp_protect_wait_list @ Get the address of the list - LDR r4, [r4, r3, LSL #2] @ Get the value at the head index + MSR CPSR_c, r3 @ Restore CPSR + B _tx_thread_smp_protect @ Try the whole process again - CMP r1, r4 - BNE _did_not_get_lock -@ -@ /* Is the lock still available? */ -@ if (_tx_thread_smp_protection.tx_thread_smp_protect_in_force == 0) -@ { -@ - LDR r3, [r2, #0] @ Pickup the protection flag - CMP r3, #0 - BNE _did_not_get_lock @ No, protection not available -@ -@ /* Get the lock. */ -@ _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 1; -@ - MOV r3, #1 @ Build lock value - STR r3, [r2, #0] @ Store lock value - DMB @ +_got_protection: @ -@ /* Got the lock. */ -@ _tx_thread_smp_protect_lock_got(); +@ /* Got the lock. Record the owning core. */ +@ _tx_thread_smp_protection.tx_thread_smp_protect_core = this_core; @ - _tx_thread_smp_protect_lock_got -@ -@ /* Remove this core from the wait list. */ -@ _tx_thread_smp_protect_remove_from_front_of_list(); -@ - _tx_thread_smp_protect_remove_from_front_of_list - - B _got_lock_after_waiting + DMB @ Ensure the protection write completes before it is used + MRC p15, 0, r2, c0, c0, 5 @ Read CPU ID register + AND r2, r2, #0x03 @ Mask off, leaving the CPU ID field + STR r2, [r0, #8] @ Save the owning core -_did_not_get_lock: -@ -@ /* For one reason or another, we didn't get the lock. */ -@ -@ /* Were we removed from the list? This can happen if we're a thread -@ and we got preempted. */ -@ if (_tx_thread_smp_protect_wait_counts[this_core] == 0) -@ { -@ - LDR r3, =_tx_thread_smp_protect_wait_counts @ Load wait list counts - LDR r4, [r3, r1, LSL #2] @ Load waiting value for this core - CMP r4, #0 - BNE _already_in_list1 @ Is this core already in the list? -@ -@ /* Add ourselves to the list. */ -@ _tx_thread_smp_protect_wait_list_add(this_core); -@ - _tx_thread_smp_protect_wait_list_add @ Call macro to add ourselves to the list -@ -@ /* Our waiting count was also reset when we were preempted. Increment it again. */ -@ _tx_thread_smp_protect_wait_counts[this_core]++; -@ - LDR r3, =_tx_thread_smp_protect_wait_counts @ Load wait list counts - LDR r4, [r3, r1, LSL #2] @ Load waiting value for this core - ADD r4, r4, #1 @ Increment wait value - STR r4, [r3, r1, LSL #2] @ Store new wait value value -@ -@ } -@ -_already_in_list1: -@ -@ /* Restore interrupts and try again. */ -@ - MSR CPSR_c, r0 @ Restore CPSR -#ifdef TX_ENABLE_WFE - WFE @ Go into standby +#ifdef TX_MPCORE_DEBUG_ENABLE + LSL r2, r2, #2 @ Build offset to array indexes + LDR r1, =_tx_thread_current_ptr @ Pickup start of the current thread array + ADD r1, r1, r2 @ Build index into the current thread array + LDR r2, [r1] @ Pickup current thread for this core + STR r2, [r0, #4] @ Save current thread pointer + STR LR, [r0, #16] @ Save caller's return address + STR r3, [r0, #20] @ Save CPSR #endif - B _try_to_get_lock @ On waking, restart the protection attempt -_got_lock_after_waiting: +_owned: @ -@ /* We're no longer waiting. */ -@ _tx_thread_smp_protect_wait_counts[this_core]--; +@ /* Increment the protection count. */ +@ _tx_thread_smp_protection.tx_thread_smp_protect_count++; @ - LDR r3, =_tx_thread_smp_protect_wait_counts @ Load waiting list - LDR r4, [r3, r1, LSL #2] @ Load current wait value - SUB r4, r4, #1 @ Decrement wait value - STR r4, [r3, r1, LSL #2] @ Store new wait value value + LDR r1, [r0, #12] @ Pickup ownership count + ADD r1, r1, #1 @ Increment ownership count + STR r1, [r0, #12] @ Store new ownership count + DMB @ + MOV r0, r3 @ Return the previous CPSR @ -@ /* Restore link register and return. */ +@} @ -_return: - - POP {r4-r6} @ Restore registers - #ifdef __THUMB_INTERWORK BX lr @ Return to caller #else MOV pc, lr @ Return to caller #endif - diff --git a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_smp_protection_wait_list_macros.h b/ports_smp/cortex_a5_smp/gnu/src/tx_thread_smp_protection_wait_list_macros.h deleted file mode 100644 index f1ad80e88..000000000 --- a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_smp_protection_wait_list_macros.h +++ /dev/null @@ -1,309 +0,0 @@ -@/*************************************************************************** -@ * Copyright (c) 2024 Microsoft Corporation -@ * -@ * This program and the accompanying materials are made available under the -@ * terms of the MIT License which is available at -@ * https://opensource.org/licenses/MIT. -@ * -@ * SPDX-License-Identifier: MIT -@ **************************************************************************/ -@ -@ -@/**************************************************************************/ -@/**************************************************************************/ -@/** */ -@/** ThreadX Component */ -@/** */ -@/** Thread - Low Level SMP Support */ -@/** */ -@/**************************************************************************/ -@/**************************************************************************/ - - .macro _tx_thread_smp_protect_lock_got -@ -@ /* Set the currently owned core. */ -@ _tx_thread_smp_protection.tx_thread_smp_protect_core = this_core; -@ - STR r1, [r2, #8] @ Store this core -@ -@ /* Increment the protection count. */ -@ _tx_thread_smp_protection.tx_thread_smp_protect_count++; -@ - LDR r3, [r2, #12] @ Pickup ownership count - ADD r3, r3, #1 @ Increment ownership count - STR r3, [r2, #12] @ Store ownership count - DMB - -#ifdef TX_MPCORE_DEBUG_ENABLE - LSL r3, r1, #2 @ Build offset to array indexes - LDR r4, =_tx_thread_current_ptr @ Pickup start of the current thread array - ADD r4, r3, r4 @ Build index into the current thread array - LDR r3, [r4] @ Pickup current thread for this core - STR r3, [r2, #4] @ Save current thread pointer - STR LR, [r2, #16] @ Save caller's return address - STR r0, [r2, #20] @ Save CPSR -#endif - - .endm - - .macro _tx_thread_smp_protect_remove_from_front_of_list -@ -@ /* Remove ourselves from the list. */ -@ _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_head++] = 0xFFFFFFFF; -@ - MOV r3, #0xFFFFFFFF @ Build the invalid core value - LDR r4, =_tx_thread_smp_protect_wait_list_head @ Get the address of the head - LDR r5, [r4] @ Get the value of the head - LDR r6, =_tx_thread_smp_protect_wait_list @ Get the address of the list - STR r3, [r6, r5, LSL #2] @ Store the invalid core value - ADD r5, r5, #1 @ Increment the head -@ -@ /* Did we wrap? */ -@ if (_tx_thread_smp_protect_wait_list_head == TX_THREAD_SMP_MAX_CORES + 1) -@ { -@ - LDR r3, =_tx_thread_smp_protect_wait_list_size @ Load address of core list size - LDR r3, [r3] @ Load the max cores value - CMP r5, r3 @ Compare the head to it - BNE _store_new_head\@ @ Are we at the max? -@ -@ _tx_thread_smp_protect_wait_list_head = 0; -@ - EOR r5, r5, r5 @ We're at the max. Set it to zero -@ -@ } -@ -_store_new_head\@: - - STR r5, [r4] @ Store the new head -@ -@ /* We have the lock! */ -@ return; -@ - .endm - - - .macro _tx_thread_smp_protect_wait_list_lock_get -@VOID _tx_thread_smp_protect_wait_list_lock_get() -@{ -@ /* We do this until we have the lock. */ -@ while (1) -@ { -@ -_tx_thread_smp_protect_wait_list_lock_get__try_to_get_lock\@: -@ -@ /* Is the list lock available? */ -@ _tx_thread_smp_protect_wait_list_lock_protect_in_force = load_exclusive(&_tx_thread_smp_protect_wait_list_lock_protect_in_force); -@ - LDR r1, =_tx_thread_smp_protect_wait_list_lock_protect_in_force - LDREX r2, [r1] @ Pickup the protection flag -@ -@ if (protect_in_force == 0) -@ { -@ - CMP r2, #0 - BNE _tx_thread_smp_protect_wait_list_lock_get__try_to_get_lock\@ @ No, protection not available -@ -@ /* Try to get the list. */ -@ int status = store_exclusive(&_tx_thread_smp_protect_wait_list_lock_protect_in_force, 1); -@ - MOV r2, #1 @ Build lock value - STREX r3, r2, [r1] @ Attempt to get the protection -@ -@ if (status == SUCCESS) -@ - CMP r3, #0 - BNE _tx_thread_smp_protect_wait_list_lock_get__try_to_get_lock\@ @ Did it fail? If so, try again. -@ -@ /* We have the lock! */ -@ return; -@ - .endm - - - .macro _tx_thread_smp_protect_wait_list_add -@VOID _tx_thread_smp_protect_wait_list_add(UINT new_core) -@{ -@ -@ /* We're about to modify the list, so get the list lock. */ -@ _tx_thread_smp_protect_wait_list_lock_get(); -@ - PUSH {r1-r2} - - _tx_thread_smp_protect_wait_list_lock_get - - POP {r1-r2} -@ -@ /* Add this core. */ -@ _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_tail++] = new_core; -@ - LDR r3, =_tx_thread_smp_protect_wait_list_tail @ Get the address of the tail - LDR r4, [r3] @ Get the value of tail - LDR r5, =_tx_thread_smp_protect_wait_list @ Get the address of the list - STR r1, [r5, r4, LSL #2] @ Store the new core value - ADD r4, r4, #1 @ Increment the tail -@ -@ /* Did we wrap? */ -@ if (_tx_thread_smp_protect_wait_list_tail == _tx_thread_smp_protect_wait_list_size) -@ { -@ - LDR r5, =_tx_thread_smp_protect_wait_list_size @ Load max cores address - LDR r5, [r5] @ Load max cores value - CMP r4, r5 @ Compare max cores to tail - BNE _tx_thread_smp_protect_wait_list_add__no_wrap\@ @ Did we wrap? -@ -@ _tx_thread_smp_protect_wait_list_tail = 0; -@ - MOV r4, #0 -@ -@ } -@ -_tx_thread_smp_protect_wait_list_add__no_wrap\@: - - STR r4, [r3] @ Store the new tail value. -@ -@ /* Release the list lock. */ -@ _tx_thread_smp_protect_wait_list_lock_protect_in_force = 0; -@ - MOV r3, #0 @ Build lock value - LDR r4, =_tx_thread_smp_protect_wait_list_lock_protect_in_force - STR r3, [r4] @ Store the new value - - .endm - - - .macro _tx_thread_smp_protect_wait_list_remove -@VOID _tx_thread_smp_protect_wait_list_remove(UINT core) -@{ -@ -@ /* Get the core index. */ -@ UINT core_index; -@ for (core_index = 0;; core_index++) -@ - EOR r1, r1, r1 @ Clear for 'core_index' - LDR r2, =_tx_thread_smp_protect_wait_list @ Get the address of the list -@ -@ { -@ -_tx_thread_smp_protect_wait_list_remove__check_cur_core\@: -@ -@ /* Is this the core? */ -@ if (_tx_thread_smp_protect_wait_list[core_index] == core) -@ { -@ break; -@ - LDR r3, [r2, r1, LSL #2] @ Get the value at the current index - CMP r3, r0 @ Did we find the core? - BEQ _tx_thread_smp_protect_wait_list_remove__found_core\@ -@ -@ } -@ - ADD r1, r1, #1 @ Increment cur index - B _tx_thread_smp_protect_wait_list_remove__check_cur_core\@ @ Restart the loop -@ -@ } -@ -_tx_thread_smp_protect_wait_list_remove__found_core\@: -@ -@ /* We're about to modify the list. Get the lock. We need the lock because another -@ core could be simultaneously adding (a core is simultaneously trying to get -@ the inter-core lock) or removing (a core is simultaneously being preempted, -@ like what is currently happening). */ -@ _tx_thread_smp_protect_wait_list_lock_get(); -@ - PUSH {r1} - - _tx_thread_smp_protect_wait_list_lock_get - - POP {r1} -@ -@ /* We remove by shifting. */ -@ while (core_index != _tx_thread_smp_protect_wait_list_tail) -@ { -@ -_tx_thread_smp_protect_wait_list_remove__compare_index_to_tail\@: - - LDR r2, =_tx_thread_smp_protect_wait_list_tail @ Load tail address - LDR r2, [r2] @ Load tail value - CMP r1, r2 @ Compare cur index and tail - BEQ _tx_thread_smp_protect_wait_list_remove__removed\@ -@ -@ UINT next_index = core_index + 1; -@ - MOV r2, r1 @ Move current index to next index register - ADD r2, r2, #1 @ Add 1 -@ -@ if (next_index == _tx_thread_smp_protect_wait_list_size) -@ { -@ - LDR r3, =_tx_thread_smp_protect_wait_list_size - LDR r3, [r3] - CMP r2, r3 - BNE _tx_thread_smp_protect_wait_list_remove__next_index_no_wrap\@ -@ -@ next_index = 0; -@ - MOV r2, #0 -@ -@ } -@ -_tx_thread_smp_protect_wait_list_remove__next_index_no_wrap\@: -@ -@ list_cores[core_index] = list_cores[next_index]; -@ - LDR r0, =_tx_thread_smp_protect_wait_list @ Get the address of the list - LDR r3, [r0, r2, LSL #2] @ Get the value at the next index - STR r3, [r0, r1, LSL #2] @ Store the value at the current index -@ -@ core_index = next_index; -@ - MOV r1, r2 - - B _tx_thread_smp_protect_wait_list_remove__compare_index_to_tail\@ -@ -@ } -@ -_tx_thread_smp_protect_wait_list_remove__removed\@: -@ -@ /* Now update the tail. */ -@ if (_tx_thread_smp_protect_wait_list_tail == 0) -@ { -@ - LDR r0, =_tx_thread_smp_protect_wait_list_tail @ Load tail address - LDR r1, [r0] @ Load tail value - CMP r1, #0 - BNE _tx_thread_smp_protect_wait_list_remove__tail_not_zero\@ -@ -@ _tx_thread_smp_protect_wait_list_tail = _tx_thread_smp_protect_wait_list_size; -@ - LDR r2, =_tx_thread_smp_protect_wait_list_size - LDR r1, [r2] -@ -@ } -@ -_tx_thread_smp_protect_wait_list_remove__tail_not_zero\@: -@ -@ _tx_thread_smp_protect_wait_list_tail--; -@ - SUB r1, r1, #1 - STR r1, [r0] @ Store new tail value -@ -@ /* Release the list lock. */ -@ _tx_thread_smp_protect_wait_list_lock_protect_in_force = 0; -@ - MOV r0, #0 @ Build lock value - LDR r1, =_tx_thread_smp_protect_wait_list_lock_protect_in_force @ Load lock address - STR r0, [r1] @ Store the new value -@ -@ /* We're no longer waiting. Note that this should be zero since, again, -@ this function is only called when a thread preemption is occurring. */ -@ _tx_thread_smp_protect_wait_counts[core]--; -@ - MRC p15, 0, r0, c0, c0, 5 @ Read CPU ID register - AND r0, r0, #0x03 @ Mask off, leaving the CPU ID field - LDR r1, =_tx_thread_smp_protect_wait_counts @ Load wait list counts - LDR r2, [r1, r0, LSL #2] @ Load waiting value - SUB r2, r2, #1 @ Subtract 1 - STR r2, [r1, r0, LSL #2] @ Store new waiting value - .endm - diff --git a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_smp_unprotect.S b/ports_smp/cortex_a5_smp/gnu/src/tx_thread_smp_unprotect.S index 4cccae923..8facdc3cb 100644 --- a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_smp_unprotect.S +++ b/ports_smp/cortex_a5_smp/gnu/src/tx_thread_smp_unprotect.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * 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 @@ -7,6 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ +@ Some portions generated by Copilot (Opus 5). @ @ @/**************************************************************************/ @@ -33,7 +35,6 @@ .global _tx_thread_current_ptr .global _tx_thread_smp_protection .global _tx_thread_preempt_disable - .global _tx_thread_smp_protect_wait_counts .arm .text @@ -105,10 +106,6 @@ _tx_thread_smp_unprotect: CMP r3, #0 @ Is the preempt disable flag set? BNE _still_protected @ Yes, skip the protection release - LDR r2,=_tx_thread_smp_protect_wait_counts @ Build build address of wait counts - LDR r3, [r2, r1, LSL #2] @ Pickup wait list value - CMP r3, #0 @ Are any entities on this core waiting? - BNE _still_protected @ Yes, skip the protection release LDR r2,=_tx_thread_smp_protection @ Build address of protection structure MOV r3, #0xFFFFFFFF @ Build invalid value diff --git a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_context_restore.s b/ports_smp/cortex_a7_smp/ac5/src/tx_thread_context_restore.s index 78ddfee14..110958b14 100644 --- a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_context_restore.s +++ b/ports_smp/cortex_a7_smp/ac5/src/tx_thread_context_restore.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * 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 @@ -7,6 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ +; Some portions generated by Copilot (Opus 5). ; ; ;/**************************************************************************/ @@ -29,8 +31,6 @@ ;#include "tx_thread.h" ;#include "tx_timer.h" ; -;/* Include macros for modifying the wait list. */ -#include "tx_thread_smp_protection_wait_list_macros.h" IF :DEF:TX_ENABLE_FIQ_SUPPORT DISABLE_INTS EQU 0xC0 ; Disable IRQ & FIQ interrupts @@ -51,11 +51,6 @@ SVC_MODE EQU 0x93 ; SVC mode IMPORT _tx_thread_preempt_disable IMPORT _tx_timer_interrupt_active IMPORT _tx_thread_smp_protection - IMPORT _tx_thread_smp_protect_wait_counts - IMPORT _tx_thread_smp_protect_wait_list - IMPORT _tx_thread_smp_protect_wait_list_lock_protect_in_force - IMPORT _tx_thread_smp_protect_wait_list_tail - IMPORT _tx_thread_smp_protect_wait_list_size IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY IMPORT _tx_execution_isr_exit ENDIF @@ -195,76 +190,6 @@ __tx_thread_no_preempt_restore ; else ; { __tx_thread_preempt_restore -; -; /* Was the thread being preempted waiting for the lock? */ -; if (_tx_thread_smp_protect_wait_counts[this_core] != 0) -; { -; - LDR r1, =_tx_thread_smp_protect_wait_counts ; Load waiting count list - LDR r2, [r1, r10, LSL #2] ; Load waiting value for this core - CMP r2, #0 - BEQ _nobody_waiting_for_lock ; Is the core waiting for the lock? -; -; /* Do we not have the lock? This means the ISR never got the inter-core lock. */ -; if (_tx_thread_smp_protection.tx_thread_smp_protect_owned != this_core) -; { -; - LDR r1, =_tx_thread_smp_protection ; Load address of protection structure - LDR r2, [r1, #8] ; Pickup the owning core - CMP r10, r2 ; Compare our core to the owning core - BEQ _this_core_has_lock ; Do we have the lock? -; -; /* We don't have the lock. This core should be in the list. Remove it. */ -; _tx_thread_smp_protect_wait_list_remove(this_core); -; -macro_call0 _tx_thread_smp_protect_wait_list_remove ; Call macro to remove core from the list - B _nobody_waiting_for_lock ; Leave -; -; } -; else -; { -; /* We have the lock. This means the ISR got the inter-core lock, but -; never released it because it saw that there was someone waiting. -; Note this core is not in the list. */ -; -_this_core_has_lock -; -; /* We're no longer waiting. Note that this should be zero since this happens during thread preemption. */ -; _tx_thread_smp_protect_wait_counts[core]--; -; - LDR r1, =_tx_thread_smp_protect_wait_counts ; Load waiting count list - LDR r2, [r1, r10, LSL #2] ; Load waiting value for this core - SUB r2, r2, #1 ; Decrement waiting value. Should be zero now - STR r2, [r1, r10, LSL #2] ; Store new waiting value -; -; /* Now release the inter-core lock. */ -; -; /* Set protected core as invalid. */ -; _tx_thread_smp_protection.tx_thread_smp_protect_core = 0xFFFFFFFF; -; - LDR r1, =_tx_thread_smp_protection ; Load address of protection structure - MOV r2, #0xFFFFFFFF ; Build invalid value - STR r2, [r1, #8] ; Mark the protected core as invalid - DMB ; Ensure that accesses to shared resource have completed -; -; /* Release protection. */ -; _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 0; -; - MOV r2, #0 ; Build release protection value - STR r2, [r1, #0] ; Release the protection - DSB ISH ; To ensure update of the protection occurs before other CPUs awake -; -; /* Wake up waiting processors. Note interrupts are already enabled. */ -; - IF :DEF:TX_ENABLE_WFE - SEV ; Send event to other CPUs - ENDIF -; -; } -; } -; - -_nobody_waiting_for_lock LDMIA sp!, {r3, r10, r12, lr} ; Recover temporarily saved registers MOV r1, lr ; Save lr (point of interrupt) diff --git a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_smp_protect.s b/ports_smp/cortex_a7_smp/ac5/src/tx_thread_smp_protect.s index 5cc9f04ef..f59d04d2c 100644 --- a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_smp_protect.s +++ b/ports_smp/cortex_a7_smp/ac5/src/tx_thread_smp_protect.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * 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 @@ -7,6 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ +; Some portions generated by Copilot (Opus 5). ; ; ;/**************************************************************************/ @@ -29,17 +31,9 @@ ;#include "tx_thread.h" ;#include "tx_timer.h" */ -;/* Include macros for modifying the wait list. */ -#include "tx_thread_smp_protection_wait_list_macros.h" IMPORT _tx_thread_current_ptr IMPORT _tx_thread_smp_protection - IMPORT _tx_thread_smp_protect_wait_counts - IMPORT _tx_thread_smp_protect_wait_list - IMPORT _tx_thread_smp_protect_wait_list_lock_protect_in_force - IMPORT _tx_thread_smp_protect_wait_list_head - IMPORT _tx_thread_smp_protect_wait_list_tail - IMPORT _tx_thread_smp_protect_wait_list_size AREA ||.text||, CODE, READONLY PRESERVE8 @@ -80,12 +74,10 @@ _tx_thread_smp_protect ;VOID _tx_thread_smp_protect(VOID) ;{ -; - PUSH {r4-r6} ; Save registers we'll be using ; ; /* Disable interrupts so we don't get preempted. */ ; - MRS r0, CPSR ; Pickup current CPSR + MRS r3, CPSR ; Pickup current CPSR IF :DEF:TX_ENABLE_FIQ_SUPPORT CPSID if ; Disable IRQ and FIQ interrupts @@ -93,266 +85,93 @@ _tx_thread_smp_protect CPSID i ; Disable IRQ interrupts ENDIF ; +; /* Pickup the CPU ID. */ +; + MRC p15, 0, r2, c0, c0, 5 ; Read CPU ID register + AND r2, r2, #0x03 ; Mask off, leaving the CPU ID field +; ; /* Do we already have protection? */ ; if (this_core == _tx_thread_smp_protection.tx_thread_smp_protect_core) ; { ; - MRC p15, 0, r1, c0, c0, 5 ; Read CPU ID register - AND r1, r1, #0x03 ; Mask off, leaving the CPU ID field - LDR r2, =_tx_thread_smp_protection ; Build address to protection structure - LDR r3, [r2, #8] ; Pickup the owning core - CMP r1, r3 ; Is it not this core? - BNE _protection_not_owned ; No, the protection is not already owned -; -; /* We already have protection. */ -; -; /* Increment the protection count. */ -; _tx_thread_smp_protection.tx_thread_smp_protect_count++; + LDR r0, =_tx_thread_smp_protection ; Build address to protection structure + LDR r1, [r0, #8] ; Pickup the owning core + CMP r1, r2 ; Is it this core? + BEQ _owned ; Yes, the protection is already owned ; - LDR r3, [r2, #12] ; Pickup ownership count - ADD r3, r3, #1 ; Increment ownership count - STR r3, [r2, #12] ; Store ownership count - DMB - - B _return - -_protection_not_owned +; } ; ; /* Is the lock available? */ ; if (_tx_thread_smp_protection.tx_thread_smp_protect_in_force == 0) ; { ; - LDREX r3, [r2, #0] ; Pickup the protection flag - CMP r3, #0 - BNE _start_waiting ; No, protection not available -; -; /* Is the list empty? */ -; if (_tx_thread_smp_protect_wait_list_head == _tx_thread_smp_protect_wait_list_tail) -; { -; - LDR r3, =_tx_thread_smp_protect_wait_list_head - LDR r3, [r3] - LDR r4, =_tx_thread_smp_protect_wait_list_tail - LDR r4, [r4] - CMP r3, r4 - BNE _list_not_empty -; -; /* Try to get the lock. */ -; if (write_exclusive(&_tx_thread_smp_protection.tx_thread_smp_protect_in_force, 1) == SUCCESS) -; { -; - MOV r3, #1 ; Build lock value - STREX r4, r3, [r2, #0] ; Attempt to get the protection - CMP r4, #0 - BNE _start_waiting ; Did it fail? -; -; /* We got the lock! */ -; _tx_thread_smp_protect_lock_got(); -; - DMB ; Ensure write to protection finishes -macro_call0 _tx_thread_smp_protect_lock_got ; Call the lock got function - - B _return - -_list_not_empty -; -; /* Are we at the front of the list? */ -; if (this_core == _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_head]) -; { -; - LDR r3, =_tx_thread_smp_protect_wait_list_head ; Get the address of the head - LDR r3, [r3] ; Get the value of the head - LDR r4, =_tx_thread_smp_protect_wait_list ; Get the address of the list - LDR r4, [r4, r3, LSL #2] ; Get the value at the head index - - CMP r1, r4 - BNE _start_waiting -; -; /* Is the lock still available? */ -; if (_tx_thread_smp_protection.tx_thread_smp_protect_in_force == 0) -; { -; - LDR r3, [r2, #0] ; Pickup the protection flag - CMP r3, #0 - BNE _start_waiting ; No, protection not available -; -; /* Get the lock. */ -; _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 1; -; - MOV r3, #1 ; Build lock value - STR r3, [r2, #0] ; Store lock value - DMB ; -; -; /* Got the lock. */ -; _tx_thread_smp_protect_lock_got(); -; -macro_call1 _tx_thread_smp_protect_lock_got -; -; /* Remove this core from the wait list. */ -; _tx_thread_smp_protect_remove_from_front_of_list(); -; -macro_call2 _tx_thread_smp_protect_remove_from_front_of_list - - B _return - -_start_waiting -; -; /* For one reason or another, we didn't get the lock. */ -; -; /* Increment wait count. */ -; _tx_thread_smp_protect_wait_counts[this_core]++; -; - LDR r3, =_tx_thread_smp_protect_wait_counts ; Load wait list counts - LDR r4, [r3, r1, LSL #2] ; Load waiting value for this core - ADD r4, r4, #1 ; Increment wait value - STR r4, [r3, r1, LSL #2] ; Store new wait value -; -; /* Have we not added ourselves to the list yet? */ -; if (_tx_thread_smp_protect_wait_counts[this_core] == 1) -; { -; - CMP r4, #1 - BNE _already_in_list0 ; Is this core already waiting? -; -; /* Add ourselves to the list. */ -; _tx_thread_smp_protect_wait_list_add(this_core); -; -macro_call3 _tx_thread_smp_protect_wait_list_add ; Call macro to add ourselves to the list + LDREX r1, [r0] ; Pickup the protection flag + CMP r1, #0 ; Is it available? + BEQ _get_protection ; Yes, attempt to get the protection ; ; } ; -_already_in_list0 -; -; /* Restore interrupts. */ +; /* The protection is held elsewhere. Restore interrupts so this core can be +; preempted while it waits, then try the whole sequence again. */ ; - MSR CPSR_c, r0 ; Restore CPSR + MSR CPSR_c, r3 ; Restore CPSR IF :DEF:TX_ENABLE_WFE WFE ; Go into standby ENDIF -; -; /* We do this until we have the lock. */ -; while (1) -; { -; -_try_to_get_lock -; -; /* Disable interrupts so we don't get preempted. */ -; - IF :DEF:TX_ENABLE_FIQ_SUPPORT - CPSID if ; Disable IRQ and FIQ interrupts - ELSE - CPSID i ; Disable IRQ interrupts - ENDIF + B _tx_thread_smp_protect ; On waking, restart the protection attempt - MRC p15, 0, r1, c0, c0, 5 ; Read CPU ID register - AND r1, r1, #0x03 ; Mask off, leaving the CPU ID field +_get_protection ; -; /* Do we already have protection? */ -; if (this_core == _tx_thread_smp_protection.tx_thread_smp_protect_core) +; /* Try to get the lock. */ +; if (write_exclusive(&_tx_thread_smp_protection.tx_thread_smp_protect_in_force, 1) == SUCCESS) ; { ; - LDR r3, [r2, #8] ; Pickup the owning core - CMP r3, r1 ; Is it this core? - BEQ _got_lock_after_waiting ; Yes, the protection is already owned. This means - ; an ISR preempted us and got protection + MOV r1, #1 ; Build lock value + STREX r2, r1, [r0] ; Attempt to get the protection + CMP r2, #0 ; Check whether the store succeeded (0 = success) + BEQ _got_protection ; Yes, we have the protection ; ; } ; -; /* Are we at the front of the list? */ -; if (this_core == _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_head]) -; { +; /* Another core beat us to it. Restore interrupts and try again. */ ; - LDR r3, =_tx_thread_smp_protect_wait_list_head ; Get the address of the head - LDR r3, [r3] ; Get the value of the head - LDR r4, =_tx_thread_smp_protect_wait_list ; Get the address of the list - LDR r4, [r4, r3, LSL #2] ; Get the value at the head index + MSR CPSR_c, r3 ; Restore CPSR + B _tx_thread_smp_protect ; Try the whole process again - CMP r1, r4 - BNE _did_not_get_lock -; -; /* Is the lock still available? */ -; if (_tx_thread_smp_protection.tx_thread_smp_protect_in_force == 0) -; { -; - LDR r3, [r2, #0] ; Pickup the protection flag - CMP r3, #0 - BNE _did_not_get_lock ; No, protection not available -; -; /* Get the lock. */ -; _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 1; -; - MOV r3, #1 ; Build lock value - STR r3, [r2, #0] ; Store lock value - DMB ; +_got_protection ; -; /* Got the lock. */ -; _tx_thread_smp_protect_lock_got(); +; /* Got the lock. Record the owning core. */ +; _tx_thread_smp_protection.tx_thread_smp_protect_core = this_core; ; -macro_call4 _tx_thread_smp_protect_lock_got -; -; /* Remove this core from the wait list. */ -; _tx_thread_smp_protect_remove_from_front_of_list(); -; -macro_call5 _tx_thread_smp_protect_remove_from_front_of_list - - B _got_lock_after_waiting + DMB ; Ensure the protection write completes before it is used + MRC p15, 0, r2, c0, c0, 5 ; Read CPU ID register + AND r2, r2, #0x03 ; Mask off, leaving the CPU ID field + STR r2, [r0, #8] ; Save the owning core -_did_not_get_lock -; -; /* For one reason or another, we didn't get the lock. */ -; -; /* Were we removed from the list? This can happen if we're a thread -; and we got preempted. */ -; if (_tx_thread_smp_protect_wait_counts[this_core] == 0) -; { -; - LDR r3, =_tx_thread_smp_protect_wait_counts ; Load wait list counts - LDR r4, [r3, r1, LSL #2] ; Load waiting value for this core - CMP r4, #0 - BNE _already_in_list1 ; Is this core already in the list? -; -; /* Add ourselves to the list. */ -; _tx_thread_smp_protect_wait_list_add(this_core); -; -macro_call6 _tx_thread_smp_protect_wait_list_add ; Call macro to add ourselves to the list -; -; /* Our waiting count was also reset when we were preempted. Increment it again. */ -; _tx_thread_smp_protect_wait_counts[this_core]++; -; - LDR r3, =_tx_thread_smp_protect_wait_counts ; Load wait list counts - LDR r4, [r3, r1, LSL #2] ; Load waiting value for this core - ADD r4, r4, #1 ; Increment wait value - STR r4, [r3, r1, LSL #2] ; Store new wait value value -; -; } -; -_already_in_list1 -; -; /* Restore interrupts and try again. */ -; - MSR CPSR_c, r0 ; Restore CPSR - IF :DEF:TX_ENABLE_WFE - WFE ; Go into standby + IF :DEF:TX_MPCORE_DEBUG_ENABLE + LSL r2, r2, #2 ; Build offset to array indexes + LDR r1, =_tx_thread_current_ptr ; Pickup start of the current thread array + ADD r1, r1, r2 ; Build index into the current thread array + LDR r2, [r1] ; Pickup current thread for this core + STR r2, [r0, #4] ; Save current thread pointer + STR LR, [r0, #16] ; Save caller's return address + STR r3, [r0, #20] ; Save CPSR ENDIF - B _try_to_get_lock ; On waking, restart the protection attempt -_got_lock_after_waiting +_owned ; -; /* We're no longer waiting. */ -; _tx_thread_smp_protect_wait_counts[this_core]--; +; /* Increment the protection count. */ +; _tx_thread_smp_protection.tx_thread_smp_protect_count++; ; - LDR r3, =_tx_thread_smp_protect_wait_counts ; Load waiting list - LDR r4, [r3, r1, LSL #2] ; Load current wait value - SUB r4, r4, #1 ; Decrement wait value - STR r4, [r3, r1, LSL #2] ; Store new wait value value + LDR r1, [r0, #12] ; Pickup ownership count + ADD r1, r1, #1 ; Increment ownership count + STR r1, [r0, #12] ; Store new ownership count + DMB ; + MOV r0, r3 ; Return the previous CPSR ; -; /* Restore link register and return. */ +;} ; -_return - - POP {r4-r6} ; Restore registers - IF {INTER} = {TRUE} BX lr ; Return to caller ELSE @@ -360,4 +179,3 @@ _return ENDIF END - diff --git a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_smp_protection_wait_list_macros.h b/ports_smp/cortex_a7_smp/ac5/src/tx_thread_smp_protection_wait_list_macros.h deleted file mode 100644 index f7581458f..000000000 --- a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_smp_protection_wait_list_macros.h +++ /dev/null @@ -1,312 +0,0 @@ -;/*************************************************************************** -; * Copyright (c) 2024 Microsoft Corporation -; * -; * This program and the accompanying materials are made available under the -; * terms of the MIT License which is available at -; * https://opensource.org/licenses/MIT. -; * -; * SPDX-License-Identifier: MIT -; **************************************************************************/ -; -; -;/**************************************************************************/ -;/**************************************************************************/ -;/** */ -;/** ThreadX Component */ -;/** */ -;/** Thread - Low Level SMP Support */ -;/** */ -;/**************************************************************************/ -;/**************************************************************************/ - - MACRO -$label _tx_thread_smp_protect_lock_got -; -; /* Set the currently owned core. */ -; _tx_thread_smp_protection.tx_thread_smp_protect_core = this_core; -; - STR r1, [r2, #8] ; Store this core -; -; /* Increment the protection count. */ -; _tx_thread_smp_protection.tx_thread_smp_protect_count++; -; - LDR r3, [r2, #12] ; Pickup ownership count - ADD r3, r3, #1 ; Increment ownership count - STR r3, [r2, #12] ; Store ownership count - DMB - - IF :DEF:TX_MPCORE_DEBUG_ENABLE - LSL r3, r1, #2 ; Build offset to array indexes - LDR r4, =_tx_thread_current_ptr ; Pickup start of the current thread array - ADD r4, r3, r4 ; Build index into the current thread array - LDR r3, [r4] ; Pickup current thread for this core - STR r3, [r2, #4] ; Save current thread pointer - STR LR, [r2, #16] ; Save caller's return address - STR r0, [r2, #20] ; Save CPSR - ENDIF - - MEND - - MACRO -$label _tx_thread_smp_protect_remove_from_front_of_list -; -; /* Remove ourselves from the list. */ -; _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_head++] = 0xFFFFFFFF; -; - MOV r3, #0xFFFFFFFF ; Build the invalid core value - LDR r4, =_tx_thread_smp_protect_wait_list_head ; Get the address of the head - LDR r5, [r4] ; Get the value of the head - LDR r6, =_tx_thread_smp_protect_wait_list ; Get the address of the list - STR r3, [r6, r5, LSL #2] ; Store the invalid core value - ADD r5, r5, #1 ; Increment the head -; -; /* Did we wrap? */ -; if (_tx_thread_smp_protect_wait_list_head == TX_THREAD_SMP_MAX_CORES + 1) -; { -; - LDR r3, =_tx_thread_smp_protect_wait_list_size ; Load address of core list size - LDR r3, [r3] ; Load the max cores value - CMP r5, r3 ; Compare the head to it - BNE $label._store_new_head ; Are we at the max? -; -; _tx_thread_smp_protect_wait_list_head = 0; -; - EOR r5, r5, r5 ; We're at the max. Set it to zero -; -; } -; -$label._store_new_head - - STR r5, [r4] ; Store the new head -; -; /* We have the lock! */ -; return; -; - MEND - - - MACRO -$label _tx_thread_smp_protect_wait_list_lock_get -;VOID _tx_thread_smp_protect_wait_list_lock_get() -;{ -; /* We do this until we have the lock. */ -; while (1) -; { -; -$label._tx_thread_smp_protect_wait_list_lock_get__try_to_get_lock -; -; /* Is the list lock available? */ -; _tx_thread_smp_protect_wait_list_lock_protect_in_force = load_exclusive(&_tx_thread_smp_protect_wait_list_lock_protect_in_force); -; - LDR r1, =_tx_thread_smp_protect_wait_list_lock_protect_in_force - LDREX r2, [r1] ; Pickup the protection flag -; -; if (protect_in_force == 0) -; { -; - CMP r2, #0 - BNE $label._tx_thread_smp_protect_wait_list_lock_get__try_to_get_lock ; No, protection not available -; -; /* Try to get the list. */ -; int status = store_exclusive(&_tx_thread_smp_protect_wait_list_lock_protect_in_force, 1); -; - MOV r2, #1 ; Build lock value - STREX r3, r2, [r1] ; Attempt to get the protection -; -; if (status == SUCCESS) -; - CMP r3, #0 - BNE $label._tx_thread_smp_protect_wait_list_lock_get__try_to_get_lock ; Did it fail? If so, try again. -; -; /* We have the lock! */ -; return; -; - MEND - - - MACRO -$label _tx_thread_smp_protect_wait_list_add -;VOID _tx_thread_smp_protect_wait_list_add(UINT new_core) -;{ -; -; /* We're about to modify the list, so get the list lock. */ -; _tx_thread_smp_protect_wait_list_lock_get(); -; - PUSH {r1-r2} - -$label _tx_thread_smp_protect_wait_list_lock_get - - POP {r1-r2} -; -; /* Add this core. */ -; _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_tail++] = new_core; -; - LDR r3, =_tx_thread_smp_protect_wait_list_tail ; Get the address of the tail - LDR r4, [r3] ; Get the value of tail - LDR r5, =_tx_thread_smp_protect_wait_list ; Get the address of the list - STR r1, [r5, r4, LSL #2] ; Store the new core value - ADD r4, r4, #1 ; Increment the tail -; -; /* Did we wrap? */ -; if (_tx_thread_smp_protect_wait_list_tail == _tx_thread_smp_protect_wait_list_size) -; { -; - LDR r5, =_tx_thread_smp_protect_wait_list_size ; Load max cores address - LDR r5, [r5] ; Load max cores value - CMP r4, r5 ; Compare max cores to tail - BNE $label._tx_thread_smp_protect_wait_list_add__no_wrap ; Did we wrap? -; -; _tx_thread_smp_protect_wait_list_tail = 0; -; - MOV r4, #0 -; -; } -; -$label._tx_thread_smp_protect_wait_list_add__no_wrap - - STR r4, [r3] ; Store the new tail value. -; -; /* Release the list lock. */ -; _tx_thread_smp_protect_wait_list_lock_protect_in_force = 0; -; - MOV r3, #0 ; Build lock value - LDR r4, =_tx_thread_smp_protect_wait_list_lock_protect_in_force - STR r3, [r4] ; Store the new value - - MEND - - - MACRO -$label _tx_thread_smp_protect_wait_list_remove -;VOID _tx_thread_smp_protect_wait_list_remove(UINT core) -;{ -; -; /* Get the core index. */ -; UINT core_index; -; for (core_index = 0;; core_index++) -; - EOR r1, r1, r1 ; Clear for 'core_index' - LDR r2, =_tx_thread_smp_protect_wait_list ; Get the address of the list -; -; { -; -$label._tx_thread_smp_protect_wait_list_remove__check_cur_core -; -; /* Is this the core? */ -; if (_tx_thread_smp_protect_wait_list[core_index] == core) -; { -; break; -; - LDR r3, [r2, r1, LSL #2] ; Get the value at the current index - CMP r3, r10 ; Did we find the core? - BEQ $label._tx_thread_smp_protect_wait_list_remove__found_core -; -; } -; - ADD r1, r1, #1 ; Increment cur index - B $label._tx_thread_smp_protect_wait_list_remove__check_cur_core ; Restart the loop -; -; } -; -$label._tx_thread_smp_protect_wait_list_remove__found_core -; -; /* We're about to modify the list. Get the lock. We need the lock because another -; core could be simultaneously adding (a core is simultaneously trying to get -; the inter-core lock) or removing (a core is simultaneously being preempted, -; like what is currently happening). */ -; _tx_thread_smp_protect_wait_list_lock_get(); -; - PUSH {r1} - -$label _tx_thread_smp_protect_wait_list_lock_get - - POP {r1} -; -; /* We remove by shifting. */ -; while (core_index != _tx_thread_smp_protect_wait_list_tail) -; { -; -$label._tx_thread_smp_protect_wait_list_remove__compare_index_to_tail - - LDR r2, =_tx_thread_smp_protect_wait_list_tail ; Load tail address - LDR r2, [r2] ; Load tail value - CMP r1, r2 ; Compare cur index and tail - BEQ $label._tx_thread_smp_protect_wait_list_remove__removed -; -; UINT next_index = core_index + 1; -; - MOV r2, r1 ; Move current index to next index register - ADD r2, r2, #1 ; Add 1 -; -; if (next_index == _tx_thread_smp_protect_wait_list_size) -; { -; - LDR r3, =_tx_thread_smp_protect_wait_list_size - LDR r3, [r3] - CMP r2, r3 - BNE $label._tx_thread_smp_protect_wait_list_remove__next_index_no_wrap -; -; next_index = 0; -; - MOV r2, #0 -; -; } -; -$label._tx_thread_smp_protect_wait_list_remove__next_index_no_wrap -; -; list_cores[core_index] = list_cores[next_index]; -; - LDR r0, =_tx_thread_smp_protect_wait_list ; Get the address of the list - LDR r3, [r0, r2, LSL #2] ; Get the value at the next index - STR r3, [r0, r1, LSL #2] ; Store the value at the current index -; -; core_index = next_index; -; - MOV r1, r2 - - B $label._tx_thread_smp_protect_wait_list_remove__compare_index_to_tail -; -; } -; -$label._tx_thread_smp_protect_wait_list_remove__removed -; -; /* Now update the tail. */ -; if (_tx_thread_smp_protect_wait_list_tail == 0) -; { -; - LDR r0, =_tx_thread_smp_protect_wait_list_tail ; Load tail address - LDR r1, [r0] ; Load tail value - CMP r1, #0 - BNE $label._tx_thread_smp_protect_wait_list_remove__tail_not_zero -; -; _tx_thread_smp_protect_wait_list_tail = _tx_thread_smp_protect_wait_list_size; -; - LDR r2, =_tx_thread_smp_protect_wait_list_size - LDR r1, [r2] -; -; } -; -$label._tx_thread_smp_protect_wait_list_remove__tail_not_zero -; -; _tx_thread_smp_protect_wait_list_tail--; -; - SUB r1, r1, #1 - STR r1, [r0] ; Store new tail value -; -; /* Release the list lock. */ -; _tx_thread_smp_protect_wait_list_lock_protect_in_force = 0; -; - MOV r0, #0 ; Build lock value - LDR r1, =_tx_thread_smp_protect_wait_list_lock_protect_in_force ; Load lock address - STR r0, [r1] ; Store the new value -; -; /* We're no longer waiting. Note that this should be zero since, again, -; this function is only called when a thread preemption is occurring. */ -; _tx_thread_smp_protect_wait_counts[core]--; -; - LDR r1, =_tx_thread_smp_protect_wait_counts ; Load wait list counts - LDR r2, [r1, r10, LSL #2] ; Load waiting value - SUB r2, r2, #1 ; Subtract 1 - STR r2, [r1, r10, LSL #2] ; Store new waiting value - MEND - diff --git a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_smp_unprotect.s b/ports_smp/cortex_a7_smp/ac5/src/tx_thread_smp_unprotect.s index 260d13dc1..072200475 100644 --- a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_smp_unprotect.s +++ b/ports_smp/cortex_a7_smp/ac5/src/tx_thread_smp_unprotect.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * 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 @@ -7,6 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ +; Some portions generated by Copilot (Opus 5). ; ; ;/**************************************************************************/ @@ -33,7 +35,6 @@ IMPORT _tx_thread_current_ptr IMPORT _tx_thread_smp_protection IMPORT _tx_thread_preempt_disable - IMPORT _tx_thread_smp_protect_wait_counts AREA ||.text||, CODE, READONLY PRESERVE8 @@ -103,10 +104,6 @@ _tx_thread_smp_unprotect CMP r3, #0 ; Is the preempt disable flag set? BNE _still_protected ; Yes, skip the protection release - LDR r2,=_tx_thread_smp_protect_wait_counts ; Build build address of wait counts - LDR r3, [r2, r1, LSL #2] ; Pickup wait list value - CMP r3, #0 ; Are any entities on this core waiting? - BNE _still_protected ; Yes, skip the protection release LDR r2,=_tx_thread_smp_protection ; Build address of protection structure MOV r3, #0xFFFFFFFF ; Build invalid value diff --git a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_context_restore.S b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_context_restore.S index 94e85ad35..398aac35c 100644 --- a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_context_restore.S +++ b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_context_restore.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * 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 @@ -7,6 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ +@ Some portions generated by Copilot (Opus 5). @ @ @/**************************************************************************/ @@ -28,8 +30,6 @@ @#include "tx_api.h" @#include "tx_thread.h" @#include "tx_timer.h" -@/* Include macros for modifying the wait list. */ -#include "tx_thread_smp_protection_wait_list_macros.h" .arm @@ -50,11 +50,6 @@ IRQ_MODE = 0x92 @ Disable IRQ, IRQ mode .global _tx_thread_preempt_disable .global _tx_timer_interrupt_active .global _tx_thread_smp_protection - .global _tx_thread_smp_protect_wait_counts - .global _tx_thread_smp_protect_wait_list - .global _tx_thread_smp_protect_wait_list_lock_protect_in_force - .global _tx_thread_smp_protect_wait_list_tail - .global _tx_thread_smp_protect_wait_list_size #ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY .global _tx_execution_isr_exit #endif @@ -200,76 +195,6 @@ __tx_thread_no_preempt_restore: @ else @ { __tx_thread_preempt_restore: -@ -@ /* Was the thread being preempted waiting for the lock? */ -@ if (_tx_thread_smp_protect_wait_counts[this_core] != 0) -@ { -@ - LDR r1, =_tx_thread_smp_protect_wait_counts @ Load waiting count list - LDR r2, [r1, r10, LSL #2] @ Load waiting value for this core - CMP r2, #0 - BEQ _nobody_waiting_for_lock @ Is the core waiting for the lock? -@ -@ /* Do we not have the lock? This means the ISR never got the inter-core lock. */ -@ if (_tx_thread_smp_protection.tx_thread_smp_protect_owned != this_core) -@ { -@ - LDR r1, =_tx_thread_smp_protection @ Load address of protection structure - LDR r2, [r1, #8] @ Pickup the owning core - CMP r10, r2 @ Compare our core to the owning core - BEQ _this_core_has_lock @ Do we have the lock? -@ -@ /* We don't have the lock. This core should be in the list. Remove it. */ -@ _tx_thread_smp_protect_wait_list_remove(this_core); -@ - _tx_thread_smp_protect_wait_list_remove @ Call macro to remove core from the list - B _nobody_waiting_for_lock @ Leave -@ -@ } -@ else -@ { -@ /* We have the lock. This means the ISR got the inter-core lock, but -@ never released it because it saw that there was someone waiting. -@ Note this core is not in the list. */ -@ -_this_core_has_lock: -@ -@ /* We're no longer waiting. Note that this should be zero since this happens during thread preemption. */ -@ _tx_thread_smp_protect_wait_counts[core]--; -@ - LDR r1, =_tx_thread_smp_protect_wait_counts @ Load waiting count list - LDR r2, [r1, r10, LSL #2] @ Load waiting value for this core - SUB r2, r2, #1 @ Decrement waiting value. Should be zero now - STR r2, [r1, r10, LSL #2] @ Store new waiting value -@ -@ /* Now release the inter-core lock. */ -@ -@ /* Set protected core as invalid. */ -@ _tx_thread_smp_protection.tx_thread_smp_protect_core = 0xFFFFFFFF; -@ - LDR r1, =_tx_thread_smp_protection @ Load address of protection structure - MOV r2, #0xFFFFFFFF @ Build invalid value - STR r2, [r1, #8] @ Mark the protected core as invalid - DMB @ Ensure that accesses to shared resource have completed -@ -@ /* Release protection. */ -@ _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 0; -@ - MOV r2, #0 @ Build release protection value - STR r2, [r1, #0] @ Release the protection - DSB ISH @ To ensure update of the protection occurs before other CPUs awake -@ -@ /* Wake up waiting processors. Note interrupts are already enabled. */ -@ -#ifdef TX_ENABLE_WFE - SEV @ Send event to other CPUs -#endif -@ -@ } -@ } -@ - -_nobody_waiting_for_lock: LDMIA sp!, {r3, r10, r12, lr} @ Recover temporarily saved registers MOV r1, lr @ Save lr (point of interrupt) diff --git a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_protect.S b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_protect.S index 638db958f..5cf03be83 100644 --- a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_protect.S +++ b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_protect.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * 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 @@ -7,6 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ +@ Some portions generated by Copilot (Opus 5). @ @ @/**************************************************************************/ @@ -29,17 +31,9 @@ @#include "tx_thread.h" @#include "tx_timer.h" */ -@/* Include macros for modifying the wait list. */ -#include "tx_thread_smp_protection_wait_list_macros.h" .global _tx_thread_current_ptr .global _tx_thread_smp_protection - .global _tx_thread_smp_protect_wait_counts - .global _tx_thread_smp_protect_wait_list - .global _tx_thread_smp_protect_wait_list_lock_protect_in_force - .global _tx_thread_smp_protect_wait_list_head - .global _tx_thread_smp_protect_wait_list_tail - .global _tx_thread_smp_protect_wait_list_size .arm .text @@ -82,12 +76,10 @@ _tx_thread_smp_protect: @VOID _tx_thread_smp_protect(VOID) @{ -@ - PUSH {r4-r6} @ Save registers we'll be using @ @ /* Disable interrupts so we don't get preempted. */ @ - MRS r0, CPSR @ Pickup current CPSR + MRS r3, CPSR @ Pickup current CPSR #ifdef TX_ENABLE_FIQ_SUPPORT CPSID if @ Disable IRQ and FIQ interrupts @@ -95,266 +87,93 @@ _tx_thread_smp_protect: CPSID i @ Disable IRQ interrupts #endif @ +@ /* Pickup the CPU ID. */ +@ + MRC p15, 0, r2, c0, c0, 5 @ Read CPU ID register + AND r2, r2, #0x03 @ Mask off, leaving the CPU ID field +@ @ /* Do we already have protection? */ @ if (this_core == _tx_thread_smp_protection.tx_thread_smp_protect_core) @ { @ - MRC p15, 0, r1, c0, c0, 5 @ Read CPU ID register - AND r1, r1, #0x03 @ Mask off, leaving the CPU ID field - LDR r2, =_tx_thread_smp_protection @ Build address to protection structure - LDR r3, [r2, #8] @ Pickup the owning core - CMP r1, r3 @ Is it not this core? - BNE _protection_not_owned @ No, the protection is not already owned -@ -@ /* We already have protection. */ -@ -@ /* Increment the protection count. */ -@ _tx_thread_smp_protection.tx_thread_smp_protect_count++; + LDR r0, =_tx_thread_smp_protection @ Build address to protection structure + LDR r1, [r0, #8] @ Pickup the owning core + CMP r1, r2 @ Is it this core? + BEQ _owned @ Yes, the protection is already owned @ - LDR r3, [r2, #12] @ Pickup ownership count - ADD r3, r3, #1 @ Increment ownership count - STR r3, [r2, #12] @ Store ownership count - DMB - - B _return - -_protection_not_owned: +@ } @ @ /* Is the lock available? */ @ if (_tx_thread_smp_protection.tx_thread_smp_protect_in_force == 0) @ { @ - LDREX r3, [r2] @ Pickup the protection flag - CMP r3, #0 - BNE _start_waiting @ No, protection not available -@ -@ /* Is the list empty? */ -@ if (_tx_thread_smp_protect_wait_list_head == _tx_thread_smp_protect_wait_list_tail) -@ { -@ - LDR r3, =_tx_thread_smp_protect_wait_list_head - LDR r3, [r3] - LDR r4, =_tx_thread_smp_protect_wait_list_tail - LDR r4, [r4] - CMP r3, r4 - BNE _list_not_empty -@ -@ /* Try to get the lock. */ -@ if (write_exclusive(&_tx_thread_smp_protection.tx_thread_smp_protect_in_force, 1) == SUCCESS) -@ { -@ - MOV r3, #1 @ Build lock value - STREX r4, r3, [r2] @ Attempt to get the protection - CMP r4, #0 - BNE _start_waiting @ Did it fail? -@ -@ /* We got the lock! */ -@ _tx_thread_smp_protect_lock_got(); -@ - DMB @ Ensure write to protection finishes - _tx_thread_smp_protect_lock_got @ Call the lock got function - - B _return - -_list_not_empty: -@ -@ /* Are we at the front of the list? */ -@ if (this_core == _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_head]) -@ { -@ - LDR r3, =_tx_thread_smp_protect_wait_list_head @ Get the address of the head - LDR r3, [r3] @ Get the value of the head - LDR r4, =_tx_thread_smp_protect_wait_list @ Get the address of the list - LDR r4, [r4, r3, LSL #2] @ Get the value at the head index - - CMP r1, r4 - BNE _start_waiting -@ -@ /* Is the lock still available? */ -@ if (_tx_thread_smp_protection.tx_thread_smp_protect_in_force == 0) -@ { -@ - LDR r3, [r2, #0] @ Pickup the protection flag - CMP r3, #0 - BNE _start_waiting @ No, protection not available -@ -@ /* Get the lock. */ -@ _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 1; -@ - MOV r3, #1 @ Build lock value - STR r3, [r2, #0] @ Store lock value - DMB @ -@ -@ /* Got the lock. */ -@ _tx_thread_smp_protect_lock_got(); -@ - _tx_thread_smp_protect_lock_got -@ -@ /* Remove this core from the wait list. */ -@ _tx_thread_smp_protect_remove_from_front_of_list(); -@ - _tx_thread_smp_protect_remove_from_front_of_list - - B _return - -_start_waiting: -@ -@ /* For one reason or another, we didn't get the lock. */ -@ -@ /* Increment wait count. */ -@ _tx_thread_smp_protect_wait_counts[this_core]++; -@ - LDR r3, =_tx_thread_smp_protect_wait_counts @ Load wait list counts - LDR r4, [r3, r1, LSL #2] @ Load waiting value for this core - ADD r4, r4, #1 @ Increment wait value - STR r4, [r3, r1, LSL #2] @ Store new wait value -@ -@ /* Have we not added ourselves to the list yet? */ -@ if (_tx_thread_smp_protect_wait_counts[this_core] == 1) -@ { -@ - CMP r4, #1 - BNE _already_in_list0 @ Is this core already waiting? -@ -@ /* Add ourselves to the list. */ -@ _tx_thread_smp_protect_wait_list_add(this_core); -@ - _tx_thread_smp_protect_wait_list_add @ Call macro to add ourselves to the list + LDREX r1, [r0] @ Pickup the protection flag + CMP r1, #0 @ Is it available? + BEQ _get_protection @ Yes, attempt to get the protection @ @ } @ -_already_in_list0: +@ /* The protection is held elsewhere. Restore interrupts so this core can be +@ preempted while it waits, then try the whole sequence again. */ @ -@ /* Restore interrupts. */ -@ - MSR CPSR_c, r0 @ Restore CPSR + MSR CPSR_c, r3 @ Restore CPSR #ifdef TX_ENABLE_WFE WFE @ Go into standby #endif -@ -@ /* We do this until we have the lock. */ -@ while (1) -@ { -@ -_try_to_get_lock: -@ -@ /* Disable interrupts so we don't get preempted. */ -@ -#ifdef TX_ENABLE_FIQ_SUPPORT - CPSID if @ Disable IRQ and FIQ interrupts -#else - CPSID i @ Disable IRQ interrupts -#endif + B _tx_thread_smp_protect @ On waking, restart the protection attempt - MRC p15, 0, r1, c0, c0, 5 @ Read CPU ID register - AND r1, r1, #0x03 @ Mask off, leaving the CPU ID field +_get_protection: @ -@ /* Do we already have protection? */ -@ if (this_core == _tx_thread_smp_protection.tx_thread_smp_protect_core) +@ /* Try to get the lock. */ +@ if (write_exclusive(&_tx_thread_smp_protection.tx_thread_smp_protect_in_force, 1) == SUCCESS) @ { @ - LDR r3, [r2, #8] @ Pickup the owning core - CMP r3, r1 @ Is it this core? - BEQ _got_lock_after_waiting @ Yes, the protection is already owned. This means - @ an ISR preempted us and got protection + MOV r1, #1 @ Build lock value + STREX r2, r1, [r0] @ Attempt to get the protection + CMP r2, #0 @ Check whether the store succeeded (0 = success) + BEQ _got_protection @ Yes, we have the protection @ @ } @ -@ /* Are we at the front of the list? */ -@ if (this_core == _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_head]) -@ { +@ /* Another core beat us to it. Restore interrupts and try again. */ @ - LDR r3, =_tx_thread_smp_protect_wait_list_head @ Get the address of the head - LDR r3, [r3] @ Get the value of the head - LDR r4, =_tx_thread_smp_protect_wait_list @ Get the address of the list - LDR r4, [r4, r3, LSL #2] @ Get the value at the head index + MSR CPSR_c, r3 @ Restore CPSR + B _tx_thread_smp_protect @ Try the whole process again - CMP r1, r4 - BNE _did_not_get_lock -@ -@ /* Is the lock still available? */ -@ if (_tx_thread_smp_protection.tx_thread_smp_protect_in_force == 0) -@ { -@ - LDR r3, [r2, #0] @ Pickup the protection flag - CMP r3, #0 - BNE _did_not_get_lock @ No, protection not available -@ -@ /* Get the lock. */ -@ _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 1; -@ - MOV r3, #1 @ Build lock value - STR r3, [r2, #0] @ Store lock value - DMB @ -@ -@ /* Got the lock. */ -@ _tx_thread_smp_protect_lock_got(); -@ - _tx_thread_smp_protect_lock_got +_got_protection: @ -@ /* Remove this core from the wait list. */ -@ _tx_thread_smp_protect_remove_from_front_of_list(); +@ /* Got the lock. Record the owning core. */ +@ _tx_thread_smp_protection.tx_thread_smp_protect_core = this_core; @ - _tx_thread_smp_protect_remove_from_front_of_list + DMB @ Ensure the protection write completes before it is used + MRC p15, 0, r2, c0, c0, 5 @ Read CPU ID register + AND r2, r2, #0x03 @ Mask off, leaving the CPU ID field + STR r2, [r0, #8] @ Save the owning core - B _got_lock_after_waiting - -_did_not_get_lock: -@ -@ /* For one reason or another, we didn't get the lock. */ -@ -@ /* Were we removed from the list? This can happen if we're a thread -@ and we got preempted. */ -@ if (_tx_thread_smp_protect_wait_counts[this_core] == 0) -@ { -@ - LDR r3, =_tx_thread_smp_protect_wait_counts @ Load wait list counts - LDR r4, [r3, r1, LSL #2] @ Load waiting value for this core - CMP r4, #0 - BNE _already_in_list1 @ Is this core already in the list? -@ -@ /* Add ourselves to the list. */ -@ _tx_thread_smp_protect_wait_list_add(this_core); -@ - _tx_thread_smp_protect_wait_list_add @ Call macro to add ourselves to the list -@ -@ /* Our waiting count was also reset when we were preempted. Increment it again. */ -@ _tx_thread_smp_protect_wait_counts[this_core]++; -@ - LDR r3, =_tx_thread_smp_protect_wait_counts @ Load wait list counts - LDR r4, [r3, r1, LSL #2] @ Load waiting value for this core - ADD r4, r4, #1 @ Increment wait value - STR r4, [r3, r1, LSL #2] @ Store new wait value value -@ -@ } -@ -_already_in_list1: -@ -@ /* Restore interrupts and try again. */ -@ - MSR CPSR_c, r0 @ Restore CPSR -#ifdef TX_ENABLE_WFE - WFE @ Go into standby +#ifdef TX_MPCORE_DEBUG_ENABLE + LSL r2, r2, #2 @ Build offset to array indexes + LDR r1, =_tx_thread_current_ptr @ Pickup start of the current thread array + ADD r1, r1, r2 @ Build index into the current thread array + LDR r2, [r1] @ Pickup current thread for this core + STR r2, [r0, #4] @ Save current thread pointer + STR LR, [r0, #16] @ Save caller's return address + STR r3, [r0, #20] @ Save CPSR #endif - B _try_to_get_lock @ On waking, restart the protection attempt -_got_lock_after_waiting: +_owned: @ -@ /* We're no longer waiting. */ -@ _tx_thread_smp_protect_wait_counts[this_core]--; +@ /* Increment the protection count. */ +@ _tx_thread_smp_protection.tx_thread_smp_protect_count++; @ - LDR r3, =_tx_thread_smp_protect_wait_counts @ Load waiting list - LDR r4, [r3, r1, LSL #2] @ Load current wait value - SUB r4, r4, #1 @ Decrement wait value - STR r4, [r3, r1, LSL #2] @ Store new wait value value + LDR r1, [r0, #12] @ Pickup ownership count + ADD r1, r1, #1 @ Increment ownership count + STR r1, [r0, #12] @ Store new ownership count + DMB @ + MOV r0, r3 @ Return the previous CPSR @ -@ /* Restore link register and return. */ +@} @ -_return: - - POP {r4-r6} @ Restore registers - #ifdef __THUMB_INTERWORK BX lr @ Return to caller #else diff --git a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_protection_wait_list_macros.h b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_protection_wait_list_macros.h deleted file mode 100644 index dff747d14..000000000 --- a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_protection_wait_list_macros.h +++ /dev/null @@ -1,308 +0,0 @@ -@/*************************************************************************** -@ * Copyright (c) 2024 Microsoft Corporation -@ * -@ * This program and the accompanying materials are made available under the -@ * terms of the MIT License which is available at -@ * https://opensource.org/licenses/MIT. -@ * -@ * SPDX-License-Identifier: MIT -@ **************************************************************************/ -@ -@ -@/**************************************************************************/ -@/**************************************************************************/ -@/** */ -@/** ThreadX Component */ -@/** */ -@/** Thread - Low Level SMP Support */ -@/** */ -@/**************************************************************************/ -@/**************************************************************************/ - - .macro _tx_thread_smp_protect_lock_got -@ -@ /* Set the currently owned core. */ -@ _tx_thread_smp_protection.tx_thread_smp_protect_core = this_core; -@ - STR r1, [r2, #8] @ Store this core -@ -@ /* Increment the protection count. */ -@ _tx_thread_smp_protection.tx_thread_smp_protect_count++; -@ - LDR r3, [r2, #12] @ Pickup ownership count - ADD r3, r3, #1 @ Increment ownership count - STR r3, [r2, #12] @ Store ownership count - DMB - -#ifdef TX_MPCORE_DEBUG_ENABLE - LSL r3, r1, #2 @ Build offset to array indexes - LDR r4, =_tx_thread_current_ptr @ Pickup start of the current thread array - ADD r4, r3, r4 @ Build index into the current thread array - LDR r3, [r4] @ Pickup current thread for this core - STR r3, [r2, #4] @ Save current thread pointer - STR LR, [r2, #16] @ Save caller's return address - STR r0, [r2, #20] @ Save CPSR -#endif - - .endm - - .macro _tx_thread_smp_protect_remove_from_front_of_list -@ -@ /* Remove ourselves from the list. */ -@ _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_head++] = 0xFFFFFFFF; -@ - MOV r3, #0xFFFFFFFF @ Build the invalid core value - LDR r4, =_tx_thread_smp_protect_wait_list_head @ Get the address of the head - LDR r5, [r4] @ Get the value of the head - LDR r6, =_tx_thread_smp_protect_wait_list @ Get the address of the list - STR r3, [r6, r5, LSL #2] @ Store the invalid core value - ADD r5, r5, #1 @ Increment the head -@ -@ /* Did we wrap? */ -@ if (_tx_thread_smp_protect_wait_list_head == TX_THREAD_SMP_MAX_CORES + 1) -@ { -@ - LDR r3, =_tx_thread_smp_protect_wait_list_size @ Load address of core list size - LDR r3, [r3] @ Load the max cores value - CMP r5, r3 @ Compare the head to it - BNE _store_new_head\@ @ Are we at the max? -@ -@ _tx_thread_smp_protect_wait_list_head = 0; -@ - EOR r5, r5, r5 @ We're at the max. Set it to zero -@ -@ } -@ -_store_new_head\@: - - STR r5, [r4] @ Store the new head -@ -@ /* We have the lock! */ -@ return; -@ - .endm - - - .macro _tx_thread_smp_protect_wait_list_lock_get -@VOID _tx_thread_smp_protect_wait_list_lock_get() -@{ -@ /* We do this until we have the lock. */ -@ while (1) -@ { -@ -_tx_thread_smp_protect_wait_list_lock_get__try_to_get_lock\@: -@ -@ /* Is the list lock available? */ -@ _tx_thread_smp_protect_wait_list_lock_protect_in_force = load_exclusive(&_tx_thread_smp_protect_wait_list_lock_protect_in_force); -@ - LDR r1, =_tx_thread_smp_protect_wait_list_lock_protect_in_force - LDREX r2, [r1] @ Pickup the protection flag -@ -@ if (protect_in_force == 0) -@ { -@ - CMP r2, #0 - BNE _tx_thread_smp_protect_wait_list_lock_get__try_to_get_lock\@ @ No, protection not available -@ -@ /* Try to get the list. */ -@ int status = store_exclusive(&_tx_thread_smp_protect_wait_list_lock_protect_in_force, 1); -@ - MOV r2, #1 @ Build lock value - STREX r3, r2, [r1] @ Attempt to get the protection -@ -@ if (status == SUCCESS) -@ - CMP r3, #0 - BNE _tx_thread_smp_protect_wait_list_lock_get__try_to_get_lock\@ @ Did it fail? If so, try again. -@ -@ /* We have the lock! */ -@ return; -@ - .endm - - - .macro _tx_thread_smp_protect_wait_list_add -@VOID _tx_thread_smp_protect_wait_list_add(UINT new_core) -@{ -@ -@ /* We're about to modify the list, so get the list lock. */ -@ _tx_thread_smp_protect_wait_list_lock_get(); -@ - PUSH {r1-r2} - - _tx_thread_smp_protect_wait_list_lock_get - - POP {r1-r2} -@ -@ /* Add this core. */ -@ _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_tail++] = new_core; -@ - LDR r3, =_tx_thread_smp_protect_wait_list_tail @ Get the address of the tail - LDR r4, [r3] @ Get the value of tail - LDR r5, =_tx_thread_smp_protect_wait_list @ Get the address of the list - STR r1, [r5, r4, LSL #2] @ Store the new core value - ADD r4, r4, #1 @ Increment the tail -@ -@ /* Did we wrap? */ -@ if (_tx_thread_smp_protect_wait_list_tail == _tx_thread_smp_protect_wait_list_size) -@ { -@ - LDR r5, =_tx_thread_smp_protect_wait_list_size @ Load max cores address - LDR r5, [r5] @ Load max cores value - CMP r4, r5 @ Compare max cores to tail - BNE _tx_thread_smp_protect_wait_list_add__no_wrap\@ @ Did we wrap? -@ -@ _tx_thread_smp_protect_wait_list_tail = 0; -@ - MOV r4, #0 -@ -@ } -@ -_tx_thread_smp_protect_wait_list_add__no_wrap\@: - - STR r4, [r3] @ Store the new tail value. -@ -@ /* Release the list lock. */ -@ _tx_thread_smp_protect_wait_list_lock_protect_in_force = 0; -@ - MOV r3, #0 @ Build lock value - LDR r4, =_tx_thread_smp_protect_wait_list_lock_protect_in_force - STR r3, [r4] @ Store the new value - - .endm - - - .macro _tx_thread_smp_protect_wait_list_remove -@VOID _tx_thread_smp_protect_wait_list_remove(UINT core) -@{ -@ -@ /* Get the core index. */ -@ UINT core_index; -@ for (core_index = 0;; core_index++) -@ - EOR r1, r1, r1 @ Clear for 'core_index' - LDR r2, =_tx_thread_smp_protect_wait_list @ Get the address of the list -@ -@ { -@ -_tx_thread_smp_protect_wait_list_remove__check_cur_core\@: -@ -@ /* Is this the core? */ -@ if (_tx_thread_smp_protect_wait_list[core_index] == core) -@ { -@ break; -@ - LDR r3, [r2, r1, LSL #2] @ Get the value at the current index - CMP r3, r10 @ Did we find the core? - BEQ _tx_thread_smp_protect_wait_list_remove__found_core\@ -@ -@ } -@ - ADD r1, r1, #1 @ Increment cur index - B _tx_thread_smp_protect_wait_list_remove__check_cur_core\@ @ Restart the loop -@ -@ } -@ -_tx_thread_smp_protect_wait_list_remove__found_core\@: -@ -@ /* We're about to modify the list. Get the lock. We need the lock because another -@ core could be simultaneously adding (a core is simultaneously trying to get -@ the inter-core lock) or removing (a core is simultaneously being preempted, -@ like what is currently happening). */ -@ _tx_thread_smp_protect_wait_list_lock_get(); -@ - PUSH {r1} - - _tx_thread_smp_protect_wait_list_lock_get - - POP {r1} -@ -@ /* We remove by shifting. */ -@ while (core_index != _tx_thread_smp_protect_wait_list_tail) -@ { -@ -_tx_thread_smp_protect_wait_list_remove__compare_index_to_tail\@: - - LDR r2, =_tx_thread_smp_protect_wait_list_tail @ Load tail address - LDR r2, [r2] @ Load tail value - CMP r1, r2 @ Compare cur index and tail - BEQ _tx_thread_smp_protect_wait_list_remove__removed\@ -@ -@ UINT next_index = core_index + 1; -@ - MOV r2, r1 @ Move current index to next index register - ADD r2, r2, #1 @ Add 1 -@ -@ if (next_index == _tx_thread_smp_protect_wait_list_size) -@ { -@ - LDR r3, =_tx_thread_smp_protect_wait_list_size - LDR r3, [r3] - CMP r2, r3 - BNE _tx_thread_smp_protect_wait_list_remove__next_index_no_wrap\@ -@ -@ next_index = 0; -@ - MOV r2, #0 -@ -@ } -@ -_tx_thread_smp_protect_wait_list_remove__next_index_no_wrap\@: -@ -@ list_cores[core_index] = list_cores[next_index]; -@ - LDR r0, =_tx_thread_smp_protect_wait_list @ Get the address of the list - LDR r3, [r0, r2, LSL #2] @ Get the value at the next index - STR r3, [r0, r1, LSL #2] @ Store the value at the current index -@ -@ core_index = next_index; -@ - MOV r1, r2 - - B _tx_thread_smp_protect_wait_list_remove__compare_index_to_tail\@ -@ -@ } -@ -_tx_thread_smp_protect_wait_list_remove__removed\@: -@ -@ /* Now update the tail. */ -@ if (_tx_thread_smp_protect_wait_list_tail == 0) -@ { -@ - LDR r0, =_tx_thread_smp_protect_wait_list_tail @ Load tail address - LDR r1, [r0] @ Load tail value - CMP r1, #0 - BNE _tx_thread_smp_protect_wait_list_remove__tail_not_zero\@ -@ -@ _tx_thread_smp_protect_wait_list_tail = _tx_thread_smp_protect_wait_list_size; -@ - LDR r2, =_tx_thread_smp_protect_wait_list_size - LDR r1, [r2] -@ -@ } -@ -_tx_thread_smp_protect_wait_list_remove__tail_not_zero\@: -@ -@ _tx_thread_smp_protect_wait_list_tail--; -@ - SUB r1, r1, #1 - STR r1, [r0] @ Store new tail value -@ -@ /* Release the list lock. */ -@ _tx_thread_smp_protect_wait_list_lock_protect_in_force = 0; -@ - MOV r0, #0 @ Build lock value - LDR r1, =_tx_thread_smp_protect_wait_list_lock_protect_in_force @ Load lock address - STR r0, [r1] @ Store the new value -@ -@ /* We're no longer waiting. Note that this should be zero since, again, -@ this function is only called when a thread preemption is occurring. */ -@ _tx_thread_smp_protect_wait_counts[core]--; -@ - LDR r1, =_tx_thread_smp_protect_wait_counts @ Load wait list counts - LDR r2, [r1, r10, LSL #2] @ Load waiting value - SUB r2, r2, #1 @ Subtract 1 - STR r2, [r1, r10, LSL #2] @ Store new waiting value - - .endm - diff --git a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_unprotect.S b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_unprotect.S index 5b939a05a..8d47131a3 100644 --- a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_unprotect.S +++ b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_unprotect.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * 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 @@ -7,6 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ +@ Some portions generated by Copilot (Opus 5). @ @ @/**************************************************************************/ @@ -33,7 +35,6 @@ .global _tx_thread_current_ptr .global _tx_thread_smp_protection .global _tx_thread_preempt_disable - .global _tx_thread_smp_protect_wait_counts .arm .text @@ -105,10 +106,6 @@ _tx_thread_smp_unprotect: CMP r3, #0 @ Is the preempt disable flag set? BNE _still_protected @ Yes, skip the protection release - LDR r2,=_tx_thread_smp_protect_wait_counts @ Build build address of wait counts - LDR r3, [r2, r1, LSL #2] @ Pickup wait list value - CMP r3, #0 @ Are any entities on this core waiting? - BNE _still_protected @ Yes, skip the protection release LDR r2,=_tx_thread_smp_protection @ Build address of protection structure MOV r3, #0xFFFFFFFF @ Build invalid value diff --git a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_context_restore.s b/ports_smp/cortex_a9_smp/ac5/src/tx_thread_context_restore.s index b6c179cd4..6327d05dc 100644 --- a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_context_restore.s +++ b/ports_smp/cortex_a9_smp/ac5/src/tx_thread_context_restore.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * 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 @@ -7,6 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ +; Some portions generated by Copilot (Opus 5). ; ; ;/**************************************************************************/ @@ -29,8 +31,6 @@ ;#include "tx_thread.h" ;#include "tx_timer.h" ; -;/* Include macros for modifying the wait list. */ -#include "tx_thread_smp_protection_wait_list_macros.h" IF :DEF:TX_ENABLE_FIQ_SUPPORT DISABLE_INTS EQU 0xC0 ; Disable IRQ & FIQ interrupts @@ -51,11 +51,6 @@ SVC_MODE EQU 0x93 ; SVC mode IMPORT _tx_thread_preempt_disable IMPORT _tx_timer_interrupt_active IMPORT _tx_thread_smp_protection - IMPORT _tx_thread_smp_protect_wait_counts - IMPORT _tx_thread_smp_protect_wait_list - IMPORT _tx_thread_smp_protect_wait_list_lock_protect_in_force - IMPORT _tx_thread_smp_protect_wait_list_tail - IMPORT _tx_thread_smp_protect_wait_list_size IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY IMPORT _tx_execution_isr_exit ENDIF @@ -196,77 +191,6 @@ __tx_thread_no_preempt_restore ; { ; __tx_thread_preempt_restore -; -; /* Was the thread being preempted waiting for the lock? */ -; if (_tx_thread_smp_protect_wait_counts[this_core] != 0) -; { -; - LDR r1, =_tx_thread_smp_protect_wait_counts ; Load waiting count list - LDR r2, [r1, r10, LSL #2] ; Load waiting value for this core - CMP r2, #0 - BEQ _nobody_waiting_for_lock ; Is the core waiting for the lock? -; -; /* Do we not have the lock? This means the ISR never got the inter-core lock. */ -; if (_tx_thread_smp_protection.tx_thread_smp_protect_owned != this_core) -; { -; - LDR r1, =_tx_thread_smp_protection ; Load address of protection structure - LDR r2, [r1, #8] ; Pickup the owning core - CMP r10, r2 ; Compare our core to the owning core - BEQ _this_core_has_lock ; Do we have the lock? -; -; /* We don't have the lock. This core should be in the list. Remove it. */ -; _tx_thread_smp_protect_wait_list_remove(this_core); -; - MOV r0, r10 ; Move the core ID to r0 for the macro -macro_call0 _tx_thread_smp_protect_wait_list_remove ; Call macro to remove core from the list - B _nobody_waiting_for_lock ; Leave -; -; } -; else -; { -; /* We have the lock. This means the ISR got the inter-core lock, but -; never released it because it saw that there was someone waiting. -; Note this core is not in the list. */ -; -_this_core_has_lock -; -; /* We're no longer waiting. Note that this should be zero since this happens during thread preemption. */ -; _tx_thread_smp_protect_wait_counts[core]--; -; - LDR r1, =_tx_thread_smp_protect_wait_counts ; Load waiting count list - LDR r2, [r1, r10, LSL #2] ; Load waiting value for this core - SUB r2, r2, #1 ; Decrement waiting value. Should be zero now - STR r2, [r1, r10, LSL #2] ; Store new waiting value -; -; /* Now release the inter-core lock. */ -; -; /* Set protected core as invalid. */ -; _tx_thread_smp_protection.tx_thread_smp_protect_core = 0xFFFFFFFF; -; - LDR r1, =_tx_thread_smp_protection ; Load address of protection structure - MOV r2, #0xFFFFFFFF ; Build invalid value - STR r2, [r1, #8] ; Mark the protected core as invalid - DMB ; Ensure that accesses to shared resource have completed -; -; /* Release protection. */ -; _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 0; -; - MOV r2, #0 ; Build release protection value - STR r2, [r1, #0] ; Release the protection - DSB ISH ; To ensure update of the protection occurs before other CPUs awake -; -; /* Wake up waiting processors. Note interrupts are already enabled. */ -; - IF :DEF:TX_ENABLE_WFE - SEV ; Send event to other CPUs - ENDIF -; -; } -; } -; - -_nobody_waiting_for_lock LDMIA sp!, {r3, r10, r12, lr} ; Recover temporarily saved registers MOV r1, lr ; Save lr (point of interrupt) diff --git a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_smp_protect.s b/ports_smp/cortex_a9_smp/ac5/src/tx_thread_smp_protect.s index 1f2330d99..82fa0b914 100644 --- a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_smp_protect.s +++ b/ports_smp/cortex_a9_smp/ac5/src/tx_thread_smp_protect.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * 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 @@ -7,6 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ +; Some portions generated by Copilot (Opus 5). ; ; ;/**************************************************************************/ @@ -31,17 +33,9 @@ ; ; -;/* Include macros for modifying the wait list. */ -#include "tx_thread_smp_protection_wait_list_macros.h" IMPORT _tx_thread_current_ptr IMPORT _tx_thread_smp_protection - IMPORT _tx_thread_smp_protect_wait_counts - IMPORT _tx_thread_smp_protect_wait_list - IMPORT _tx_thread_smp_protect_wait_list_lock_protect_in_force - IMPORT _tx_thread_smp_protect_wait_list_head - IMPORT _tx_thread_smp_protect_wait_list_tail - IMPORT _tx_thread_smp_protect_wait_list_size AREA ||.text||, CODE, READONLY PRESERVE8 @@ -82,12 +76,10 @@ _tx_thread_smp_protect ;VOID _tx_thread_smp_protect(VOID) ;{ -; - PUSH {r4-r6} ; Save registers we'll be using ; ; /* Disable interrupts so we don't get preempted. */ ; - MRS r0, CPSR ; Pickup current CPSR + MRS r3, CPSR ; Pickup current CPSR IF :DEF:TX_ENABLE_FIQ_SUPPORT CPSID if ; Disable IRQ and FIQ interrupts @@ -95,266 +87,93 @@ _tx_thread_smp_protect CPSID i ; Disable IRQ interrupts ENDIF ; +; /* Pickup the CPU ID. */ +; + MRC p15, 0, r2, c0, c0, 5 ; Read CPU ID register + AND r2, r2, #0x03 ; Mask off, leaving the CPU ID field +; ; /* Do we already have protection? */ ; if (this_core == _tx_thread_smp_protection.tx_thread_smp_protect_core) ; { ; - MRC p15, 0, r1, c0, c0, 5 ; Read CPU ID register - AND r1, r1, #0x03 ; Mask off, leaving the CPU ID field - LDR r2, =_tx_thread_smp_protection ; Build address to protection structure - LDR r3, [r2, #8] ; Pickup the owning core - CMP r1, r3 ; Is it not this core? - BNE _protection_not_owned ; No, the protection is not already owned -; -; /* We already have protection. */ -; -; /* Increment the protection count. */ -; _tx_thread_smp_protection.tx_thread_smp_protect_count++; + LDR r0, =_tx_thread_smp_protection ; Build address to protection structure + LDR r1, [r0, #8] ; Pickup the owning core + CMP r1, r2 ; Is it this core? + BEQ _owned ; Yes, the protection is already owned ; - LDR r3, [r2, #12] ; Pickup ownership count - ADD r3, r3, #1 ; Increment ownership count - STR r3, [r2, #12] ; Store ownership count - DMB - - B _return - -_protection_not_owned +; } ; ; /* Is the lock available? */ ; if (_tx_thread_smp_protection.tx_thread_smp_protect_in_force == 0) ; { ; - LDREX r3, [r2, #0] ; Pickup the protection flag - CMP r3, #0 - BNE _start_waiting ; No, protection not available -; -; /* Is the list empty? */ -; if (_tx_thread_smp_protect_wait_list_head == _tx_thread_smp_protect_wait_list_tail) -; { -; - LDR r3, =_tx_thread_smp_protect_wait_list_head - LDR r3, [r3] - LDR r4, =_tx_thread_smp_protect_wait_list_tail - LDR r4, [r4] - CMP r3, r4 - BNE _list_not_empty -; -; /* Try to get the lock. */ -; if (write_exclusive(&_tx_thread_smp_protection.tx_thread_smp_protect_in_force, 1) == SUCCESS) -; { -; - MOV r3, #1 ; Build lock value - STREX r4, r3, [r2, #0] ; Attempt to get the protection - CMP r4, #0 - BNE _start_waiting ; Did it fail? -; -; /* We got the lock! */ -; _tx_thread_smp_protect_lock_got(); -; - DMB ; Ensure write to protection finishes -macro_call0 _tx_thread_smp_protect_lock_got ; Call the lock got function - - B _return - -_list_not_empty -; -; /* Are we at the front of the list? */ -; if (this_core == _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_head]) -; { -; - LDR r3, =_tx_thread_smp_protect_wait_list_head ; Get the address of the head - LDR r3, [r3] ; Get the value of the head - LDR r4, =_tx_thread_smp_protect_wait_list ; Get the address of the list - LDR r4, [r4, r3, LSL #2] ; Get the value at the head index - - CMP r1, r4 - BNE _start_waiting -; -; /* Is the lock still available? */ -; if (_tx_thread_smp_protection.tx_thread_smp_protect_in_force == 0) -; { -; - LDR r3, [r2, #0] ; Pickup the protection flag - CMP r3, #0 - BNE _start_waiting ; No, protection not available -; -; /* Get the lock. */ -; _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 1; -; - MOV r3, #1 ; Build lock value - STR r3, [r2, #0] ; Store lock value - DMB ; -; -; /* Got the lock. */ -; _tx_thread_smp_protect_lock_got(); -; -macro_call1 _tx_thread_smp_protect_lock_got -; -; /* Remove this core from the wait list. */ -; _tx_thread_smp_protect_remove_from_front_of_list(); -; -macro_call2 _tx_thread_smp_protect_remove_from_front_of_list - - B _return - -_start_waiting -; -; /* For one reason or another, we didn't get the lock. */ -; -; /* Increment wait count. */ -; _tx_thread_smp_protect_wait_counts[this_core]++; -; - LDR r3, =_tx_thread_smp_protect_wait_counts ; Load wait list counts - LDR r4, [r3, r1, LSL #2] ; Load waiting value for this core - ADD r4, r4, #1 ; Increment wait value - STR r4, [r3, r1, LSL #2] ; Store new wait value -; -; /* Have we not added ourselves to the list yet? */ -; if (_tx_thread_smp_protect_wait_counts[this_core] == 1) -; { -; - CMP r4, #1 - BNE _already_in_list0 ; Is this core already waiting? -; -; /* Add ourselves to the list. */ -; _tx_thread_smp_protect_wait_list_add(this_core); -; -macro_call3 _tx_thread_smp_protect_wait_list_add ; Call macro to add ourselves to the list + LDREX r1, [r0] ; Pickup the protection flag + CMP r1, #0 ; Is it available? + BEQ _get_protection ; Yes, attempt to get the protection ; ; } ; -_already_in_list0 -; -; /* Restore interrupts. */ +; /* The protection is held elsewhere. Restore interrupts so this core can be +; preempted while it waits, then try the whole sequence again. */ ; - MSR CPSR_c, r0 ; Restore CPSR + MSR CPSR_c, r3 ; Restore CPSR IF :DEF:TX_ENABLE_WFE WFE ; Go into standby ENDIF -; -; /* We do this until we have the lock. */ -; while (1) -; { -; -_try_to_get_lock -; -; /* Disable interrupts so we don't get preempted. */ -; - IF :DEF:TX_ENABLE_FIQ_SUPPORT - CPSID if ; Disable IRQ and FIQ interrupts - ELSE - CPSID i ; Disable IRQ interrupts - ENDIF + B _tx_thread_smp_protect ; On waking, restart the protection attempt - MRC p15, 0, r1, c0, c0, 5 ; Read CPU ID register - AND r1, r1, #0x03 ; Mask off, leaving the CPU ID field +_get_protection ; -; /* Do we already have protection? */ -; if (this_core == _tx_thread_smp_protection.tx_thread_smp_protect_core) +; /* Try to get the lock. */ +; if (write_exclusive(&_tx_thread_smp_protection.tx_thread_smp_protect_in_force, 1) == SUCCESS) ; { ; - LDR r3, [r2, #8] ; Pickup the owning core - CMP r3, r1 ; Is it this core? - BEQ _got_lock_after_waiting ; Yes, the protection is already owned. This means - ; an ISR preempted us and got protection + MOV r1, #1 ; Build lock value + STREX r2, r1, [r0] ; Attempt to get the protection + CMP r2, #0 ; Check whether the store succeeded (0 = success) + BEQ _got_protection ; Yes, we have the protection ; ; } ; -; /* Are we at the front of the list? */ -; if (this_core == _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_head]) -; { +; /* Another core beat us to it. Restore interrupts and try again. */ ; - LDR r3, =_tx_thread_smp_protect_wait_list_head ; Get the address of the head - LDR r3, [r3] ; Get the value of the head - LDR r4, =_tx_thread_smp_protect_wait_list ; Get the address of the list - LDR r4, [r4, r3, LSL #2] ; Get the value at the head index + MSR CPSR_c, r3 ; Restore CPSR + B _tx_thread_smp_protect ; Try the whole process again - CMP r1, r4 - BNE _did_not_get_lock -; -; /* Is the lock still available? */ -; if (_tx_thread_smp_protection.tx_thread_smp_protect_in_force == 0) -; { -; - LDR r3, [r2, #0] ; Pickup the protection flag - CMP r3, #0 - BNE _did_not_get_lock ; No, protection not available -; -; /* Get the lock. */ -; _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 1; -; - MOV r3, #1 ; Build lock value - STR r3, [r2, #0] ; Store lock value - DMB ; +_got_protection ; -; /* Got the lock. */ -; _tx_thread_smp_protect_lock_got(); +; /* Got the lock. Record the owning core. */ +; _tx_thread_smp_protection.tx_thread_smp_protect_core = this_core; ; -macro_call4 _tx_thread_smp_protect_lock_got -; -; /* Remove this core from the wait list. */ -; _tx_thread_smp_protect_remove_from_front_of_list(); -; -macro_call5 _tx_thread_smp_protect_remove_from_front_of_list - - B _got_lock_after_waiting + DMB ; Ensure the protection write completes before it is used + MRC p15, 0, r2, c0, c0, 5 ; Read CPU ID register + AND r2, r2, #0x03 ; Mask off, leaving the CPU ID field + STR r2, [r0, #8] ; Save the owning core -_did_not_get_lock -; -; /* For one reason or another, we didn't get the lock. */ -; -; /* Were we removed from the list? This can happen if we're a thread -; and we got preempted. */ -; if (_tx_thread_smp_protect_wait_counts[this_core] == 0) -; { -; - LDR r3, =_tx_thread_smp_protect_wait_counts ; Load wait list counts - LDR r4, [r3, r1, LSL #2] ; Load waiting value for this core - CMP r4, #0 - BNE _already_in_list1 ; Is this core already in the list? -; -; /* Add ourselves to the list. */ -; _tx_thread_smp_protect_wait_list_add(this_core); -; -macro_call6 _tx_thread_smp_protect_wait_list_add ; Call macro to add ourselves to the list -; -; /* Our waiting count was also reset when we were preempted. Increment it again. */ -; _tx_thread_smp_protect_wait_counts[this_core]++; -; - LDR r3, =_tx_thread_smp_protect_wait_counts ; Load wait list counts - LDR r4, [r3, r1, LSL #2] ; Load waiting value for this core - ADD r4, r4, #1 ; Increment wait value - STR r4, [r3, r1, LSL #2] ; Store new wait value value -; -; } -; -_already_in_list1 -; -; /* Restore interrupts and try again. */ -; - MSR CPSR_c, r0 ; Restore CPSR - IF :DEF:TX_ENABLE_WFE - WFE ; Go into standby + IF :DEF:TX_MPCORE_DEBUG_ENABLE + LSL r2, r2, #2 ; Build offset to array indexes + LDR r1, =_tx_thread_current_ptr ; Pickup start of the current thread array + ADD r1, r1, r2 ; Build index into the current thread array + LDR r2, [r1] ; Pickup current thread for this core + STR r2, [r0, #4] ; Save current thread pointer + STR LR, [r0, #16] ; Save caller's return address + STR r3, [r0, #20] ; Save CPSR ENDIF - B _try_to_get_lock ; On waking, restart the protection attempt -_got_lock_after_waiting +_owned ; -; /* We're no longer waiting. */ -; _tx_thread_smp_protect_wait_counts[this_core]--; +; /* Increment the protection count. */ +; _tx_thread_smp_protection.tx_thread_smp_protect_count++; ; - LDR r3, =_tx_thread_smp_protect_wait_counts ; Load waiting list - LDR r4, [r3, r1, LSL #2] ; Load current wait value - SUB r4, r4, #1 ; Decrement wait value - STR r4, [r3, r1, LSL #2] ; Store new wait value value + LDR r1, [r0, #12] ; Pickup ownership count + ADD r1, r1, #1 ; Increment ownership count + STR r1, [r0, #12] ; Store new ownership count + DMB ; + MOV r0, r3 ; Return the previous CPSR ; -; /* Restore link register and return. */ +;} ; -_return - - POP {r4-r6} ; Restore registers - IF {INTER} = {TRUE} BX lr ; Return to caller ELSE @@ -362,4 +181,3 @@ _return ENDIF END - diff --git a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_smp_protection_wait_list_macros.h b/ports_smp/cortex_a9_smp/ac5/src/tx_thread_smp_protection_wait_list_macros.h deleted file mode 100644 index fec515810..000000000 --- a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_smp_protection_wait_list_macros.h +++ /dev/null @@ -1,314 +0,0 @@ -;/*************************************************************************** -; * Copyright (c) 2024 Microsoft Corporation -; * -; * This program and the accompanying materials are made available under the -; * terms of the MIT License which is available at -; * https://opensource.org/licenses/MIT. -; * -; * SPDX-License-Identifier: MIT -; **************************************************************************/ -; -; -;/**************************************************************************/ -;/**************************************************************************/ -;/** */ -;/** ThreadX Component */ -;/** */ -;/** Thread - Low Level SMP Support */ -;/** */ -;/**************************************************************************/ -;/**************************************************************************/ - - MACRO -$label _tx_thread_smp_protect_lock_got -; -; /* Set the currently owned core. */ -; _tx_thread_smp_protection.tx_thread_smp_protect_core = this_core; -; - STR r1, [r2, #8] ; Store this core -; -; /* Increment the protection count. */ -; _tx_thread_smp_protection.tx_thread_smp_protect_count++; -; - LDR r3, [r2, #12] ; Pickup ownership count - ADD r3, r3, #1 ; Increment ownership count - STR r3, [r2, #12] ; Store ownership count - DMB - - IF :DEF:TX_MPCORE_DEBUG_ENABLE - LSL r3, r1, #2 ; Build offset to array indexes - LDR r4, =_tx_thread_current_ptr ; Pickup start of the current thread array - ADD r4, r3, r4 ; Build index into the current thread array - LDR r3, [r4] ; Pickup current thread for this core - STR r3, [r2, #4] ; Save current thread pointer - STR LR, [r2, #16] ; Save caller's return address - STR r0, [r2, #20] ; Save CPSR - ENDIF - - MEND - - MACRO -$label _tx_thread_smp_protect_remove_from_front_of_list -; -; /* Remove ourselves from the list. */ -; _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_head++] = 0xFFFFFFFF; -; - MOV r3, #0xFFFFFFFF ; Build the invalid core value - LDR r4, =_tx_thread_smp_protect_wait_list_head ; Get the address of the head - LDR r5, [r4] ; Get the value of the head - LDR r6, =_tx_thread_smp_protect_wait_list ; Get the address of the list - STR r3, [r6, r5, LSL #2] ; Store the invalid core value - ADD r5, r5, #1 ; Increment the head -; -; /* Did we wrap? */ -; if (_tx_thread_smp_protect_wait_list_head == TX_THREAD_SMP_MAX_CORES + 1) -; { -; - LDR r3, =_tx_thread_smp_protect_wait_list_size ; Load address of core list size - LDR r3, [r3] ; Load the max cores value - CMP r5, r3 ; Compare the head to it - BNE $label._store_new_head ; Are we at the max? -; -; _tx_thread_smp_protect_wait_list_head = 0; -; - EOR r5, r5, r5 ; We're at the max. Set it to zero -; -; } -; -$label._store_new_head - - STR r5, [r4] ; Store the new head -; -; /* We have the lock! */ -; return; -; - MEND - - - MACRO -$label _tx_thread_smp_protect_wait_list_lock_get -;VOID _tx_thread_smp_protect_wait_list_lock_get() -;{ -; /* We do this until we have the lock. */ -; while (1) -; { -; -$label._tx_thread_smp_protect_wait_list_lock_get__try_to_get_lock -; -; /* Is the list lock available? */ -; _tx_thread_smp_protect_wait_list_lock_protect_in_force = load_exclusive(&_tx_thread_smp_protect_wait_list_lock_protect_in_force); -; - LDR r1, =_tx_thread_smp_protect_wait_list_lock_protect_in_force - LDREX r2, [r1] ; Pickup the protection flag -; -; if (protect_in_force == 0) -; { -; - CMP r2, #0 - BNE $label._tx_thread_smp_protect_wait_list_lock_get__try_to_get_lock ; No, protection not available -; -; /* Try to get the list. */ -; int status = store_exclusive(&_tx_thread_smp_protect_wait_list_lock_protect_in_force, 1); -; - MOV r2, #1 ; Build lock value - STREX r3, r2, [r1] ; Attempt to get the protection -; -; if (status == SUCCESS) -; - CMP r3, #0 - BNE $label._tx_thread_smp_protect_wait_list_lock_get__try_to_get_lock ; Did it fail? If so, try again. -; -; /* We have the lock! */ -; return; -; - MEND - - - MACRO -$label _tx_thread_smp_protect_wait_list_add -;VOID _tx_thread_smp_protect_wait_list_add(UINT new_core) -;{ -; -; /* We're about to modify the list, so get the list lock. */ -; _tx_thread_smp_protect_wait_list_lock_get(); -; - PUSH {r1-r2} - -$label _tx_thread_smp_protect_wait_list_lock_get - - POP {r1-r2} -; -; /* Add this core. */ -; _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_tail++] = new_core; -; - LDR r3, =_tx_thread_smp_protect_wait_list_tail ; Get the address of the tail - LDR r4, [r3] ; Get the value of tail - LDR r5, =_tx_thread_smp_protect_wait_list ; Get the address of the list - STR r1, [r5, r4, LSL #2] ; Store the new core value - ADD r4, r4, #1 ; Increment the tail -; -; /* Did we wrap? */ -; if (_tx_thread_smp_protect_wait_list_tail == _tx_thread_smp_protect_wait_list_size) -; { -; - LDR r5, =_tx_thread_smp_protect_wait_list_size ; Load max cores address - LDR r5, [r5] ; Load max cores value - CMP r4, r5 ; Compare max cores to tail - BNE $label._tx_thread_smp_protect_wait_list_add__no_wrap ; Did we wrap? -; -; _tx_thread_smp_protect_wait_list_tail = 0; -; - MOV r4, #0 -; -; } -; -$label._tx_thread_smp_protect_wait_list_add__no_wrap - - STR r4, [r3] ; Store the new tail value. -; -; /* Release the list lock. */ -; _tx_thread_smp_protect_wait_list_lock_protect_in_force = 0; -; - MOV r3, #0 ; Build lock value - LDR r4, =_tx_thread_smp_protect_wait_list_lock_protect_in_force - STR r3, [r4] ; Store the new value - - MEND - - - MACRO -$label _tx_thread_smp_protect_wait_list_remove -;VOID _tx_thread_smp_protect_wait_list_remove(UINT core) -;{ -; -; /* Get the core index. */ -; UINT core_index; -; for (core_index = 0;; core_index++) -; - EOR r1, r1, r1 ; Clear for 'core_index' - LDR r2, =_tx_thread_smp_protect_wait_list ; Get the address of the list -; -; { -; -$label._tx_thread_smp_protect_wait_list_remove__check_cur_core -; -; /* Is this the core? */ -; if (_tx_thread_smp_protect_wait_list[core_index] == core) -; { -; break; -; - LDR r3, [r2, r1, LSL #2] ; Get the value at the current index - CMP r3, r0 ; Did we find the core? - BEQ $label._tx_thread_smp_protect_wait_list_remove__found_core -; -; } -; - ADD r1, r1, #1 ; Increment cur index - B $label._tx_thread_smp_protect_wait_list_remove__check_cur_core ; Restart the loop -; -; } -; -$label._tx_thread_smp_protect_wait_list_remove__found_core -; -; /* We're about to modify the list. Get the lock. We need the lock because another -; core could be simultaneously adding (a core is simultaneously trying to get -; the inter-core lock) or removing (a core is simultaneously being preempted, -; like what is currently happening). */ -; _tx_thread_smp_protect_wait_list_lock_get(); -; - PUSH {r1} - -$label _tx_thread_smp_protect_wait_list_lock_get - - POP {r1} -; -; /* We remove by shifting. */ -; while (core_index != _tx_thread_smp_protect_wait_list_tail) -; { -; -$label._tx_thread_smp_protect_wait_list_remove__compare_index_to_tail - - LDR r2, =_tx_thread_smp_protect_wait_list_tail ; Load tail address - LDR r2, [r2] ; Load tail value - CMP r1, r2 ; Compare cur index and tail - BEQ $label._tx_thread_smp_protect_wait_list_remove__removed -; -; UINT next_index = core_index + 1; -; - MOV r2, r1 ; Move current index to next index register - ADD r2, r2, #1 ; Add 1 -; -; if (next_index == _tx_thread_smp_protect_wait_list_size) -; { -; - LDR r3, =_tx_thread_smp_protect_wait_list_size - LDR r3, [r3] - CMP r2, r3 - BNE $label._tx_thread_smp_protect_wait_list_remove__next_index_no_wrap -; -; next_index = 0; -; - MOV r2, #0 -; -; } -; -$label._tx_thread_smp_protect_wait_list_remove__next_index_no_wrap -; -; list_cores[core_index] = list_cores[next_index]; -; - LDR r0, =_tx_thread_smp_protect_wait_list ; Get the address of the list - LDR r3, [r0, r2, LSL #2] ; Get the value at the next index - STR r3, [r0, r1, LSL #2] ; Store the value at the current index -; -; core_index = next_index; -; - MOV r1, r2 - - B $label._tx_thread_smp_protect_wait_list_remove__compare_index_to_tail -; -; } -; -$label._tx_thread_smp_protect_wait_list_remove__removed -; -; /* Now update the tail. */ -; if (_tx_thread_smp_protect_wait_list_tail == 0) -; { -; - LDR r0, =_tx_thread_smp_protect_wait_list_tail ; Load tail address - LDR r1, [r0] ; Load tail value - CMP r1, #0 - BNE $label._tx_thread_smp_protect_wait_list_remove__tail_not_zero -; -; _tx_thread_smp_protect_wait_list_tail = _tx_thread_smp_protect_wait_list_size; -; - LDR r2, =_tx_thread_smp_protect_wait_list_size - LDR r1, [r2] -; -; } -; -$label._tx_thread_smp_protect_wait_list_remove__tail_not_zero -; -; _tx_thread_smp_protect_wait_list_tail--; -; - SUB r1, r1, #1 - STR r1, [r0] ; Store new tail value -; -; /* Release the list lock. */ -; _tx_thread_smp_protect_wait_list_lock_protect_in_force = 0; -; - MOV r0, #0 ; Build lock value - LDR r1, =_tx_thread_smp_protect_wait_list_lock_protect_in_force ; Load lock address - STR r0, [r1] ; Store the new value -; -; /* We're no longer waiting. Note that this should be zero since, again, -; this function is only called when a thread preemption is occurring. */ -; _tx_thread_smp_protect_wait_counts[core]--; -; - MRC p15, 0, r0, c0, c0, 5 ; Read CPU ID register - AND r0, r0, #0x03 ; Mask off, leaving the CPU ID field - LDR r1, =_tx_thread_smp_protect_wait_counts ; Load wait list counts - LDR r2, [r1, r0, LSL #2] ; Load waiting value - SUB r2, r2, #1 ; Subtract 1 - STR r2, [r1, r0, LSL #2] ; Store new waiting value - MEND - diff --git a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_smp_unprotect.s b/ports_smp/cortex_a9_smp/ac5/src/tx_thread_smp_unprotect.s index ed3fae486..c161987cc 100644 --- a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_smp_unprotect.s +++ b/ports_smp/cortex_a9_smp/ac5/src/tx_thread_smp_unprotect.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * 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 @@ -7,6 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ +; Some portions generated by Copilot (Opus 5). ; ; ;/**************************************************************************/ @@ -33,7 +35,6 @@ IMPORT _tx_thread_current_ptr IMPORT _tx_thread_smp_protection IMPORT _tx_thread_preempt_disable - IMPORT _tx_thread_smp_protect_wait_counts AREA ||.text||, CODE, READONLY PRESERVE8 @@ -103,10 +104,6 @@ _tx_thread_smp_unprotect CMP r3, #0 ; Is the preempt disable flag set? BNE _still_protected ; Yes, skip the protection release - LDR r2,=_tx_thread_smp_protect_wait_counts ; Build build address of wait counts - LDR r3, [r2, r1, LSL #2] ; Pickup wait list value - CMP r3, #0 ; Are any entities on this core waiting? - BNE _still_protected ; Yes, skip the protection release LDR r2,=_tx_thread_smp_protection ; Build address of protection structure MOV r3, #0xFFFFFFFF ; Build invalid value diff --git a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_context_restore.S b/ports_smp/cortex_a9_smp/gnu/src/tx_thread_context_restore.S index 2fbf25fd1..c96d96380 100644 --- a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_context_restore.S +++ b/ports_smp/cortex_a9_smp/gnu/src/tx_thread_context_restore.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * 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 @@ -7,6 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ +@ Some portions generated by Copilot (Opus 5). @ @ @/**************************************************************************/ @@ -29,8 +31,6 @@ @#include "tx_thread.h" @#include "tx_timer.h" @ -@/* Include macros for modifying the wait list. */ -#include "tx_thread_smp_protection_wait_list_macros.h" #ifdef TX_ENABLE_FIQ_SUPPORT DISABLE_INTS = 0xC0 @ Disable IRQ & FIQ interrupts @@ -51,11 +51,6 @@ SVC_MODE = 0x93 @ SVC mode .global _tx_thread_preempt_disable .global _tx_timer_interrupt_active .global _tx_thread_smp_protection - .global _tx_thread_smp_protect_wait_counts - .global _tx_thread_smp_protect_wait_list - .global _tx_thread_smp_protect_wait_list_lock_protect_in_force - .global _tx_thread_smp_protect_wait_list_tail - .global _tx_thread_smp_protect_wait_list_size #ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY .global _tx_execution_isr_exit #endif @@ -198,77 +193,6 @@ __tx_thread_no_preempt_restore: @ { @ __tx_thread_preempt_restore: -@ -@ /* Was the thread being preempted waiting for the lock? */ -@ if (_tx_thread_smp_protect_wait_counts[this_core] != 0) -@ { -@ - LDR r1, =_tx_thread_smp_protect_wait_counts @ Load waiting count list - LDR r2, [r1, r10, LSL #2] @ Load waiting value for this core - CMP r2, #0 - BEQ _nobody_waiting_for_lock @ Is the core waiting for the lock? -@ -@ /* Do we not have the lock? This means the ISR never got the inter-core lock. */ -@ if (_tx_thread_smp_protection.tx_thread_smp_protect_owned != this_core) -@ { -@ - LDR r1, =_tx_thread_smp_protection @ Load address of protection structure - LDR r2, [r1, #8] @ Pickup the owning core - CMP r10, r2 @ Compare our core to the owning core - BEQ _this_core_has_lock @ Do we have the lock? -@ -@ /* We don't have the lock. This core should be in the list. Remove it. */ -@ _tx_thread_smp_protect_wait_list_remove(this_core); -@ - MOV r0, r10 @ Move the core ID to r0 for the macro - _tx_thread_smp_protect_wait_list_remove @ Call macro to remove core from the list - B _nobody_waiting_for_lock @ Leave -@ -@ } -@ else -@ { -@ /* We have the lock. This means the ISR got the inter-core lock, but -@ never released it because it saw that there was someone waiting. -@ Note this core is not in the list. */ -@ -_this_core_has_lock: -@ -@ /* We're no longer waiting. Note that this should be zero since this happens during thread preemption. */ -@ _tx_thread_smp_protect_wait_counts[core]--; -@ - LDR r1, =_tx_thread_smp_protect_wait_counts @ Load waiting count list - LDR r2, [r1, r10, LSL #2] @ Load waiting value for this core - SUB r2, r2, #1 @ Decrement waiting value. Should be zero now - STR r2, [r1, r10, LSL #2] @ Store new waiting value -@ -@ /* Now release the inter-core lock. */ -@ -@ /* Set protected core as invalid. */ -@ _tx_thread_smp_protection.tx_thread_smp_protect_core = 0xFFFFFFFF; -@ - LDR r1, =_tx_thread_smp_protection @ Load address of protection structure - MOV r2, #0xFFFFFFFF @ Build invalid value - STR r2, [r1, #8] @ Mark the protected core as invalid - DMB @ Ensure that accesses to shared resource have completed -@ -@ /* Release protection. */ -@ _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 0; -@ - MOV r2, #0 @ Build release protection value - STR r2, [r1, #0] @ Release the protection - DSB ISH @ To ensure update of the protection occurs before other CPUs awake -@ -@ /* Wake up waiting processors. Note interrupts are already enabled. */ -@ -#ifdef TX_ENABLE_WFE - SEV @ Send event to other CPUs -#endif -@ -@ } -@ } -@ - -_nobody_waiting_for_lock: LDMIA sp!, {r3, r10, r12, lr} @ Recover temporarily saved registers MOV r1, lr @ Save lr (point of interrupt) diff --git a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_smp_protect.S b/ports_smp/cortex_a9_smp/gnu/src/tx_thread_smp_protect.S index 44b36587a..05bf52566 100644 --- a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_smp_protect.S +++ b/ports_smp/cortex_a9_smp/gnu/src/tx_thread_smp_protect.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * 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 @@ -7,6 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ +@ Some portions generated by Copilot (Opus 5). @ @ @/**************************************************************************/ @@ -31,17 +33,9 @@ @ @ -@/* Include macros for modifying the wait list. */ -#include "tx_thread_smp_protection_wait_list_macros.h" .global _tx_thread_current_ptr .global _tx_thread_smp_protection - .global _tx_thread_smp_protect_wait_counts - .global _tx_thread_smp_protect_wait_list - .global _tx_thread_smp_protect_wait_list_lock_protect_in_force - .global _tx_thread_smp_protect_wait_list_head - .global _tx_thread_smp_protect_wait_list_tail - .global _tx_thread_smp_protect_wait_list_size .arm .text @@ -84,12 +78,10 @@ _tx_thread_smp_protect: @VOID _tx_thread_smp_protect(VOID) @{ -@ - PUSH {r4-r6} @ Save registers we'll be using @ @ /* Disable interrupts so we don't get preempted. */ @ - MRS r0, CPSR @ Pickup current CPSR + MRS r3, CPSR @ Pickup current CPSR #ifdef TX_ENABLE_FIQ_SUPPORT CPSID if @ Disable IRQ and FIQ interrupts @@ -97,270 +89,96 @@ _tx_thread_smp_protect: CPSID i @ Disable IRQ interrupts #endif @ +@ /* Pickup the CPU ID. */ +@ + MRC p15, 0, r2, c0, c0, 5 @ Read CPU ID register + AND r2, r2, #0x03 @ Mask off, leaving the CPU ID field +@ @ /* Do we already have protection? */ @ if (this_core == _tx_thread_smp_protection.tx_thread_smp_protect_core) @ { @ - MRC p15, 0, r1, c0, c0, 5 @ Read CPU ID register - AND r1, r1, #0x03 @ Mask off, leaving the CPU ID field - LDR r2, =_tx_thread_smp_protection @ Build address to protection structure - LDR r3, [r2, #8] @ Pickup the owning core - CMP r1, r3 @ Is it not this core? - BNE _protection_not_owned @ No, the protection is not already owned -@ -@ /* We already have protection. */ -@ -@ /* Increment the protection count. */ -@ _tx_thread_smp_protection.tx_thread_smp_protect_count++; + LDR r0, =_tx_thread_smp_protection @ Build address to protection structure + LDR r1, [r0, #8] @ Pickup the owning core + CMP r1, r2 @ Is it this core? + BEQ _owned @ Yes, the protection is already owned @ - LDR r3, [r2, #12] @ Pickup ownership count - ADD r3, r3, #1 @ Increment ownership count - STR r3, [r2, #12] @ Store ownership count - DMB - - B _return - -_protection_not_owned: +@ } @ @ /* Is the lock available? */ @ if (_tx_thread_smp_protection.tx_thread_smp_protect_in_force == 0) @ { @ - LDREX r3, [r2] @ Pickup the protection flag - CMP r3, #0 - BNE _start_waiting @ No, protection not available -@ -@ /* Is the list empty? */ -@ if (_tx_thread_smp_protect_wait_list_head == _tx_thread_smp_protect_wait_list_tail) -@ { -@ - LDR r3, =_tx_thread_smp_protect_wait_list_head - LDR r3, [r3] - LDR r4, =_tx_thread_smp_protect_wait_list_tail - LDR r4, [r4] - CMP r3, r4 - BNE _list_not_empty -@ -@ /* Try to get the lock. */ -@ if (write_exclusive(&_tx_thread_smp_protection.tx_thread_smp_protect_in_force, 1) == SUCCESS) -@ { -@ - MOV r3, #1 @ Build lock value - STREX r4, r3, [r2] @ Attempt to get the protection - CMP r4, #0 - BNE _start_waiting @ Did it fail? -@ -@ /* We got the lock! */ -@ _tx_thread_smp_protect_lock_got(); -@ - DMB @ Ensure write to protection finishes - _tx_thread_smp_protect_lock_got @ Call the lock got function - - B _return - -_list_not_empty: -@ -@ /* Are we at the front of the list? */ -@ if (this_core == _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_head]) -@ { -@ - LDR r3, =_tx_thread_smp_protect_wait_list_head @ Get the address of the head - LDR r3, [r3] @ Get the value of the head - LDR r4, =_tx_thread_smp_protect_wait_list @ Get the address of the list - LDR r4, [r4, r3, LSL #2] @ Get the value at the head index - - CMP r1, r4 - BNE _start_waiting -@ -@ /* Is the lock still available? */ -@ if (_tx_thread_smp_protection.tx_thread_smp_protect_in_force == 0) -@ { -@ - LDR r3, [r2, #0] @ Pickup the protection flag - CMP r3, #0 - BNE _start_waiting @ No, protection not available -@ -@ /* Get the lock. */ -@ _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 1; -@ - MOV r3, #1 @ Build lock value - STR r3, [r2, #0] @ Store lock value - DMB @ -@ -@ /* Got the lock. */ -@ _tx_thread_smp_protect_lock_got(); -@ - _tx_thread_smp_protect_lock_got -@ -@ /* Remove this core from the wait list. */ -@ _tx_thread_smp_protect_remove_from_front_of_list(); -@ - _tx_thread_smp_protect_remove_from_front_of_list - - B _return - -_start_waiting: -@ -@ /* For one reason or another, we didn't get the lock. */ -@ -@ /* Increment wait count. */ -@ _tx_thread_smp_protect_wait_counts[this_core]++; -@ - LDR r3, =_tx_thread_smp_protect_wait_counts @ Load wait list counts - LDR r4, [r3, r1, LSL #2] @ Load waiting value for this core - ADD r4, r4, #1 @ Increment wait value - STR r4, [r3, r1, LSL #2] @ Store new wait value -@ -@ /* Have we not added ourselves to the list yet? */ -@ if (_tx_thread_smp_protect_wait_counts[this_core] == 1) -@ { -@ - CMP r4, #1 - BNE _already_in_list0 @ Is this core already waiting? -@ -@ /* Add ourselves to the list. */ -@ _tx_thread_smp_protect_wait_list_add(this_core); -@ - _tx_thread_smp_protect_wait_list_add @ Call macro to add ourselves to the list + LDREX r1, [r0] @ Pickup the protection flag + CMP r1, #0 @ Is it available? + BEQ _get_protection @ Yes, attempt to get the protection @ @ } @ -_already_in_list0: -@ -@ /* Restore interrupts. */ +@ /* The protection is held elsewhere. Restore interrupts so this core can be +@ preempted while it waits, then try the whole sequence again. */ @ - MSR CPSR_c, r0 @ Restore CPSR + MSR CPSR_c, r3 @ Restore CPSR #ifdef TX_ENABLE_WFE WFE @ Go into standby #endif -@ -@ /* We do this until we have the lock. */ -@ while (1) -@ { -@ -_try_to_get_lock: -@ -@ /* Disable interrupts so we don't get preempted. */ -@ -#ifdef TX_ENABLE_FIQ_SUPPORT - CPSID if @ Disable IRQ and FIQ interrupts -#else - CPSID i @ Disable IRQ interrupts -#endif + B _tx_thread_smp_protect @ On waking, restart the protection attempt - MRC p15, 0, r1, c0, c0, 5 @ Read CPU ID register - AND r1, r1, #0x03 @ Mask off, leaving the CPU ID field +_get_protection: @ -@ /* Do we already have protection? */ -@ if (this_core == _tx_thread_smp_protection.tx_thread_smp_protect_core) +@ /* Try to get the lock. */ +@ if (write_exclusive(&_tx_thread_smp_protection.tx_thread_smp_protect_in_force, 1) == SUCCESS) @ { @ - LDR r3, [r2, #8] @ Pickup the owning core - CMP r3, r1 @ Is it this core? - BEQ _got_lock_after_waiting @ Yes, the protection is already owned. This means - @ an ISR preempted us and got protection + MOV r1, #1 @ Build lock value + STREX r2, r1, [r0] @ Attempt to get the protection + CMP r2, #0 @ Check whether the store succeeded (0 = success) + BEQ _got_protection @ Yes, we have the protection @ @ } @ -@ /* Are we at the front of the list? */ -@ if (this_core == _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_head]) -@ { +@ /* Another core beat us to it. Restore interrupts and try again. */ @ - LDR r3, =_tx_thread_smp_protect_wait_list_head @ Get the address of the head - LDR r3, [r3] @ Get the value of the head - LDR r4, =_tx_thread_smp_protect_wait_list @ Get the address of the list - LDR r4, [r4, r3, LSL #2] @ Get the value at the head index + MSR CPSR_c, r3 @ Restore CPSR + B _tx_thread_smp_protect @ Try the whole process again - CMP r1, r4 - BNE _did_not_get_lock -@ -@ /* Is the lock still available? */ -@ if (_tx_thread_smp_protection.tx_thread_smp_protect_in_force == 0) -@ { -@ - LDR r3, [r2, #0] @ Pickup the protection flag - CMP r3, #0 - BNE _did_not_get_lock @ No, protection not available -@ -@ /* Get the lock. */ -@ _tx_thread_smp_protection.tx_thread_smp_protect_in_force = 1; -@ - MOV r3, #1 @ Build lock value - STR r3, [r2, #0] @ Store lock value - DMB @ +_got_protection: @ -@ /* Got the lock. */ -@ _tx_thread_smp_protect_lock_got(); +@ /* Got the lock. Record the owning core. */ +@ _tx_thread_smp_protection.tx_thread_smp_protect_core = this_core; @ - _tx_thread_smp_protect_lock_got -@ -@ /* Remove this core from the wait list. */ -@ _tx_thread_smp_protect_remove_from_front_of_list(); -@ - _tx_thread_smp_protect_remove_from_front_of_list - - B _got_lock_after_waiting + DMB @ Ensure the protection write completes before it is used + MRC p15, 0, r2, c0, c0, 5 @ Read CPU ID register + AND r2, r2, #0x03 @ Mask off, leaving the CPU ID field + STR r2, [r0, #8] @ Save the owning core -_did_not_get_lock: -@ -@ /* For one reason or another, we didn't get the lock. */ -@ -@ /* Were we removed from the list? This can happen if we're a thread -@ and we got preempted. */ -@ if (_tx_thread_smp_protect_wait_counts[this_core] == 0) -@ { -@ - LDR r3, =_tx_thread_smp_protect_wait_counts @ Load wait list counts - LDR r4, [r3, r1, LSL #2] @ Load waiting value for this core - CMP r4, #0 - BNE _already_in_list1 @ Is this core already in the list? -@ -@ /* Add ourselves to the list. */ -@ _tx_thread_smp_protect_wait_list_add(this_core); -@ - _tx_thread_smp_protect_wait_list_add @ Call macro to add ourselves to the list -@ -@ /* Our waiting count was also reset when we were preempted. Increment it again. */ -@ _tx_thread_smp_protect_wait_counts[this_core]++; -@ - LDR r3, =_tx_thread_smp_protect_wait_counts @ Load wait list counts - LDR r4, [r3, r1, LSL #2] @ Load waiting value for this core - ADD r4, r4, #1 @ Increment wait value - STR r4, [r3, r1, LSL #2] @ Store new wait value value -@ -@ } -@ -_already_in_list1: -@ -@ /* Restore interrupts and try again. */ -@ - MSR CPSR_c, r0 @ Restore CPSR -#ifdef TX_ENABLE_WFE - WFE @ Go into standby +#ifdef TX_MPCORE_DEBUG_ENABLE + LSL r2, r2, #2 @ Build offset to array indexes + LDR r1, =_tx_thread_current_ptr @ Pickup start of the current thread array + ADD r1, r1, r2 @ Build index into the current thread array + LDR r2, [r1] @ Pickup current thread for this core + STR r2, [r0, #4] @ Save current thread pointer + STR LR, [r0, #16] @ Save caller's return address + STR r3, [r0, #20] @ Save CPSR #endif - B _try_to_get_lock @ On waking, restart the protection attempt -_got_lock_after_waiting: +_owned: @ -@ /* We're no longer waiting. */ -@ _tx_thread_smp_protect_wait_counts[this_core]--; +@ /* Increment the protection count. */ +@ _tx_thread_smp_protection.tx_thread_smp_protect_count++; @ - LDR r3, =_tx_thread_smp_protect_wait_counts @ Load waiting list - LDR r4, [r3, r1, LSL #2] @ Load current wait value - SUB r4, r4, #1 @ Decrement wait value - STR r4, [r3, r1, LSL #2] @ Store new wait value value + LDR r1, [r0, #12] @ Pickup ownership count + ADD r1, r1, #1 @ Increment ownership count + STR r1, [r0, #12] @ Store new ownership count + DMB @ + MOV r0, r3 @ Return the previous CPSR @ -@ /* Restore link register and return. */ +@} @ -_return: - - POP {r4-r6} @ Restore registers - #ifdef __THUMB_INTERWORK BX lr @ Return to caller #else MOV pc, lr @ Return to caller #endif - diff --git a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_smp_protection_wait_list_macros.h b/ports_smp/cortex_a9_smp/gnu/src/tx_thread_smp_protection_wait_list_macros.h deleted file mode 100644 index f1ad80e88..000000000 --- a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_smp_protection_wait_list_macros.h +++ /dev/null @@ -1,309 +0,0 @@ -@/*************************************************************************** -@ * Copyright (c) 2024 Microsoft Corporation -@ * -@ * This program and the accompanying materials are made available under the -@ * terms of the MIT License which is available at -@ * https://opensource.org/licenses/MIT. -@ * -@ * SPDX-License-Identifier: MIT -@ **************************************************************************/ -@ -@ -@/**************************************************************************/ -@/**************************************************************************/ -@/** */ -@/** ThreadX Component */ -@/** */ -@/** Thread - Low Level SMP Support */ -@/** */ -@/**************************************************************************/ -@/**************************************************************************/ - - .macro _tx_thread_smp_protect_lock_got -@ -@ /* Set the currently owned core. */ -@ _tx_thread_smp_protection.tx_thread_smp_protect_core = this_core; -@ - STR r1, [r2, #8] @ Store this core -@ -@ /* Increment the protection count. */ -@ _tx_thread_smp_protection.tx_thread_smp_protect_count++; -@ - LDR r3, [r2, #12] @ Pickup ownership count - ADD r3, r3, #1 @ Increment ownership count - STR r3, [r2, #12] @ Store ownership count - DMB - -#ifdef TX_MPCORE_DEBUG_ENABLE - LSL r3, r1, #2 @ Build offset to array indexes - LDR r4, =_tx_thread_current_ptr @ Pickup start of the current thread array - ADD r4, r3, r4 @ Build index into the current thread array - LDR r3, [r4] @ Pickup current thread for this core - STR r3, [r2, #4] @ Save current thread pointer - STR LR, [r2, #16] @ Save caller's return address - STR r0, [r2, #20] @ Save CPSR -#endif - - .endm - - .macro _tx_thread_smp_protect_remove_from_front_of_list -@ -@ /* Remove ourselves from the list. */ -@ _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_head++] = 0xFFFFFFFF; -@ - MOV r3, #0xFFFFFFFF @ Build the invalid core value - LDR r4, =_tx_thread_smp_protect_wait_list_head @ Get the address of the head - LDR r5, [r4] @ Get the value of the head - LDR r6, =_tx_thread_smp_protect_wait_list @ Get the address of the list - STR r3, [r6, r5, LSL #2] @ Store the invalid core value - ADD r5, r5, #1 @ Increment the head -@ -@ /* Did we wrap? */ -@ if (_tx_thread_smp_protect_wait_list_head == TX_THREAD_SMP_MAX_CORES + 1) -@ { -@ - LDR r3, =_tx_thread_smp_protect_wait_list_size @ Load address of core list size - LDR r3, [r3] @ Load the max cores value - CMP r5, r3 @ Compare the head to it - BNE _store_new_head\@ @ Are we at the max? -@ -@ _tx_thread_smp_protect_wait_list_head = 0; -@ - EOR r5, r5, r5 @ We're at the max. Set it to zero -@ -@ } -@ -_store_new_head\@: - - STR r5, [r4] @ Store the new head -@ -@ /* We have the lock! */ -@ return; -@ - .endm - - - .macro _tx_thread_smp_protect_wait_list_lock_get -@VOID _tx_thread_smp_protect_wait_list_lock_get() -@{ -@ /* We do this until we have the lock. */ -@ while (1) -@ { -@ -_tx_thread_smp_protect_wait_list_lock_get__try_to_get_lock\@: -@ -@ /* Is the list lock available? */ -@ _tx_thread_smp_protect_wait_list_lock_protect_in_force = load_exclusive(&_tx_thread_smp_protect_wait_list_lock_protect_in_force); -@ - LDR r1, =_tx_thread_smp_protect_wait_list_lock_protect_in_force - LDREX r2, [r1] @ Pickup the protection flag -@ -@ if (protect_in_force == 0) -@ { -@ - CMP r2, #0 - BNE _tx_thread_smp_protect_wait_list_lock_get__try_to_get_lock\@ @ No, protection not available -@ -@ /* Try to get the list. */ -@ int status = store_exclusive(&_tx_thread_smp_protect_wait_list_lock_protect_in_force, 1); -@ - MOV r2, #1 @ Build lock value - STREX r3, r2, [r1] @ Attempt to get the protection -@ -@ if (status == SUCCESS) -@ - CMP r3, #0 - BNE _tx_thread_smp_protect_wait_list_lock_get__try_to_get_lock\@ @ Did it fail? If so, try again. -@ -@ /* We have the lock! */ -@ return; -@ - .endm - - - .macro _tx_thread_smp_protect_wait_list_add -@VOID _tx_thread_smp_protect_wait_list_add(UINT new_core) -@{ -@ -@ /* We're about to modify the list, so get the list lock. */ -@ _tx_thread_smp_protect_wait_list_lock_get(); -@ - PUSH {r1-r2} - - _tx_thread_smp_protect_wait_list_lock_get - - POP {r1-r2} -@ -@ /* Add this core. */ -@ _tx_thread_smp_protect_wait_list[_tx_thread_smp_protect_wait_list_tail++] = new_core; -@ - LDR r3, =_tx_thread_smp_protect_wait_list_tail @ Get the address of the tail - LDR r4, [r3] @ Get the value of tail - LDR r5, =_tx_thread_smp_protect_wait_list @ Get the address of the list - STR r1, [r5, r4, LSL #2] @ Store the new core value - ADD r4, r4, #1 @ Increment the tail -@ -@ /* Did we wrap? */ -@ if (_tx_thread_smp_protect_wait_list_tail == _tx_thread_smp_protect_wait_list_size) -@ { -@ - LDR r5, =_tx_thread_smp_protect_wait_list_size @ Load max cores address - LDR r5, [r5] @ Load max cores value - CMP r4, r5 @ Compare max cores to tail - BNE _tx_thread_smp_protect_wait_list_add__no_wrap\@ @ Did we wrap? -@ -@ _tx_thread_smp_protect_wait_list_tail = 0; -@ - MOV r4, #0 -@ -@ } -@ -_tx_thread_smp_protect_wait_list_add__no_wrap\@: - - STR r4, [r3] @ Store the new tail value. -@ -@ /* Release the list lock. */ -@ _tx_thread_smp_protect_wait_list_lock_protect_in_force = 0; -@ - MOV r3, #0 @ Build lock value - LDR r4, =_tx_thread_smp_protect_wait_list_lock_protect_in_force - STR r3, [r4] @ Store the new value - - .endm - - - .macro _tx_thread_smp_protect_wait_list_remove -@VOID _tx_thread_smp_protect_wait_list_remove(UINT core) -@{ -@ -@ /* Get the core index. */ -@ UINT core_index; -@ for (core_index = 0;; core_index++) -@ - EOR r1, r1, r1 @ Clear for 'core_index' - LDR r2, =_tx_thread_smp_protect_wait_list @ Get the address of the list -@ -@ { -@ -_tx_thread_smp_protect_wait_list_remove__check_cur_core\@: -@ -@ /* Is this the core? */ -@ if (_tx_thread_smp_protect_wait_list[core_index] == core) -@ { -@ break; -@ - LDR r3, [r2, r1, LSL #2] @ Get the value at the current index - CMP r3, r0 @ Did we find the core? - BEQ _tx_thread_smp_protect_wait_list_remove__found_core\@ -@ -@ } -@ - ADD r1, r1, #1 @ Increment cur index - B _tx_thread_smp_protect_wait_list_remove__check_cur_core\@ @ Restart the loop -@ -@ } -@ -_tx_thread_smp_protect_wait_list_remove__found_core\@: -@ -@ /* We're about to modify the list. Get the lock. We need the lock because another -@ core could be simultaneously adding (a core is simultaneously trying to get -@ the inter-core lock) or removing (a core is simultaneously being preempted, -@ like what is currently happening). */ -@ _tx_thread_smp_protect_wait_list_lock_get(); -@ - PUSH {r1} - - _tx_thread_smp_protect_wait_list_lock_get - - POP {r1} -@ -@ /* We remove by shifting. */ -@ while (core_index != _tx_thread_smp_protect_wait_list_tail) -@ { -@ -_tx_thread_smp_protect_wait_list_remove__compare_index_to_tail\@: - - LDR r2, =_tx_thread_smp_protect_wait_list_tail @ Load tail address - LDR r2, [r2] @ Load tail value - CMP r1, r2 @ Compare cur index and tail - BEQ _tx_thread_smp_protect_wait_list_remove__removed\@ -@ -@ UINT next_index = core_index + 1; -@ - MOV r2, r1 @ Move current index to next index register - ADD r2, r2, #1 @ Add 1 -@ -@ if (next_index == _tx_thread_smp_protect_wait_list_size) -@ { -@ - LDR r3, =_tx_thread_smp_protect_wait_list_size - LDR r3, [r3] - CMP r2, r3 - BNE _tx_thread_smp_protect_wait_list_remove__next_index_no_wrap\@ -@ -@ next_index = 0; -@ - MOV r2, #0 -@ -@ } -@ -_tx_thread_smp_protect_wait_list_remove__next_index_no_wrap\@: -@ -@ list_cores[core_index] = list_cores[next_index]; -@ - LDR r0, =_tx_thread_smp_protect_wait_list @ Get the address of the list - LDR r3, [r0, r2, LSL #2] @ Get the value at the next index - STR r3, [r0, r1, LSL #2] @ Store the value at the current index -@ -@ core_index = next_index; -@ - MOV r1, r2 - - B _tx_thread_smp_protect_wait_list_remove__compare_index_to_tail\@ -@ -@ } -@ -_tx_thread_smp_protect_wait_list_remove__removed\@: -@ -@ /* Now update the tail. */ -@ if (_tx_thread_smp_protect_wait_list_tail == 0) -@ { -@ - LDR r0, =_tx_thread_smp_protect_wait_list_tail @ Load tail address - LDR r1, [r0] @ Load tail value - CMP r1, #0 - BNE _tx_thread_smp_protect_wait_list_remove__tail_not_zero\@ -@ -@ _tx_thread_smp_protect_wait_list_tail = _tx_thread_smp_protect_wait_list_size; -@ - LDR r2, =_tx_thread_smp_protect_wait_list_size - LDR r1, [r2] -@ -@ } -@ -_tx_thread_smp_protect_wait_list_remove__tail_not_zero\@: -@ -@ _tx_thread_smp_protect_wait_list_tail--; -@ - SUB r1, r1, #1 - STR r1, [r0] @ Store new tail value -@ -@ /* Release the list lock. */ -@ _tx_thread_smp_protect_wait_list_lock_protect_in_force = 0; -@ - MOV r0, #0 @ Build lock value - LDR r1, =_tx_thread_smp_protect_wait_list_lock_protect_in_force @ Load lock address - STR r0, [r1] @ Store the new value -@ -@ /* We're no longer waiting. Note that this should be zero since, again, -@ this function is only called when a thread preemption is occurring. */ -@ _tx_thread_smp_protect_wait_counts[core]--; -@ - MRC p15, 0, r0, c0, c0, 5 @ Read CPU ID register - AND r0, r0, #0x03 @ Mask off, leaving the CPU ID field - LDR r1, =_tx_thread_smp_protect_wait_counts @ Load wait list counts - LDR r2, [r1, r0, LSL #2] @ Load waiting value - SUB r2, r2, #1 @ Subtract 1 - STR r2, [r1, r0, LSL #2] @ Store new waiting value - .endm - diff --git a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_smp_unprotect.S b/ports_smp/cortex_a9_smp/gnu/src/tx_thread_smp_unprotect.S index a76677ec6..a9baf0c80 100644 --- a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_smp_unprotect.S +++ b/ports_smp/cortex_a9_smp/gnu/src/tx_thread_smp_unprotect.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * 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 @@ -7,6 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ +@ Some portions generated by Copilot (Opus 5). @ @ @/**************************************************************************/ @@ -33,7 +35,6 @@ .global _tx_thread_current_ptr .global _tx_thread_smp_protection .global _tx_thread_preempt_disable - .global _tx_thread_smp_protect_wait_counts .arm .text @@ -105,10 +106,6 @@ _tx_thread_smp_unprotect: CMP r3, #0 @ Is the preempt disable flag set? BNE _still_protected @ Yes, skip the protection release - LDR r2,=_tx_thread_smp_protect_wait_counts @ Build build address of wait counts - LDR r3, [r2, r1, LSL #2] @ Pickup wait list value - CMP r3, #0 @ Are any entities on this core waiting? - BNE _still_protected @ Yes, skip the protection release LDR r2,=_tx_thread_smp_protection @ Build address of protection structure MOV r3, #0xFFFFFFFF @ Build invalid value From 9a0383838166cacd130210248905ac9b5445374e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Wed, 9 Sep 2026 10:56:28 -0400 Subject: [PATCH 111/181] Stopped the test runners from reporting an incomplete build as test failures (#709) The cmake test runners drove Ninja with its default keep-going of 1, so the first failing target ended the build. Every target scheduled after it was simply absent, and ctest reports a missing binary as a failing test. A single link error therefore produced a failure count that moved with build scheduling order rather than with the code. Measured on the RISC-V64 regression suite, where two targets genuinely cannot link: before 79 of 95 test binaries built after 93 of 95 test binaries built Fourteen perfectly good binaries were being skipped and counted as failures. Passing -k 0 lets Ninja finish everything it can; the build still exits non-zero when a target fails. Three related problems in the same paths are fixed with it. A failing configuration used to abort the loop over configurations, so under set -e the ones after it went unbuilt or untested. The build loops and the serial test loops now accumulate status and return it at the end, which is what the parallel test branch already did with wait, and what cmake_bootstrap.sh already documented for ctest. Capturing that status removes the set -e protection inside the functions, so two latent faults become reachable and are closed here. A failed pushd would have let ctest run in the source tree, where it finds no tests and reports success; the pushd is now guarded. And ctest's status was discarded by the popd that follows it, so a configuration with failing tests returned 0 and was reported as a pass; the status is now carried past the popd and the summary steps. Verified on the RISC-V32 suite, which has two genuine failures in each of its five configurations. Both the serial and the parallel branch now test all five and exit 8, where the serial branch previously stopped after the first configuration. The tx and smp runners are symlinks to scripts/cmake_bootstrap.sh, so they are covered by the one change there. Assisted-by: Claude Code (Opus 5) --- scripts/cmake_bootstrap.sh | 18 +++++++++++++++--- test/freertos/cmake/run.sh | 35 +++++++++++++++++++++++++++++------ test/posix/cmake/run.sh | 33 ++++++++++++++++++++++++++++----- test/tx/cmake/riscv/run.sh | 33 ++++++++++++++++++++++++++++----- 4 files changed, 100 insertions(+), 19 deletions(-) diff --git a/scripts/cmake_bootstrap.sh b/scripts/cmake_bootstrap.sh index eb9bee1b4..855a79009 100755 --- a/scripts/cmake_bootstrap.sh +++ b/scripts/cmake_bootstrap.sh @@ -61,7 +61,11 @@ function generate() { } function build() { - cmake --build build/$1 + # -k 0 keeps Ninja going after a target fails, so one broken target no + # longer decides whether the targets after it exist. ctest reports a + # missing binary as a failing test, which turned a single link error into + # a failure count that varied with build scheduling order. + cmake --build build/$1 -- -k 0 } function build_libs() { @@ -74,7 +78,10 @@ function build_libs() { } function test() { - pushd build/$1 + # Guard the pushd: with the caller capturing this function's status, set -e + # no longer aborts here, so a missing build directory would otherwise let + # ctest run in the source tree and report "no tests" as success. + pushd build/$1 || return 1 [ -z "${CTEST_PARALLEL_LEVEL}" ] && parallel="-j$2" if [ -z "${CTEST_REPEAT_FAIL}" ]; then @@ -198,11 +205,16 @@ if [ "$command" == "build" ]; then echo "" done + # A failing configuration must not stop the ones after it: under set -e + # the loop would abort and leave them unbuilt, which then reads as a wall + # of missing-binary test failures. The status is accumulated and returned. + build_status=0 for item in $builds; do echo "Building $item" - build $item + build $item || build_status=$? echo "" done + [ $build_status -eq 0 ] || exit $build_status elif [ "$command" == "test" ]; then cores=$(nproc) if [ -z "${CTEST_PARALLEL_LEVEL}" ]; diff --git a/test/freertos/cmake/run.sh b/test/freertos/cmake/run.sh index bb1c70f88..896a5c37a 100755 --- a/test/freertos/cmake/run.sh +++ b/test/freertos/cmake/run.sh @@ -44,11 +44,18 @@ function generate() { } function build() { - cmake --build build/$1 + # -k 0 keeps Ninja going after a target fails, so one broken target no + # longer decides whether the targets after it exist. ctest reports a + # missing binary as a failing test, which turned a single link error into + # a failure count that varied with build scheduling order. + cmake --build build/$1 -- -k 0 } function test() { - pushd build/$1 + # Guard the pushd: with the caller capturing this function's status, set -e + # no longer aborts here, so a missing build directory would otherwise let + # ctest run in the source tree and report "no tests" as success. + pushd build/$1 || return 1 [ -z "${CTEST_PARALLEL_LEVEL}" ] && parallel="-j$2" if [ -z "${CTEST_REPEAT_FAIL}" ]; then @@ -56,10 +63,17 @@ function test() { else repeat_fail=${CTEST_REPEAT_FAIL} fi - ctest $parallel --timeout 300 -O $1.txt -T test --no-compress-output --test-output-size-passed 4194304 --test-output-size-failed 4194304 --output-on-failure --repeat until-pass:${repeat_fail} --output-junit $1.xml + # ctest's status is captured and returned past the popd and the summary + # steps, which all succeed. Without this the function would return 0 and a + # failing configuration would be reported as a pass. + local status=0 + ctest $parallel --timeout 300 -O $1.txt -T test --no-compress-output --test-output-size-passed 4194304 --test-output-size-failed 4194304 --output-on-failure --repeat until-pass:${repeat_fail} --output-junit $1.xml || status=$? popd - grep -E "^(\s*[0-9]+|Total)" build/$1/$1.txt >build/$1.txt + # Tolerated: this is a summary for humans, and a ctest that died early + # enough to leave no matching line must not mask its own status. + grep -E "^(\s*[0-9]+|Total)" build/$1/$1.txt >build/$1.txt || true sed -i "s/\x1B\[[0-9;]*[JKmsu]//g" build/$1.txt + return $status } cd $(dirname $0) @@ -92,21 +106,30 @@ if [ "$command" == "build" ]; then echo "" done + # A failing configuration must not stop the ones after it: under set -e + # the loop would abort and leave them unbuilt, which then reads as a wall + # of missing-binary test failures. The status is accumulated and returned. + build_status=0 for item in $builds; do echo "Building $item" - build $item + build $item || build_status=$? echo "" done + [ $build_status -eq 0 ] || exit $build_status elif [ "$command" == "test" ]; then cores=$(nproc) if [ -z "${CTEST_PARALLEL_LEVEL}" ]; then parallel_jobs=$(($cores + 2)) fi + # ctest's status is accumulated rather than allowed to abort the loop, so + # a failing configuration does not leave the ones after it untested. + exit_code=0 for item in $builds; do echo "Testing $item" - test $item $parallel_jobs + test $item $parallel_jobs || exit_code=$? done + exit $exit_code else help fi diff --git a/test/posix/cmake/run.sh b/test/posix/cmake/run.sh index aa65f7a73..76536cf73 100755 --- a/test/posix/cmake/run.sh +++ b/test/posix/cmake/run.sh @@ -65,7 +65,11 @@ function generate() { function build() { local arch=$1 local build=$2 - cmake --build "build/${arch}_${build}" + # -k 0 keeps Ninja going after a target fails, so one broken target no + # longer decides whether the targets after it exist. ctest reports a + # missing binary as a failing test, which turned a single link error into + # a failure count that varied with build scheduling order. + cmake --build "build/${arch}_${build}" -- -k 0 } function run_test() { @@ -73,13 +77,20 @@ function run_test() { local build=$2 local parallel_jobs=$3 - pushd "build/${arch}_${build}" + # Guard the pushd: with the caller capturing this function's status, set -e + # no longer aborts here, so a missing build directory would otherwise let + # ctest run in the source tree and report "no tests" as success. + pushd "build/${arch}_${build}" || return 1 [ -z "${CTEST_PARALLEL_LEVEL}" ] && parallel="-j${parallel_jobs}" if [ -z "${CTEST_REPEAT_FAIL}" ]; then repeat_fail=2 else repeat_fail=${CTEST_REPEAT_FAIL} fi + # ctest's status is captured and returned past the popd and the summary + # steps, which all succeed. Without this the function would return 0 and a + # failing configuration would be reported as a pass. + local status=0 ctest $parallel --timeout 1000 \ -O "${arch}_${build}.txt" \ -T test --no-compress-output \ @@ -87,8 +98,9 @@ function run_test() { --test-output-size-failed 4194304 \ --output-on-failure \ --repeat until-pass:${repeat_fail} \ - --output-junit "${arch}_${build}.xml" + --output-junit "${arch}_${build}.xml" || status=$? popd + return $status } # Determine repo root and script directory @@ -133,11 +145,16 @@ if [ "$command" == "build" ]; then echo "" done + # A failing configuration must not stop the ones after it: under set -e + # the loop would abort and leave them unbuilt, which then reads as a wall + # of missing-binary test failures. The status is accumulated and returned. + build_status=0 for item in $builds; do echo "Building ${arch} ${item}" - build "$arch" "$item" + build "$arch" "$item" || build_status=$? echo "" done + [ $build_status -eq 0 ] || exit $build_status elif [ "$command" == "test" ]; then cores=$(nproc) if [ -z "${CTEST_PARALLEL_LEVEL}" ]; then @@ -156,10 +173,16 @@ elif [ "$command" == "test" ]; then done exit $exit_code else + # ctest's status is accumulated rather than allowed to abort the loop. + # set -e would otherwise stop at the first failing configuration and + # leave every configuration after it untested. This mirrors what the + # parallel branch above already does with wait. + exit_code=0 for item in $builds; do echo "Testing ${arch} ${item}" - run_test "$arch" "$item" "$parallel_jobs" + run_test "$arch" "$item" "$parallel_jobs" || exit_code=$? done + exit $exit_code fi else help diff --git a/test/tx/cmake/riscv/run.sh b/test/tx/cmake/riscv/run.sh index 3b0905e74..0e4fb7a11 100755 --- a/test/tx/cmake/riscv/run.sh +++ b/test/tx/cmake/riscv/run.sh @@ -61,7 +61,11 @@ function generate() { function build() { local arch=$1 local build=$2 - cmake --build "build/${arch}_${build}" + # -k 0 keeps Ninja going after a target fails, so one broken target no + # longer decides whether the targets after it exist. ctest reports a + # missing binary as a failing test, which turned a single link error into + # a failure count that varied with build scheduling order. + cmake --build "build/${arch}_${build}" -- -k 0 } function run_test() { @@ -69,13 +73,20 @@ function run_test() { local build=$2 local parallel_jobs=$3 - pushd "build/${arch}_${build}" + # Guard the pushd: with the caller capturing this function's status, set -e + # no longer aborts here, so a missing build directory would otherwise let + # ctest run in the source tree and report "no tests" as success. + pushd "build/${arch}_${build}" || return 1 [ -z "${CTEST_PARALLEL_LEVEL}" ] && parallel="-j${parallel_jobs}" if [ -z "${CTEST_REPEAT_FAIL}" ]; then repeat_fail=2 else repeat_fail=${CTEST_REPEAT_FAIL} fi + # ctest's status is captured and returned past the popd. popd succeeds, so + # without this the function would return 0 and a failing configuration + # would be reported as a pass. + local status=0 ctest $parallel --timeout 1000 \ -O "${arch}_${build}.txt" \ -T test --no-compress-output \ @@ -83,8 +94,9 @@ function run_test() { --test-output-size-failed 4194304 \ --output-on-failure \ --repeat until-pass:${repeat_fail} \ - --output-junit "${arch}_${build}.xml" + --output-junit "${arch}_${build}.xml" || status=$? popd + return $status } # Determine repo root and script directory @@ -129,11 +141,16 @@ if [ "$command" == "build" ]; then echo "" done + # A failing configuration must not stop the ones after it: under set -e + # the loop would abort and leave them unbuilt, which then reads as a wall + # of missing-binary test failures. The status is accumulated and returned. + build_status=0 for item in $builds; do echo "Building ${arch} ${item}" - build "$arch" "$item" + build "$arch" "$item" || build_status=$? echo "" done + [ $build_status -eq 0 ] || exit $build_status elif [ "$command" == "test" ]; then cores=$(nproc) if [ -z "${CTEST_PARALLEL_LEVEL}" ]; then @@ -152,10 +169,16 @@ elif [ "$command" == "test" ]; then done exit $exit_code else + # ctest's status is accumulated rather than allowed to abort the loop. + # set -e would otherwise stop at the first failing configuration and + # leave every configuration after it untested. This mirrors what the + # parallel branch above already does with wait. + exit_code=0 for item in $builds; do echo "Testing ${arch} ${item}" - run_test "$arch" "$item" "$parallel_jobs" + run_test "$arch" "$item" "$parallel_jobs" || exit_code=$? done + exit $exit_code fi else help From 146d57b2351bc1154bf1ccdacf657eb1aeb4182d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Wed, 9 Sep 2026 10:56:57 -0400 Subject: [PATCH 112/181] Fixed the RISC-V64 trap frame size mismatch in the regression test BSP (#708) The RISC-V64 port moved its interrupt frame to 528 bytes (65 slots plus 8 bytes of padding, so sp stays 16-byte aligned at a call) and published the size as TX_RISCV_TRAP_FRAME_SIZE. The port sources were converted to use it, but the shared regression test BSP was not: its trap_entry still allocated a hardcoded 65 * REGBYTES, or 520 bytes. Every interrupt therefore unwound 8 bytes more than it allocated: trap_entry: addi sp,sp,-520 _tx_thread_context_restore: addi sp,sp,528 On the RISC-V64 regression suite that left 24 of 95 tests failing in the default configuration, typically as an illegal instruction once execution reached a corrupted frame. The example BSP under the port directory was converted with the port and was unaffected, which is why the functional QEMU test kept passing. The test BSP now takes both frame sizes from the port it is linked against, so the two cannot drift apart again. A port that publishes no contract keeps the historical layout, so the RISC-V32 side is unchanged until its own port publishes one. TX_RISCV_TRAP_CALL_FRAME_SIZE is restored to the RISC-V64 tx_port.h. It was removed as unused when the frame sizes were introduced, but it is part of the same contract: it is the space a trap entry reserves around a call into C, and the psABI requires 16 bytes there rather than one register slot. Verified on QEMU with every linkable test built, comparing against the commit before the port change: before the port change 2 failures out of 95 (both unlinkable) current dev 24 failures out of 95 with this change 2 failures out of 95 (both unlinkable) The two remaining failures predate all of this: newlib pulls _impure_ptr out of R_RISCV_HI20 range for time(), so those two binaries do not link. RISC-V32 is unchanged at 2 failures across all five configurations. Assisted-by: Claude Code (Opus 5) --- ports/risc-v64/gnu/inc/tx_port.h | 5 +++ .../cmake/riscv/bsp/tx_initialize_low_level.S | 33 +++++++++++++++---- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/ports/risc-v64/gnu/inc/tx_port.h b/ports/risc-v64/gnu/inc/tx_port.h index 0e31cc426..ad71694be 100644 --- a/ports/risc-v64/gnu/inc/tx_port.h +++ b/ports/risc-v64/gnu/inc/tx_port.h @@ -84,6 +84,11 @@ #define TX_RISCV_TRAP_FRAME_SIZE 256 #endif +/* Bytes a trap entry reserves around a call into C. The RISC-V psABI + requires sp to stay 16-byte aligned at a call boundary, so this is 16 + rather than one register slot. */ +#define TX_RISCV_TRAP_CALL_FRAME_SIZE 16 + #if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) #define TX_RISCV_SOL_FRAME_SIZE 240 diff --git a/test/tx/cmake/riscv/bsp/tx_initialize_low_level.S b/test/tx/cmake/riscv/bsp/tx_initialize_low_level.S index 8d474d66b..327946bb0 100644 --- a/test/tx/cmake/riscv/bsp/tx_initialize_low_level.S +++ b/test/tx/cmake/riscv/bsp/tx_initialize_low_level.S @@ -1,5 +1,6 @@ /*************************************************************************** * Copyright (c) 2026 10xEngineers + * 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 @@ -8,10 +9,13 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Claude Code (Opus 5). + /* Trap entry and low-level init for RISC-V QEMU virt regression tests. Supports both RV32 and RV64 via __riscv_xlen conditionals. */ #include "csr.h" +#include "tx_port.h" #if __riscv_xlen == 64 #define STORE sd @@ -33,13 +37,28 @@ .extern trap_handler .extern _tx_thread_context_restore -trap_entry: +/* Take the interrupt frame size from the port that this BSP is linked + against, so the two can never disagree. A port that publishes no + contract keeps the historical layout. */ +#ifndef TX_RISCV_TRAP_FRAME_SIZE #if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - addi sp, sp, -(65 * REGBYTES) +#define TX_RISCV_TRAP_FRAME_SIZE (65 * REGBYTES) #else - addi sp, sp, -(32 * REGBYTES) +#define TX_RISCV_TRAP_FRAME_SIZE (32 * REGBYTES) +#endif +#endif + +/* The RISC-V psABI requires sp to be 16-byte aligned at a call. */ +#ifndef TX_RISCV_TRAP_CALL_FRAME_SIZE +#define TX_RISCV_TRAP_CALL_FRAME_SIZE 16 #endif + .equ TX_TRAP_FRAME_SIZE, TX_RISCV_TRAP_FRAME_SIZE + .equ TX_TRAP_CALL_FRAME_SIZE, TX_RISCV_TRAP_CALL_FRAME_SIZE + +trap_entry: + addi sp, sp, -TX_TRAP_FRAME_SIZE + STORE x1, (28 * REGBYTES)(sp) call _tx_thread_context_save @@ -47,11 +66,11 @@ trap_entry: csrr a0, mcause csrr a1, mepc csrr a2, mtval - addi sp, sp, -REGBYTES + addi sp, sp, -TX_TRAP_CALL_FRAME_SIZE STORE ra, 0(sp) call trap_handler LOAD ra, 0(sp) - addi sp, sp, REGBYTES + addi sp, sp, TX_TRAP_CALL_FRAME_SIZE call _tx_thread_context_restore @@ -89,11 +108,11 @@ _tx_initialize_low_level: fscsr x0 #endif - addi sp, sp, -REGBYTES + addi sp, sp, -TX_TRAP_CALL_FRAME_SIZE STORE ra, 0(sp) call board_init LOAD ra, 0(sp) - addi sp, sp, REGBYTES + addi sp, sp, TX_TRAP_CALL_FRAME_SIZE la t0, trap_entry csrw mtvec, t0 From 3fc28d8979828b5f928650e78c3a134c562de579 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Wed, 9 Sep 2026 11:29:14 -0400 Subject: [PATCH 113/181] Allowed a BASEPRI-masked interrupt to wake the Cortex-M idle loop from WFI (#711) The idle loop in _tx_thread_schedule masks interrupts before re-reading _tx_thread_execute_ptr, so that an interrupt cannot make a thread ready between that read and the WFI and then be lost. With PRIMASK that is safe: the architecture excludes PRIMASK from the WFI wake-up condition, so the interrupt still wakes the processor and is taken as soon as the loop re-enables interrupts. BASEPRI is not excluded. When TX_PORT_USE_BASEPRI is defined, the mask written at the top of the loop is still in place at the WFI, so any interrupt at or below TX_PORT_BASEPRI fails to wake the processor at all. On a system where every interrupt is managed by ThreadX, that is every interrupt, and the processor stays in WFI or in the low power mode entered by tx_low_power_enter until something outside the mask happens. Set PRIMASK and clear BASEPRI for the duration of the WFI, then restore BASEPRI and clear PRIMASK. Interrupts remain masked across the whole window, so the original race is still closed, but the wake-up condition is now evaluated with BASEPRI clear and any enabled interrupt can end the wait. A pending interrupt is taken at the CPSIE i, or at the existing unmask further down the loop if it falls below TX_PORT_BASEPRI. The change is made in the ARMv7-M and ARMv8-M sources under ports_arch, including the module manager, and propagated to the generated ports with the copy scripts. The ghs and keil ports do not implement TX_PORT_USE_BASEPRI, and Cortex-M0/M0+/M23 have no BASEPRI register, so those ports are unaffected. Verified by assembling every patched GNU port for Cortex-M3, M4, M7, M33, M55 and M85, with and without TX_PORT_USE_BASEPRI, TX_LOW_POWER and TX_ENABLE_EXECUTION_CHANGE_NOTIFY, and by checking the disassembly of the idle loop. Fixes #279 Assisted-by: Copilot (Opus 5) --- ports/cortex_m3/ac5/src/tx_thread_schedule.s | 10 ++++++++++ ports/cortex_m3/ac6/src/tx_thread_schedule.S | 11 +++++++++++ ports/cortex_m3/gnu/src/tx_thread_schedule.S | 11 +++++++++++ ports/cortex_m3/iar/src/tx_thread_schedule.s | 10 ++++++++++ ports/cortex_m33/ac6/src/tx_thread_schedule.S | 11 +++++++++++ ports/cortex_m33/gnu/src/tx_thread_schedule.S | 11 +++++++++++ ports/cortex_m33/iar/src/tx_thread_schedule.s | 10 ++++++++++ ports/cortex_m4/ac5/src/tx_thread_schedule.s | 10 ++++++++++ ports/cortex_m4/ac6/src/tx_thread_schedule.S | 11 +++++++++++ ports/cortex_m4/gnu/src/tx_thread_schedule.S | 11 +++++++++++ ports/cortex_m4/iar/src/tx_thread_schedule.s | 10 ++++++++++ ports/cortex_m52/ac6/src/tx_thread_schedule.S | 11 +++++++++++ ports/cortex_m52/gnu/src/tx_thread_schedule.S | 11 +++++++++++ ports/cortex_m52/iar/src/tx_thread_schedule.s | 10 ++++++++++ ports/cortex_m55/ac6/src/tx_thread_schedule.S | 11 +++++++++++ ports/cortex_m55/gnu/src/tx_thread_schedule.S | 11 +++++++++++ ports/cortex_m55/iar/src/tx_thread_schedule.s | 10 ++++++++++ ports/cortex_m7/ac5/src/tx_thread_schedule.s | 10 ++++++++++ ports/cortex_m7/ac6/src/tx_thread_schedule.S | 11 +++++++++++ ports/cortex_m7/gnu/src/tx_thread_schedule.S | 11 +++++++++++ ports/cortex_m7/iar/src/tx_thread_schedule.s | 10 ++++++++++ ports/cortex_m85/ac6/src/tx_thread_schedule.S | 11 +++++++++++ ports/cortex_m85/gnu/src/tx_thread_schedule.S | 11 +++++++++++ ports/cortex_m85/iar/src/tx_thread_schedule.s | 10 ++++++++++ .../ARMv7-M/threadx/ac5/src/tx_thread_schedule.s | 10 ++++++++++ .../ARMv7-M/threadx/ac6/src/tx_thread_schedule.S | 11 +++++++++++ .../ARMv7-M/threadx/gnu/src/tx_thread_schedule.S | 11 +++++++++++ .../ARMv7-M/threadx/iar/src/tx_thread_schedule.s | 10 ++++++++++ .../ac5/module_manager/src/tx_thread_schedule.s | 10 ++++++++++ .../ac6/module_manager/src/tx_thread_schedule.S | 11 +++++++++++ .../gnu/module_manager/src/tx_thread_schedule.S | 11 +++++++++++ .../iar/module_manager/src/tx_thread_schedule.s | 10 ++++++++++ .../ARMv8-M/threadx/ac6/src/tx_thread_schedule.S | 11 +++++++++++ .../ARMv8-M/threadx/gnu/src/tx_thread_schedule.S | 11 +++++++++++ .../ARMv8-M/threadx/iar/src/tx_thread_schedule.s | 10 ++++++++++ .../ac5/module_manager/src/tx_thread_schedule.s | 10 ++++++++++ .../ac6/module_manager/src/tx_thread_schedule.S | 11 +++++++++++ .../gnu/module_manager/src/tx_thread_schedule.S | 11 +++++++++++ .../iar/module_manager/src/tx_thread_schedule.s | 10 ++++++++++ .../ac6/module_manager/src/tx_thread_schedule.S | 11 +++++++++++ .../gnu/module_manager/src/tx_thread_schedule.S | 11 +++++++++++ .../iar/module_manager/src/tx_thread_schedule.s | 10 ++++++++++ .../ac5/module_manager/src/tx_thread_schedule.s | 10 ++++++++++ .../ac6/module_manager/src/tx_thread_schedule.S | 11 +++++++++++ .../gnu/module_manager/src/tx_thread_schedule.S | 11 +++++++++++ .../iar/module_manager/src/tx_thread_schedule.s | 10 ++++++++++ .../ac5/module_manager/src/tx_thread_schedule.s | 10 ++++++++++ .../ac6/module_manager/src/tx_thread_schedule.S | 11 +++++++++++ .../gnu/module_manager/src/tx_thread_schedule.S | 11 +++++++++++ .../iar/module_manager/src/tx_thread_schedule.s | 10 ++++++++++ 50 files changed, 528 insertions(+) diff --git a/ports/cortex_m3/ac5/src/tx_thread_schedule.s b/ports/cortex_m3/ac5/src/tx_thread_schedule.s index 8a971d39c..d7ad0b72d 100644 --- a/ports/cortex_m3/ac5/src/tx_thread_schedule.s +++ b/ports/cortex_m3/ac5/src/tx_thread_schedule.s @@ -262,9 +262,19 @@ __tx_ts_wait #endif #ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif #endif #ifdef TX_LOW_POWER diff --git a/ports/cortex_m3/ac6/src/tx_thread_schedule.S b/ports/cortex_m3/ac6/src/tx_thread_schedule.S index f1a6deed6..f585c6f48 100644 --- a/ports/cortex_m3/ac6/src/tx_thread_schedule.S +++ b/ports/cortex_m3/ac6/src/tx_thread_schedule.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ // Some portions generated by Codex (GPT-5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -268,9 +269,19 @@ __tx_ts_wait: #endif #ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif #endif #ifdef TX_LOW_POWER diff --git a/ports/cortex_m3/gnu/src/tx_thread_schedule.S b/ports/cortex_m3/gnu/src/tx_thread_schedule.S index 7a7126c95..724a0ed97 100644 --- a/ports/cortex_m3/gnu/src/tx_thread_schedule.S +++ b/ports/cortex_m3/gnu/src/tx_thread_schedule.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ // Some portions generated by Codex (GPT-5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -266,9 +267,19 @@ __tx_ts_wait: #endif #ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif #endif #ifdef TX_LOW_POWER diff --git a/ports/cortex_m3/iar/src/tx_thread_schedule.s b/ports/cortex_m3/iar/src/tx_thread_schedule.s index 93e17e21e..8ed1b469c 100644 --- a/ports/cortex_m3/iar/src/tx_thread_schedule.s +++ b/ports/cortex_m3/iar/src/tx_thread_schedule.s @@ -262,9 +262,19 @@ __tx_ts_wait: #endif #ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif #endif #ifdef TX_LOW_POWER diff --git a/ports/cortex_m33/ac6/src/tx_thread_schedule.S b/ports/cortex_m33/ac6/src/tx_thread_schedule.S index 365f228fc..c0794e2a4 100644 --- a/ports/cortex_m33/ac6/src/tx_thread_schedule.S +++ b/ports/cortex_m33/ac6/src/tx_thread_schedule.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ // Some portions generated by Codex (GPT-5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -279,9 +280,19 @@ __tx_ts_wait: #endif #ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif #endif #ifdef TX_LOW_POWER diff --git a/ports/cortex_m33/gnu/src/tx_thread_schedule.S b/ports/cortex_m33/gnu/src/tx_thread_schedule.S index dcc35afb2..63c97eb14 100644 --- a/ports/cortex_m33/gnu/src/tx_thread_schedule.S +++ b/ports/cortex_m33/gnu/src/tx_thread_schedule.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ // Some portions generated by Codex (GPT-5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -275,9 +276,19 @@ __tx_ts_wait: #endif #ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif #endif #ifdef TX_LOW_POWER diff --git a/ports/cortex_m33/iar/src/tx_thread_schedule.s b/ports/cortex_m33/iar/src/tx_thread_schedule.s index 99fbac9e2..0018babb4 100644 --- a/ports/cortex_m33/iar/src/tx_thread_schedule.s +++ b/ports/cortex_m33/iar/src/tx_thread_schedule.s @@ -280,9 +280,19 @@ __tx_ts_wait: #endif #ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif #endif #ifdef TX_LOW_POWER diff --git a/ports/cortex_m4/ac5/src/tx_thread_schedule.s b/ports/cortex_m4/ac5/src/tx_thread_schedule.s index 79c6d6608..7aa6a366f 100644 --- a/ports/cortex_m4/ac5/src/tx_thread_schedule.s +++ b/ports/cortex_m4/ac5/src/tx_thread_schedule.s @@ -262,9 +262,19 @@ __tx_ts_wait #endif #ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif #endif #ifdef TX_LOW_POWER diff --git a/ports/cortex_m4/ac6/src/tx_thread_schedule.S b/ports/cortex_m4/ac6/src/tx_thread_schedule.S index 0ff44a1df..227e76f50 100644 --- a/ports/cortex_m4/ac6/src/tx_thread_schedule.S +++ b/ports/cortex_m4/ac6/src/tx_thread_schedule.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ // Some portions generated by Codex (GPT-5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -268,9 +269,19 @@ __tx_ts_wait: #endif #ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif #endif #ifdef TX_LOW_POWER diff --git a/ports/cortex_m4/gnu/src/tx_thread_schedule.S b/ports/cortex_m4/gnu/src/tx_thread_schedule.S index ebd149729..8e9f0664f 100644 --- a/ports/cortex_m4/gnu/src/tx_thread_schedule.S +++ b/ports/cortex_m4/gnu/src/tx_thread_schedule.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ // Some portions generated by Codex (GPT-5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -266,9 +267,19 @@ __tx_ts_wait: #endif #ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif #endif #ifdef TX_LOW_POWER diff --git a/ports/cortex_m4/iar/src/tx_thread_schedule.s b/ports/cortex_m4/iar/src/tx_thread_schedule.s index 9f8228934..e4ea3bfc9 100644 --- a/ports/cortex_m4/iar/src/tx_thread_schedule.s +++ b/ports/cortex_m4/iar/src/tx_thread_schedule.s @@ -262,9 +262,19 @@ __tx_ts_wait: #endif #ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif #endif #ifdef TX_LOW_POWER diff --git a/ports/cortex_m52/ac6/src/tx_thread_schedule.S b/ports/cortex_m52/ac6/src/tx_thread_schedule.S index 937d03d5f..2458a417e 100644 --- a/ports/cortex_m52/ac6/src/tx_thread_schedule.S +++ b/ports/cortex_m52/ac6/src/tx_thread_schedule.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ // Some portions generated by Codex (GPT-5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -279,9 +280,19 @@ __tx_ts_wait: #endif #ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif #endif #ifdef TX_LOW_POWER diff --git a/ports/cortex_m52/gnu/src/tx_thread_schedule.S b/ports/cortex_m52/gnu/src/tx_thread_schedule.S index 736f084b2..bc830c302 100644 --- a/ports/cortex_m52/gnu/src/tx_thread_schedule.S +++ b/ports/cortex_m52/gnu/src/tx_thread_schedule.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ // Some portions generated by Codex (GPT-5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -275,9 +276,19 @@ __tx_ts_wait: #endif #ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif #endif #ifdef TX_LOW_POWER diff --git a/ports/cortex_m52/iar/src/tx_thread_schedule.s b/ports/cortex_m52/iar/src/tx_thread_schedule.s index ccb7c83e8..a89ca7784 100644 --- a/ports/cortex_m52/iar/src/tx_thread_schedule.s +++ b/ports/cortex_m52/iar/src/tx_thread_schedule.s @@ -280,9 +280,19 @@ __tx_ts_wait: #endif #ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif #endif #ifdef TX_LOW_POWER diff --git a/ports/cortex_m55/ac6/src/tx_thread_schedule.S b/ports/cortex_m55/ac6/src/tx_thread_schedule.S index 3665179aa..08a48000b 100644 --- a/ports/cortex_m55/ac6/src/tx_thread_schedule.S +++ b/ports/cortex_m55/ac6/src/tx_thread_schedule.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ // Some portions generated by Codex (GPT-5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -279,9 +280,19 @@ __tx_ts_wait: #endif #ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif #endif #ifdef TX_LOW_POWER diff --git a/ports/cortex_m55/gnu/src/tx_thread_schedule.S b/ports/cortex_m55/gnu/src/tx_thread_schedule.S index e70b44c8e..7d331dc83 100644 --- a/ports/cortex_m55/gnu/src/tx_thread_schedule.S +++ b/ports/cortex_m55/gnu/src/tx_thread_schedule.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ // Some portions generated by Codex (GPT-5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -275,9 +276,19 @@ __tx_ts_wait: #endif #ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif #endif #ifdef TX_LOW_POWER diff --git a/ports/cortex_m55/iar/src/tx_thread_schedule.s b/ports/cortex_m55/iar/src/tx_thread_schedule.s index f3e5f6500..7edba8302 100644 --- a/ports/cortex_m55/iar/src/tx_thread_schedule.s +++ b/ports/cortex_m55/iar/src/tx_thread_schedule.s @@ -280,9 +280,19 @@ __tx_ts_wait: #endif #ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif #endif #ifdef TX_LOW_POWER diff --git a/ports/cortex_m7/ac5/src/tx_thread_schedule.s b/ports/cortex_m7/ac5/src/tx_thread_schedule.s index e48f8fac8..ed1c93922 100644 --- a/ports/cortex_m7/ac5/src/tx_thread_schedule.s +++ b/ports/cortex_m7/ac5/src/tx_thread_schedule.s @@ -262,9 +262,19 @@ __tx_ts_wait #endif #ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif #endif #ifdef TX_LOW_POWER diff --git a/ports/cortex_m7/ac6/src/tx_thread_schedule.S b/ports/cortex_m7/ac6/src/tx_thread_schedule.S index beb6e0bb5..26355e374 100644 --- a/ports/cortex_m7/ac6/src/tx_thread_schedule.S +++ b/ports/cortex_m7/ac6/src/tx_thread_schedule.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ // Some portions generated by Codex (GPT-5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -268,9 +269,19 @@ __tx_ts_wait: #endif #ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif #endif #ifdef TX_LOW_POWER diff --git a/ports/cortex_m7/gnu/src/tx_thread_schedule.S b/ports/cortex_m7/gnu/src/tx_thread_schedule.S index 999970c2d..66b033ac1 100644 --- a/ports/cortex_m7/gnu/src/tx_thread_schedule.S +++ b/ports/cortex_m7/gnu/src/tx_thread_schedule.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ // Some portions generated by Codex (GPT-5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -266,9 +267,19 @@ __tx_ts_wait: #endif #ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif #endif #ifdef TX_LOW_POWER diff --git a/ports/cortex_m7/iar/src/tx_thread_schedule.s b/ports/cortex_m7/iar/src/tx_thread_schedule.s index bc85b5440..47aac1f86 100644 --- a/ports/cortex_m7/iar/src/tx_thread_schedule.s +++ b/ports/cortex_m7/iar/src/tx_thread_schedule.s @@ -262,9 +262,19 @@ __tx_ts_wait: #endif #ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif #endif #ifdef TX_LOW_POWER diff --git a/ports/cortex_m85/ac6/src/tx_thread_schedule.S b/ports/cortex_m85/ac6/src/tx_thread_schedule.S index 57e1c10f4..ab60b30e4 100644 --- a/ports/cortex_m85/ac6/src/tx_thread_schedule.S +++ b/ports/cortex_m85/ac6/src/tx_thread_schedule.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ // Some portions generated by Codex (GPT-5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -279,9 +280,19 @@ __tx_ts_wait: #endif #ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif #endif #ifdef TX_LOW_POWER diff --git a/ports/cortex_m85/gnu/src/tx_thread_schedule.S b/ports/cortex_m85/gnu/src/tx_thread_schedule.S index 57123f9b8..1f1ded319 100644 --- a/ports/cortex_m85/gnu/src/tx_thread_schedule.S +++ b/ports/cortex_m85/gnu/src/tx_thread_schedule.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ // Some portions generated by Codex (GPT-5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -275,9 +276,19 @@ __tx_ts_wait: #endif #ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif #endif #ifdef TX_LOW_POWER diff --git a/ports/cortex_m85/iar/src/tx_thread_schedule.s b/ports/cortex_m85/iar/src/tx_thread_schedule.s index 1651108c1..0d412f859 100644 --- a/ports/cortex_m85/iar/src/tx_thread_schedule.s +++ b/ports/cortex_m85/iar/src/tx_thread_schedule.s @@ -280,9 +280,19 @@ __tx_ts_wait: #endif #ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif #endif #ifdef TX_LOW_POWER diff --git a/ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_schedule.s b/ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_schedule.s index 9853f3734..2f0f22821 100644 --- a/ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_schedule.s +++ b/ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_schedule.s @@ -262,9 +262,19 @@ __tx_ts_wait #endif #ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif #endif #ifdef TX_LOW_POWER diff --git a/ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_schedule.S b/ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_schedule.S index a368f5d6c..edf3cea58 100644 --- a/ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_schedule.S +++ b/ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_schedule.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ // Some portions generated by Codex (GPT-5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -268,9 +269,19 @@ __tx_ts_wait: #endif #ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif #endif #ifdef TX_LOW_POWER diff --git a/ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_schedule.S b/ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_schedule.S index d70a7b00c..75c95d0bb 100644 --- a/ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_schedule.S +++ b/ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_schedule.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ // Some portions generated by Codex (GPT-5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -266,9 +267,19 @@ __tx_ts_wait: #endif #ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif #endif #ifdef TX_LOW_POWER diff --git a/ports_arch/ARMv7-M/threadx/iar/src/tx_thread_schedule.s b/ports_arch/ARMv7-M/threadx/iar/src/tx_thread_schedule.s index 416aeff64..c3ce6e31d 100644 --- a/ports_arch/ARMv7-M/threadx/iar/src/tx_thread_schedule.s +++ b/ports_arch/ARMv7-M/threadx/iar/src/tx_thread_schedule.s @@ -262,9 +262,19 @@ __tx_ts_wait: #endif #ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif #endif #ifdef TX_LOW_POWER diff --git a/ports_arch/ARMv7-M/threadx_modules/ac5/module_manager/src/tx_thread_schedule.s b/ports_arch/ARMv7-M/threadx_modules/ac5/module_manager/src/tx_thread_schedule.s index 55c94a94f..f7e2bcb9d 100644 --- a/ports_arch/ARMv7-M/threadx_modules/ac5/module_manager/src/tx_thread_schedule.s +++ b/ports_arch/ARMv7-M/threadx_modules/ac5/module_manager/src/tx_thread_schedule.s @@ -320,9 +320,19 @@ __tx_ts_wait #endif #ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif #endif #ifdef TX_LOW_POWER diff --git a/ports_arch/ARMv7-M/threadx_modules/ac6/module_manager/src/tx_thread_schedule.S b/ports_arch/ARMv7-M/threadx_modules/ac6/module_manager/src/tx_thread_schedule.S index 715055592..cd030c9f9 100644 --- a/ports_arch/ARMv7-M/threadx_modules/ac6/module_manager/src/tx_thread_schedule.S +++ b/ports_arch/ARMv7-M/threadx_modules/ac6/module_manager/src/tx_thread_schedule.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ // Some portions generated by Codex (GPT-5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -333,9 +334,19 @@ __tx_ts_wait: #endif #ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif #endif #ifdef TX_LOW_POWER diff --git a/ports_arch/ARMv7-M/threadx_modules/gnu/module_manager/src/tx_thread_schedule.S b/ports_arch/ARMv7-M/threadx_modules/gnu/module_manager/src/tx_thread_schedule.S index 92d557d5f..a4aa07ad0 100644 --- a/ports_arch/ARMv7-M/threadx_modules/gnu/module_manager/src/tx_thread_schedule.S +++ b/ports_arch/ARMv7-M/threadx_modules/gnu/module_manager/src/tx_thread_schedule.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ // Some portions generated by Codex (GPT-5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -331,9 +332,19 @@ __tx_ts_wait: #endif #ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif #endif #ifdef TX_LOW_POWER diff --git a/ports_arch/ARMv7-M/threadx_modules/iar/module_manager/src/tx_thread_schedule.s b/ports_arch/ARMv7-M/threadx_modules/iar/module_manager/src/tx_thread_schedule.s index 121311ba1..81c319b0e 100644 --- a/ports_arch/ARMv7-M/threadx_modules/iar/module_manager/src/tx_thread_schedule.s +++ b/ports_arch/ARMv7-M/threadx_modules/iar/module_manager/src/tx_thread_schedule.s @@ -321,9 +321,19 @@ __tx_ts_wait: #endif #ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif #endif #ifdef TX_LOW_POWER diff --git a/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_schedule.S b/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_schedule.S index 40c86d71c..29141833f 100644 --- a/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_schedule.S +++ b/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_schedule.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ // Some portions generated by Codex (GPT-5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -279,9 +280,19 @@ __tx_ts_wait: #endif #ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif #endif #ifdef TX_LOW_POWER diff --git a/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_schedule.S b/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_schedule.S index b69e50455..b566fa2a1 100644 --- a/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_schedule.S +++ b/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_schedule.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ // Some portions generated by Codex (GPT-5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -275,9 +276,19 @@ __tx_ts_wait: #endif #ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif #endif #ifdef TX_LOW_POWER diff --git a/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_schedule.s b/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_schedule.s index de2b7bcf7..adbb2d5aa 100644 --- a/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_schedule.s +++ b/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_schedule.s @@ -280,9 +280,19 @@ __tx_ts_wait: #endif #ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif #endif #ifdef TX_LOW_POWER diff --git a/ports_module/cortex_m3/ac5/module_manager/src/tx_thread_schedule.s b/ports_module/cortex_m3/ac5/module_manager/src/tx_thread_schedule.s index b0f068145..fbc79a257 100644 --- a/ports_module/cortex_m3/ac5/module_manager/src/tx_thread_schedule.s +++ b/ports_module/cortex_m3/ac5/module_manager/src/tx_thread_schedule.s @@ -320,9 +320,19 @@ __tx_ts_wait #endif #ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif #endif #ifdef TX_LOW_POWER diff --git a/ports_module/cortex_m3/ac6/module_manager/src/tx_thread_schedule.S b/ports_module/cortex_m3/ac6/module_manager/src/tx_thread_schedule.S index 0850b7081..a62ac22fc 100644 --- a/ports_module/cortex_m3/ac6/module_manager/src/tx_thread_schedule.S +++ b/ports_module/cortex_m3/ac6/module_manager/src/tx_thread_schedule.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ // Some portions generated by Codex (GPT-5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -333,9 +334,19 @@ __tx_ts_wait: #endif #ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif #endif #ifdef TX_LOW_POWER diff --git a/ports_module/cortex_m3/gnu/module_manager/src/tx_thread_schedule.S b/ports_module/cortex_m3/gnu/module_manager/src/tx_thread_schedule.S index 83210ac73..00483552a 100644 --- a/ports_module/cortex_m3/gnu/module_manager/src/tx_thread_schedule.S +++ b/ports_module/cortex_m3/gnu/module_manager/src/tx_thread_schedule.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ // Some portions generated by Codex (GPT-5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -331,9 +332,19 @@ __tx_ts_wait: #endif #ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif #endif #ifdef TX_LOW_POWER diff --git a/ports_module/cortex_m3/iar/module_manager/src/tx_thread_schedule.s b/ports_module/cortex_m3/iar/module_manager/src/tx_thread_schedule.s index 408a8b4c9..efb1abf11 100644 --- a/ports_module/cortex_m3/iar/module_manager/src/tx_thread_schedule.s +++ b/ports_module/cortex_m3/iar/module_manager/src/tx_thread_schedule.s @@ -321,9 +321,19 @@ __tx_ts_wait: #endif #ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif #endif #ifdef TX_LOW_POWER diff --git a/ports_module/cortex_m33/ac6/module_manager/src/tx_thread_schedule.S b/ports_module/cortex_m33/ac6/module_manager/src/tx_thread_schedule.S index 30357a854..f9885a5ff 100644 --- a/ports_module/cortex_m33/ac6/module_manager/src/tx_thread_schedule.S +++ b/ports_module/cortex_m33/ac6/module_manager/src/tx_thread_schedule.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ // Some portions generated by Codex (GPT-5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -335,9 +336,19 @@ __tx_ts_wait: #endif #ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif #endif #ifdef TX_LOW_POWER diff --git a/ports_module/cortex_m33/gnu/module_manager/src/tx_thread_schedule.S b/ports_module/cortex_m33/gnu/module_manager/src/tx_thread_schedule.S index e2ec1edcd..6dcd33c5f 100644 --- a/ports_module/cortex_m33/gnu/module_manager/src/tx_thread_schedule.S +++ b/ports_module/cortex_m33/gnu/module_manager/src/tx_thread_schedule.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ // Some portions generated by Codex (GPT-5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -334,9 +335,19 @@ __tx_ts_wait: #endif #ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif #endif #ifdef TX_LOW_POWER diff --git a/ports_module/cortex_m33/iar/module_manager/src/tx_thread_schedule.s b/ports_module/cortex_m33/iar/module_manager/src/tx_thread_schedule.s index 39e2aef10..5fcb99a4c 100644 --- a/ports_module/cortex_m33/iar/module_manager/src/tx_thread_schedule.s +++ b/ports_module/cortex_m33/iar/module_manager/src/tx_thread_schedule.s @@ -332,9 +332,19 @@ __tx_ts_wait: #endif #ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif #endif #ifdef TX_LOW_POWER diff --git a/ports_module/cortex_m4/ac5/module_manager/src/tx_thread_schedule.s b/ports_module/cortex_m4/ac5/module_manager/src/tx_thread_schedule.s index 9840641c4..ddf5e8e5b 100644 --- a/ports_module/cortex_m4/ac5/module_manager/src/tx_thread_schedule.s +++ b/ports_module/cortex_m4/ac5/module_manager/src/tx_thread_schedule.s @@ -320,9 +320,19 @@ __tx_ts_wait #endif #ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif #endif #ifdef TX_LOW_POWER diff --git a/ports_module/cortex_m4/ac6/module_manager/src/tx_thread_schedule.S b/ports_module/cortex_m4/ac6/module_manager/src/tx_thread_schedule.S index 83ea99abd..9d976db56 100644 --- a/ports_module/cortex_m4/ac6/module_manager/src/tx_thread_schedule.S +++ b/ports_module/cortex_m4/ac6/module_manager/src/tx_thread_schedule.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ // Some portions generated by Codex (GPT-5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -333,9 +334,19 @@ __tx_ts_wait: #endif #ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif #endif #ifdef TX_LOW_POWER diff --git a/ports_module/cortex_m4/gnu/module_manager/src/tx_thread_schedule.S b/ports_module/cortex_m4/gnu/module_manager/src/tx_thread_schedule.S index e4ceee8ab..a5680bc21 100644 --- a/ports_module/cortex_m4/gnu/module_manager/src/tx_thread_schedule.S +++ b/ports_module/cortex_m4/gnu/module_manager/src/tx_thread_schedule.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ // Some portions generated by Codex (GPT-5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -331,9 +332,19 @@ __tx_ts_wait: #endif #ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif #endif #ifdef TX_LOW_POWER diff --git a/ports_module/cortex_m4/iar/module_manager/src/tx_thread_schedule.s b/ports_module/cortex_m4/iar/module_manager/src/tx_thread_schedule.s index 242f83c51..8006f7bcf 100644 --- a/ports_module/cortex_m4/iar/module_manager/src/tx_thread_schedule.s +++ b/ports_module/cortex_m4/iar/module_manager/src/tx_thread_schedule.s @@ -321,9 +321,19 @@ __tx_ts_wait: #endif #ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif #endif #ifdef TX_LOW_POWER diff --git a/ports_module/cortex_m7/ac5/module_manager/src/tx_thread_schedule.s b/ports_module/cortex_m7/ac5/module_manager/src/tx_thread_schedule.s index 0c87b3ee9..75771a45b 100644 --- a/ports_module/cortex_m7/ac5/module_manager/src/tx_thread_schedule.s +++ b/ports_module/cortex_m7/ac5/module_manager/src/tx_thread_schedule.s @@ -320,9 +320,19 @@ __tx_ts_wait #endif #ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif #endif #ifdef TX_LOW_POWER diff --git a/ports_module/cortex_m7/ac6/module_manager/src/tx_thread_schedule.S b/ports_module/cortex_m7/ac6/module_manager/src/tx_thread_schedule.S index f3af5f71a..3019df1e3 100644 --- a/ports_module/cortex_m7/ac6/module_manager/src/tx_thread_schedule.S +++ b/ports_module/cortex_m7/ac6/module_manager/src/tx_thread_schedule.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ // Some portions generated by Codex (GPT-5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -333,9 +334,19 @@ __tx_ts_wait: #endif #ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif #endif #ifdef TX_LOW_POWER diff --git a/ports_module/cortex_m7/gnu/module_manager/src/tx_thread_schedule.S b/ports_module/cortex_m7/gnu/module_manager/src/tx_thread_schedule.S index e7284c639..8fc9307d5 100644 --- a/ports_module/cortex_m7/gnu/module_manager/src/tx_thread_schedule.S +++ b/ports_module/cortex_m7/gnu/module_manager/src/tx_thread_schedule.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ // Some portions generated by Codex (GPT-5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -331,9 +332,19 @@ __tx_ts_wait: #endif #ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif #endif #ifdef TX_LOW_POWER diff --git a/ports_module/cortex_m7/iar/module_manager/src/tx_thread_schedule.s b/ports_module/cortex_m7/iar/module_manager/src/tx_thread_schedule.s index 392ca6162..8a3da5c9b 100644 --- a/ports_module/cortex_m7/iar/module_manager/src/tx_thread_schedule.s +++ b/ports_module/cortex_m7/iar/module_manager/src/tx_thread_schedule.s @@ -321,9 +321,19 @@ __tx_ts_wait: #endif #ifdef TX_ENABLE_WFI +#ifdef TX_PORT_USE_BASEPRI + CPSID i // Mask every interrupt with PRIMASK, which WFI ignores + MOV r1, #0 // Clear BASEPRI so that an interrupt masked by it + MSR BASEPRI, r1 // is still able to wake the processor +#endif DSB // Ensure no outstanding memory transactions WFI // Wait for interrupt ISB // Ensure pipeline is flushed +#ifdef TX_PORT_USE_BASEPRI + LDR r1, =TX_PORT_BASEPRI // Restore the BASEPRI mask + MSR BASEPRI, r1 + CPSIE i // Clear PRIMASK; a pending interrupt is taken here +#endif #endif #ifdef TX_LOW_POWER From 40db27e843e06657e5320049a2c10e215cc95dc4 Mon Sep 17 00:00:00 2001 From: Akif Ejaz Date: Wed, 9 Sep 2026 20:40:05 +0500 Subject: [PATCH 114/181] riscv32: spec compliance and regression test fix (#691) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * riscv32: spec compliance and regression test fix Signed-off-by: Akif Ejaz * Derived the RISC-V32 frame sizes from the port contract in one place tx_port.h published TX_RISCV_TRAP_FRAME_SIZE for the GNU BSP assembly, but nothing in the port consumed it. Six .S files each rebuilt the same numbers from their own #if, so the interrupt frame size was written out in seven places and the solicited frame size in three. That is the shape that produced the RISC-V64 fault fixed in #708, where the port moved to a padded frame and one copy of the constant did not. The sources now include tx_port.h and take both sizes from it, and no literal frame size remains in the port. TX_RISCV_SOL_FRAME_SIZE joins the contract, since the solicited frame was never published at all. The emitted code is unchanged: 400 and 176 bytes for ILP32D, 128 for soft-float, confirmed by disassembly before and after. Two further corrections: _tx_initialize_low_level carried .global immediately followed by .weak, so the symbol stayed weak and the .global did nothing. Weak is what the port wants, because the example and regression BSPs both provide their own definition, so the stray .global is removed rather than the .weak. Verified with nm that the symbol is still W. The QEMU runner seeded fpu_verified from skip_fpu, so a soft-float run satisfied the FPU gate whether or not the script ever reported the skip. It now starts false and is set only when the skip marker is present, so a run that dies before reaching that point fails instead of passing. Assisted-by: Claude Code (Opus 5) --------- Signed-off-by: Akif Ejaz Co-authored-by: Frédéric Desbiens --- cmake/riscv32-unknown-elf.cmake | 2 +- cmake/riscv32_gnu.cmake | 2 +- .../gnu/example_build/qemu_virt/.gitignore | 4 + .../example_build/qemu_virt/CMakeLists.txt | 24 +- .../gnu/example_build/qemu_virt/board.c | 14 +- .../example_build/qemu_virt/demo_threadx.c | 4 + .../gnu/example_build/qemu_virt/hwtimer.c | 69 ++++- .../gnu/example_build/qemu_virt/hwtimer.h | 4 +- .../gnu/example_build/qemu_virt/link.lds | 21 +- .../test/threadx_test_tx_gnu_riscv32_qemu.py | 279 ++++++++++++------ .../qemu_virt/tx_initialize_low_level.S | 21 +- ports/risc-v32/gnu/inc/tx_port.h | 42 ++- .../gnu/src/tx_initialize_low_level.S | 9 +- .../gnu/src/tx_thread_context_restore.S | 205 +++++-------- .../risc-v32/gnu/src/tx_thread_context_save.S | 154 ++++------ ports/risc-v32/gnu/src/tx_thread_schedule.S | 171 ++++------- .../risc-v32/gnu/src/tx_thread_stack_build.S | 104 ++----- .../gnu/src/tx_thread_system_return.S | 57 ++-- ports/risc-v32/gnu/src/tx_timer_interrupt.S | 4 +- test/tx/cmake/riscv/bsp/entry.S | 6 + test/tx/cmake/riscv/bsp/hwtimer.c | 84 +++++- test/tx/cmake/riscv/bsp/hwtimer.h | 4 +- test/tx/cmake/riscv/bsp/link.lds | 32 +- test/tx/cmake/riscv/bsp/plic.c | 25 +- test/tx/cmake/riscv/bsp/syscalls.c | 49 ++- test/tx/cmake/riscv/bsp/trap.c | 3 - .../cmake/riscv/bsp/tx_initialize_low_level.S | 2 +- 27 files changed, 767 insertions(+), 628 deletions(-) create mode 100644 ports/risc-v32/gnu/example_build/qemu_virt/.gitignore diff --git a/cmake/riscv32-unknown-elf.cmake b/cmake/riscv32-unknown-elf.cmake index d21e729ca..b428dc8e3 100644 --- a/cmake/riscv32-unknown-elf.cmake +++ b/cmake/riscv32-unknown-elf.cmake @@ -20,7 +20,7 @@ set(CMAKE_CXX_FLAGS "${CXXFLAGS}" CACHE INTERNAL "cxx compiler flags") if(DEFINED SOFT_FLOAT) set(CMAKE_ASM_FLAGS "${ASFLAGS} -D__ASSEMBLER__" CACHE INTERNAL "asm compiler flags") else() - set(CMAKE_ASM_FLAGS "${ASFLAGS} -D__ASSEMBLER__ -D__riscv_float_abi_single" CACHE INTERNAL "asm compiler flags") + set(CMAKE_ASM_FLAGS "${ASFLAGS} -D__ASSEMBLER__" CACHE INTERNAL "asm compiler flags") endif() set(CMAKE_EXE_LINKER_FLAGS "${LDFLAGS}" CACHE INTERNAL "exe link flags") diff --git a/cmake/riscv32_gnu.cmake b/cmake/riscv32_gnu.cmake index 6843423c5..584cbf0ed 100644 --- a/cmake/riscv32_gnu.cmake +++ b/cmake/riscv32_gnu.cmake @@ -5,7 +5,7 @@ set(THREADX_ARCH "risc-v32") set(THREADX_TOOLCHAIN "gnu") if(DEFINED SOFT_FLOAT) set(ARCH_FLAGS "-g -march=rv32ima_zicsr -mabi=ilp32 -mcmodel=medany") - set(CACHE{SOFT_FLOAT} FORCE 1) + set(SOFT_FLOAT 1 CACHE BOOL "build the soft-float rv32ima_zicsr/ilp32 configuration" FORCE) else() set(ARCH_FLAGS "-g -march=rv32gc -mabi=ilp32d -mcmodel=medany -mrelax") endif() diff --git a/ports/risc-v32/gnu/example_build/qemu_virt/.gitignore b/ports/risc-v32/gnu/example_build/qemu_virt/.gitignore new file mode 100644 index 000000000..18a4075cc --- /dev/null +++ b/ports/risc-v32/gnu/example_build/qemu_virt/.gitignore @@ -0,0 +1,4 @@ +# Ignore generated QEMU test files. +kernel.elf +qemu-riscv32.log +test_cmds.gdb diff --git a/ports/risc-v32/gnu/example_build/qemu_virt/CMakeLists.txt b/ports/risc-v32/gnu/example_build/qemu_virt/CMakeLists.txt index 43e757ace..cbf67798e 100644 --- a/ports/risc-v32/gnu/example_build/qemu_virt/CMakeLists.txt +++ b/ports/risc-v32/gnu/example_build/qemu_virt/CMakeLists.txt @@ -11,7 +11,7 @@ add_executable(kernel.elf EXCLUDE_FROM_ALL ${QEMU_DEMO_DIR}/tx_initialize_low_level.S ) -target_link_libraries(kernel.elf PRIVATE threadx) +target_link_libraries(kernel.elf PRIVATE threadx gcc) target_include_directories(kernel.elf PRIVATE ${CMAKE_SOURCE_DIR}/common/inc @@ -28,18 +28,32 @@ target_link_options(kernel.elf PRIVATE # QEMU/GDB functional test runner. Optional: skipped silently if the # host has no Python 3 interpreter on PATH. find_package(Python3 COMPONENTS Interpreter) -if(Python3_FOUND) +# The runner needs a GDB that understands riscv:rv32 remote targets +find_program(RISCV32_GDB NAMES riscv32-unknown-elf-gdb gdb-multiarch) +find_program(RISCV32_QEMU NAMES qemu-system-riscv32) +if(Python3_FOUND AND RISCV32_GDB AND RISCV32_QEMU) + set(RISCV32_QEMU_TEST_ARGS) + if(SOFT_FLOAT) + list(APPEND RISCV32_QEMU_TEST_ARGS --skip-fpu) + endif() add_custom_target(check-functional-riscv32 COMMAND ${Python3_EXECUTABLE} ${QEMU_DEMO_DIR}/test/threadx_test_tx_gnu_riscv32_qemu.py --elf $ - --qemu qemu-system-riscv32 - --gdb gdb + --qemu ${RISCV32_QEMU} + --gdb ${RISCV32_GDB} + ${RISCV32_QEMU_TEST_ARGS} DEPENDS kernel.elf WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} COMMENT "Running RISC-V32 QEMU/GDB functional test runner..." ) -else() +elseif(NOT Python3_FOUND) message(STATUS "Python3 not found; check-functional-riscv32 target unavailable.") +elseif(NOT RISCV32_GDB) + message(STATUS + "RISC-V GDB not found; check-functional-riscv32 target unavailable.") +else() + message(STATUS + "qemu-system-riscv32 not found; check-functional-riscv32 target unavailable.") endif() diff --git a/ports/risc-v32/gnu/example_build/qemu_virt/board.c b/ports/risc-v32/gnu/example_build/qemu_virt/board.c index fc75de668..4d0056a81 100644 --- a/ports/risc-v32/gnu/example_build/qemu_virt/board.c +++ b/ports/risc-v32/gnu/example_build/qemu_virt/board.c @@ -14,15 +14,13 @@ #include #include -void *memset(const void *des, int c,size_t n) +void *memset(void *des, int c, size_t n) { - if((des == NULL) || n <=0) - return (void*)des; - char* t = (char*)des; - int i; - for(i=0;i> 32); + MTIMECMP_LO(hart) = (uint32_t)value; +} int hwtimer_init(void) { - int hart = riscv_get_core(); - uint64_t time = *((uint64_t*)CLINT_TIME); - *((uint64_t*)CLINT_TIMECMP(hart)) = time + TICKNUM_PER_TIMER; - return 0; + int hart = riscv_get_core(); + + clint_timecmp_write(hart, clint_time_read() + TICKNUM_PER_TIMER); + return 0; } int hwtimer_handler(void) { - int hart = riscv_get_core(); - uint64_t time = *((uint64_t*)CLINT_TIME); - *((uint64_t*)CLINT_TIMECMP(hart)) = time + TICKNUM_PER_TIMER; - return 0; -} + int hart = riscv_get_core(); + + /* Advance from the previous compare value, so trap + latency does not accumulate as tick drift */ + uint64_t next = clint_timecmp_read(hart) + TICKNUM_PER_TIMER; + uint64_t now = clint_time_read(); + if (next <= now) + next = now + TICKNUM_PER_TIMER; + + clint_timecmp_write(hart, next); + return 0; +} diff --git a/ports/risc-v32/gnu/example_build/qemu_virt/hwtimer.h b/ports/risc-v32/gnu/example_build/qemu_virt/hwtimer.h index 966b1abfb..7bc2d0e3a 100644 --- a/ports/risc-v32/gnu/example_build/qemu_virt/hwtimer.h +++ b/ports/risc-v32/gnu/example_build/qemu_virt/hwtimer.h @@ -14,8 +14,8 @@ #include -#define TICKNUM_PER_SECOND 10000000 -#define TICKNUM_PER_TIMER (TICKNUM_PER_SECOND / 10) +#define TICKNUM_PER_SECOND 10000000UL +#define TICKNUM_PER_TIMER (TICKNUM_PER_SECOND / TX_TIMER_TICKS_PER_SECOND) int hwtimer_init(void); int hwtimer_handler(void); diff --git a/ports/risc-v32/gnu/example_build/qemu_virt/link.lds b/ports/risc-v32/gnu/example_build/qemu_virt/link.lds index d2ef5f289..42f5d3662 100644 --- a/ports/risc-v32/gnu/example_build/qemu_virt/link.lds +++ b/ports/risc-v32/gnu/example_build/qemu_virt/link.lds @@ -1,6 +1,12 @@ OUTPUT_ARCH( "riscv" ) ENTRY( _start ) +PHDRS +{ + text PT_LOAD FLAGS(5); + data PT_LOAD FLAGS(6); +} + SECTIONS { /* @@ -14,15 +20,16 @@ SECTIONS *(.text .text.*) . = ALIGN(0x1000); PROVIDE(etext = .); - } + } :text .rodata : { . = ALIGN(16); *(.srodata .srodata.*) /* do not need to distinguish this from .rodata */ . = ALIGN(16); *(.rodata .rodata.*) - } + } :text + . = ALIGN(0x1000); .data : { . = ALIGN(16); /* Centre __global_pointer$ in the small-data window so the +/-2 KiB @@ -31,23 +38,23 @@ SECTIONS *(.sdata .sdata.*) /* do not need to distinguish this from .data */ . = ALIGN(16); *(.data .data.*) - } + } :data - .bss : { + .bss (NOLOAD) : { . = ALIGN(16); _bss_start = .; *(.sbss .sbss.*) /* do not need to distinguish this from .bss */ . = ALIGN(16); *(.bss .bss.*) _bss_end = .; - } + } :data - .stack : { + .stack (NOLOAD) : { . = ALIGN(4096); _sysstack_start = .; . += 0x1000; _sysstack_end = .; - } + } :data PROVIDE(_end = .); } diff --git a/ports/risc-v32/gnu/example_build/qemu_virt/test/threadx_test_tx_gnu_riscv32_qemu.py b/ports/risc-v32/gnu/example_build/qemu_virt/test/threadx_test_tx_gnu_riscv32_qemu.py index 6123cd73b..bc97e7450 100644 --- a/ports/risc-v32/gnu/example_build/qemu_virt/test/threadx_test_tx_gnu_riscv32_qemu.py +++ b/ports/risc-v32/gnu/example_build/qemu_virt/test/threadx_test_tx_gnu_riscv32_qemu.py @@ -17,134 +17,186 @@ import select def print_content(content): - """Prints content using os.write to handle non-blocking stdout robustly.""" - try: - msg = f"{content}\n".encode('utf-8') - total_len = len(msg) - written = 0 - fd = sys.stdout.fileno() - while written < total_len: - try: - n = os.write(fd, msg[written:]) - written += n - except BlockingIOError: - select.select([], [fd], []) - except Exception: - pass + """Write content to nonblocking stdout with os.write.""" + msg = f"{content}\n".encode('utf-8') + total_len = len(msg) + written = 0 + fd = sys.stdout.fileno() + while written < total_len: + try: + n = os.write(fd, msg[written:]) + written += n + except BlockingIOError: + select.select([], [fd], []) def get_free_port(): - """Finds a free TCP port.""" + """Get an unused TCP port.""" with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.bind(('', 0)) return s.getsockname()[1] -def run_qemu_test(elf_path, qemu_bin, gdb_bin): - """ - Runs a test cycle using QEMU and GDB. - """ +def run_qemu_test(elf_path, qemu_bin, gdb_bin, skip_fpu): + """Run one QEMU and GDB test cycle.""" print(f"Testing ELF: {elf_path}") print(f"QEMU: {qemu_bin}") print(f"GDB: {gdb_bin}") - # Find a free port for GDB connection + # Get an unused GDB port. gdb_port = get_free_port() print(f"Using GDB port: {gdb_port}") - # 1. Start QEMU in the background + # Start QEMU and wait for GDB. + GDB_TIMEOUT_S = 120 + qemu_log_path = os.path.abspath("qemu-riscv32.log") qemu_cmd = [ qemu_bin, "-M", "virt", "-nographic", - "-bios", "none", # Disable default OpenSBI to avoid overlap at 0x80000000 + "-bios", "none", # Start without OpenSBI at 0x80000000. "-kernel", elf_path, "-gdb", f"tcp::{gdb_port}", "-S", - "-monitor", "none", # Disable monitor to avoid clutter - "-serial", "stdio" # Redirect serial output to stdio so we can see it + "-monitor", "none", # Disable the QEMU monitor. + "-serial", "stdio" # Send serial output to stdout. ] print(f"Starting QEMU: {' '.join(qemu_cmd)}") - qemu_process = subprocess.Popen( - qemu_cmd, - stdout=subprocess.PIPE, - stderr=subprocess.PIPE, - text=True + qemu_log = open(qemu_log_path, "w", encoding="utf-8") + try: + qemu_process = subprocess.Popen( + qemu_cmd, + stdout=qemu_log, + stderr=subprocess.STDOUT, + text=True + ) + except OSError as e: + qemu_log.close() + print_content(f"FAILURE: QEMU did not start: {e}") + return False + + print_content( + f"QEMU PID {qemu_process.pid}; expected runtime under 30s; " + f"wall timeout {GDB_TIMEOUT_S}s; log {qemu_log_path}" ) if qemu_process.poll() is not None: - print("QEMU failed to start.") - print(qemu_process.stderr.read()) + qemu_log.close() + print_content("FAILURE: QEMU exited during startup.") + with open(qemu_log_path, encoding="utf-8") as failed_log: + print_content(failed_log.read()) return False - # 2. Create a GDB command file - # We use a defined command for the timer interrupt to perform the check automatically + # Create the GDB command file. gdb_cmds = """ file {elf} target remote :{port} set pagination off set confirm off -# Setup Breakpoints +# Set breakpoints. break tx_application_define break thread_0_entry break thread_6_and_7_entry break _tx_timer_interrupt -# Execute to Application Definition +disable 4 + +# Run to the application setup. continue -# Inspect mstatus once thread_0 has started (FS bits should be observable; -# kept as a smoke check, the lazy-save logic itself is targeted by a -# follow-up PR). + continue print/x $mstatus - -# Verify FPU Logic and Register State exercised by thread_6/7 continue -finish -step -step -step + +# Check for fpu_test_val before GDB uses it. +# An absent symbol fails the required FPU test. +python gdb.execute("set $fpu_sym = %d" % (1 if gdb.lookup_global_symbol("fpu_test_val") else 0)) +set $fpu_required = {fpu_required} + +set $fpu_iter = 0 +if $fpu_sym != 0 + set $fpu_before = fpu_test_val + # Continue until one FPU addition completes. + # Limit the wait to 64 thread passes. + while fpu_test_val == $fpu_before && $fpu_iter < 64 + set $fpu_iter = $fpu_iter + 1 + continue + end +end + print/x $mstatus info registers float -print fpu_test_val -# Await Timer Interrupt +if $fpu_sym == 0 + if $fpu_required != 0 + printf "FPU_VERIFIED_FAIL_NO_SYMBOL\\n" + else + printf "FPU_VERIFIED_SKIP_SOFT_FLOAT\\n" + end +else + print fpu_test_val + # Check for a multiple of 1.1f with a 0.01 tolerance. + set $fpu_n = (int)((fpu_test_val / 1.1) + 0.5) + set $fpu_err = fpu_test_val - ($fpu_n * 1.1) + if $fpu_n >= 1 && $fpu_err > -0.01 && $fpu_err < 0.01 + printf "FPU_VERIFIED_OK value=%f adds=%d\\n", fpu_test_val, $fpu_n + else + printf "FPU_VERIFIED_FAIL value=%f adds=%d passes=%d\\n", fpu_test_val, $fpu_n, $fpu_iter + end +end + +# Enable only the timer breakpoint. +# Then $ra contains the ISR return address. +disable 1 +disable 2 +disable 3 +enable 4 continue print "Hit Timer Interrupt" -# Verify MEPC Integrity - Save State +# Save mepc at timer entry. print/x $mepc set $saved_pc = $mepc -# Verify System Timer Before ISR +# Read the system clock before the ISR completes. set $clock_before = _tx_timer_system_clock print $clock_before -# Configure Time-Slice Test Conditions +# Force time-slice processing. set _tx_timer_time_slice = 1 set _tx_timer_expired_time_slice = 0 set $ts_handler_called = 0 -# Set Breakpoint at Time-Slice Handler with Auto-Continue +# Record time-slice handler calls. tbreak _tx_thread_time_slice commands set $ts_handler_called = 1 continue end -# Set Breakpoint at ISR Return Address +# Stop at the ISR return address. +# Disable the timer breakpoint during this interval. set $ret_addr = $ra +disable 4 tbreak *$ret_addr continue -# Verify Time-Slice Handler Was Called +# Check the live CSR and the saved frame PC. +set $frame_pc = ((unsigned int *)_tx_thread_current_ptr->tx_thread_stack_ptr)[30] +if $mepc == $saved_pc && $frame_pc == $saved_pc + printf "MEPC_VERIFIED_OK mepc=0x%x frame_pc=0x%x\\n", $mepc, $frame_pc +else + printf "MEPC_VERIFIED_FAIL saved=0x%x mepc=0x%x frame_pc=0x%x\\n", $saved_pc, $mepc, $frame_pc +end + +# Check time-slice handler execution. if $ts_handler_called == 1 print "SUCCESS: Time-slice handler called." else print "FAILURE: Time-slice handler NOT called." end -# Verify System Timer Increment (Monotonicity) +# Check that the system clock increased. set $clock_after = _tx_timer_system_clock print $clock_after @@ -154,37 +206,56 @@ def run_qemu_test(elf_path, qemu_bin, gdb_bin): print "FAILURE: System timer did not increment." end -# Verify Preemption Logic (Thread Priority) -# -# We are now stopped at the return address from _tx_timer_interrupt, -# after _tx_thread_time_slice has had a chance to update -# _tx_thread_execute_ptr but before trap_handler returns into -# _tx_thread_context_restore. At this point, a pending preemption is -# observable directly by comparing current_ptr (interrupted thread) -# and execute_ptr (thread chosen by the scheduler). -set $curr_ptr = _tx_thread_current_ptr -set $exec_ptr = _tx_thread_execute_ptr -if $curr_ptr != 0 && $exec_ptr != 0 - set $curr_prio = $curr_ptr->tx_thread_priority - set $exec_prio = $exec_ptr->tx_thread_priority - printf "PREEMPT_CHECK current_prio=%d execute_prio=%d\\n", $curr_prio, $exec_prio - if $exec_prio < $curr_prio - printf "PREEMPT_VERIFIED_OK\\n" +# Compare the current and selected thread priorities at the ISR return. +# Check each tick until preemption occurs or 250 ticks expire. +# Each retry uses the same ISR point and starts a new time slice. +set $preempt_ok = 0 +set $preempt_null = 0 +set $preempt_iter = 0 +while $preempt_iter < 250 && $preempt_ok == 0 + set $curr_ptr = _tx_thread_current_ptr + set $exec_ptr = _tx_thread_execute_ptr + if $curr_ptr == 0 || $exec_ptr == 0 + set $preempt_null = $preempt_null + 1 else - printf "PREEMPT_VERIFIED_FAIL_NOT_OBSERVED\\n" + set $curr_prio = $curr_ptr->tx_thread_priority + set $exec_prio = $exec_ptr->tx_thread_priority + if $exec_prio < $curr_prio + printf "PREEMPT_CHECK current_prio=%d execute_prio=%d\\n", $curr_prio, $exec_prio + set $preempt_ok = 1 + end end + if $preempt_ok == 0 + set $preempt_iter = $preempt_iter + 1 + enable 4 + continue + set _tx_timer_time_slice = 1 + set _tx_timer_expired_time_slice = 0 + set $ret_addr = $ra + disable 4 + tbreak *$ret_addr + continue + end +end + +if $preempt_ok == 1 + printf "PREEMPT_VERIFIED_OK ticks=%d\\n", $preempt_iter else - printf "PREEMPT_VERIFIED_FAIL_NULL\\n" + if $preempt_null == $preempt_iter + printf "PREEMPT_VERIFIED_FAIL_NULL\\n" + else + printf "PREEMPT_VERIFIED_FAIL_NOT_OBSERVED ticks=%d\\n", $preempt_iter + end end quit -""".format(port=gdb_port, elf=elf_path) +""".format(port=gdb_port, elf=elf_path, fpu_required=0 if skip_fpu else 1) gdb_cmd_file = "test_cmds.gdb" with open(gdb_cmd_file, "w") as f: f.write(gdb_cmds) - # 3. Run GDB + # Run GDB in batch mode. gdb_cmd = [ gdb_bin, "--batch", @@ -193,10 +264,8 @@ def run_qemu_test(elf_path, qemu_bin, gdb_bin): print_content(f"Starting GDB: {' '.join(gdb_cmd)}") - # Cap the GDB session to 30 s so a wedged batch script (e.g. a - # `continue` that never hits its breakpoint) cannot hang CI. - GDB_TIMEOUT_S = 30 - + # Limit GDB to 120 seconds. + # The loop uses at most 250 ticks and two gdbstub exchanges for each tick. try: gdb_process = subprocess.run( gdb_cmd, @@ -232,25 +301,46 @@ def run_qemu_test(elf_path, qemu_bin, gdb_bin): return False finally: - # 4. Clean up + # Stop QEMU and close its log. print_content("Stopping QEMU...") qemu_process.terminate() try: qemu_process.wait(timeout=2) except subprocess.TimeoutExpired: - print_content("QEMU did not terminate gracefully, killing it forcefullly.") + print_content("QEMU did not terminate gracefully, killing it forcefully.") qemu_process.kill() + qemu_process.wait() + qemu_log.close() - # Verify results + # Check each required test result. stdout = gdb_process.stdout + gdb_succeeded = gdb_process.returncode == 0 timer_hit = "Breakpoint 4, _tx_timer_interrupt" in stdout fpu_verified = False + mepc_verified = "MEPC_VERIFIED_OK" in stdout preemption_verified = "PREEMPT_VERIFIED_OK" in stdout - - if "Breakpoint 3, thread_6_and_7_entry" in stdout: - if "1.10" in stdout or "fpu_test_val" in stdout: + time_slice_verified = "SUCCESS: Time-slice handler called." in stdout + system_timer_verified = "SUCCESS: System timer incremented." in stdout + + if not gdb_succeeded: + print_content(f"FAILURE: GDB exited with status {gdb_process.returncode}.") + + if skip_fpu and "FPU_VERIFIED_SKIP_SOFT_FLOAT" in stdout: + print_content("SUCCESS: Soft-float mode omitted the hardware FPU check.") + fpu_verified = True + elif skip_fpu: + print_content("FAILURE: Soft-float build did not report the FPU skip, so " + "the GDB script did not run to that point.") + elif "Breakpoint 3, thread_6_and_7_entry" in stdout: + if "FPU_VERIFIED_OK" in stdout: print_content("SUCCESS: FPU instructions executed and registers inspected.") fpu_verified = True + elif "FPU_VERIFIED_FAIL_NO_SYMBOL" in stdout: + print_content("FAILURE: Hit thread, but this demo defines no " + "fpu_test_val, so the FPU result is unverifiable.") + elif "FPU_VERIFIED_FAIL" in stdout: + print_content("FAILURE: Hit thread, but fpu_test_val is not an exact " + "multiple of 1.1f. Output does not contain expected value.") else: print_content("FAILURE: Hit thread, but failed to inspect FPU. Output does not contain expected value.") @@ -259,6 +349,21 @@ def run_qemu_test(elf_path, qemu_bin, gdb_bin): else: print_content("FAILURE: Did not hit timer interrupt.") + if mepc_verified: + print_content("SUCCESS: MEPC and the saved frame PC are unchanged.") + else: + print_content("FAILURE: MEPC or the saved frame PC changed in the ISR.") + + if time_slice_verified: + print_content("SUCCESS: Time-slice handler verified.") + else: + print_content("FAILURE: Time-slice handler was not called.") + + if system_timer_verified: + print_content("SUCCESS: System timer increment verified.") + else: + print_content("FAILURE: System timer did not increment.") + if preemption_verified: print_content("SUCCESS: Preemption verified (higher-priority thread " "preempted a lower-priority one).") @@ -274,7 +379,9 @@ def run_qemu_test(elf_path, qemu_bin, gdb_bin): else: print_content("FAILURE: Preemption check did not run to completion.") - if timer_hit and fpu_verified and preemption_verified: + if (gdb_succeeded and timer_hit and fpu_verified and mepc_verified and + time_slice_verified and system_timer_verified and + preemption_verified): return True else: return False @@ -284,10 +391,12 @@ def run_qemu_test(elf_path, qemu_bin, gdb_bin): parser.add_argument("--elf", required=True, help="Path to the kernel ELF file") parser.add_argument("--qemu", default="qemu-system-riscv32", help="Path to QEMU binary") parser.add_argument("--gdb", default="riscv-none-elf-gdb", help="Path to GDB binary") + parser.add_argument("--skip-fpu", action="store_true", + help="Skip the hardware FPU check for a soft-float build") args = parser.parse_args() - success = run_qemu_test(args.elf, args.qemu, args.gdb) + success = run_qemu_test(args.elf, args.qemu, args.gdb, args.skip_fpu) if success: sys.exit(0) diff --git a/ports/risc-v32/gnu/example_build/qemu_virt/tx_initialize_low_level.S b/ports/risc-v32/gnu/example_build/qemu_virt/tx_initialize_low_level.S index 9a7a74ffd..9cda8096d 100644 --- a/ports/risc-v32/gnu/example_build/qemu_virt/tx_initialize_low_level.S +++ b/ports/risc-v32/gnu/example_build/qemu_virt/tx_initialize_low_level.S @@ -59,12 +59,12 @@ .global trap_entry .extern trap_handler .extern _tx_thread_context_restore +/* Trap frame: integer slots 0-31 at i*4; FP build adds f0-f31 as doubles + at 128 + i*8, fcsr at 384, pad to 400 (total mod 16 = 0). */ +#include "tx_port.h" + .equ TX_TRAP_FRAME_SIZE, TX_RISCV_TRAP_FRAME_SIZE trap_entry: -#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - addi sp, sp, -260 // Allocate space for all registers - with floating point enabled (65*4) -#else - addi sp, sp, -128 // Allocate space for all registers - without floating point enabled (32*4) -#endif + addi sp, sp, -TX_TRAP_FRAME_SIZE // Allocate space for all registers (400 with FP double, 128 without) sw x1, 112(sp) // Store RA (28*4 = 112, because call will override ra [ra is a callee register in riscv]) @@ -73,11 +73,11 @@ csrr a0, mcause csrr a1, mepc csrr a2, mtval - addi sp, sp, -4 + addi sp, sp, -16 // 16-byte temporary frame: ilp32 psABI requires sp = 0 mod 16 at the call sw ra, 0(sp) call trap_handler lw ra, 0(sp) - addi sp, sp, 4 + addi sp, sp, 16 call _tx_thread_context_restore // it will nerver return _err: @@ -128,7 +128,6 @@ _err: /* VOID _tx_initialize_low_level(VOID) { */ .global _tx_initialize_low_level - .weak _tx_initialize_low_level .extern _end .extern board_init _tx_initialize_low_level: @@ -147,16 +146,16 @@ _tx_initialize_low_level: 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 +#if defined(__riscv_float_abi_double) 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, -4 + addi sp, sp, -16 // 16-byte temporary frame: ilp32 psABI requires sp = 0 mod 16 at the call sw ra, 0(sp) call board_init lw ra, 0(sp) - addi sp, sp, 4 + addi sp, sp, 16 la t0, trap_entry csrw mtvec, t0 ret diff --git a/ports/risc-v32/gnu/inc/tx_port.h b/ports/risc-v32/gnu/inc/tx_port.h index c990aa970..642b12750 100644 --- a/ports/risc-v32/gnu/inc/tx_port.h +++ b/ports/risc-v32/gnu/inc/tx_port.h @@ -25,7 +25,7 @@ /* PORT SPECIFIC C INFORMATION RELEASE */ /* */ /* tx_port.h RISC-V32/GNU */ -/* 6.4.x */ +/* 6.5.1.202602a */ /* */ /* AUTHOR */ /* */ @@ -47,6 +47,46 @@ #ifndef TX_PORT_H #define TX_PORT_H +#ifdef __riscv_vector +#error "The ThreadX RISC-V32 GNU port does not save or restore vector state. Build without the V extension." +#endif + +#ifdef __riscv_32e +#error "The ThreadX RISC-V32 GNU port requires the RV32I register set. RV32E is not supported." +#endif + +#ifdef __riscv_float_abi_single +#error "The ThreadX RISC-V32 GNU port does not support ILP32F. Use ILP32D or a soft-float ABI." +#endif + +#ifdef __riscv_float_abi_quad +#error "The ThreadX RISC-V32 GNU port does not support ILP32Q." +#endif + +#if defined(__riscv_flen) && !defined(__riscv_float_abi_double) +#error "The ThreadX RISC-V32 GNU port requires ILP32D when the ISA enables floating-point state." +#endif + +#if defined(__riscv_float_abi_double) && (!defined(__riscv_flen) || (__riscv_flen != 64)) +#error "The ThreadX RISC-V32 GNU ILP32D port requires FLEN=64." +#endif + +/* Publish the interrupt frame contract to GNU BSP assembly files. */ +#if defined(__riscv_float_abi_double) +#define TX_RISCV_TRAP_FRAME_SIZE 400 +#else +#define TX_RISCV_TRAP_FRAME_SIZE 128 +#endif +#define TX_RISCV_TRAP_CALL_FRAME_SIZE 16 + +/* Solicited (cooperative) frame built by _tx_thread_system_return: fs0-fs11 + as doubles plus fcsr with FP, callee-saved integer state without. */ +#if defined(__riscv_float_abi_double) +#define TX_RISCV_SOL_FRAME_SIZE 176 +#else +#define TX_RISCV_SOL_FRAME_SIZE 128 +#endif + /* Include shared RISC-V32 port definitions common to all toolchain ports. */ #include "../../common/tx_port_riscv32_common.h" diff --git a/ports/risc-v32/gnu/src/tx_initialize_low_level.S b/ports/risc-v32/gnu/src/tx_initialize_low_level.S index 2940f2159..ca97ba62d 100644 --- a/ports/risc-v32/gnu/src/tx_initialize_low_level.S +++ b/ports/risc-v32/gnu/src/tx_initialize_low_level.S @@ -62,8 +62,7 @@ __tx_free_memory_start: /**************************************************************************/ /* VOID _tx_initialize_low_level(VOID) { */ - .weak _tx_initialize_low_level - .weak _tx_initialize_low_level + .weak _tx_initialize_low_level // Weak: a BSP definition overrides this default _tx_initialize_low_level: /* Save the system stack pointer. */ @@ -79,8 +78,10 @@ _tx_initialize_low_level: la t1, _tx_initialize_unused_memory // Pickup address of unused memory sw t0, 0(t1) // Save unused memory address - /* Initialize floating point control/status register if floating point is enabled. */ -#ifdef __riscv_flen + /* Initialize floating point state if floating point is enabled. */ +#if defined(__riscv_float_abi_double) + li t0, 0x2000 // mstatus.FS = Initial (bits 14:13 = 01) + csrrs zero, mstatus, t0 // Enable the FP unit before touching fcsr li t0, 0 csrw fcsr, t0 // Clear FP control/status register #endif diff --git a/ports/risc-v32/gnu/src/tx_thread_context_restore.S b/ports/risc-v32/gnu/src/tx_thread_context_restore.S index d3d449e47..c48546433 100644 --- a/ports/risc-v32/gnu/src/tx_thread_context_restore.S +++ b/ports/risc-v32/gnu/src/tx_thread_context_restore.S @@ -20,6 +20,14 @@ /**************************************************************************/ .section .text + +/* Trap frame layout (stack grows down, all totals mod 16 = 0): + FP build (double ABI): integer slots 0-31 at i*4 (0-127; slot 31 is pad), + f0-f31 as doubles at 128 + i*8 (128-383), fcsr at 384, pad 388-399. + SOFT_FLOAT build: integer slots 0-31 at i*4 only. */ +#include "tx_port.h" + .equ TX_TRAP_FRAME_SIZE, TX_RISCV_TRAP_FRAME_SIZE + /**************************************************************************/ /* */ /* FUNCTION RELEASE */ @@ -84,57 +92,32 @@ _tx_thread_context_restore: interrupt. */ /* Recover floating point registers only if saved mstatus.FS was not Off. */ -#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) +#if defined(__riscv_float_abi_double) lw t1, 29*4(sp) // Pickup saved mstatus srli t1, t1, 13 andi t1, t1, 0x3 beqz t1, _tx_thread_skip_fp_restore // Skip if FS was Off -#endif -#if defined(__riscv_float_abi_single) - flw f0, 31*4(sp) // Recover ft0 - flw f1, 32*4(sp) // Recover ft1 - flw f2, 33*4(sp) // Recover ft2 - flw f3, 34*4(sp) // Recover ft3 - flw f4, 35*4(sp) // Recover ft4 - flw f5, 36*4(sp) // Recover ft5 - flw f6, 37*4(sp) // Recover ft6 - flw f7, 38*4(sp) // Recover ft7 - flw f10, 41*4(sp) // Recover fa0 - flw f11, 42*4(sp) // Recover fa1 - flw f12, 43*4(sp) // Recover fa2 - flw f13, 44*4(sp) // Recover fa3 - flw f14, 45*4(sp) // Recover fa4 - flw f15, 46*4(sp) // Recover fa5 - flw f16, 47*4(sp) // Recover fa6 - flw f17, 48*4(sp) // Recover fa7 - flw f28, 59*4(sp) // Recover ft8 - flw f29, 60*4(sp) // Recover ft9 - flw f30, 61*4(sp) // Recover ft10 - flw f31, 62*4(sp) // Recover ft11 - lw t0, 63*4(sp) // Recover fcsr - csrw fcsr, t0 // Restore fcsr -#elif defined(__riscv_float_abi_double) - fld f0, 31*4(sp) // Recover ft0 - fld f1, 32*4(sp) // Recover ft1 - fld f2, 33*4(sp) // Recover ft2 - fld f3, 34*4(sp) // Recover ft3 - fld f4, 35*4(sp) // Recover ft4 - fld f5, 36*4(sp) // Recover ft5 - fld f6, 37*4(sp) // Recover ft6 - fld f7, 38*4(sp) // Recover ft7 - fld f10, 41*4(sp) // Recover fa0 - fld f11, 42*4(sp) // Recover fa1 - fld f12, 43*4(sp) // Recover fa2 - fld f13, 44*4(sp) // Recover fa3 - fld f14, 45*4(sp) // Recover fa4 - fld f15, 46*4(sp) // Recover fa5 - fld f16, 47*4(sp) // Recover fa6 - fld f17, 48*4(sp) // Recover fa7 - fld f28, 59*4(sp) // Recover ft8 - fld f29, 60*4(sp) // Recover ft9 - fld f30, 61*4(sp) // Recover ft10 - fld f31, 62*4(sp) // Recover ft11 - lw t0, 63*4(sp) // Recover fcsr + fld f0, 16*8(sp) // Recover ft0 + fld f1, 17*8(sp) // Recover ft1 + fld f2, 18*8(sp) // Recover ft2 + fld f3, 19*8(sp) // Recover ft3 + fld f4, 20*8(sp) // Recover ft4 + fld f5, 21*8(sp) // Recover ft5 + fld f6, 22*8(sp) // Recover ft6 + fld f7, 23*8(sp) // Recover ft7 + fld f10, 26*8(sp) // Recover fa0 + fld f11, 27*8(sp) // Recover fa1 + fld f12, 28*8(sp) // Recover fa2 + fld f13, 29*8(sp) // Recover fa3 + fld f14, 30*8(sp) // Recover fa4 + fld f15, 31*8(sp) // Recover fa5 + fld f16, 32*8(sp) // Recover fa6 + fld f17, 33*8(sp) // Recover fa7 + fld f28, 44*8(sp) // Recover ft8 + fld f29, 45*8(sp) // Recover ft9 + fld f30, 46*8(sp) // Recover ft10 + fld f31, 47*8(sp) // Recover ft11 + lw t0, 96*4(sp) // Recover fcsr csrw fcsr, t0 // Restore fcsr #endif _tx_thread_skip_fp_restore: @@ -166,7 +149,7 @@ _tx_thread_skip_fp_restore: and t1, t1, t4 or t1, t1, t3 -#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) +#if defined(__riscv_float_abi_double) li t0, 0x2000 // Set FS bits (bits 14:13 to 01) for FP state or t1, t1, t0 #endif @@ -190,11 +173,7 @@ _tx_thread_skip_fp_restore: lw t5, 14*4(sp) // Recover t5 lw t6, 13*4(sp) // Recover t6 -#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - addi sp, sp, 65*4 // Recover stack frame - with floating point enabled -#else - addi sp, sp, 32*4 // Recover stack frame - without floating point enabled -#endif + addi sp, sp, TX_TRAP_FRAME_SIZE // Recover stack frame mret // Return to point of interrupt /* } */ @@ -213,7 +192,7 @@ _tx_thread_not_nested_restore: la t0, _tx_thread_preempt_disable // Pickup preempt disable flag address lw t2, 0(t0) // Pickup preempt disable flag (UINT) - bgtz t2, _tx_thread_no_preempt_restore // If set, restore interrupted thread + bnez t2, _tx_thread_no_preempt_restore // If set, restore interrupted thread la t0, _tx_thread_execute_ptr // Pickup thread execute pointer address @@ -231,57 +210,32 @@ _tx_thread_no_preempt_restore: lw sp, 8(t1) // Switch back to thread's stack /* Recover floating point registers only if saved mstatus.FS was not Off. */ -#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) +#if defined(__riscv_float_abi_double) lw t3, 29*4(sp) // Pickup saved mstatus srli t3, t3, 13 andi t3, t3, 0x3 beqz t3, _tx_thread_no_preempt_skip_fp_restore // Skip if FS was Off -#endif -#if defined(__riscv_float_abi_single) - flw f0, 31*4(sp) // Recover ft0 - flw f1, 32*4(sp) // Recover ft1 - flw f2, 33*4(sp) // Recover ft2 - flw f3, 34*4(sp) // Recover ft3 - flw f4, 35*4(sp) // Recover ft4 - flw f5, 36*4(sp) // Recover ft5 - flw f6, 37*4(sp) // Recover ft6 - flw f7, 38*4(sp) // Recover ft7 - flw f10, 41*4(sp) // Recover fa0 - flw f11, 42*4(sp) // Recover fa1 - flw f12, 43*4(sp) // Recover fa2 - flw f13, 44*4(sp) // Recover fa3 - flw f14, 45*4(sp) // Recover fa4 - flw f15, 46*4(sp) // Recover fa5 - flw f16, 47*4(sp) // Recover fa6 - flw f17, 48*4(sp) // Recover fa7 - flw f28, 59*4(sp) // Recover ft8 - flw f29, 60*4(sp) // Recover ft9 - flw f30, 61*4(sp) // Recover ft10 - flw f31, 62*4(sp) // Recover ft11 - lw t0, 63*4(sp) // Recover fcsr - csrw fcsr, t0 // Restore fcsr -#elif defined(__riscv_float_abi_double) - fld f0, 31*4(sp) // Recover ft0 - fld f1, 32*4(sp) // Recover ft1 - fld f2, 33*4(sp) // Recover ft2 - fld f3, 34*4(sp) // Recover ft3 - fld f4, 35*4(sp) // Recover ft4 - fld f5, 36*4(sp) // Recover ft5 - fld f6, 37*4(sp) // Recover ft6 - fld f7, 38*4(sp) // Recover ft7 - fld f10, 41*4(sp) // Recover fa0 - fld f11, 42*4(sp) // Recover fa1 - fld f12, 43*4(sp) // Recover fa2 - fld f13, 44*4(sp) // Recover fa3 - fld f14, 45*4(sp) // Recover fa4 - fld f15, 46*4(sp) // Recover fa5 - fld f16, 47*4(sp) // Recover fa6 - fld f17, 48*4(sp) // Recover fa7 - fld f28, 59*4(sp) // Recover ft8 - fld f29, 60*4(sp) // Recover ft9 - fld f30, 61*4(sp) // Recover ft10 - fld f31, 62*4(sp) // Recover ft11 - lw t0, 63*4(sp) // Recover fcsr + fld f0, 16*8(sp) // Recover ft0 + fld f1, 17*8(sp) // Recover ft1 + fld f2, 18*8(sp) // Recover ft2 + fld f3, 19*8(sp) // Recover ft3 + fld f4, 20*8(sp) // Recover ft4 + fld f5, 21*8(sp) // Recover ft5 + fld f6, 22*8(sp) // Recover ft6 + fld f7, 23*8(sp) // Recover ft7 + fld f10, 26*8(sp) // Recover fa0 + fld f11, 27*8(sp) // Recover fa1 + fld f12, 28*8(sp) // Recover fa2 + fld f13, 29*8(sp) // Recover fa3 + fld f14, 30*8(sp) // Recover fa4 + fld f15, 31*8(sp) // Recover fa5 + fld f16, 32*8(sp) // Recover fa6 + fld f17, 33*8(sp) // Recover fa7 + fld f28, 44*8(sp) // Recover ft8 + fld f29, 45*8(sp) // Recover ft9 + fld f30, 46*8(sp) // Recover ft10 + fld f31, 47*8(sp) // Recover ft11 + lw t0, 96*4(sp) // Recover fcsr csrw fcsr, t0 // Restore fcsr #endif _tx_thread_no_preempt_skip_fp_restore: @@ -304,7 +258,7 @@ _tx_thread_no_preempt_skip_fp_restore: and t1, t1, t4 or t1, t1, t3 -#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) +#if defined(__riscv_float_abi_double) li t0, 0x2000 // Set FS bits for FP state or t1, t1, t0 #endif @@ -328,11 +282,7 @@ _tx_thread_no_preempt_skip_fp_restore: lw t5, 14*4(sp) // Recover t5 lw t6, 13*4(sp) // Recover t6 -#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - addi sp, sp, 65*4 // Recover stack frame - with floating point enabled -#else - addi sp, sp, 32*4 // Recover stack frame - without floating point enabled -#endif + addi sp, sp, TX_TRAP_FRAME_SIZE // Recover stack frame mret // Return to point of interrupt /* } @@ -347,38 +297,23 @@ _tx_thread_preempt_restore: sw t3, 0(t0) // Store stack type /* Store floating point preserved registers only if saved mstatus.FS was not Off. */ -#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) +#if defined(__riscv_float_abi_double) lw t3, 29*4(t0) // Pickup saved mstatus srli t3, t3, 13 andi t3, t3, 0x3 beqz t3, _tx_thread_preempt_skip_fp_restore // Skip if FS was Off -#endif -#ifdef __riscv_float_abi_single - fsw f8, 39*4(t0) // Store fs0 - fsw f9, 40*4(t0) // Store fs1 - fsw f18, 49*4(t0) // Store fs2 - fsw f19, 50*4(t0) // Store fs3 - fsw f20, 51*4(t0) // Store fs4 - fsw f21, 52*4(t0) // Store fs5 - fsw f22, 53*4(t0) // Store fs6 - fsw f23, 54*4(t0) // Store fs7 - fsw f24, 55*4(t0) // Store fs8 - fsw f25, 56*4(t0) // Store fs9 - fsw f26, 57*4(t0) // Store fs10 - fsw f27, 58*4(t0) // Store fs11 -#elif defined(__riscv_float_abi_double) - fsd f8, 39*4(t0) // Store fs0 - fsd f9, 40*4(t0) // Store fs1 - fsd f18, 49*4(t0) // Store fs2 - fsd f19, 50*4(t0) // Store fs3 - fsd f20, 51*4(t0) // Store fs4 - fsd f21, 52*4(t0) // Store fs5 - fsd f22, 53*4(t0) // Store fs6 - fsd f23, 54*4(t0) // Store fs7 - fsd f24, 55*4(t0) // Store fs8 - fsd f25, 56*4(t0) // Store fs9 - fsd f26, 57*4(t0) // Store fs10 - fsd f27, 58*4(t0) // Store fs11 + fsd f8, 192(t0) // Store fs0 + fsd f9, 200(t0) // Store fs1 + fsd f18, 272(t0) // Store fs2 + fsd f19, 280(t0) // Store fs3 + fsd f20, 288(t0) // Store fs4 + fsd f21, 296(t0) // Store fs5 + fsd f22, 304(t0) // Store fs6 + fsd f23, 312(t0) // Store fs7 + fsd f24, 320(t0) // Store fs8 + fsd f25, 328(t0) // Store fs9 + fsd f26, 336(t0) // Store fs10 + fsd f27, 344(t0) // Store fs11 #endif _tx_thread_preempt_skip_fp_restore: diff --git a/ports/risc-v32/gnu/src/tx_thread_context_save.S b/ports/risc-v32/gnu/src/tx_thread_context_save.S index d61cea86e..9a67520aa 100644 --- a/ports/risc-v32/gnu/src/tx_thread_context_save.S +++ b/ports/risc-v32/gnu/src/tx_thread_context_save.S @@ -22,6 +22,10 @@ /**************************************************************************/ .section .text + +#include "tx_port.h" + .equ TX_TRAP_FRAME_SIZE, TX_RISCV_TRAP_FRAME_SIZE + /**************************************************************************/ /* */ /* FUNCTION RELEASE */ @@ -63,7 +67,7 @@ _tx_thread_context_save: /* Upon entry to this routine, RA/x1 has been saved on the stack and the stack has been already allocated for the entire context: - addi sp, sp, -32*4 (or -65*4) + addi sp, sp, -TX_TRAP_FRAME_SIZE (400 with FP, 128 without) sw ra, 28*4(sp) */ @@ -102,59 +106,34 @@ _tx_thread_context_save: /* Save mstatus and skip FP state if FS is Off. */ csrr t0, mstatus sw t0, 29*4(sp) -#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) +#if defined(__riscv_float_abi_double) srli t1, t0, 13 andi t1, t1, 0x3 beqz t1, _tx_thread_skip_fpu_save -#endif - /* Save floating point registers. */ -#if defined(__riscv_float_abi_single) - fsw f0, 31*4(sp) // Store ft0 - fsw f1, 32*4(sp) // Store ft1 - fsw f2, 33*4(sp) // Store ft2 - fsw f3, 34*4(sp) // Store ft3 - fsw f4, 35*4(sp) // Store ft4 - fsw f5, 36*4(sp) // Store ft5 - fsw f6, 37*4(sp) // Store ft6 - fsw f7, 38*4(sp) // Store ft7 - fsw f10, 41*4(sp) // Store fa0 - fsw f11, 42*4(sp) // Store fa1 - fsw f12, 43*4(sp) // Store fa2 - fsw f13, 44*4(sp) // Store fa3 - fsw f14, 45*4(sp) // Store fa4 - fsw f15, 46*4(sp) // Store fa5 - fsw f16, 47*4(sp) // Store fa6 - fsw f17, 48*4(sp) // Store fa7 - fsw f28, 59*4(sp) // Store ft8 - fsw f29, 60*4(sp) // Store ft9 - fsw f30, 61*4(sp) // Store ft10 - fsw f31, 62*4(sp) // Store ft11 - csrr t0, fcsr - sw t0, 63*4(sp) // Store fcsr -#elif defined(__riscv_float_abi_double) - fsd f0, 31*4(sp) // Store ft0 - fsd f1, 32*4(sp) // Store ft1 - fsd f2, 33*4(sp) // Store ft2 - fsd f3, 34*4(sp) // Store ft3 - fsd f4, 35*4(sp) // Store ft4 - fsd f5, 36*4(sp) // Store ft5 - fsd f6, 37*4(sp) // Store ft6 - fsd f7, 38*4(sp) // Store ft7 - fsd f10, 41*4(sp) // Store fa0 - fsd f11, 42*4(sp) // Store fa1 - fsd f12, 43*4(sp) // Store fa2 - fsd f13, 44*4(sp) // Store fa3 - fsd f14, 45*4(sp) // Store fa4 - fsd f15, 46*4(sp) // Store fa5 - fsd f16, 47*4(sp) // Store fa6 - fsd f17, 48*4(sp) // Store fa7 - fsd f28, 59*4(sp) // Store ft8 - fsd f29, 60*4(sp) // Store ft9 - fsd f30, 61*4(sp) // Store ft10 - fsd f31, 62*4(sp) // Store ft11 + /* Save floating point registers (doubles at 128 + i*8). */ + fsd f0, 16*8(sp) // Store ft0 + fsd f1, 17*8(sp) // Store ft1 + fsd f2, 18*8(sp) // Store ft2 + fsd f3, 19*8(sp) // Store ft3 + fsd f4, 20*8(sp) // Store ft4 + fsd f5, 21*8(sp) // Store ft5 + fsd f6, 22*8(sp) // Store ft6 + fsd f7, 23*8(sp) // Store ft7 + fsd f10, 26*8(sp) // Store fa0 + fsd f11, 27*8(sp) // Store fa1 + fsd f12, 28*8(sp) // Store fa2 + fsd f13, 29*8(sp) // Store fa3 + fsd f14, 30*8(sp) // Store fa4 + fsd f15, 31*8(sp) // Store fa5 + fsd f16, 32*8(sp) // Store fa6 + fsd f17, 33*8(sp) // Store fa7 + fsd f28, 44*8(sp) // Store ft8 + fsd f29, 45*8(sp) // Store ft9 + fsd f30, 46*8(sp) // Store ft10 + fsd f31, 47*8(sp) // Store ft11 csrr t0, fcsr - sw t0, 63*4(sp) // Store fcsr + sw t0, 96*4(sp) // Store fcsr #endif _tx_thread_skip_fpu_save: @@ -206,59 +185,34 @@ _tx_thread_nested_save: /* Save mstatus and skip FP state if FS is Off. */ csrr t0, mstatus sw t0, 29*4(sp) -#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) +#if defined(__riscv_float_abi_double) srli t1, t0, 13 andi t1, t1, 0x3 beqz t1, _tx_thread_skip_nested_fpu_save -#endif - /* Save floating point registers. */ -#if defined(__riscv_float_abi_single) - fsw f0, 31*4(sp) // Store ft0 - fsw f1, 32*4(sp) // Store ft1 - fsw f2, 33*4(sp) // Store ft2 - fsw f3, 34*4(sp) // Store ft3 - fsw f4, 35*4(sp) // Store ft4 - fsw f5, 36*4(sp) // Store ft5 - fsw f6, 37*4(sp) // Store ft6 - fsw f7, 38*4(sp) // Store ft7 - fsw f10, 41*4(sp) // Store fa0 - fsw f11, 42*4(sp) // Store fa1 - fsw f12, 43*4(sp) // Store fa2 - fsw f13, 44*4(sp) // Store fa3 - fsw f14, 45*4(sp) // Store fa4 - fsw f15, 46*4(sp) // Store fa5 - fsw f16, 47*4(sp) // Store fa6 - fsw f17, 48*4(sp) // Store fa7 - fsw f28, 59*4(sp) // Store ft8 - fsw f29, 60*4(sp) // Store ft9 - fsw f30, 61*4(sp) // Store ft10 - fsw f31, 62*4(sp) // Store ft11 - csrr t0, fcsr - sw t0, 63*4(sp) // Store fcsr -#elif defined(__riscv_float_abi_double) - fsd f0, 31*4(sp) // Store ft0 - fsd f1, 32*4(sp) // Store ft1 - fsd f2, 33*4(sp) // Store ft2 - fsd f3, 34*4(sp) // Store ft3 - fsd f4, 35*4(sp) // Store ft4 - fsd f5, 36*4(sp) // Store ft5 - fsd f6, 37*4(sp) // Store ft6 - fsd f7, 38*4(sp) // Store ft7 - fsd f10, 41*4(sp) // Store fa0 - fsd f11, 42*4(sp) // Store fa1 - fsd f12, 43*4(sp) // Store fa2 - fsd f13, 44*4(sp) // Store fa3 - fsd f14, 45*4(sp) // Store fa4 - fsd f15, 46*4(sp) // Store fa5 - fsd f16, 47*4(sp) // Store fa6 - fsd f17, 48*4(sp) // Store fa7 - fsd f28, 59*4(sp) // Store ft8 - fsd f29, 60*4(sp) // Store ft9 - fsd f30, 61*4(sp) // Store ft10 - fsd f31, 62*4(sp) // Store ft11 + /* Save floating point registers (doubles at 128 + i*8). */ + fsd f0, 16*8(sp) // Store ft0 + fsd f1, 17*8(sp) // Store ft1 + fsd f2, 18*8(sp) // Store ft2 + fsd f3, 19*8(sp) // Store ft3 + fsd f4, 20*8(sp) // Store ft4 + fsd f5, 21*8(sp) // Store ft5 + fsd f6, 22*8(sp) // Store ft6 + fsd f7, 23*8(sp) // Store ft7 + fsd f10, 26*8(sp) // Store fa0 + fsd f11, 27*8(sp) // Store fa1 + fsd f12, 28*8(sp) // Store fa2 + fsd f13, 29*8(sp) // Store fa3 + fsd f14, 30*8(sp) // Store fa4 + fsd f15, 31*8(sp) // Store fa5 + fsd f16, 32*8(sp) // Store fa6 + fsd f17, 33*8(sp) // Store fa7 + fsd f28, 44*8(sp) // Store ft8 + fsd f29, 45*8(sp) // Store ft9 + fsd f30, 46*8(sp) // Store ft10 + fsd f31, 47*8(sp) // Store ft11 csrr t0, fcsr - sw t0, 63*4(sp) // Store fcsr + sw t0, 96*4(sp) // Store fcsr #endif _tx_thread_skip_nested_fpu_save: @@ -291,9 +245,5 @@ _tx_thread_idle_system_save: /* } } */ -#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - addi sp, sp, 65*4 // Recover stack frame - with floating point enabled -#else - addi sp, sp, 32*4 // Recover the reserved stack space -#endif + addi sp, sp, TX_TRAP_FRAME_SIZE // Recover the reserved stack space ret // Return to calling ISR diff --git a/ports/risc-v32/gnu/src/tx_thread_schedule.S b/ports/risc-v32/gnu/src/tx_thread_schedule.S index 79bfd51a7..7d2c41917 100644 --- a/ports/risc-v32/gnu/src/tx_thread_schedule.S +++ b/ports/risc-v32/gnu/src/tx_thread_schedule.S @@ -21,6 +21,11 @@ .section .text + +#include "tx_port.h" + .equ TX_TRAP_FRAME_SIZE, TX_RISCV_TRAP_FRAME_SIZE + .equ TX_SOL_FRAME_SIZE, TX_RISCV_SOL_FRAME_SIZE + /**************************************************************************/ /* */ /* FUNCTION RELEASE */ @@ -130,86 +135,49 @@ _tx_thread_ready_to_run: /* if (*sp) { */ - lw t0, 0(sp) // Pickup stack type + lw t0, 0*4(sp) // Pickup stack type beqz t0, _tx_thread_solicited_return // If 0, solicited return /* Recover floating point registers only if saved mstatus.FS was not Off. */ -#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) +#if defined(__riscv_float_abi_double) lw t1, 29*4(sp) // Pickup saved mstatus srli t1, t1, 13 andi t1, t1, 0x3 beqz t1, _tx_thread_schedule_skip_fp_restore // Skip if FS was Off -#if defined(__riscv_float_abi_single) - flw f0, 31*4(sp) // Recover ft0 - flw f1, 32*4(sp) // Recover ft1 - flw f2, 33*4(sp) // Recover ft2 - flw f3, 34*4(sp) // Recover ft3 - flw f4, 35*4(sp) // Recover ft4 - flw f5, 36*4(sp) // Recover ft5 - flw f6, 37*4(sp) // Recover ft6 - flw f7, 38*4(sp) // Recover ft7 - flw f8, 39*4(sp) // Recover fs0 - flw f9, 40*4(sp) // Recover fs1 - flw f10, 41*4(sp) // Recover fa0 - flw f11, 42*4(sp) // Recover fa1 - flw f12, 43*4(sp) // Recover fa2 - flw f13, 44*4(sp) // Recover fa3 - flw f14, 45*4(sp) // Recover fa4 - flw f15, 46*4(sp) // Recover fa5 - flw f16, 47*4(sp) // Recover fa6 - flw f17, 48*4(sp) // Recover fa7 - flw f18, 49*4(sp) // Recover fs2 - flw f19, 50*4(sp) // Recover fs3 - flw f20, 51*4(sp) // Recover fs4 - flw f21, 52*4(sp) // Recover fs5 - flw f22, 53*4(sp) // Recover fs6 - flw f23, 54*4(sp) // Recover fs7 - flw f24, 55*4(sp) // Recover fs8 - flw f25, 56*4(sp) // Recover fs9 - flw f26, 57*4(sp) // Recover fs10 - flw f27, 58*4(sp) // Recover fs11 - flw f28, 59*4(sp) // Recover ft8 - flw f29, 60*4(sp) // Recover ft9 - flw f30, 61*4(sp) // Recover ft10 - flw f31, 62*4(sp) // Recover ft11 - lw t0, 63*4(sp) // Recover fcsr + fld f0, 16*8(sp) // Recover ft0 + fld f1, 17*8(sp) // Recover ft1 + fld f2, 18*8(sp) // Recover ft2 + fld f3, 19*8(sp) // Recover ft3 + fld f4, 20*8(sp) // Recover ft4 + fld f5, 21*8(sp) // Recover ft5 + fld f6, 22*8(sp) // Recover ft6 + fld f7, 23*8(sp) // Recover ft7 + fld f8, 24*8(sp) // Recover fs0 + fld f9, 25*8(sp) // Recover fs1 + fld f10, 26*8(sp) // Recover fa0 + fld f11, 27*8(sp) // Recover fa1 + fld f12, 28*8(sp) // Recover fa2 + fld f13, 29*8(sp) // Recover fa3 + fld f14, 30*8(sp) // Recover fa4 + fld f15, 31*8(sp) // Recover fa5 + fld f16, 32*8(sp) // Recover fa6 + fld f17, 33*8(sp) // Recover fa7 + fld f18, 34*8(sp) // Recover fs2 + fld f19, 35*8(sp) // Recover fs3 + fld f20, 36*8(sp) // Recover fs4 + fld f21, 37*8(sp) // Recover fs5 + fld f22, 38*8(sp) // Recover fs6 + fld f23, 39*8(sp) // Recover fs7 + fld f24, 40*8(sp) // Recover fs8 + fld f25, 41*8(sp) // Recover fs9 + fld f26, 42*8(sp) // Recover fs10 + fld f27, 43*8(sp) // Recover fs11 + fld f28, 44*8(sp) // Recover ft8 + fld f29, 45*8(sp) // Recover ft9 + fld f30, 46*8(sp) // Recover ft10 + fld f31, 47*8(sp) // Recover ft11 + lw t0, 96*4(sp) // Recover fcsr csrw fcsr, t0 // Restore fcsr -#elif defined(__riscv_float_abi_double) - fld f0, 31*4(sp) // Recover ft0 - fld f1, 32*4(sp) // Recover ft1 - fld f2, 33*4(sp) // Recover ft2 - fld f3, 34*4(sp) // Recover ft3 - fld f4, 35*4(sp) // Recover ft4 - fld f5, 36*4(sp) // Recover ft5 - fld f6, 37*4(sp) // Recover ft6 - fld f7, 38*4(sp) // Recover ft7 - fld f8, 39*4(sp) // Recover fs0 - fld f9, 40*4(sp) // Recover fs1 - fld f10, 41*4(sp) // Recover fa0 - fld f11, 42*4(sp) // Recover fa1 - fld f12, 43*4(sp) // Recover fa2 - fld f13, 44*4(sp) // Recover fa3 - fld f14, 45*4(sp) // Recover fa4 - fld f15, 46*4(sp) // Recover fa5 - fld f16, 47*4(sp) // Recover fa6 - fld f17, 48*4(sp) // Recover fa7 - fld f18, 49*4(sp) // Recover fs2 - fld f19, 50*4(sp) // Recover fs3 - fld f20, 51*4(sp) // Recover fs4 - fld f21, 52*4(sp) // Recover fs5 - fld f22, 53*4(sp) // Recover fs6 - fld f23, 54*4(sp) // Recover fs7 - fld f24, 55*4(sp) // Recover fs8 - fld f25, 56*4(sp) // Recover fs9 - fld f26, 57*4(sp) // Recover fs10 - fld f27, 58*4(sp) // Recover fs11 - fld f28, 59*4(sp) // Recover ft8 - fld f29, 60*4(sp) // Recover ft9 - fld f30, 61*4(sp) // Recover ft10 - fld f31, 62*4(sp) // Recover ft11 - lw t0, 63*4(sp) // Recover fcsr - csrw fcsr, t0 // Restore fcsr -#endif _tx_thread_schedule_skip_fp_restore: #endif @@ -218,7 +186,7 @@ _tx_thread_schedule_skip_fp_restore: csrw mepc, t0 // Setup mepc li t0, 0x1880 // Prepare mstatus: MPP=Machine(0x1800) | MPIE(0x80) -#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) +#if defined(__riscv_float_abi_double) li t1, 0x2000 // Set FS bits for FP state or t0, t0, t1 #endif @@ -253,52 +221,31 @@ _tx_thread_schedule_skip_fp_restore: lw x26, 2*4(sp) // Recover s10 lw x27, 1*4(sp) // Recover s11 -#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - addi sp, sp, 65*4 // Recover stack frame - with floating point enabled -#else - addi sp, sp, 32*4 // Recover stack frame - without floating point enabled -#endif + addi sp, sp, TX_TRAP_FRAME_SIZE // Recover stack frame mret // Return to thread _tx_thread_solicited_return: /* Recover floating point registers only if saved mstatus.FS was not Off. */ -#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) +#if defined(__riscv_float_abi_double) lw t1, 14*4(sp) // Pickup saved mstatus srli t1, t1, 13 andi t1, t1, 0x3 beqz t1, _tx_thread_schedule_solicited_skip_fp_restore // Skip if FS was Off -#if defined(__riscv_float_abi_single) - flw f8, 15*4(sp) // Recover fs0 - flw f9, 16*4(sp) // Recover fs1 - flw f18, 17*4(sp) // Recover fs2 - flw f19, 18*4(sp) // Recover fs3 - flw f20, 19*4(sp) // Recover fs4 - flw f21, 20*4(sp) // Recover fs5 - flw f22, 21*4(sp) // Recover fs6 - flw f23, 22*4(sp) // Recover fs7 - flw f24, 23*4(sp) // Recover fs8 - flw f25, 24*4(sp) // Recover fs9 - flw f26, 25*4(sp) // Recover fs10 - flw f27, 26*4(sp) // Recover fs11 - lw t0, 27*4(sp) // Recover fcsr - csrw fcsr, t0 // Restore fcsr -#elif defined(__riscv_float_abi_double) - fld f8, 15*4(sp) // Recover fs0 - fld f9, 16*4(sp) // Recover fs1 - fld f18, 17*4(sp) // Recover fs2 - fld f19, 18*4(sp) // Recover fs3 - fld f20, 19*4(sp) // Recover fs4 - fld f21, 20*4(sp) // Recover fs5 - fld f22, 21*4(sp) // Recover fs6 - fld f23, 22*4(sp) // Recover fs7 - fld f24, 23*4(sp) // Recover fs8 - fld f25, 24*4(sp) // Recover fs9 - fld f26, 25*4(sp) // Recover fs10 - fld f27, 26*4(sp) // Recover fs11 - lw t0, 27*4(sp) // Recover fcsr + fld f8, 8*8(sp) // Recover fs0 + fld f9, 9*8(sp) // Recover fs1 + fld f18, 10*8(sp) // Recover fs2 + fld f19, 11*8(sp) // Recover fs3 + fld f20, 12*8(sp) // Recover fs4 + fld f21, 13*8(sp) // Recover fs5 + fld f22, 14*8(sp) // Recover fs6 + fld f23, 15*8(sp) // Recover fs7 + fld f24, 16*8(sp) // Recover fs8 + fld f25, 17*8(sp) // Recover fs9 + fld f26, 18*8(sp) // Recover fs10 + fld f27, 19*8(sp) // Recover fs11 + lw t0, 40*4(sp) // Recover fcsr csrw fcsr, t0 // Restore fcsr -#endif _tx_thread_schedule_solicited_skip_fp_restore: #endif @@ -320,11 +267,7 @@ _tx_thread_schedule_solicited_skip_fp_restore: lw x26, 2*4(sp) // Recover s10 lw x27, 1*4(sp) // Recover s11 -#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - addi sp, sp, 29*4 // Recover stack frame - with floating point enabled -#else - addi sp, sp, 16*4 // Recover stack frame - without floating point enabled -#endif + addi sp, sp, TX_SOL_FRAME_SIZE // Recover stack frame ret // Return to thread /* } */ diff --git a/ports/risc-v32/gnu/src/tx_thread_stack_build.S b/ports/risc-v32/gnu/src/tx_thread_stack_build.S index 4ade60ca6..3f7ae5d6e 100644 --- a/ports/risc-v32/gnu/src/tx_thread_stack_build.S +++ b/ports/risc-v32/gnu/src/tx_thread_stack_build.S @@ -21,6 +21,10 @@ .section .text + +#include "tx_port.h" + .equ TX_TRAP_FRAME_SIZE, TX_RISCV_TRAP_FRAME_SIZE + /**************************************************************************/ /* */ /* FUNCTION RELEASE */ @@ -92,42 +96,14 @@ _tx_thread_stack_build: x11 26 Initial a1 x10 27 Initial a0 x1 28 Initial ra - -- 29 reserved + mstatus 29 Initial mstatus seed mepc 30 Initial mepc -If floating point support: - f0 31 Initial ft0 - f1 32 Initial ft1 - f2 33 Initial ft2 - f3 34 Initial ft3 - f4 35 Initial ft4 - f5 36 Initial ft5 - f6 37 Initial ft6 - f7 38 Initial ft7 - f8 39 Initial fs0 - f9 40 Initial fs1 - f10 41 Initial fa0 - f11 42 Initial fa1 - f12 43 Initial fa2 - f13 44 Initial fa3 - f14 45 Initial fa4 - f15 46 Initial fa5 - f16 47 Initial fa6 - f17 48 Initial fa7 - f18 49 Initial fs2 - f19 50 Initial fs3 - f20 51 Initial fs4 - f21 52 Initial fs5 - f22 53 Initial fs6 - f23 54 Initial fs7 - f24 55 Initial fs8 - f25 56 Initial fs9 - f26 57 Initial fs10 - f27 58 Initial fs11 - f28 59 Initial ft8 - f29 60 Initial ft9 - f30 61 Initial ft10 - f31 62 Initial ft11 - fscr 63 Initial fscr + -- 31 pad (0) + If floating point support (double ABI), byte offsets from + the frame base: + f0-f31 128 + i*8 Initial FP registers (all 0) + fcsr 384 Initial fcsr (0) + pad 388-399 (0) Stack Bottom: (higher memory address) */ @@ -137,11 +113,7 @@ If floating point support: /* Actually build the stack frame. */ -#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - addi t0, t0, -65*4 -#else - addi t0, t0, -32*4 // Allocate space for the stack frame -#endif + addi t0, t0, -TX_TRAP_FRAME_SIZE // Allocate space for the stack frame li t1, 1 // Build stack type sw t1, 0*4(t0) // Place stack type on the top sw zero, 1*4(t0) // Initial s11 @@ -173,44 +145,22 @@ If floating point support: sw zero, 27*4(t0) // Initial a0 sw zero, 28*4(t0) // Initial ra sw a1, 30*4(t0) // Initial mepc (thread entry point) -#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - sw zero, 31*4(t0) // Initial ft0 - sw zero, 32*4(t0) // Initial ft1 - sw zero, 33*4(t0) // Initial ft2 - sw zero, 34*4(t0) // Initial ft3 - sw zero, 35*4(t0) // Initial ft4 - sw zero, 36*4(t0) // Initial ft5 - sw zero, 37*4(t0) // Initial ft6 - sw zero, 38*4(t0) // Initial ft7 - sw zero, 39*4(t0) // Initial fs0 - sw zero, 40*4(t0) // Initial fs1 - sw zero, 41*4(t0) // Initial fa0 - sw zero, 42*4(t0) // Initial fa1 - sw zero, 43*4(t0) // Initial fa2 - sw zero, 44*4(t0) // Initial fa3 - sw zero, 45*4(t0) // Initial fa4 - sw zero, 46*4(t0) // Initial fa5 - sw zero, 47*4(t0) // Initial fa6 - sw zero, 48*4(t0) // Initial fa7 - sw zero, 49*4(t0) // Initial fs2 - sw zero, 50*4(t0) // Initial fs3 - sw zero, 51*4(t0) // Initial fs4 - sw zero, 52*4(t0) // Initial fs5 - sw zero, 53*4(t0) // Initial fs6 - sw zero, 54*4(t0) // Initial fs7 - sw zero, 55*4(t0) // Initial fs8 - sw zero, 56*4(t0) // Initial fs9 - sw zero, 57*4(t0) // Initial fs10 - sw zero, 58*4(t0) // Initial fs11 - sw zero, 59*4(t0) // Initial ft8 - sw zero, 60*4(t0) // Initial ft9 - sw zero, 61*4(t0) // Initial ft10 - sw zero, 62*4(t0) // Initial ft11 - csrr a1, fcsr // Read fcsr for initial value - sw a1, 63*4(t0) // Initial fcsr - sw zero, 64*4(t0) // Reserved word (0) + sw zero, 31*4(t0) // Pad word (0) +#if defined(__riscv_float_abi_double) + li t1, 0x6000 // mstatus seed: FS = Dirty (bits 14:13 = 11) + sw t1, 29*4(t0) // so the first dispatch restores the clean FP state + + /* Zero the whole FP area: f0-f31 double slots (128-383), fcsr (384) + and the pad words up to the frame end. Threads start with clean + FP registers and fcsr = 0. */ + addi t1, t0, 32*4 // First FP-area word (offset 128) + addi t2, t0, TX_TRAP_FRAME_SIZE // One past the frame end (offset 400) +_tx_thread_stack_build_fp_zero: + sw zero, 0(t1) // Clear FP-area word + addi t1, t1, 4 + bne t1, t2, _tx_thread_stack_build_fp_zero #else - sw zero, 31*4(t0) // Reserved word (0) + sw zero, 29*4(t0) // Initial mstatus slot (0, no FP gate) #endif /* Setup stack pointer. */ diff --git a/ports/risc-v32/gnu/src/tx_thread_system_return.S b/ports/risc-v32/gnu/src/tx_thread_system_return.S index 20ff25f21..2e49bc3fe 100644 --- a/ports/risc-v32/gnu/src/tx_thread_system_return.S +++ b/ports/risc-v32/gnu/src/tx_thread_system_return.S @@ -21,6 +21,10 @@ .section .text + +#include "tx_port.h" + .equ TX_SOL_FRAME_SIZE, TX_RISCV_SOL_FRAME_SIZE + /**************************************************************************/ /* */ /* FUNCTION RELEASE */ @@ -63,54 +67,33 @@ _tx_thread_system_return: /* Save minimal context on the stack. */ /* sp -= sizeof(stack_frame); */ -#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) - addi sp, sp, -29*4 // Allocate space on the stack - with floating point enabled -#else - addi sp, sp, -16*4 // Allocate space on the stack - without floating point enabled -#endif + addi sp, sp, -TX_SOL_FRAME_SIZE // Allocate the solicited stack frame - sw zero, 0(sp) // Solicited stack type (store early so slot is always written) + sw zero, 0*4(sp) // Solicited stack type (store early so slot is always written) /* Read and save mstatus first; use it to guard FP register save. */ csrr t0, mstatus // Pickup current mstatus sw t0, 14*4(sp) // Save mstatus /* Store floating point preserved registers — only if FS != Off. */ -#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) +#if defined(__riscv_float_abi_double) srli t1, t0, 13 // Shift FS field to bits [1:0] andi t1, t1, 0x3 // Isolate FS bits beqz t1, _tx_thread_system_return_skip_fp // Skip FP save if FS == Off -#if defined(__riscv_float_abi_single) - fsw f8, 15*4(sp) // Store fs0 - fsw f9, 16*4(sp) // Store fs1 - fsw f18, 17*4(sp) // Store fs2 - fsw f19, 18*4(sp) // Store fs3 - fsw f20, 19*4(sp) // Store fs4 - fsw f21, 20*4(sp) // Store fs5 - fsw f22, 21*4(sp) // Store fs6 - fsw f23, 22*4(sp) // Store fs7 - fsw f24, 23*4(sp) // Store fs8 - fsw f25, 24*4(sp) // Store fs9 - fsw f26, 25*4(sp) // Store fs10 - fsw f27, 26*4(sp) // Store fs11 + fsd f8, 8*8(sp) // Store fs0 + fsd f9, 9*8(sp) // Store fs1 + fsd f18, 10*8(sp) // Store fs2 + fsd f19, 11*8(sp) // Store fs3 + fsd f20, 12*8(sp) // Store fs4 + fsd f21, 13*8(sp) // Store fs5 + fsd f22, 14*8(sp) // Store fs6 + fsd f23, 15*8(sp) // Store fs7 + fsd f24, 16*8(sp) // Store fs8 + fsd f25, 17*8(sp) // Store fs9 + fsd f26, 18*8(sp) // Store fs10 + fsd f27, 19*8(sp) // Store fs11 csrr t0, fcsr - sw t0, 27*4(sp) // Store fcsr -#elif defined(__riscv_float_abi_double) - fsd f8, 15*4(sp) // Store fs0 - fsd f9, 16*4(sp) // Store fs1 - fsd f18, 17*4(sp) // Store fs2 - fsd f19, 18*4(sp) // Store fs3 - fsd f20, 19*4(sp) // Store fs4 - fsd f21, 20*4(sp) // Store fs5 - fsd f22, 21*4(sp) // Store fs6 - fsd f23, 22*4(sp) // Store fs7 - fsd f24, 23*4(sp) // Store fs8 - fsd f25, 24*4(sp) // Store fs9 - fsd f26, 25*4(sp) // Store fs10 - fsd f27, 26*4(sp) // Store fs11 - csrr t0, fcsr - sw t0, 27*4(sp) // Store fcsr -#endif + sw t0, 40*4(sp) // Store fcsr _tx_thread_system_return_skip_fp: #endif diff --git a/ports/risc-v32/gnu/src/tx_timer_interrupt.S b/ports/risc-v32/gnu/src/tx_timer_interrupt.S index d3b2fc603..8b5d7df3d 100644 --- a/ports/risc-v32/gnu/src/tx_timer_interrupt.S +++ b/ports/risc-v32/gnu/src/tx_timer_interrupt.S @@ -88,7 +88,7 @@ _tx_timer_interrupt: /* Check for expiration. */ /* if (_tx_timer_time_slice == 0) */ - bgtz t3, _tx_timer_no_time_slice // If not 0, has not expired yet + bnez t3, _tx_timer_no_time_slice // If not 0, has not expired yet li t1, 1 // Build expired flag /* Set the time-slice expired flag. */ @@ -181,7 +181,7 @@ _tx_timer_dont_activate: /* if (_tx_timer_expired_time_slice) { */ - andi t2, t6, 1 // Is the timer expired bit set? + andi t2, t6, 1 // Is the time-slice expired bit set? beqz t2, _tx_timer_not_ts_expiration // If not, skip time slice processing /* Time slice interrupted thread. */ diff --git a/test/tx/cmake/riscv/bsp/entry.S b/test/tx/cmake/riscv/bsp/entry.S index 2f16c0525..5abe98523 100644 --- a/test/tx/cmake/riscv/bsp/entry.S +++ b/test/tx/cmake/riscv/bsp/entry.S @@ -18,6 +18,7 @@ .extern _sysstack_end .extern _bss_start .extern _bss_end +.extern __global_pointer$ _start: csrr t0, mhartid @@ -56,6 +57,11 @@ _start: li x30, 0 li x31, 0 + .option push + .option norelax + la gp, __global_pointer$ + .option pop + /* Set up stack pointer from linker symbol. */ la sp, _sysstack_end diff --git a/test/tx/cmake/riscv/bsp/hwtimer.c b/test/tx/cmake/riscv/bsp/hwtimer.c index 99821f1ee..8b81268a9 100644 --- a/test/tx/cmake/riscv/bsp/hwtimer.c +++ b/test/tx/cmake/riscv/bsp/hwtimer.c @@ -9,25 +9,99 @@ **************************************************************************/ #include "csr.h" +#include "tx_api.h" #include "hwtimer.h" -#include #define CLINT (0x02000000L) #define CLINT_TIME (CLINT + 0xBFF8) #define CLINT_TIMECMP(id) (CLINT + 0x4000 + 8 * (id)) +#if __riscv_xlen == 32 + +/* RV32 has no 64-bit load/store, so the 64-bit CLINT registers are + accessed as two volatile 32-bit MMIO words. */ +#define MTIME_LO (*(volatile uint32_t *)(CLINT_TIME)) +#define MTIME_HI (*(volatile uint32_t *)(CLINT_TIME + 4)) +#define MTIMECMP_LO(id) (*(volatile uint32_t *)(CLINT_TIMECMP(id))) +#define MTIMECMP_HI(id) (*(volatile uint32_t *)(CLINT_TIMECMP(id) + 4)) + +/* RV32 mtime read: re-read the high word until it is stable, so a + low-word rollover between the two loads cannot tear the value. */ +static uint64_t clint_time_read(void) +{ + uint32_t hi; + uint32_t lo; + + do + { + hi = MTIME_HI; + lo = MTIME_LO; + } while (hi != MTIME_HI); + + return ((uint64_t)hi << 32) | lo; +} + +/* Only this hart writes its own mtimecmp, so a plain two-word read + cannot tear. */ +static uint64_t clint_timecmp_read(uintptr_t hart) +{ + uint32_t lo = MTIMECMP_LO(hart); + uint32_t hi = MTIMECMP_HI(hart); + + return ((uint64_t)hi << 32) | lo; +} + +/* RV32 mtimecmp write, safe sequence: park the low word at all-ones + first, so no intermediate 64-bit value compares below mtime and + raises a spurious timer interrupt. */ +static void clint_timecmp_write(uintptr_t hart, uint64_t value) +{ + MTIMECMP_LO(hart) = 0xFFFFFFFF; + MTIMECMP_HI(hart) = (uint32_t)(value >> 32); + MTIMECMP_LO(hart) = (uint32_t)value; +} + +#else /* __riscv_xlen == 64 */ + +/* RV64: naturally aligned 64-bit MMIO accesses are single loads/stores. */ +static uint64_t clint_time_read(void) +{ + return *(volatile uint64_t *)CLINT_TIME; +} + +static uint64_t clint_timecmp_read(uintptr_t hart) +{ + return *(volatile uint64_t *)CLINT_TIMECMP(hart); +} + +static void clint_timecmp_write(uintptr_t hart, uint64_t value) +{ + *(volatile uint64_t *)CLINT_TIMECMP(hart) = value; +} + +#endif /* __riscv_xlen */ + int hwtimer_init(void) { uintptr_t hart = riscv_get_core(); - uint64_t time = *((volatile uint64_t *)CLINT_TIME); - *((volatile uint64_t *)CLINT_TIMECMP(hart)) = time + TICKNUM_PER_TIMER; + + clint_timecmp_write(hart, clint_time_read() + TICKNUM_PER_TIMER); return 0; } int hwtimer_handler(void) { uintptr_t hart = riscv_get_core(); - uint64_t time = *((volatile uint64_t *)CLINT_TIME); - *((volatile uint64_t *)CLINT_TIMECMP(hart)) = time + TICKNUM_PER_TIMER; + + /* Absolute re-arm: advance from the previous compare value, so trap + latency does not accumulate as tick drift; catch up if the next + compare already passed. */ + uint64_t next = clint_timecmp_read(hart) + TICKNUM_PER_TIMER; + uint64_t now = clint_time_read(); + + if (next <= now) + next = now + TICKNUM_PER_TIMER; + + clint_timecmp_write(hart, next); return 0; } diff --git a/test/tx/cmake/riscv/bsp/hwtimer.h b/test/tx/cmake/riscv/bsp/hwtimer.h index e6b9efa4e..bde0bba56 100644 --- a/test/tx/cmake/riscv/bsp/hwtimer.h +++ b/test/tx/cmake/riscv/bsp/hwtimer.h @@ -13,8 +13,8 @@ #include -#define TICKNUM_PER_SECOND 10000000 -#define TICKNUM_PER_TIMER (TICKNUM_PER_SECOND / 10) +#define TICKNUM_PER_SECOND 10000000UL +#define TICKNUM_PER_TIMER (TICKNUM_PER_SECOND / TX_TIMER_TICKS_PER_SECOND) int hwtimer_init(void); int hwtimer_handler(void); diff --git a/test/tx/cmake/riscv/bsp/link.lds b/test/tx/cmake/riscv/bsp/link.lds index 42f08fb6e..717530b3b 100644 --- a/test/tx/cmake/riscv/bsp/link.lds +++ b/test/tx/cmake/riscv/bsp/link.lds @@ -12,6 +12,12 @@ MEMORY RAM (rwx) : ORIGIN = 0x80000000, LENGTH = 128M } +PHDRS +{ + text PT_LOAD FLAGS(5); + data PT_LOAD FLAGS(6); +} + SECTIONS { . = 0x80000000; @@ -21,23 +27,24 @@ SECTIONS *(.text .text.*) . = ALIGN(0x1000); PROVIDE(etext = .); - } > RAM + } > RAM :text .rodata : { . = ALIGN(16); *(.srodata .srodata.*) . = ALIGN(16); *(.rodata .rodata.*) - } > RAM + } > RAM :text .data : { - . = ALIGN(16); + . = ALIGN(0x1000); + PROVIDE(__global_pointer$ = . + 0x800); *(.sdata .sdata.*) . = ALIGN(16); *(.data .data.*) - } > RAM + } > RAM :data - .bss : { + .bss (NOLOAD) : { . = ALIGN(16); _bss_start = .; *(.sbss .sbss.*) @@ -45,14 +52,23 @@ SECTIONS *(.bss .bss.*) *(COMMON) _bss_end = .; - } > RAM + } > RAM :data - .stack : { + .stack (NOLOAD) : { . = ALIGN(4096); _sysstack_start = .; . += 0x4000; _sysstack_end = .; - } > RAM + } > RAM :data + + /* Fixed 64 KiB newlib sbrk heap window. _end stays after it, so the + ThreadX first-unused-memory pointer starts past the heap. */ + .heap (NOLOAD) : { + . = ALIGN(16); + _heap_start = .; + . += 0x10000; + _heap_end = .; + } > RAM :data PROVIDE(_end = .); diff --git a/test/tx/cmake/riscv/bsp/plic.c b/test/tx/cmake/riscv/bsp/plic.c index a2b44feca..16dad815f 100644 --- a/test/tx/cmake/riscv/bsp/plic.c +++ b/test/tx/cmake/riscv/bsp/plic.c @@ -52,32 +52,47 @@ int plic_unregister_callback(int irqno) int plic_init(void) { + uintptr_t hart = riscv_get_core(); + for (int i = 0; i < MAX_CALLBACK_NUM; i++) { callbacks[i] = NULL; } + + /* Do not depend on the reset state or on a prior boot stage: accept + every priority (threshold 0) and start with all sources for this + hart disabled. */ + *(volatile uint32_t *)PLIC_MPRIORITY(hart) = 0; + for (int w = 0; w < MAX_CALLBACK_NUM / 32; w++) + *(volatile uint32_t *)(PLIC_MENABLE(hart) + w * 4) = 0; + return 0; } int plic_claim(void) { uintptr_t hart = riscv_get_core(); - return (int)(*(uint32_t *)PLIC_MCLAIM(hart)); + return (int)(*(volatile uint32_t *)PLIC_MCLAIM(hart)); } void plic_complete(int irqno) { uintptr_t hart = riscv_get_core(); - *(uint32_t *)(PLIC_MCOMPLETE(hart)) = (uint32_t)irqno; + *(volatile uint32_t *)(PLIC_MCOMPLETE(hart)) = (uint32_t)irqno; } int plic_irq_intr(void) { int ret = -1; int irqno = plic_claim(); - if (irqno <= 0 || irqno >= MAX_CALLBACK_NUM) { - plic_complete(irqno); - return 0; // spurious or out-of-range, not an error + + if (irqno == 0) + return 0; + + if (irqno < 0 || irqno >= MAX_CALLBACK_NUM) { + if (irqno > 0) + plic_complete(irqno); + return -1; } if (callbacks[irqno] != NULL) ret = (callbacks[irqno])(irqno); diff --git a/test/tx/cmake/riscv/bsp/syscalls.c b/test/tx/cmake/riscv/bsp/syscalls.c index 802fe8afa..40ca86f32 100644 --- a/test/tx/cmake/riscv/bsp/syscalls.c +++ b/test/tx/cmake/riscv/bsp/syscalls.c @@ -15,6 +15,7 @@ #include #include #include +#include #define UART0_THR (*(volatile unsigned char *)0x10000000L) #define UART0_LSR (*(volatile unsigned char *)0x10000005L) @@ -25,6 +26,39 @@ #define VIRT_TEST_PASS 0x5555u #define VIRT_TEST_FAIL 0x3333u +#define QEMU_TIMEBASE_HZ 10000000ULL + +static uint64_t read_time_counter(void) +{ +#if __riscv_xlen == 64 + uint64_t value; + __asm__ volatile("rdtime %0" : "=r" (value)); + return value; +#else + uint32_t high; + uint32_t low; + uint32_t high_check; + + do + { + __asm__ volatile("rdtimeh %0" : "=r" (high)); + __asm__ volatile("rdtime %0" : "=r" (low)); + __asm__ volatile("rdtimeh %0" : "=r" (high_check)); + } while (high != high_check); + + return ((uint64_t)high << 32) | low; +#endif +} + +time_t time(time_t *timer) +{ + time_t seconds = (time_t)(read_time_counter() / QEMU_TIMEBASE_HZ); + + if (timer != NULL) + *timer = seconds; + return seconds; +} + /* Called by testcontrol.c when EXTERNAL_EXIT is defined. */ __attribute__((noreturn)) void external_exit(unsigned int code) { @@ -50,13 +84,24 @@ int _write(int fd, const char *buf, int count) return count; } -extern char _end[]; +/* Fixed 64 KiB heap window from the linker script. It keeps the newlib + heap out of the ThreadX first-unused-memory area, which starts at + _end (placed after _heap_end). */ +extern char _heap_start[]; +extern char _heap_end[]; static char *heap_ptr = 0; void *_sbrk(int incr) { if (heap_ptr == 0) - heap_ptr = _end; + heap_ptr = _heap_start; + + if ((incr > 0 && _heap_end - heap_ptr < incr) || + (incr < 0 && heap_ptr - _heap_start < -incr)) + { + errno = ENOMEM; + return (void *)-1; + } char *prev = heap_ptr; heap_ptr += incr; diff --git a/test/tx/cmake/riscv/bsp/trap.c b/test/tx/cmake/riscv/bsp/trap.c index 0ac7990ac..f54ea2ffa 100644 --- a/test/tx/cmake/riscv/bsp/trap.c +++ b/test/tx/cmake/riscv/bsp/trap.c @@ -36,9 +36,6 @@ extern void _exit(int code) __attribute__((noreturn)); void trap_handler(uintptr_t mcause, uintptr_t mepc, uintptr_t mtval) { - (void)mepc; - (void)mtval; - if (OS_IS_INTERUPT(mcause)) { if (OS_IS_TICK_INT(mcause)) diff --git a/test/tx/cmake/riscv/bsp/tx_initialize_low_level.S b/test/tx/cmake/riscv/bsp/tx_initialize_low_level.S index 327946bb0..5a1cbcd6a 100644 --- a/test/tx/cmake/riscv/bsp/tx_initialize_low_level.S +++ b/test/tx/cmake/riscv/bsp/tx_initialize_low_level.S @@ -99,7 +99,7 @@ _tx_initialize_low_level: csrrc zero, mstatus, t0 li t0, (MSTATUS_MPP_M | MSTATUS_MPIE) csrrs zero, mstatus, t0 - li t0, (MIE_MTIE | MIE_MSIE | MIE_MEIE) + li t0, (MIE_MTIE | MIE_MEIE) // No MSIE: software interrupts are never dispatched here csrrs zero, mie, t0 #ifdef __riscv_flen From 4d90a0c21c2eea06aee1d43705ff8a02f393421f Mon Sep 17 00:00:00 2001 From: Spencer Oliver <264539+ntfreak@users.noreply.github.com> Date: Wed, 9 Sep 2026 18:39:13 +0100 Subject: [PATCH 115/181] Stopped the win32 and win64 ports from enabling performance metrics and event trace (#676) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * win32: do not always enable trace or performance metrics in tx_port.h if these are required they can be enabled in tx_user.h * win64: do not always enable performance metrics in tx_port.h if required they can be enabled in tx_user.h * Removed the disabled blocks rather than commenting them out The win32 and win64 ports were the only two that turned performance metrics on for the application, and win32 the only one that turned event trace on. Leaving those to tx_user.h is right: the symbols extend the control blocks, so a port that sets them behind the application's back changes structures the application also sees. The blocks were disabled with #if 0 rather than deleted. That is the form MISRA C:2012 Directive 4.4 is about -- sections of code should not be commented out -- and it leaves two copies of a list that now has no reader. They are removed, and a short note in their place says where the symbols belong and why the port does not set them. No behaviour change beyond what this pull request already made. Checked that the preprocessor nesting in both headers is still balanced. Worth recording for whoever looks next: with this in, no port defines either symbol. The linux port carries the same list commented out, which reads at a glance like a third case but is not one. Assisted-by: Claude Code (Opus 5) --------- Co-authored-by: r Co-authored-by: Frédéric Desbiens --- ports/win32/vs_2019/inc/tx_port.h | 47 ++++--------------------------- ports/win64/vs_2022/inc/tx_port.h | 42 ++++----------------------- 2 files changed, 12 insertions(+), 77 deletions(-) diff --git a/ports/win32/vs_2019/inc/tx_port.h b/ports/win32/vs_2019/inc/tx_port.h index 5dd656534..655a2f697 100644 --- a/ports/win32/vs_2019/inc/tx_port.h +++ b/ports/win32/vs_2019/inc/tx_port.h @@ -155,47 +155,12 @@ extern TEST_FLAG test_forced_mutex_timeout; #endif - -/* Define performance metric symbols. */ - -#ifndef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO -#define TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO -#endif - -#ifndef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO -#define TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO -#endif - -#ifndef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO -#define TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO -#endif - -#ifndef TX_MUTEX_ENABLE_PERFORMANCE_INFO -#define TX_MUTEX_ENABLE_PERFORMANCE_INFO -#endif - -#ifndef TX_QUEUE_ENABLE_PERFORMANCE_INFO -#define TX_QUEUE_ENABLE_PERFORMANCE_INFO -#endif - -#ifndef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO -#define TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO -#endif - -#ifndef TX_THREAD_ENABLE_PERFORMANCE_INFO -#define TX_THREAD_ENABLE_PERFORMANCE_INFO -#endif - -#ifndef TX_TIMER_ENABLE_PERFORMANCE_INFO -#define TX_TIMER_ENABLE_PERFORMANCE_INFO -#endif - -/* Enable trace info. */ - -#ifndef TX_ENABLE_EVENT_TRACE -#define TX_ENABLE_EVENT_TRACE -#endif - +/* Performance metrics and event trace are left to the application. Set the + TX_*_ENABLE_PERFORMANCE_INFO symbols, or TX_ENABLE_EVENT_TRACE, in + tx_user.h or on the command line when they are wanted. They extend the + control blocks, so a port that turns them on behind the application's + back changes structures the application also sees. This port and the + win64 one were the only two that did. */ /* Define ThreadX basic types for this port. */ diff --git a/ports/win64/vs_2022/inc/tx_port.h b/ports/win64/vs_2022/inc/tx_port.h index 2a44237d8..eeabf651c 100644 --- a/ports/win64/vs_2022/inc/tx_port.h +++ b/ports/win64/vs_2022/inc/tx_port.h @@ -160,42 +160,12 @@ extern TEST_FLAG test_forced_mutex_timeout; #endif - -/* Define performance metric symbols. */ - -#ifndef TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO -#define TX_BLOCK_POOL_ENABLE_PERFORMANCE_INFO -#endif - -#ifndef TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO -#define TX_BYTE_POOL_ENABLE_PERFORMANCE_INFO -#endif - -#ifndef TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO -#define TX_EVENT_FLAGS_ENABLE_PERFORMANCE_INFO -#endif - -#ifndef TX_MUTEX_ENABLE_PERFORMANCE_INFO -#define TX_MUTEX_ENABLE_PERFORMANCE_INFO -#endif - -#ifndef TX_QUEUE_ENABLE_PERFORMANCE_INFO -#define TX_QUEUE_ENABLE_PERFORMANCE_INFO -#endif - -#ifndef TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO -#define TX_SEMAPHORE_ENABLE_PERFORMANCE_INFO -#endif - -#ifndef TX_THREAD_ENABLE_PERFORMANCE_INFO -#define TX_THREAD_ENABLE_PERFORMANCE_INFO -#endif - -#ifndef TX_TIMER_ENABLE_PERFORMANCE_INFO -#define TX_TIMER_ENABLE_PERFORMANCE_INFO -#endif - - +/* Performance metrics and event trace are left to the application. Set the + TX_*_ENABLE_PERFORMANCE_INFO symbols, or TX_ENABLE_EVENT_TRACE, in + tx_user.h or on the command line when they are wanted. They extend the + control blocks, so a port that turns them on behind the application's + back changes structures the application also sees. This port and the + win32 one were the only two that did. */ /* Define ThreadX basic types for this port. */ From 6ce8d5cc7616334b90aaa9679b33321b95195d1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Wed, 9 Sep 2026 14:27:02 -0400 Subject: [PATCH 116/181] Marked every published ThreadX include directory as SYSTEM so applications no longer get warnings from ThreadX headers (#713) * Marked every published ThreadX include directory as SYSTEM so applications no longer get warnings from ThreadX headers Commit 8c3c08f added the SYSTEM keyword to the target_include_directories call in common/CMakeLists.txt, but the same call in every port, in the SMP common directory's consumers, in the POSIX and FreeRTOS compatibility layers, and for the generated tx_user.h directory was left unchanged. A consumer building with a strict warning set therefore still saw diagnostics coming from tx_port.h and from the compatibility layer headers, which is exactly what the original change set out to avoid. Added the SYSTEM keyword to all of those calls so CMake emits -isystem rather than -I for every directory holding a ThreadX public header. The ARMv7-M, ARMv8-M, ARMv7-A and ARMv8-A architecture sources under ports_arch were updated alongside the ports they generate, keeping the two in step. Directories that are PRIVATE to an example or test build were left as they are, since nothing is published from them. Fixes #290 Assisted-by: Copilot (Opus 5) * Stopped apt-get update being a gate it was never meant to be apt-get update fails if any configured repository serves a bad index, including ones this project never reads. The GitHub runner image carries Google's and Microsoft's apt repositories, and a Hash Sum mismatch from Google's, their CDN caught mid-publish with the index and the Release file eight hours apart, failed all three attempts and turned a run red over a browser nobody was installing. Made a failed update warn and carry on, leaving apt-get install as the gate. Nothing is weakened by that: the install still exits on a package it cannot find, so an unreachable archive still stops the script, one step later and naming the package it could not get, which is a better diagnostic than a hash mismatch in a repository nobody asked for. Disabling third-party sources before updating would keep the update strict, but this script also runs on a contributor's own machine, and rewriting someone's apt configuration to suit CI would be worse than tolerating a stale index for an archive we do not read. Assisted-by: Copilot (Opus 5) --- CMakeLists.txt | 2 ++ ports/arm11/gnu/CMakeLists.txt | 1 + ports/arm9/gnu/CMakeLists.txt | 1 + ports/cortex_a12/gnu/CMakeLists.txt | 1 + ports/cortex_a15/gnu/CMakeLists.txt | 1 + ports/cortex_a17/gnu/CMakeLists.txt | 1 + ports/cortex_a34/gnu/CMakeLists.txt | 1 + ports/cortex_a35/gnu/CMakeLists.txt | 1 + ports/cortex_a5/gnu/CMakeLists.txt | 1 + ports/cortex_a53/gnu/CMakeLists.txt | 1 + ports/cortex_a55/gnu/CMakeLists.txt | 1 + ports/cortex_a57/gnu/CMakeLists.txt | 1 + ports/cortex_a65/gnu/CMakeLists.txt | 1 + ports/cortex_a65ae/gnu/CMakeLists.txt | 1 + ports/cortex_a7/gnu/CMakeLists.txt | 1 + ports/cortex_a72/gnu/CMakeLists.txt | 1 + ports/cortex_a73/gnu/CMakeLists.txt | 1 + ports/cortex_a75/gnu/CMakeLists.txt | 1 + ports/cortex_a76/gnu/CMakeLists.txt | 1 + ports/cortex_a76ae/gnu/CMakeLists.txt | 1 + ports/cortex_a77/gnu/CMakeLists.txt | 1 + ports/cortex_a8/gnu/CMakeLists.txt | 1 + ports/cortex_a9/gnu/CMakeLists.txt | 1 + ports/cortex_m0/gnu/CMakeLists.txt | 1 + ports/cortex_m0/iar/CMakeLists.txt | 1 + ports/cortex_m23/gnu/CMakeLists.txt | 1 + ports/cortex_m3/gnu/CMakeLists.txt | 1 + ports/cortex_m3/iar/CMakeLists.txt | 1 + ports/cortex_m33/ac6/CMakeLists.txt | 4 ++- ports/cortex_m33/gnu/CMakeLists.txt | 1 + ports/cortex_m4/gnu/CMakeLists.txt | 1 + ports/cortex_m4/iar/CMakeLists.txt | 1 + ports/cortex_m52/ac6/CMakeLists.txt | 4 ++- ports/cortex_m52/gnu/CMakeLists.txt | 1 + ports/cortex_m55/ac6/CMakeLists.txt | 4 ++- ports/cortex_m55/gnu/CMakeLists.txt | 1 + ports/cortex_m7/gnu/CMakeLists.txt | 4 ++- ports/cortex_m7/iar/CMakeLists.txt | 1 + ports/cortex_m85/ac6/CMakeLists.txt | 4 ++- ports/cortex_m85/gnu/CMakeLists.txt | 1 + ports/cortex_r4/gnu/CMakeLists.txt | 1 + ports/cortex_r5/gnu/CMakeLists.txt | 1 + ports/cortex_r52/gnu/CMakeLists.txt | 1 + ports/linux/gnu/CMakeLists.txt | 1 + ports/rxv1/ccrx/CMakeLists.txt | 1 + ports/rxv1/gnu/CMakeLists.txt | 1 + ports/rxv2/ccrx/CMakeLists.txt | 1 + ports/rxv2/gnu/CMakeLists.txt | 1 + ports/rxv3/ccrx/CMakeLists.txt | 1 + ports/rxv3/gnu/CMakeLists.txt | 1 + ports/win32/vs_2019/CMakeLists.txt | 1 + ports/win64/vs_2022/CMakeLists.txt | 1 + ports/xtensa/xcc/CMakeLists.txt | 1 + .../ARMv7-A/threadx/ports/gnu/CMakeLists.txt | 1 + ports_arch/ARMv7-M/threadx/gnu/CMakeLists.txt | 4 ++- .../ARMv8-A/threadx/ports/gnu/CMakeLists.txt | 1 + .../threadx_smp/ports/gnu/CMakeLists.txt | 1 + ports_arch/ARMv8-M/threadx/ac6/CMakeLists.txt | 4 ++- ports_arch/ARMv8-M/threadx/gnu/CMakeLists.txt | 1 + ports_smp/cortex_a34_smp/gnu/CMakeLists.txt | 1 + ports_smp/cortex_a35_smp/gnu/CMakeLists.txt | 1 + ports_smp/cortex_a53_smp/gnu/CMakeLists.txt | 1 + ports_smp/cortex_a55_smp/gnu/CMakeLists.txt | 1 + ports_smp/cortex_a57_smp/gnu/CMakeLists.txt | 1 + ports_smp/cortex_a5_smp/gnu/CMakeLists.txt | 1 + ports_smp/cortex_a5x_smp/gnu/CMakeLists.txt | 1 + ports_smp/cortex_a65_smp/gnu/CMakeLists.txt | 1 + ports_smp/cortex_a65ae_smp/gnu/CMakeLists.txt | 1 + ports_smp/cortex_a72_smp/gnu/CMakeLists.txt | 1 + ports_smp/cortex_a73_smp/gnu/CMakeLists.txt | 1 + ports_smp/cortex_a75_smp/gnu/CMakeLists.txt | 1 + ports_smp/cortex_a76_smp/gnu/CMakeLists.txt | 1 + ports_smp/cortex_a76ae_smp/gnu/CMakeLists.txt | 1 + ports_smp/cortex_a77_smp/gnu/CMakeLists.txt | 1 + ports_smp/cortex_a78_smp/gnu/CMakeLists.txt | 1 + ports_smp/cortex_a7_smp/gnu/CMakeLists.txt | 1 + ports_smp/cortex_a9_smp/gnu/CMakeLists.txt | 1 + ports_smp/linux/gnu/CMakeLists.txt | 1 + .../mips32_interaptiv_smp/gnu/CMakeLists.txt | 1 + ports_smp/win64/vs_2022/CMakeLists.txt | 1 + scripts/install.sh | 29 +++++++++++++++++-- test/smp/cmake/threadx_smp/CMakeLists.txt | 1 + .../threadx_smp/common_smp/CMakeLists.txt | 1 + .../ports_smp/linux/gnu/CMakeLists.txt | 1 + .../ports_smp/win64/vs_2022/CMakeLists.txt | 1 + .../posix/CMakeLists.txt | 1 + 86 files changed, 127 insertions(+), 9 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9fbe6982b..940717df9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -73,6 +73,7 @@ add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/${TX_COMMON_DIR}) # Define the FreeRTOS adaptation layer add_library(freertos-threadx EXCLUDE_FROM_ALL) target_include_directories(freertos-threadx + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/utility/rtos_compatibility_layers/FreeRTOS ) @@ -109,6 +110,7 @@ else() endif() configure_file(${TX_USER_FILE} ${CUSTOM_INC_DIR}/tx_user.h COPYONLY) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CUSTOM_INC_DIR} ) diff --git a/ports/arm11/gnu/CMakeLists.txt b/ports/arm11/gnu/CMakeLists.txt index 208d51751..83d7e0fa8 100644 --- a/ports/arm11/gnu/CMakeLists.txt +++ b/ports/arm11/gnu/CMakeLists.txt @@ -27,6 +27,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports/arm9/gnu/CMakeLists.txt b/ports/arm9/gnu/CMakeLists.txt index 669cedc2c..6d071937c 100644 --- a/ports/arm9/gnu/CMakeLists.txt +++ b/ports/arm9/gnu/CMakeLists.txt @@ -27,6 +27,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports/cortex_a12/gnu/CMakeLists.txt b/ports/cortex_a12/gnu/CMakeLists.txt index 531df96e1..d03910d1d 100644 --- a/ports/cortex_a12/gnu/CMakeLists.txt +++ b/ports/cortex_a12/gnu/CMakeLists.txt @@ -28,6 +28,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports/cortex_a15/gnu/CMakeLists.txt b/ports/cortex_a15/gnu/CMakeLists.txt index 531df96e1..d03910d1d 100644 --- a/ports/cortex_a15/gnu/CMakeLists.txt +++ b/ports/cortex_a15/gnu/CMakeLists.txt @@ -28,6 +28,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports/cortex_a17/gnu/CMakeLists.txt b/ports/cortex_a17/gnu/CMakeLists.txt index 531df96e1..d03910d1d 100644 --- a/ports/cortex_a17/gnu/CMakeLists.txt +++ b/ports/cortex_a17/gnu/CMakeLists.txt @@ -28,6 +28,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports/cortex_a34/gnu/CMakeLists.txt b/ports/cortex_a34/gnu/CMakeLists.txt index 25e5b6b89..12a58cbeb 100644 --- a/ports/cortex_a34/gnu/CMakeLists.txt +++ b/ports/cortex_a34/gnu/CMakeLists.txt @@ -24,6 +24,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports/cortex_a35/gnu/CMakeLists.txt b/ports/cortex_a35/gnu/CMakeLists.txt index 25e5b6b89..12a58cbeb 100644 --- a/ports/cortex_a35/gnu/CMakeLists.txt +++ b/ports/cortex_a35/gnu/CMakeLists.txt @@ -24,6 +24,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports/cortex_a5/gnu/CMakeLists.txt b/ports/cortex_a5/gnu/CMakeLists.txt index 531df96e1..d03910d1d 100644 --- a/ports/cortex_a5/gnu/CMakeLists.txt +++ b/ports/cortex_a5/gnu/CMakeLists.txt @@ -28,6 +28,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports/cortex_a53/gnu/CMakeLists.txt b/ports/cortex_a53/gnu/CMakeLists.txt index 25e5b6b89..12a58cbeb 100644 --- a/ports/cortex_a53/gnu/CMakeLists.txt +++ b/ports/cortex_a53/gnu/CMakeLists.txt @@ -24,6 +24,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports/cortex_a55/gnu/CMakeLists.txt b/ports/cortex_a55/gnu/CMakeLists.txt index 25e5b6b89..12a58cbeb 100644 --- a/ports/cortex_a55/gnu/CMakeLists.txt +++ b/ports/cortex_a55/gnu/CMakeLists.txt @@ -24,6 +24,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports/cortex_a57/gnu/CMakeLists.txt b/ports/cortex_a57/gnu/CMakeLists.txt index 25e5b6b89..12a58cbeb 100644 --- a/ports/cortex_a57/gnu/CMakeLists.txt +++ b/ports/cortex_a57/gnu/CMakeLists.txt @@ -24,6 +24,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports/cortex_a65/gnu/CMakeLists.txt b/ports/cortex_a65/gnu/CMakeLists.txt index 25e5b6b89..12a58cbeb 100644 --- a/ports/cortex_a65/gnu/CMakeLists.txt +++ b/ports/cortex_a65/gnu/CMakeLists.txt @@ -24,6 +24,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports/cortex_a65ae/gnu/CMakeLists.txt b/ports/cortex_a65ae/gnu/CMakeLists.txt index 25e5b6b89..12a58cbeb 100644 --- a/ports/cortex_a65ae/gnu/CMakeLists.txt +++ b/ports/cortex_a65ae/gnu/CMakeLists.txt @@ -24,6 +24,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports/cortex_a7/gnu/CMakeLists.txt b/ports/cortex_a7/gnu/CMakeLists.txt index 531df96e1..d03910d1d 100644 --- a/ports/cortex_a7/gnu/CMakeLists.txt +++ b/ports/cortex_a7/gnu/CMakeLists.txt @@ -28,6 +28,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports/cortex_a72/gnu/CMakeLists.txt b/ports/cortex_a72/gnu/CMakeLists.txt index 25e5b6b89..12a58cbeb 100644 --- a/ports/cortex_a72/gnu/CMakeLists.txt +++ b/ports/cortex_a72/gnu/CMakeLists.txt @@ -24,6 +24,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports/cortex_a73/gnu/CMakeLists.txt b/ports/cortex_a73/gnu/CMakeLists.txt index 25e5b6b89..12a58cbeb 100644 --- a/ports/cortex_a73/gnu/CMakeLists.txt +++ b/ports/cortex_a73/gnu/CMakeLists.txt @@ -24,6 +24,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports/cortex_a75/gnu/CMakeLists.txt b/ports/cortex_a75/gnu/CMakeLists.txt index 25e5b6b89..12a58cbeb 100644 --- a/ports/cortex_a75/gnu/CMakeLists.txt +++ b/ports/cortex_a75/gnu/CMakeLists.txt @@ -24,6 +24,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports/cortex_a76/gnu/CMakeLists.txt b/ports/cortex_a76/gnu/CMakeLists.txt index 25e5b6b89..12a58cbeb 100644 --- a/ports/cortex_a76/gnu/CMakeLists.txt +++ b/ports/cortex_a76/gnu/CMakeLists.txt @@ -24,6 +24,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports/cortex_a76ae/gnu/CMakeLists.txt b/ports/cortex_a76ae/gnu/CMakeLists.txt index 25e5b6b89..12a58cbeb 100644 --- a/ports/cortex_a76ae/gnu/CMakeLists.txt +++ b/ports/cortex_a76ae/gnu/CMakeLists.txt @@ -24,6 +24,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports/cortex_a77/gnu/CMakeLists.txt b/ports/cortex_a77/gnu/CMakeLists.txt index 25e5b6b89..12a58cbeb 100644 --- a/ports/cortex_a77/gnu/CMakeLists.txt +++ b/ports/cortex_a77/gnu/CMakeLists.txt @@ -24,6 +24,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports/cortex_a8/gnu/CMakeLists.txt b/ports/cortex_a8/gnu/CMakeLists.txt index 531df96e1..d03910d1d 100644 --- a/ports/cortex_a8/gnu/CMakeLists.txt +++ b/ports/cortex_a8/gnu/CMakeLists.txt @@ -28,6 +28,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports/cortex_a9/gnu/CMakeLists.txt b/ports/cortex_a9/gnu/CMakeLists.txt index 531df96e1..d03910d1d 100644 --- a/ports/cortex_a9/gnu/CMakeLists.txt +++ b/ports/cortex_a9/gnu/CMakeLists.txt @@ -28,6 +28,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports/cortex_m0/gnu/CMakeLists.txt b/ports/cortex_m0/gnu/CMakeLists.txt index 0e3cc8ecd..3c318e650 100755 --- a/ports/cortex_m0/gnu/CMakeLists.txt +++ b/ports/cortex_m0/gnu/CMakeLists.txt @@ -16,6 +16,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports/cortex_m0/iar/CMakeLists.txt b/ports/cortex_m0/iar/CMakeLists.txt index 57be3aebc..e95835027 100644 --- a/ports/cortex_m0/iar/CMakeLists.txt +++ b/ports/cortex_m0/iar/CMakeLists.txt @@ -16,6 +16,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports/cortex_m23/gnu/CMakeLists.txt b/ports/cortex_m23/gnu/CMakeLists.txt index 93f52d68f..e7c71e07d 100644 --- a/ports/cortex_m23/gnu/CMakeLists.txt +++ b/ports/cortex_m23/gnu/CMakeLists.txt @@ -28,6 +28,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports/cortex_m3/gnu/CMakeLists.txt b/ports/cortex_m3/gnu/CMakeLists.txt index 71e2d4f2e..1507e7362 100755 --- a/ports/cortex_m3/gnu/CMakeLists.txt +++ b/ports/cortex_m3/gnu/CMakeLists.txt @@ -13,6 +13,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports/cortex_m3/iar/CMakeLists.txt b/ports/cortex_m3/iar/CMakeLists.txt index 57be3aebc..e95835027 100644 --- a/ports/cortex_m3/iar/CMakeLists.txt +++ b/ports/cortex_m3/iar/CMakeLists.txt @@ -16,6 +16,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports/cortex_m33/ac6/CMakeLists.txt b/ports/cortex_m33/ac6/CMakeLists.txt index 5ad3b8e75..81b479e0c 100644 --- a/ports/cortex_m33/ac6/CMakeLists.txt +++ b/ports/cortex_m33/ac6/CMakeLists.txt @@ -16,6 +16,8 @@ target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S ) -target_include_directories(${PROJECT_NAME} PUBLIC +target_include_directories(${PROJECT_NAME} + SYSTEM + PUBLIC inc ) diff --git a/ports/cortex_m33/gnu/CMakeLists.txt b/ports/cortex_m33/gnu/CMakeLists.txt index 763a2696c..a8e45b82f 100644 --- a/ports/cortex_m33/gnu/CMakeLists.txt +++ b/ports/cortex_m33/gnu/CMakeLists.txt @@ -19,6 +19,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports/cortex_m4/gnu/CMakeLists.txt b/ports/cortex_m4/gnu/CMakeLists.txt index 71e2d4f2e..1507e7362 100755 --- a/ports/cortex_m4/gnu/CMakeLists.txt +++ b/ports/cortex_m4/gnu/CMakeLists.txt @@ -13,6 +13,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports/cortex_m4/iar/CMakeLists.txt b/ports/cortex_m4/iar/CMakeLists.txt index 57be3aebc..e95835027 100644 --- a/ports/cortex_m4/iar/CMakeLists.txt +++ b/ports/cortex_m4/iar/CMakeLists.txt @@ -16,6 +16,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports/cortex_m52/ac6/CMakeLists.txt b/ports/cortex_m52/ac6/CMakeLists.txt index 5ad3b8e75..81b479e0c 100644 --- a/ports/cortex_m52/ac6/CMakeLists.txt +++ b/ports/cortex_m52/ac6/CMakeLists.txt @@ -16,6 +16,8 @@ target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S ) -target_include_directories(${PROJECT_NAME} PUBLIC +target_include_directories(${PROJECT_NAME} + SYSTEM + PUBLIC inc ) diff --git a/ports/cortex_m52/gnu/CMakeLists.txt b/ports/cortex_m52/gnu/CMakeLists.txt index 763a2696c..a8e45b82f 100644 --- a/ports/cortex_m52/gnu/CMakeLists.txt +++ b/ports/cortex_m52/gnu/CMakeLists.txt @@ -19,6 +19,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports/cortex_m55/ac6/CMakeLists.txt b/ports/cortex_m55/ac6/CMakeLists.txt index 5ad3b8e75..81b479e0c 100644 --- a/ports/cortex_m55/ac6/CMakeLists.txt +++ b/ports/cortex_m55/ac6/CMakeLists.txt @@ -16,6 +16,8 @@ target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S ) -target_include_directories(${PROJECT_NAME} PUBLIC +target_include_directories(${PROJECT_NAME} + SYSTEM + PUBLIC inc ) diff --git a/ports/cortex_m55/gnu/CMakeLists.txt b/ports/cortex_m55/gnu/CMakeLists.txt index 763a2696c..a8e45b82f 100644 --- a/ports/cortex_m55/gnu/CMakeLists.txt +++ b/ports/cortex_m55/gnu/CMakeLists.txt @@ -19,6 +19,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports/cortex_m7/gnu/CMakeLists.txt b/ports/cortex_m7/gnu/CMakeLists.txt index 6a8d58525..7285f9d4b 100755 --- a/ports/cortex_m7/gnu/CMakeLists.txt +++ b/ports/cortex_m7/gnu/CMakeLists.txt @@ -11,6 +11,8 @@ target_sources(${PROJECT_NAME} PRIVATE # {{END_TARGET_SOURCES}} ) -target_include_directories(${PROJECT_NAME} PUBLIC +target_include_directories(${PROJECT_NAME} + SYSTEM + PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports/cortex_m7/iar/CMakeLists.txt b/ports/cortex_m7/iar/CMakeLists.txt index 57be3aebc..e95835027 100644 --- a/ports/cortex_m7/iar/CMakeLists.txt +++ b/ports/cortex_m7/iar/CMakeLists.txt @@ -16,6 +16,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports/cortex_m85/ac6/CMakeLists.txt b/ports/cortex_m85/ac6/CMakeLists.txt index 5ad3b8e75..81b479e0c 100644 --- a/ports/cortex_m85/ac6/CMakeLists.txt +++ b/ports/cortex_m85/ac6/CMakeLists.txt @@ -16,6 +16,8 @@ target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S ) -target_include_directories(${PROJECT_NAME} PUBLIC +target_include_directories(${PROJECT_NAME} + SYSTEM + PUBLIC inc ) diff --git a/ports/cortex_m85/gnu/CMakeLists.txt b/ports/cortex_m85/gnu/CMakeLists.txt index 763a2696c..a8e45b82f 100644 --- a/ports/cortex_m85/gnu/CMakeLists.txt +++ b/ports/cortex_m85/gnu/CMakeLists.txt @@ -19,6 +19,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports/cortex_r4/gnu/CMakeLists.txt b/ports/cortex_r4/gnu/CMakeLists.txt index a5d37879c..b40b5b998 100644 --- a/ports/cortex_r4/gnu/CMakeLists.txt +++ b/ports/cortex_r4/gnu/CMakeLists.txt @@ -28,6 +28,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports/cortex_r5/gnu/CMakeLists.txt b/ports/cortex_r5/gnu/CMakeLists.txt index bb1864ef3..46d1dadb7 100644 --- a/ports/cortex_r5/gnu/CMakeLists.txt +++ b/ports/cortex_r5/gnu/CMakeLists.txt @@ -28,6 +28,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports/cortex_r52/gnu/CMakeLists.txt b/ports/cortex_r52/gnu/CMakeLists.txt index 26ca3028f..957e2cbed 100644 --- a/ports/cortex_r52/gnu/CMakeLists.txt +++ b/ports/cortex_r52/gnu/CMakeLists.txt @@ -26,6 +26,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports/linux/gnu/CMakeLists.txt b/ports/linux/gnu/CMakeLists.txt index 073f4b7e2..17138044f 100644 --- a/ports/linux/gnu/CMakeLists.txt +++ b/ports/linux/gnu/CMakeLists.txt @@ -15,6 +15,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports/rxv1/ccrx/CMakeLists.txt b/ports/rxv1/ccrx/CMakeLists.txt index f2269c518..4118eb376 100644 --- a/ports/rxv1/ccrx/CMakeLists.txt +++ b/ports/rxv1/ccrx/CMakeLists.txt @@ -14,6 +14,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports/rxv1/gnu/CMakeLists.txt b/ports/rxv1/gnu/CMakeLists.txt index 9357c6970..1735b774b 100644 --- a/ports/rxv1/gnu/CMakeLists.txt +++ b/ports/rxv1/gnu/CMakeLists.txt @@ -14,6 +14,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports/rxv2/ccrx/CMakeLists.txt b/ports/rxv2/ccrx/CMakeLists.txt index f2269c518..4118eb376 100644 --- a/ports/rxv2/ccrx/CMakeLists.txt +++ b/ports/rxv2/ccrx/CMakeLists.txt @@ -14,6 +14,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports/rxv2/gnu/CMakeLists.txt b/ports/rxv2/gnu/CMakeLists.txt index 9357c6970..1735b774b 100644 --- a/ports/rxv2/gnu/CMakeLists.txt +++ b/ports/rxv2/gnu/CMakeLists.txt @@ -14,6 +14,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports/rxv3/ccrx/CMakeLists.txt b/ports/rxv3/ccrx/CMakeLists.txt index f2269c518..4118eb376 100644 --- a/ports/rxv3/ccrx/CMakeLists.txt +++ b/ports/rxv3/ccrx/CMakeLists.txt @@ -14,6 +14,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports/rxv3/gnu/CMakeLists.txt b/ports/rxv3/gnu/CMakeLists.txt index 9357c6970..1735b774b 100644 --- a/ports/rxv3/gnu/CMakeLists.txt +++ b/ports/rxv3/gnu/CMakeLists.txt @@ -14,6 +14,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports/win32/vs_2019/CMakeLists.txt b/ports/win32/vs_2019/CMakeLists.txt index 5a766f06e..d2210a8fd 100644 --- a/ports/win32/vs_2019/CMakeLists.txt +++ b/ports/win32/vs_2019/CMakeLists.txt @@ -15,6 +15,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports/win64/vs_2022/CMakeLists.txt b/ports/win64/vs_2022/CMakeLists.txt index 328b89d19..073f0f99a 100644 --- a/ports/win64/vs_2022/CMakeLists.txt +++ b/ports/win64/vs_2022/CMakeLists.txt @@ -14,6 +14,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports/xtensa/xcc/CMakeLists.txt b/ports/xtensa/xcc/CMakeLists.txt index 31768e580..dbc3eeb69 100644 --- a/ports/xtensa/xcc/CMakeLists.txt +++ b/ports/xtensa/xcc/CMakeLists.txt @@ -26,6 +26,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports_arch/ARMv7-A/threadx/ports/gnu/CMakeLists.txt b/ports_arch/ARMv7-A/threadx/ports/gnu/CMakeLists.txt index 531df96e1..d03910d1d 100644 --- a/ports_arch/ARMv7-A/threadx/ports/gnu/CMakeLists.txt +++ b/ports_arch/ARMv7-A/threadx/ports/gnu/CMakeLists.txt @@ -28,6 +28,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports_arch/ARMv7-M/threadx/gnu/CMakeLists.txt b/ports_arch/ARMv7-M/threadx/gnu/CMakeLists.txt index ab9464d2c..4abc1c064 100644 --- a/ports_arch/ARMv7-M/threadx/gnu/CMakeLists.txt +++ b/ports_arch/ARMv7-M/threadx/gnu/CMakeLists.txt @@ -13,6 +13,8 @@ target_sources(${PROJECT_NAME} PRIVATE # {{END_TARGET_SOURCES}} ) -target_include_directories(${PROJECT_NAME} PUBLIC +target_include_directories(${PROJECT_NAME} + SYSTEM + PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports_arch/ARMv8-A/threadx/ports/gnu/CMakeLists.txt b/ports_arch/ARMv8-A/threadx/ports/gnu/CMakeLists.txt index 25e5b6b89..12a58cbeb 100644 --- a/ports_arch/ARMv8-A/threadx/ports/gnu/CMakeLists.txt +++ b/ports_arch/ARMv8-A/threadx/ports/gnu/CMakeLists.txt @@ -24,6 +24,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports_arch/ARMv8-A/threadx_smp/ports/gnu/CMakeLists.txt b/ports_arch/ARMv8-A/threadx_smp/ports/gnu/CMakeLists.txt index a10302809..b4758a855 100644 --- a/ports_arch/ARMv8-A/threadx_smp/ports/gnu/CMakeLists.txt +++ b/ports_arch/ARMv8-A/threadx_smp/ports/gnu/CMakeLists.txt @@ -33,6 +33,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports_arch/ARMv8-M/threadx/ac6/CMakeLists.txt b/ports_arch/ARMv8-M/threadx/ac6/CMakeLists.txt index 5ad3b8e75..81b479e0c 100644 --- a/ports_arch/ARMv8-M/threadx/ac6/CMakeLists.txt +++ b/ports_arch/ARMv8-M/threadx/ac6/CMakeLists.txt @@ -16,6 +16,8 @@ target_sources(${PROJECT_NAME} PRIVATE ${CMAKE_CURRENT_LIST_DIR}/src/tx_timer_interrupt.S ) -target_include_directories(${PROJECT_NAME} PUBLIC +target_include_directories(${PROJECT_NAME} + SYSTEM + PUBLIC inc ) diff --git a/ports_arch/ARMv8-M/threadx/gnu/CMakeLists.txt b/ports_arch/ARMv8-M/threadx/gnu/CMakeLists.txt index 763a2696c..a8e45b82f 100644 --- a/ports_arch/ARMv8-M/threadx/gnu/CMakeLists.txt +++ b/ports_arch/ARMv8-M/threadx/gnu/CMakeLists.txt @@ -19,6 +19,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports_smp/cortex_a34_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a34_smp/gnu/CMakeLists.txt index a10302809..b4758a855 100644 --- a/ports_smp/cortex_a34_smp/gnu/CMakeLists.txt +++ b/ports_smp/cortex_a34_smp/gnu/CMakeLists.txt @@ -33,6 +33,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports_smp/cortex_a35_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a35_smp/gnu/CMakeLists.txt index a10302809..b4758a855 100644 --- a/ports_smp/cortex_a35_smp/gnu/CMakeLists.txt +++ b/ports_smp/cortex_a35_smp/gnu/CMakeLists.txt @@ -33,6 +33,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports_smp/cortex_a53_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a53_smp/gnu/CMakeLists.txt index a10302809..b4758a855 100644 --- a/ports_smp/cortex_a53_smp/gnu/CMakeLists.txt +++ b/ports_smp/cortex_a53_smp/gnu/CMakeLists.txt @@ -33,6 +33,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports_smp/cortex_a55_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a55_smp/gnu/CMakeLists.txt index a10302809..b4758a855 100644 --- a/ports_smp/cortex_a55_smp/gnu/CMakeLists.txt +++ b/ports_smp/cortex_a55_smp/gnu/CMakeLists.txt @@ -33,6 +33,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports_smp/cortex_a57_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a57_smp/gnu/CMakeLists.txt index a10302809..b4758a855 100644 --- a/ports_smp/cortex_a57_smp/gnu/CMakeLists.txt +++ b/ports_smp/cortex_a57_smp/gnu/CMakeLists.txt @@ -33,6 +33,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports_smp/cortex_a5_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a5_smp/gnu/CMakeLists.txt index f08066585..d3b42149c 100644 --- a/ports_smp/cortex_a5_smp/gnu/CMakeLists.txt +++ b/ports_smp/cortex_a5_smp/gnu/CMakeLists.txt @@ -32,6 +32,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports_smp/cortex_a5x_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a5x_smp/gnu/CMakeLists.txt index 8e8f8cd0c..dfbd61b30 100644 --- a/ports_smp/cortex_a5x_smp/gnu/CMakeLists.txt +++ b/ports_smp/cortex_a5x_smp/gnu/CMakeLists.txt @@ -32,6 +32,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports_smp/cortex_a65_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a65_smp/gnu/CMakeLists.txt index a10302809..b4758a855 100644 --- a/ports_smp/cortex_a65_smp/gnu/CMakeLists.txt +++ b/ports_smp/cortex_a65_smp/gnu/CMakeLists.txt @@ -33,6 +33,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports_smp/cortex_a65ae_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a65ae_smp/gnu/CMakeLists.txt index a10302809..b4758a855 100644 --- a/ports_smp/cortex_a65ae_smp/gnu/CMakeLists.txt +++ b/ports_smp/cortex_a65ae_smp/gnu/CMakeLists.txt @@ -33,6 +33,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports_smp/cortex_a72_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a72_smp/gnu/CMakeLists.txt index a10302809..b4758a855 100644 --- a/ports_smp/cortex_a72_smp/gnu/CMakeLists.txt +++ b/ports_smp/cortex_a72_smp/gnu/CMakeLists.txt @@ -33,6 +33,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports_smp/cortex_a73_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a73_smp/gnu/CMakeLists.txt index a10302809..b4758a855 100644 --- a/ports_smp/cortex_a73_smp/gnu/CMakeLists.txt +++ b/ports_smp/cortex_a73_smp/gnu/CMakeLists.txt @@ -33,6 +33,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports_smp/cortex_a75_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a75_smp/gnu/CMakeLists.txt index a10302809..b4758a855 100644 --- a/ports_smp/cortex_a75_smp/gnu/CMakeLists.txt +++ b/ports_smp/cortex_a75_smp/gnu/CMakeLists.txt @@ -33,6 +33,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports_smp/cortex_a76_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a76_smp/gnu/CMakeLists.txt index a10302809..b4758a855 100644 --- a/ports_smp/cortex_a76_smp/gnu/CMakeLists.txt +++ b/ports_smp/cortex_a76_smp/gnu/CMakeLists.txt @@ -33,6 +33,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports_smp/cortex_a76ae_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a76ae_smp/gnu/CMakeLists.txt index a10302809..b4758a855 100644 --- a/ports_smp/cortex_a76ae_smp/gnu/CMakeLists.txt +++ b/ports_smp/cortex_a76ae_smp/gnu/CMakeLists.txt @@ -33,6 +33,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports_smp/cortex_a77_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a77_smp/gnu/CMakeLists.txt index a10302809..b4758a855 100644 --- a/ports_smp/cortex_a77_smp/gnu/CMakeLists.txt +++ b/ports_smp/cortex_a77_smp/gnu/CMakeLists.txt @@ -33,6 +33,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports_smp/cortex_a78_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a78_smp/gnu/CMakeLists.txt index a10302809..b4758a855 100644 --- a/ports_smp/cortex_a78_smp/gnu/CMakeLists.txt +++ b/ports_smp/cortex_a78_smp/gnu/CMakeLists.txt @@ -33,6 +33,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports_smp/cortex_a7_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a7_smp/gnu/CMakeLists.txt index 7e2719460..ef6be36c9 100644 --- a/ports_smp/cortex_a7_smp/gnu/CMakeLists.txt +++ b/ports_smp/cortex_a7_smp/gnu/CMakeLists.txt @@ -31,6 +31,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports_smp/cortex_a9_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a9_smp/gnu/CMakeLists.txt index 4b13e1a15..dd2c1a413 100644 --- a/ports_smp/cortex_a9_smp/gnu/CMakeLists.txt +++ b/ports_smp/cortex_a9_smp/gnu/CMakeLists.txt @@ -26,6 +26,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports_smp/linux/gnu/CMakeLists.txt b/ports_smp/linux/gnu/CMakeLists.txt index 67209ee7f..23d4a1a58 100644 --- a/ports_smp/linux/gnu/CMakeLists.txt +++ b/ports_smp/linux/gnu/CMakeLists.txt @@ -28,6 +28,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports_smp/mips32_interaptiv_smp/gnu/CMakeLists.txt b/ports_smp/mips32_interaptiv_smp/gnu/CMakeLists.txt index 1c0ad10df..6f8133312 100644 --- a/ports_smp/mips32_interaptiv_smp/gnu/CMakeLists.txt +++ b/ports_smp/mips32_interaptiv_smp/gnu/CMakeLists.txt @@ -28,6 +28,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/ports_smp/win64/vs_2022/CMakeLists.txt b/ports_smp/win64/vs_2022/CMakeLists.txt index 982f9684f..447a00262 100644 --- a/ports_smp/win64/vs_2022/CMakeLists.txt +++ b/ports_smp/win64/vs_2022/CMakeLists.txt @@ -23,6 +23,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR}/inc ) diff --git a/scripts/install.sh b/scripts/install.sh index c142370de..84279c4e4 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -35,7 +35,8 @@ rm -rf /opt/hostedtoolcache # # The Acquire options are kept anyway, since they make a slow mirror give up # sooner. The loop covers a mirror that is down rather than merely slow. The -# explicit exits stop a failed fetch from being carried forward into a build. +# explicit exits stop a failed fetch from being carried forward into a build, +# with one deliberate exception noted at the update below. APT_OPTIONS=(-o Acquire::Retries=3 -o Acquire::http::Timeout=20 -o Acquire::https::Timeout=20) @@ -63,7 +64,31 @@ retry() { return 1 } -retry sudo "${TIMEOUT[@]}" apt-get "${APT_OPTIONS[@]}" update || exit 1 +# THE UPDATE IS NOT THE GATE, AND IT MUST NOT BE. apt-get update fails if ANY +# configured repository serves a bad index, including ones this project does +# not use. On a GitHub runner the image carries Google's and Microsoft's +# repositories, and a Hash Sum mismatch from Google's -- their CDN caught +# mid-publish, index and Release file eight hours apart -- failed this script +# three attempts running and turned a build red over a browser nobody was +# installing. +# +# The alternative of disabling third-party sources before updating is wrong +# here: this script also runs on a contributor's own machine, where silently +# rewriting their apt configuration would be a far worse thing to do than +# tolerating a stale index. +# +# So a failed update WARNS and the install below is the gate. Nothing is +# weakened by that: apt-get install still fails hard on a package it cannot +# find, so an archive that is genuinely unreachable still stops the script -- +# one step later, and saying which package it could not get. +if ! retry sudo "${TIMEOUT[@]}" apt-get "${APT_OPTIONS[@]}" update; then + echo "" + echo "install.sh: apt-get update did not fully succeed." + echo "install.sh: continuing, because a repository this project does not" + echo "install.sh: use can fail an update. The install below is the real" + echo "install.sh: gate and fails if any package needed is unavailable." + echo "" +fi retry sudo "${TIMEOUT[@]}" apt-get "${APT_OPTIONS[@]}" install -y \ gcc-multilib \ git \ diff --git a/test/smp/cmake/threadx_smp/CMakeLists.txt b/test/smp/cmake/threadx_smp/CMakeLists.txt index 568fece41..a2e17636c 100644 --- a/test/smp/cmake/threadx_smp/CMakeLists.txt +++ b/test/smp/cmake/threadx_smp/CMakeLists.txt @@ -45,6 +45,7 @@ else() endif() configure_file(${TX_USER_FILE} ${CUSTOM_INC_DIR}/tx_user.h COPYONLY) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CUSTOM_INC_DIR} ) diff --git a/test/smp/cmake/threadx_smp/common_smp/CMakeLists.txt b/test/smp/cmake/threadx_smp/common_smp/CMakeLists.txt index 646b200b9..770379af0 100644 --- a/test/smp/cmake/threadx_smp/common_smp/CMakeLists.txt +++ b/test/smp/cmake/threadx_smp/common_smp/CMakeLists.txt @@ -214,6 +214,7 @@ target_sources(${PROJECT_NAME} # Add the Common/inc directory to the project include list target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CURRENT_DIR}/inc ) diff --git a/test/smp/cmake/threadx_smp/ports_smp/linux/gnu/CMakeLists.txt b/test/smp/cmake/threadx_smp/ports_smp/linux/gnu/CMakeLists.txt index 9c51522c7..64d972550 100644 --- a/test/smp/cmake/threadx_smp/ports_smp/linux/gnu/CMakeLists.txt +++ b/test/smp/cmake/threadx_smp/ports_smp/linux/gnu/CMakeLists.txt @@ -25,6 +25,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CURRENT_DIR}/inc ) diff --git a/test/smp/cmake/threadx_smp/ports_smp/win64/vs_2022/CMakeLists.txt b/test/smp/cmake/threadx_smp/ports_smp/win64/vs_2022/CMakeLists.txt index 6b219bb21..8635647ae 100644 --- a/test/smp/cmake/threadx_smp/ports_smp/win64/vs_2022/CMakeLists.txt +++ b/test/smp/cmake/threadx_smp/ports_smp/win64/vs_2022/CMakeLists.txt @@ -24,6 +24,7 @@ target_sources(${PROJECT_NAME} ) target_include_directories(${PROJECT_NAME} + SYSTEM PUBLIC ${CURRENT_DIR}/inc ) diff --git a/utility/rtos_compatibility_layers/posix/CMakeLists.txt b/utility/rtos_compatibility_layers/posix/CMakeLists.txt index 6ddcd6a8f..8cf3ab9ae 100644 --- a/utility/rtos_compatibility_layers/posix/CMakeLists.txt +++ b/utility/rtos_compatibility_layers/posix/CMakeLists.txt @@ -12,6 +12,7 @@ add_library(posix-threadx EXCLUDE_FROM_ALL) target_include_directories(posix-threadx + SYSTEM PUBLIC ${CMAKE_CURRENT_LIST_DIR} ) From 8be4c45cce877cc3e7351904a579a26d2b3afb04 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Wed, 9 Sep 2026 14:39:30 -0400 Subject: [PATCH 117/181] Compiled the module manager C sources, which no check had ever built (#689) * Compiled the module manager C sources, which no check had ever built #672 corrected this script's assembly glob and brought the module ports into the count, but only their assembly. Their C stayed outside every check: 27 files of portable module manager under common_modules, plus the per-port code under ports_module//gnu/module_manager/src. By this script's own standard -- a port simply absent from the count reads as covered -- 293 files across nine Arm module ports were compiled by nothing, with either compiler. Each module port ships its own tx_port.h and txm_module_port.h carrying the control-block extensions the dispatch code needs, so a port is compiled against its own headers rather than the base port's. Two details the ports themselves dictate: An SMP port's control blocks come from common_smp. Pairing cortex_a35_smp with the single-core headers hid _tx_thread_smp_protect and _tx_thread_smp_unprotect behind implicit declarations and lost tx_thread_smp_core_executing from TX_THREAD, so fourteen files reported errors for a port that builds correctly. The TrustZone ports carry cmse_nonsecure_entry, which needs -mcmse to be honoured rather than ignored. tx_thread_secure_stack.c also carries GCC's optimize attribute, which clang does not implement; that divergence is suppressed by name, for a file GCC builds cleanly. All nine ports compile: 293 of 293. Verified that the stage fails as intended by injecting a defect into a throwaway worktree -- a defect in common_modules is reported under every port, one in a port's own source only under that port. Assisted-by: Claude Code (Opus 5) * Ran the module manager stage against the sources that reach it Three corrections to the new stage, all found by running it against dev rather than against the tree it was written on. The workflows did not trigger on common_modules. Both check_clang.yml and check_gcc.yml list ports_module but not common_modules, and the portable module manager under it is the larger half of what the stage compiles -- 28 of the 31 to 37 files each port builds, plus two include directories. A change there left the stage unrun, which is the same "absent from the count reads as covered" that the stage exists to close. Both lists gain common_modules, and they stay identical to each other as the comment in each asks. A deliberate deprecation notice read as a build failure. Since this PR was opened, txm_module_manager_absolute_load.c gained a #pragma message steering callers to the extended entry point. The stage treats any compiler output as a failure, so that one notice failed every port: nine failures on a tree where nothing is wrong. Pragma messages are now waived for the stage, because a notice to callers is not a defect in the file that carries it. That failure also printed nothing. Both C stages report by grepping the output for "error:", so a diagnostic that is not an error produced a bare FAIL line with no reason under it, and the only way to learn the reason was to reproduce the compile by hand. Both stages now fall back to showing what the compiler actually said. The TrustZone attribute waiver is narrowed to the one file that needs it. tx_thread_secure_stack.c carries GCC's optimize attribute, which clang does not implement; it is the only file among the 300-odd this stage compiles that does. Waiving the warning for the whole port would have swallowed a stray unknown attribute anywhere else in it. Verified with the same toolchain CI uses, ATfE 22.1.0: the full script passes, and every port compiles every file. cortex_a35 31/31 cortex_a35_smp 31/31 cortex_a7 34/34 cortex_m0+ 33/33 cortex_m23 37/37 cortex_m3 33/33 cortex_m33 37/37 cortex_m4 33/33 cortex_m7 33/33 The counts are each one higher than this PR first reported, because txm_module_manager_absolute_load_extended.c has landed since. The stage picked it up with no edit, which is what globbing the directories was for. Assisted-by: Claude Code (Opus 5) --------- Co-authored-by: r --- .github/workflows/clang_check.yml | 6 ++ .github/workflows/gcc_check.yml | 12 ++++ scripts/check_clang.sh | 108 ++++++++++++++++++++++++++++-- 3 files changed, 122 insertions(+), 4 deletions(-) diff --git a/.github/workflows/clang_check.yml b/.github/workflows/clang_check.yml index 2c90c790b..53b60bfeb 100644 --- a/.github/workflows/clang_check.yml +++ b/.github/workflows/clang_check.yml @@ -20,6 +20,12 @@ on: - "CMakeLists.txt" - "cmake/**" - "common/**" + # common_modules/ holds the portable module manager that the module + # manager stage compiles once per Arm module port -- the larger half of + # what that stage builds. Without it a change there leaves the stage + # unrun, which is the same "absent from the count reads as covered" the + # stage exists to close. + - "common_modules/**" - "common_smp/**" - "ports/**" - "ports_arch/**" diff --git a/.github/workflows/gcc_check.yml b/.github/workflows/gcc_check.yml index 31e1ec346..eabbd0a7e 100644 --- a/.github/workflows/gcc_check.yml +++ b/.github/workflows/gcc_check.yml @@ -42,6 +42,12 @@ on: - "CMakeLists.txt" - "cmake/**" - "common/**" + # common_modules/ holds the portable module manager that the module + # manager stage compiles once per Arm module port -- the larger half of + # what that stage builds. Without it a change there leaves the stage + # unrun, which is the same "absent from the count reads as covered" the + # stage exists to close. + - "common_modules/**" - "common_smp/**" - "ports/**" - "ports_arch/**" @@ -67,6 +73,12 @@ on: - "CMakeLists.txt" - "cmake/**" - "common/**" + # common_modules/ holds the portable module manager that the module + # manager stage compiles once per Arm module port -- the larger half of + # what that stage builds. Without it a change there leaves the stage + # unrun, which is the same "absent from the count reads as covered" the + # stage exists to close. + - "common_modules/**" - "common_smp/**" - "ports/**" - "ports_arch/**" diff --git a/scripts/check_clang.sh b/scripts/check_clang.sh index f8ced1dd0..57c4d63af 100755 --- a/scripts/check_clang.sh +++ b/scripts/check_clang.sh @@ -14,11 +14,12 @@ # SPDX-License-Identifier: MIT and CC0-1.0 ############################################################################## -# Builds the Arm ports with an LLVM based toolchain, in five stages: assemble +# Builds the Arm ports with an LLVM based toolchain, in six stages: assemble # every assembly source of every Arm gnu port, assemble again the parts guarded # by feature macros, compile the common C sources for one core per architecture -# profile, then link the example builds, both the script-driven ones and those -# driven by CMake. Only the linking stages need a target C library. +# profile, compile the module manager C sources once per Arm module port, then +# link the example builds, both the script-driven ones and those driven by +# CMake. Only the linking stages need a target C library. # # scripts/check_clang.sh # clang from PATH # scripts/check_clang.sh --clang /path/to/clang @@ -310,7 +311,14 @@ if [ "$asm_only" -eq 0 ]; then -Iports/"$core"/gnu/inc -Icommon/inc -c "$src" -o /dev/null 2>&1)" if [ -n "$output" ]; then fail "$core: $src" - echo "$output" | grep "error:" | head -3 | sed 's/^/ /' + # Show the error lines when there are any, and otherwise + # whatever the compiler did say -- a FAIL with nothing under it + # sends the reader off to reproduce the command by hand. + if echo "$output" | grep -q "error:"; then + echo "$output" | grep "error:" | head -3 | sed 's/^/ /' + else + echo "$output" | head -3 | sed 's/^/ /' + fi bad=$((bad + 1)); failures=$((failures + 1)) fi done @@ -319,6 +327,98 @@ if [ "$asm_only" -eq 0 ]; then fi +# -------------------------------------------------------------------------- +if [ "$asm_only" -eq 0 ]; then + say "" + say "== Module manager C sources, one per Arm module port ==" + + # Correcting the assembly glob above brought the module ports into the count, + # but only their assembly. Their C stayed outside every check: 27 files of + # portable module manager under common_modules, plus the per-port code under + # ports_module//gnu/module_manager/src. Nothing compiled either one, so + # by this script's own standard they read as covered while being unbuilt. + # + # Each module port ships its own tx_port.h and txm_module_port.h, carrying the + # control-block extensions the dispatch code needs, so a port is compiled + # against its own headers rather than the base port's. + module_skipped="" + for dir in ports_module/*/gnu/module_manager/src; do + [ -d "$dir" ] || continue + core="$(echo "$dir" | cut -d/ -f2)" + spec="${PORT_TARGET[$core]:-}" + if [ -z "$spec" ]; then + module_skipped="$module_skipped $core" + continue + fi + + inc="ports_module/$core/gnu/inc" + if [ ! -f "$inc/tx_port.h" ] || [ ! -f "$inc/txm_module_port.h" ]; then + module_skipped="$module_skipped $core(headers)" + continue + fi + + # shellcheck disable=SC2086 + set -- $spec + target="$1"; cpu="$2"; shift 2; extra="$*" + + # An SMP port's control blocks come from common_smp; pairing it with the + # single-core headers hides _tx_thread_smp_protect behind an implicit + # declaration instead of compiling the port that is actually shipped. + case "$core" in + *_smp) kernel_inc="common_smp/inc" ;; + *) kernel_inc="common/inc" ;; + esac + + # The TrustZone ports carry cmse_nonsecure_entry, which needs -mcmse to + # be honoured rather than ignored. + port_extra="" + if [ -f "$inc/tx_secure_interface.h" ]; then + port_extra="-mcmse" + fi + + count=0; bad=0 + for src in common_modules/module_manager/src/*.c "$dir"/*.c; do + [ -f "$src" ] || continue + count=$((count + 1)) + # tx_thread_secure_stack.c carries GCC's optimize attribute, which + # clang does not implement and warns about. That is a toolchain + # divergence in a file GCC builds cleanly, so it is waived for that + # file alone -- a stray unknown attribute anywhere else in the port + # must still be reported. + src_extra="" + case "$src" in + */tx_thread_secure_stack.c) src_extra="-Wno-unknown-attributes" ;; + esac + + # A #pragma message is a deliberate notice to callers, not a defect + # in the file that carries it. txm_module_manager_absolute_load.c + # deprecates itself in favour of the extended entry point, and this + # stage compiles it once per port. + output="$("$CC" --target="$target" -mcpu="$cpu" $extra $port_extra \ + $src_extra "-Wno-#pragma-messages" \ + -I"$inc" -I"$kernel_inc" -Icommon_modules/inc \ + -Icommon_modules/module_manager/inc -c "$src" -o /dev/null 2>&1)" + if [ -n "$output" ]; then + fail "$core: $src" + # Show the error lines when there are any, and otherwise + # whatever the compiler did say -- a FAIL with nothing under it + # sends the reader off to reproduce the command by hand. + if echo "$output" | grep -q "error:"; then + echo "$output" | grep "error:" | head -3 | sed 's/^/ /' + else + echo "$output" | head -3 | sed 's/^/ /' + fi + bad=$((bad + 1)); failures=$((failures + 1)) + fi + done + say " $core: $((count - bad)) of $count compiled" + done + if [ -n "$module_skipped" ]; then + say " no target mapping, skipped:$module_skipped" + fi +fi + + # -------------------------------------------------------------------------- if [ "$no_examples" -eq 0 ]; then say "" From 16297d7a2ab529b610a1ab1cf6c762ff0b91299e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Wed, 9 Sep 2026 14:39:54 -0400 Subject: [PATCH 118/181] Added a workflow that runs the Cortex-R52 images on the Armv8-R AEM FVP (#688) * Added a workflow that runs the Cortex-R52 images on the Armv8-R AEM FVP Nothing in CI executed a single instruction of any ThreadX port. gcc_check compiles and links -- its own header says it "executes nothing" -- and its CMake stage covers one R52 configuration, the base FVP example. A change that assembles cleanly, links cleanly and then hangs on the first context switch passed every required check. This workflow builds both supported configurations and runs them on the Armv8-R AEM FVP, asserting each image's self-reported result. The feature configuration matters as much as the default one: VFP with the hard float ABI, FIQ, IRQ nesting and FIQ nesting gate whole assembly blocks that the default configuration never assembles, and it builds eight images where the default builds five. Arm distributes the model free of charge but behind a click-through licence with no stable unauthenticated URL -- the developer.arm.com permalink forms all 404 for it -- so the download location is a repository variable rather than a literal. When it is unset the build lanes still run and still gate the pull request; only execution is skipped, and it says so in the log and in the job summary rather than passing quietly. The image list is read from the generated ninja graph rather than kept in the workflow. The images are EXCLUDE_FROM_ALL, so a bare build reports "no work to do", and reading the graph means a target added to CMakeLists.txt cannot escape the check by nobody remembering to list it here. The module manager port and the S32Z280 targets are not on dev yet. Their lanes belong in this workflow when they land, not in a second one. Assisted-by: Claude Code (Opus 5) * Kept the FVP cache honest and stopped ctest passing on an empty suite Two corrections to the new workflow. The FVP cache key named the URL and hashed the workflow file. hashFiles() reads files, so it cannot hash a repository variable, and pointing it at this workflow keyed the cache on the file's own contents instead. That is wrong in both directions: repointing FVP_AEMV8R_URL at a different model kept serving the old one from cache, which is exactly what the comment claimed the key prevented, and editing anything in this file forced a needless refetch of a large archive. A small step hashes the URL and the key uses that, so it now tracks what it names. ctest reported success when it found nothing to run. Its default is to pass an empty suite, and the example registers its tests inside both if(FVP found) and if(Python3_FOUND). Either one going unmet on a runner would have left this stage green having executed no image at all, which is the hole the workflow exists to close. --no-tests=error makes an empty suite a failure. Verified with the pinned toolchain, Arm GNU 14.3.rel1: both configurations configure, enumerate and build, and the image lists are the ones claimed. default: 5 images boot_check demo_m2 demo_m3 demo_mpu demo_threadx feature: 8 images the above plus demo_fiq demo_m5 demo_nesting Also checked that the target enumeration survives the real ninja graph: the generated graph offers twenty .elf paths, and the filter reduces them to those eight, dropping the cmake_object_order_depends_target aliases and the CMakeFiles copies. Assisted-by: Claude Code (Opus 5) --------- Co-authored-by: r --- .github/workflows/r52_fvp.yml | 335 ++++++++++++++++++++++++++++++++++ 1 file changed, 335 insertions(+) create mode 100644 .github/workflows/r52_fvp.yml diff --git a/.github/workflows/r52_fvp.yml b/.github/workflows/r52_fvp.yml new file mode 100644 index 000000000..8adc1c2be --- /dev/null +++ b/.github/workflows/r52_fvp.yml @@ -0,0 +1,335 @@ +name: r52_fvp + +# Builds every Cortex-R52 CMake image in both supported configurations and +# EXECUTES them on the Armv8-R AEM FVP, asserting each image's self-reported +# result. +# +# Why this exists: until this workflow landed, nothing in CI ran a single +# instruction of any ThreadX port. gcc_check compiles and links -- its own +# header says so, "it compiles and links and **executes nothing**" -- and its +# CMake stage covers exactly one R52 configuration, the base FVP example with +# -DTX_R52_ENABLE_MPU=ON. So a change that assembles cleanly and links cleanly +# and then hangs on the first context switch passes every required check. +# +# That gap matters more for cortex_r52 than for the other ports, because the +# R52 is the foundation the partitioning work is sequenced behind: the EL2 boot +# path in entry.S, the MPU programming, and the generic-timer plumbing are all +# things later work attaches to rather than replaces. A regression in any of +# them has to be caught by an execution test; there is no static check for +# "the scheduler still schedules". +# +# What it covers: +# +# - the default configuration -- the images gcc_check's CMake stage builds, +# but run rather than merely linked; +# - the feature configuration -- VFP with the hard float ABI, FIQ, IRQ +# nesting and FIQ nesting. Those four options gate whole assembly blocks +# (the VMRS/VSTMDB/VLDMIA sequences, the FIQ context paths, the nesting +# start/end pairs) that the default configuration never assembles, let +# alone runs. +# +# What it does not cover: the module manager port and the S32Z280 targets are +# not on dev yet -- they are PR #639. When that merges, add their lanes here +# rather than starting a second workflow; the matrix already has the shape. +# +# The S32Z280 targets will be build-only in CI regardless. They need silicon, +# and a hosted runner has none. + +on: + # push as well as pull_request, for the reason gcc_check.yml states at + # length: dev needs its own baseline so a bad squash-merge is caught then + # rather than by whoever opens the next pull request. + push: + branches: [ master, dev ] + paths: + - ".github/workflows/r52_fvp.yml" + - "CMakeLists.txt" + - "cmake/cortex_r52*.cmake" + - "common/**" + - "ports/cortex_r52/**" + - "ports_module/cortex_r52/**" + pull_request: + branches: [ master, dev ] + # Duplicated rather than shared through a YAML anchor. GitHub Actions' + # parser does not dependably honour anchors and the failure mode is the + # whole workflow refusing to parse -- a job that dies before it does + # anything, which is the exact defect gcc_check.yml carries a comment + # about. **Edit both.** + paths: + - ".github/workflows/r52_fvp.yml" + - "CMakeLists.txt" + - "cmake/cortex_r52*.cmake" + - "common/**" + - "ports/cortex_r52/**" + - "ports_module/cortex_r52/**" + +jobs: + # One job rather than one per configuration, for the reason gcc_check.yml + # gives for folding its two toolchains together: the checks list stays short, + # and a single run sees every configuration so a cross-configuration + # regression shows up in one log instead of two. + r52: + runs-on: ubuntu-24.04 + + env: + # Pinned deliberately. Matches gcc_check.yml and ci_cortex_m.yml so all + # three share one cache entry rather than each holding its own copy of + # the same archive; change them together or the sharing silently stops. + # 14.3.rel1 is AGENTS.md's declared GCC 14 default. + GCC_VERSION: 14.3.rel1 + + # Where the Armv8-R AEM FVP comes from. + # + # Arm distributes it free of charge but behind a click-through licence, + # with no stable unauthenticated download URL we can hard-code -- the + # permalink forms under developer.arm.com/-/cdn-downloads all 404 for + # this model. So the URL is a repository variable rather than a literal + # here, and the maintainer sets it once to a location the runner can + # reach (an Eclipse-hosted mirror, a release asset, or Arm's own URL if + # a durable one appears). + # + # Set FVP_AEMV8R_URL to a .tgz/.tar.gz of the model, and optionally + # FVP_AEMV8R_SHA256 to its checksum. With the checksum set the download + # is verified; without it the run says so rather than pretending. + # + # When the variable is unset the build lanes still run and still gate the + # pull request -- only execution is skipped, loudly, in the log and in + # the job summary. A silent green here would recreate the exact hole this + # workflow exists to close. + FVP_URL: ${{ vars.FVP_AEMV8R_URL }} + FVP_SHA256: ${{ vars.FVP_AEMV8R_SHA256 }} + + steps: + # Actions are pinned to a commit SHA with the version in the trailing + # comment. A tag can be moved; a SHA cannot. Dependabot moves these pins + # and rewrites the comments -- see .github/dependabot.yml. + - name: Check out the repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + # Path and key match gcc_check.yml's AArch32 entry exactly, so the two + # workflows share one cache entry. Only the AArch32 toolchain is needed + # here: cortex_r52 is Armv8-R AArch32, and nothing this workflow builds + # targets aarch64. + - name: Cache the AArch32 Arm GNU toolchain + id: cache-arm32 + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: toolchain + key: arm-gnu-toolchain-${{ env.GCC_VERSION }}-x86_64-arm-none-eabi + + # The checksum suffix is .sha256asc and not .sha256. Arm publishes both, + # and for arm-none-eabi the .sha256 file contains a 32-character MD5, so + # sha256sum -c on it fails with "no properly formatted checksum lines + # found". Do not "simplify" the suffix. (Same note as gcc_check.yml, which + # is where it was first paid for.) + - name: Install the AArch32 Arm GNU toolchain + if: steps.cache-arm32.outputs.cache-hit != 'true' + run: | + set -eu + base="https://developer.arm.com/-/media/Files/downloads/gnu/${GCC_VERSION}/binrel" + archive="arm-gnu-toolchain-${GCC_VERSION}-x86_64-arm-none-eabi.tar.xz" + mkdir -p toolchain && cd toolchain + curl -fsSLO "$base/$archive" + curl -fsSLO "$base/$archive.sha256asc" + sha256sum -c "$archive.sha256asc" + tar xf "$archive" + rm -f "$archive" + + # Only reaches apt if the runner image has stopped shipping ninja. This + # repository has already paid for unguarded apt calls -- scripts/install.sh + # carries a long comment about apt-get update stalling for over two hours + # and taking whole regression runs with it. Do not make this + # unconditional. + - name: Ensure ninja is available + run: | + set -eu + if command -v ninja >/dev/null 2>&1; then + ninja --version + else + sudo apt-get update + sudo apt-get install -y --no-install-recommends ninja-build + fi + + # The cache key has to move when the model does, and stay put when it does + # not. hashFiles() reads files, so it cannot hash a variable: pointing it + # at this workflow keyed the cache on the file's own contents, which is + # wrong twice over -- repointing FVP_AEMV8R_URL kept serving the old model, + # and editing anything here forced a needless refetch of a large archive. + # The URL is hashed here instead, so the key tracks exactly what it names. + - name: Key the FVP cache on the download URL + id: fvp-key + if: env.FVP_URL != '' + run: | + set -eu + printf 'hash=%s\n' "$(printf '%s' "$FVP_URL" | sha256sum | cut -d' ' -f1)" >>"$GITHUB_OUTPUT" + + - name: Cache the Armv8-R AEM FVP + id: cache-fvp + if: env.FVP_URL != '' + uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 + with: + path: fvp + key: fvp-aemv8r-${{ steps.fvp-key.outputs.hash }}-${{ env.FVP_SHA256 || 'nosum' }} + + - name: Install the Armv8-R AEM FVP + if: env.FVP_URL != '' && steps.cache-fvp.outputs.cache-hit != 'true' + run: | + set -eu + mkdir -p fvp && cd fvp + curl -fsSL -o fvp.tgz "$FVP_URL" + if [ -n "${FVP_SHA256:-}" ]; then + echo "$FVP_SHA256 fvp.tgz" | sha256sum -c - + else + echo "::warning::FVP_AEMV8R_SHA256 is not set; the download was not verified." + fi + tar xf fvp.tgz + rm -f fvp.tgz + + # The model links against libatomic. Everything else it needs + # (libstdc++, libgcc_s, librt, libpthread) is already on the runner image, + # and its own libscxframework/libsystemc ship inside the tarball. The + # runner usually has libatomic1 by way of gcc, so this is guarded for the + # same reason the ninja step is. + - name: Ensure the FVP's runtime dependencies are present + if: env.FVP_URL != '' + run: | + set -eu + if ldconfig -p | grep -q 'libatomic\.so\.1'; then + echo "libatomic1 present" + else + sudo apt-get update + sudo apt-get install -y --no-install-recommends libatomic1 + fi + + # Resolve the model once and hand its absolute path to CMake below. + # + # ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/CMakeLists.txt finds + # it with find_program(... HINTS $ENV{HOME}/FVP_Base_AEMv8R_11.32_19/bin), + # a hint that is right on a developer's machine and meaningless here, so + # the path is passed explicitly. find_program caches into FVP_BASER_AEMV8R, + # which means -DFVP_BASER_AEMV8R= overrides it with no change to the + # CMake files. + # + # FVP_PRESENT, not a bare "did the variable exist", so that a URL which + # downloads something that is not the model fails here rather than + # silently skipping every test later. + - name: Locate the FVP + id: fvp + run: | + set -eu + if [ -z "${FVP_URL:-}" ]; then + echo "present=false" >>"$GITHUB_OUTPUT" + echo "::warning::FVP_AEMV8R_URL is not set for this repository, so the Cortex-R52 images were built but NOT executed. Set the repository variable to enable the execution lanes." + { + echo "### Cortex-R52 FVP execution: SKIPPED" + echo "" + echo "\`FVP_AEMV8R_URL\` is not set, so this run built the images but executed none of them." + echo "Set the repository variable (Settings -> Secrets and variables -> Actions -> Variables)" + echo "to a download URL for the Armv8-R AEM FVP to turn the execution lanes on." + } >>"$GITHUB_STEP_SUMMARY" + exit 0 + fi + binary="$(find fvp -type f -name FVP_BaseR_AEMv8R -perm -u+x | head -1)" + if [ -z "$binary" ]; then + echo "FVP_AEMV8R_URL was set, but no FVP_BaseR_AEMv8R binary was found in the archive." >&2 + find fvp -maxdepth 3 -type d | sed 's/^/ /' >&2 + exit 1 + fi + binary="$(cd "$(dirname "$binary")" && pwd)/$(basename "$binary")" + echo "present=true" >>"$GITHUB_OUTPUT" + echo "binary=$binary" >>"$GITHUB_OUTPUT" + "$binary" --version + + # Both configurations are configured, built and (when the model is here) + # run by one script, so that adding a configuration is one line rather + # than three near-identical blocks of YAML. + # + # Every image is named explicitly from the generated ninja graph rather + # than from a list kept here. The images are EXCLUDE_FROM_ALL -- a bare + # "cmake --build" reports "no work to do" and would compare nothing -- + # and reading the graph means a target added to CMakeLists.txt cannot + # escape this check by nobody remembering to list it. This is the same + # technique, and the same reasoning, as scripts/check_gcc.sh's CMake stage. + # + # TX_R52_FLOAT_ABI=hard is not optional alongside TX_R52_ENABLE_VFP: the + # port's CMakeLists.txt refuses the combination outright (#686), because + # TX_ENABLE_VFP_SUPPORT enables VMRS/VSTMDB/VLDMIA blocks that a soft + # float ABI leaves the assembler unable to accept. + - name: Build and run the Cortex-R52 images + run: | + set -eu + export PATH="$GITHUB_WORKSPACE/toolchain/arm-gnu-toolchain-${GCC_VERSION}-x86_64-arm-none-eabi/bin:$PATH" + arm-none-eabi-gcc --version | head -1 + + fvp_present='${{ steps.fvp.outputs.present }}' + fvp_binary='${{ steps.fvp.outputs.binary }}' + + fvp_arg="" + if [ "$fvp_present" = "true" ]; then + fvp_arg="-DFVP_BASER_AEMV8R=$fvp_binary" + fi + + status=0 + + run_configuration() { + name="$1"; shift + build="build/$name" + + echo "" + echo "==============================================================" + echo "== $name" + echo "==============================================================" + + if ! cmake -S . -B "$build" -G Ninja \ + -DCMAKE_TOOLCHAIN_FILE=cmake/cortex_r52.cmake \ + $fvp_arg "$@"; then + echo "::error::$name: CMake configure failed" + status=1 + return + fi + + images="$(ninja -C "$build" -t targets all 2>/dev/null \ + | grep -oE '^[A-Za-z0-9_]+\.elf' \ + | grep -v '^cmake_' | sort -u)" + if [ -z "$images" ]; then + echo "::error::$name: no .elf targets found in the CMake graph" + status=1 + return + fi + + echo "$name: building $(echo "$images" | wc -l) images" + # shellcheck disable=SC2086 + if ! cmake --build "$build" --target $images; then + echo "::error::$name: one or more images did not build" + status=1 + return + fi + + if [ "$fvp_present" != "true" ]; then + echo "$name: built, not executed (no FVP configured)" + return + fi + + # --no-tests=error, because ctest's default is to report success + # when it finds nothing to run. The example registers its tests + # inside if(FVP found) and if(Python3_FOUND), so either one going + # unmet would leave this stage green having executed nothing -- the + # very hole this workflow exists to close. + if ! ctest --test-dir "$build" --output-on-failure --no-tests=error; then + echo "::error::$name: one or more images failed on the FVP, or no tests were registered" + status=1 + fi + } + + run_configuration default \ + -DTX_R52_BUILD_FVP_EXAMPLE=ON + + run_configuration feature \ + -DTX_R52_BUILD_FVP_EXAMPLE=ON \ + -DTX_R52_ENABLE_VFP=ON \ + -DTX_R52_FLOAT_ABI=hard \ + -DTX_R52_ENABLE_FIQ=ON \ + -DTX_R52_ENABLE_IRQ_NESTING=ON \ + -DTX_R52_ENABLE_FIQ_NESTING=ON + + exit $status From 850a172bac0d26bedf8d92768e880d1613527f84 Mon Sep 17 00:00:00 2001 From: Wei-Chen Lai Date: Thu, 10 Sep 2026 04:25:28 +0800 Subject: [PATCH 119/181] Added lazy FPU stacking and QEMU functional tests for RV64 GNU port (#549) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * add lazy FPU stacking to context save/restore Save mstatus/sstatus to stack slot 29 and skip floating-point register save/restore when FS is Off (bits 14:13). This avoids unnecessary FP context work for threads that do not use the FPU. - context_save: check FS in nested and first-level interrupt paths - context_restore: gate FP restore on nested, no-preempt, and preempt paths - use sstatus when TX_RISCV_SMODE is defined, otherwise mstatus * add QEMU virt CMake build and automated test runner Wire the QEMU virt demo into the CMake build system and add a Python/GDB functional test runner, mirroring the risc-v32/gnu port. - Add qemu_virt/CMakeLists.txt to build kernel.elf and register the check-functional-riscv64 target (requires Python3; skipped if absent) - Link kernel.elf with --whole-archive so all ThreadX symbols resolve - Pin _start at 0x80000000 via .text.boot in entry.s and KEEP(*(.text.boot)) in link.lds - Extend demo_threadx.c with fpu_test_val and shorten thread_0 sleep for GDB-driven FPU, timer, and preemption checks - Add test/azrtos_test_tx_gnu_riscv64_qemu.py; verified passing on QEMU virt (FPU, timer interrupt, preemption) * Clean up RV64 PR scope and remove QEMU test integration leftovers Revert accidental RV64 qemu_virt test/CMake integration changes and keep this branch focused on lazy FPU context handling only. Also remove unintended TX_RISCV_SMODE-based mstatus/sstatus save path and align comments/logic to mstatus-only behavior. * Initialize mstatus.FS in RV64 stack build so new threads start with clean FP state Slot 29 was left uninitialized while context restore reads it as an FP-live hint; garbage FS bits could make a new thread inherit the previous thread's floating-point registers. * Add RV64 regression test for the FP state of a newly created thread The test dirties every floating point register, then creates a thread and checks that the stack builder wrote the mstatus slot and that the new thread starts with all floating point registers zeroed. It is registered for RV64 only, since the RV32 stack builder still leaves the slot unwritten. * Completed the RISC-V64 lazy FPU so the restore side matches the save side The lazy FPU save in this branch skips the floating-point stores when mstatus.FS is Off, and records the mstatus it judged that on in frame slot 29. Merged onto current dev, only the save side had that treatment: both restore paths and the scheduler's interrupt-frame path still reloaded the FP registers unconditionally, from slots the save had deliberately left alone. A thread that never touched the FP unit would have had whatever the frame happened to contain loaded into its registers, and FS driven to Dirty on the way out. The guard is added at the three places that consume an interrupt frame: both paths in _tx_thread_context_restore, and _tx_thread_schedule_loop. Each reads slot 29 and skips the FP block when FS was Off, which is the same shape the risc-v32 port already uses. The solicited path is deliberately left alone. _tx_thread_system_return saves the callee-saved FP registers unconditionally, so restoring them unconditionally is consistent; making that pair lazy as well is a separate change, and risc-v32 is the model for it. Verified with QEMU on all five configurations: risc-v64 96 of 96 passing, five configurations, nothing unlinkable risc-v32 95 of 95 passing, five configurations, unchanged functional check-functional-riscv64 passes every check The ninety-sixth test is the one this branch adds. It is load bearing: seeding stack build with FS = Off instead of Initial makes it fail, and restoring the seed makes it pass, so it guards the behaviour the rest of this branch is about rather than passing regardless. Assisted-by: Claude Code (Opus 5) --------- Co-authored-by: r Co-authored-by: Frédéric Desbiens --- .../gnu/src/tx_thread_context_restore.S | 22 ++ .../risc-v64/gnu/src/tx_thread_context_save.S | 21 ++ ports/risc-v64/gnu/src/tx_thread_schedule.S | 12 +- .../risc-v64/gnu/src/tx_thread_stack_build.S | 5 +- test/tx/cmake/riscv/regression/CMakeLists.txt | 8 + .../threadx_riscv_new_thread_fpu_state_test.c | 278 ++++++++++++++++++ 6 files changed, 344 insertions(+), 2 deletions(-) create mode 100644 test/tx/cmake/riscv/regression/threadx_riscv_new_thread_fpu_state_test.c diff --git a/ports/risc-v64/gnu/src/tx_thread_context_restore.S b/ports/risc-v64/gnu/src/tx_thread_context_restore.S index 6ffb541e7..f5a68d2ec 100644 --- a/ports/risc-v64/gnu/src/tx_thread_context_restore.S +++ b/ports/risc-v64/gnu/src/tx_thread_context_restore.S @@ -90,6 +90,16 @@ _tx_thread_context_restore: /* Just recover the saved registers and return to the point of interrupt. */ + /* Recover the FP state only when the saved mstatus.FS was not Off. The + save side skips the FP stores for a thread that has not touched the + unit, so those slots hold nothing worth loading back. */ +#if (__riscv_flen == 32) || (__riscv_flen == 64) + ld t1, 29*8(sp) // Pickup saved mstatus + srli t1, t1, 13 + andi t1, t1, 0x3 + beqz t1, _tx_thread_skip_fp_restore // Skip if FS was Off +#endif + /* Recover floating point registers. */ #if (__riscv_flen == 32) flw f0, 31*8(sp) // Recover ft0 @@ -152,6 +162,7 @@ _tx_thread_context_restore: ld t0, 63*8(sp) // Recover fcsr csrw fcsr, t0 #endif +_tx_thread_skip_fp_restore: #if defined(__riscv_vector) /* Recover vector registers v0-v31 */ @@ -297,6 +308,16 @@ _tx_thread_no_preempt_restore: ld sp, 8(t1) // Switch back to thread's stack + /* Recover the FP state only when the saved mstatus.FS was not Off. The + save side skips the FP stores for a thread that has not touched the + unit, so those slots hold nothing worth loading back. */ +#if (__riscv_flen == 32) || (__riscv_flen == 64) + ld t3, 29*8(sp) // Pickup saved mstatus + srli t3, t3, 13 + andi t3, t3, 0x3 + beqz t3, _tx_thread_no_preempt_skip_fp_restore // Skip if FS was Off +#endif + /* Recover floating point registers. */ #if (__riscv_flen == 32) flw f0, 31*8(sp) // Recover ft0 @@ -359,6 +380,7 @@ _tx_thread_no_preempt_restore: ld t0, 63*8(sp) // Recover fcsr csrw fcsr, t0 // Restore fcsr #endif +_tx_thread_no_preempt_skip_fp_restore: #if defined(__riscv_vector) /* Recover vector registers v0-v31 */ diff --git a/ports/risc-v64/gnu/src/tx_thread_context_save.S b/ports/risc-v64/gnu/src/tx_thread_context_save.S index d8526fd98..d85833b37 100644 --- a/ports/risc-v64/gnu/src/tx_thread_context_save.S +++ b/ports/risc-v64/gnu/src/tx_thread_context_save.S @@ -33,6 +33,7 @@ /* AUTHOR */ /* */ /* Scott Larson, Microsoft Corporation */ +/* Wei-Chen Lai, National Cheng Kung University */ /* */ /* DESCRIPTION */ /* */ @@ -104,6 +105,15 @@ _tx_thread_context_save: #endif sd t0, 30*8(sp) // Save it on the stack + /* Save mstatus and skip FP state if FS is Off. */ + csrr t0, mstatus + sd t0, 29*8(sp) // Save mstatus +#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) + srli t1, t0, 13 + andi t1, t1, 0x3 + beqz t1, _tx_thread_skip_nested_fpu_save // Skip if FS was Off +#endif + /* Save floating point scratch registers if floating point is enabled. */ #if (__riscv_flen == 32) fsw f0, 31*8(sp) // Store ft0 @@ -166,6 +176,7 @@ _tx_thread_context_save: csrr t0, fcsr sd t0, 63*8(sp) // Store fcsr #endif +_tx_thread_skip_nested_fpu_save: #if defined(__riscv_vector) /* Store vector registers and CSRs */ @@ -246,6 +257,15 @@ _tx_thread_not_nested_save: #endif sd t1, 30*8(sp) // Save it on the stack + /* Save mstatus and skip FP state if FS is Off. */ + csrr t1, mstatus + sd t1, 29*8(sp) // Save mstatus +#if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) + srli t2, t1, 13 + andi t2, t2, 0x3 + beqz t2, _tx_thread_skip_fpu_save // Skip if FS was Off +#endif + /* Save floating point scratch registers if floating point is enabled. */ #if (__riscv_flen == 32) fsw f0, 31*8(sp) // Store ft0 @@ -308,6 +328,7 @@ _tx_thread_not_nested_save: csrr t0, fcsr sd t0, 63*8(sp) // Store fcsr #endif +_tx_thread_skip_fpu_save: #if defined(__riscv_vector) /* Store vector registers and CSRs */ diff --git a/ports/risc-v64/gnu/src/tx_thread_schedule.S b/ports/risc-v64/gnu/src/tx_thread_schedule.S index 85405c9e0..262207265 100644 --- a/ports/risc-v64/gnu/src/tx_thread_schedule.S +++ b/ports/risc-v64/gnu/src/tx_thread_schedule.S @@ -143,7 +143,16 @@ _tx_thread_schedule_loop: ld t2, 0(sp) // Pickup stack type beqz t2, _tx_thread_synch_return // If 0, solicited thread return - /* Determine if floating point registers need to be recovered. */ + /* Determine if floating point registers need to be recovered. This is an + interrupt frame, so _tx_thread_context_save built it and may have + skipped the FP stores when mstatus.FS was Off. Read back the same slot + it wrote rather than reloading whatever those slots happen to hold. */ +#if (__riscv_flen == 32) || (__riscv_flen == 64) + ld t1, 29*8(sp) // Pickup saved mstatus + srli t1, t1, 13 + andi t1, t1, 0x3 + beqz t1, _tx_thread_schedule_skip_fp_restore // Skip if FS was Off +#endif #if (__riscv_flen == 32) flw f0, 31*8(sp) // Recover ft0 @@ -216,6 +225,7 @@ _tx_thread_schedule_loop: ld t0, 63*8(sp) // Recover fcsr csrw fcsr, t0 // Restore fcsr #endif +_tx_thread_schedule_skip_fp_restore: #if defined(__riscv_vector) /* Recover vector registers v0-v31 */ diff --git a/ports/risc-v64/gnu/src/tx_thread_stack_build.S b/ports/risc-v64/gnu/src/tx_thread_stack_build.S index 8d478242e..47e5c995f 100644 --- a/ports/risc-v64/gnu/src/tx_thread_stack_build.S +++ b/ports/risc-v64/gnu/src/tx_thread_stack_build.S @@ -32,6 +32,7 @@ /* AUTHOR */ /* */ /* Scott Larson, Microsoft Corporation */ +/* Wei-Chen Lai, National Cheng Kung University */ /* */ /* DESCRIPTION */ /* */ @@ -94,7 +95,7 @@ _tx_thread_stack_build: x11 26 Initial a1 x10 27 Initial a0 x1 28 Initial ra - -- 29 reserved + mstatus 29 Initial mstatus mepc 30 Initial mepc If floating point support: f0 31 Inital ft0 @@ -193,6 +194,8 @@ If vector extension support: sd zero, 26*8(t0) // Initial a1 sd zero, 27*8(t0) // Initial a0 sd zero, 28*8(t0) // Initial ra + li t1, 0x2000 // mstatus.FS = Initial + sd t1, 29*8(t0) // Initial mstatus sd a1, 30*8(t0) // Initial mepc/sepc (thread entry point) #if defined(__riscv_float_abi_single) || defined(__riscv_float_abi_double) sd zero, 31*8(t0) // Initial ft0 diff --git a/test/tx/cmake/riscv/regression/CMakeLists.txt b/test/tx/cmake/riscv/regression/CMakeLists.txt index 80b6e3bdb..3db2eeec5 100644 --- a/test/tx/cmake/riscv/regression/CMakeLists.txt +++ b/test/tx/cmake/riscv/regression/CMakeLists.txt @@ -115,6 +115,14 @@ set(regression_test_cases # interrupt_save on RISC-V. ) +# Architecture specific tests living next to this file. The RV32 stack +# builder still leaves the mstatus slot of the frame unwritten, so the new +# thread FPU state test only applies to RV64 for now. +if(THREADX_ARCH STREQUAL "risc-v64") + list(APPEND regression_test_cases + ${CMAKE_CURRENT_LIST_DIR}/threadx_riscv_new_thread_fpu_state_test.c) +endif() + # Tests that provide their own main() and must NOT link with testcontrol. set(standalone_test_cases ${SOURCE_DIR}/threadx_initialize_kernel_setup_test.c diff --git a/test/tx/cmake/riscv/regression/threadx_riscv_new_thread_fpu_state_test.c b/test/tx/cmake/riscv/regression/threadx_riscv_new_thread_fpu_state_test.c new file mode 100644 index 000000000..b388ad621 --- /dev/null +++ b/test/tx/cmake/riscv/regression/threadx_riscv_new_thread_fpu_state_test.c @@ -0,0 +1,278 @@ +/***************************************************************************/ +/* 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. */ +/* */ +/* AI Disclosure: This file was largely AI-generated by Claude Opus 5. */ +/* The AI-generated portions may be considered public domain (CC0-1.0) */ +/* and not subject to the project's licence. The human contributor has */ +/* reviewed and verified that the code is correct. */ +/* */ +/* SPDX-License-Identifier: MIT and CC0-1.0 */ +/***************************************************************************/ + +/* This test is designed to verify that a thread created after another + thread has used the floating point registers starts with a clean + floating point state. + + The interrupt stack frame reserves slot 29 for mstatus, and the context + restore path uses the FS field of that slot to decide whether the saved + floating point registers have to be recovered. When the stack builder + leaves the slot untouched, the decision is made on whatever the thread + stack happened to contain, so the new thread can silently inherit the + floating point registers of the thread that ran before it. + + Thread 0 fills every floating point register with a non-zero value and + then creates thread 1. The test checks that the stack builder wrote the + mstatus slot at all, that the slot describes a live floating point state, + and that thread 1 observes all floating point registers as zero once it + preempts thread 0. + + An unwritten slot still holds the stack fill pattern, so it is detected + by comparing the slot against a stack word the builder never touches. */ + +#include +#include "tx_api.h" + + +/* The mstatus slot of the interrupt stack frame. */ + +#define FRAME_MSTATUS_INDEX 29 + + +#if defined(__riscv_float_abi_double) + +#define FP_SUPPORTED 1 +#define FP_LOAD "fld" +#define FP_STORE "fsd" +#define FP_WORD_SIZE "8" +typedef double FP_WORD; + +#elif defined(__riscv_float_abi_single) + +#define FP_SUPPORTED 1 +#define FP_LOAD "flw" +#define FP_STORE "fsw" +#define FP_WORD_SIZE "4" +typedef float FP_WORD; + +#else + +#define FP_SUPPORTED 0 + +#endif + + +#if FP_SUPPORTED + +/* Walk f0-f31 in register number order so that the index is both the + register number and the slot in the state buffers. */ + +#define FP_REG_LIST(op) \ + op(ft0, 0) op(ft1, 1) op(ft2, 2) op(ft3, 3) \ + op(ft4, 4) op(ft5, 5) op(ft6, 6) op(ft7, 7) \ + op(fs0, 8) op(fs1, 9) op(fa0, 10) op(fa1, 11) \ + op(fa2, 12) op(fa3, 13) op(fa4, 14) op(fa5, 15) \ + op(fa6, 16) op(fa7, 17) op(fs2, 18) op(fs3, 19) \ + op(fs4, 20) op(fs5, 21) op(fs6, 22) op(fs7, 23) \ + op(fs8, 24) op(fs9, 25) op(fs10, 26) op(fs11, 27) \ + op(ft8, 28) op(ft9, 29) op(ft10, 30) op(ft11, 31) + +#define FP_LOAD_ONE(reg, index) FP_LOAD " " #reg ", " #index "*" FP_WORD_SIZE "(%0)\n" +#define FP_STORE_ONE(reg, index) FP_STORE " " #reg ", " #index "*" FP_WORD_SIZE "(%0)\n" +#define FP_CLOBBER_ONE(reg, index) #reg, + +#define FP_REGISTERS 32 + +static FP_WORD dirty_pattern[FP_REGISTERS]; +static FP_WORD thread_1_fp_state[FP_REGISTERS]; +static unsigned long thread_1_fp_dirty = 0; + +#endif + + +static TX_THREAD thread_0; +static TX_THREAD thread_1; + +/* Give thread 1 a private stack so it can be cleared before the thread is + created. */ + +static unsigned long thread_1_stack[TEST_STACK_SIZE_PRINTF/sizeof(unsigned long)]; + +static unsigned long thread_1_executed = 0; + + +/* Define thread prototypes. */ + +static void thread_0_entry(ULONG thread_input); +static void thread_1_entry(ULONG thread_input); + + +/* Prototype for test control return. */ +void test_control_return(UINT status); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_riscv_new_thread_fpu_state_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, TX_NO_TIME_SLICE, TX_AUTO_START); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running RISC-V New Thread FPU State Test............................ ERROR #1\n"); + test_control_return(1); + } +} + + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; +unsigned long *frame; +unsigned long stack_fill; +unsigned long frame_fs; +#if FP_SUPPORTED +UINT i; +#endif + + + /* Inform user. */ + printf("Running RISC-V New Thread FPU State Test............................ "); + +#if FP_SUPPORTED + + /* Build a pattern that is non-zero in every register. */ + for (i = 0; i < FP_REGISTERS; i++) + { + + dirty_pattern[i] = (FP_WORD) (i + 1); + } + + /* Make the floating point state of this thread dirty. */ + __asm__ volatile (FP_REG_LIST(FP_LOAD_ONE) + : + : "r" (dirty_pattern) + : FP_REG_LIST(FP_CLOBBER_ONE) "memory"); +#endif + + /* Create thread 1 without starting it, so the built frame can be + inspected before the thread is scheduled. */ + status = tx_thread_create(&thread_1, "thread 1", thread_1_entry, 0, + thread_1_stack, sizeof(thread_1_stack), + 15, 15, TX_NO_TIME_SLICE, TX_DONT_START); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("ERROR #2\n"); + test_control_return(1); + } + + /* The bottom of the stack is never part of the frame, so it still holds + the fill pattern that thread creation left behind. */ + frame = (unsigned long *) thread_1.tx_thread_stack_ptr; + stack_fill = thread_1_stack[0]; + + /* The stack builder must have written the mstatus slot. */ + if (frame[FRAME_MSTATUS_INDEX] == stack_fill) + { + + printf("ERROR #3\n"); + test_control_return(1); + } + + /* The built frame must describe a live floating point state. */ + frame_fs = (frame[FRAME_MSTATUS_INDEX] >> 13) & 0x3UL; + + if (frame_fs == 0) + { + + printf("ERROR #4\n"); + test_control_return(1); + } + + /* Let thread 1 preempt and run to completion. */ + status = tx_thread_resume(&thread_1); + + /* Check for status. */ + if ((status != TX_SUCCESS) || (thread_1_executed != 1)) + { + + printf("ERROR #5\n"); + test_control_return(1); + } + +#if FP_SUPPORTED + + /* Thread 1 must not have inherited the floating point registers of + thread 0. */ + if (thread_1_fp_dirty) + { + + printf("ERROR #6\n"); + test_control_return(1); + } +#endif + + /* Successful test. */ + printf("SUCCESS!\n"); + test_control_return(0); +} + + +static void thread_1_entry(ULONG thread_input) +{ + +#if FP_SUPPORTED + +const unsigned char *state_bytes; +UINT i; + + + /* Capture the floating point registers before anything else can use + them. */ + __asm__ volatile (FP_REG_LIST(FP_STORE_ONE) + : + : "r" (thread_1_fp_state) + : "memory"); + + state_bytes = (const unsigned char *) thread_1_fp_state; + + for (i = 0; i < (UINT) sizeof(thread_1_fp_state); i++) + { + + if (state_bytes[i] != 0) + { + + thread_1_fp_dirty = 1; + break; + } + } +#endif + + thread_1_executed = 1; +} From 383dd311cd3be0302f6621eb9c05457ee7b7d4b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Wed, 9 Sep 2026 16:28:59 -0400 Subject: [PATCH 120/181] Removed the vector table offset register and system stack pointer setup from the Cortex-M low-level initialization (#714) _tx_initialize_low_level wrote VTOR and derived _tx_thread_system_stack_ptr from the reset vector on every Cortex-M port. Programming VTOR is the job of the low-level startup code that runs before the kernel is entered, and doing it again inside ThreadX silently overrode a vector table that the application, a bootloader or a firmware update had already installed. It also forced every application to export a vector table symbol that the kernel itself never needed. _tx_thread_system_stack_ptr is never read by any Cortex-M port, so the value copied out of the reset vector served no purpose. Both blocks are removed from all Cortex-M ports, together with the now-unused symbol declarations. The GreenHills files keep the NVIC base address load that the removed block used to leave in r0 for the SysTick setup that follows. Applications that relied on ThreadX programming VTOR must now set it in their startup code. The bundled examples link their vector table at address zero and run on the reset default. Fixes #370 Assisted-by: Copilot (Opus 5) --- .../example_build/tx_initialize_low_level.s | 24 ++----------------- .../sample_threadx/tx_initialize_low_level.S | 18 ++------------ .../example_build/tx_initialize_low_level.S | 19 ++------------- .../example_build/tx_initialize_low_level.s | 19 ++------------- .../example_build/tx_initialize_low_level.s | 24 ++----------------- .../example_build/tx_initialize_low_level.S | 12 +--------- .../gnu/src/tx_initialize_low_level.S | 12 +--------- .../iar/src/tx_initialize_low_level.s | 14 +---------- .../example_build/tx_initialize_low_level.s | 16 ++----------- .../sample_threadx/tx_initialize_low_level.S | 16 ++----------- .../example_build/tx_initialize_low_level.arm | 17 +++---------- .../example_build/tx_initialize_low_level.S | 14 +---------- .../example_build/tx_initialize_low_level.s | 17 ++----------- .../example_build/tx_initialize_low_level.s | 16 ++----------- .../example_build/tx_initialize_low_level.S | 12 +--------- .../ac6/src/tx_initialize_low_level.S | 12 +--------- .../example_build/tx_initialize_low_level.S | 12 +--------- .../iar/src/tx_initialize_low_level.s | 14 +---------- .../example_build/tx_initialize_low_level.s | 15 +----------- .../sample_threadx/tx_initialize_low_level.S | 16 ++----------- .../example_build/tx_initialize_low_level.arm | 17 +++---------- .../example_build/tx_initialize_low_level.S | 17 ++----------- .../example_build/tx_initialize_low_level.s | 17 ++----------- .../example_build/tx_initialize_low_level.s | 16 ++----------- .../ac6/src/tx_initialize_low_level.S | 12 +--------- .../iar/src/tx_initialize_low_level.s | 14 +---------- .../example_build/tx_initialize_low_level.S | 12 +--------- .../ac6/src/tx_initialize_low_level.S | 12 +--------- .../example_build/tx_initialize_low_level.S | 12 +--------- .../iar/src/tx_initialize_low_level.s | 14 +---------- .../example_build/tx_initialize_low_level.s | 16 ++----------- .../sample_threadx/tx_initialize_low_level.S | 16 ++----------- .../example_build/tx_initialize_low_level.arm | 17 +++---------- .../example_build/tx_initialize_low_level.S | 14 +---------- .../example_build/tx_initialize_low_level.s | 17 ++----------- .../ac6/src/tx_initialize_low_level.S | 12 +--------- .../example_build/tx_initialize_low_level.S | 12 +--------- .../iar/src/tx_initialize_low_level.s | 14 +---------- .../example_build/tx_initialize_low_level.s | 13 +--------- .../sample_threadx/tx_initialize_low_level.S | 13 +--------- .../example_build/tx_initialize_low_level.arm | 17 +++---------- .../example_build/tx_initialize_low_level.S | 14 +---------- .../example_build/tx_initialize_low_level.s | 14 +---------- .../threadx/ac6/src/tx_initialize_low_level.S | 12 +--------- .../threadx/iar/src/tx_initialize_low_level.s | 14 +---------- .../sample_threadx/tx_initialize_low_level.S | 15 +----------- .../tx_initialize_low_level.S | 16 +------------ .../sample_threadx/tx_initialize_low_level.S | 16 +------------ .../tx_initialize_low_level.S | 16 +------------ .../example_build/tx_initialize_low_level.s | 17 ++----------- .../example_build/tx_initialize_low_level.S | 12 +--------- .../src/tx_initialize_low_level.S | 12 +--------- .../example_build/tx_initialize_low_level.s | 14 +---------- .../example_build/tx_initialize_low_level.S | 16 ++----------- .../sample_threadx/tx_initialize_low_level.S | 15 +----------- .../tx_initialize_low_level.S | 15 +----------- .../example_build/tx_initialize_low_level.S | 14 +---------- .../example_build/tx_initialize_low_level.s | 17 ++----------- .../example_build/tx_initialize_low_level.S | 12 +--------- .../src/tx_initialize_low_level.S | 12 +--------- .../example_build/tx_initialize_low_level.s | 14 +---------- .../example_build/tx_initialize_low_level.S | 15 +----------- .../sample_threadx/tx_initialize_low_level.S | 15 +----------- .../tx_initialize_low_level.S | 15 +----------- .../example_build/tx_initialize_low_level.S | 16 +------------ .../example_build/tx_initialize_low_level.s | 16 +------------ .../example_build/tx_initialize_low_level.S | 15 +----------- .../sample_threadx/tx_initialize_low_level.S | 15 +----------- .../tx_initialize_low_level.S | 15 +----------- .../example_build/tx_initialize_low_level.S | 16 +------------ .../example_build/tx_initialize_low_level.s | 16 +------------ 71 files changed, 98 insertions(+), 966 deletions(-) diff --git a/ports/cortex_m0/ac5/example_build/tx_initialize_low_level.s b/ports/cortex_m0/ac5/example_build/tx_initialize_low_level.s index 3a585477f..0c2206ad8 100644 --- a/ports/cortex_m0/ac5/example_build/tx_initialize_low_level.s +++ b/ports/cortex_m0/ac5/example_build/tx_initialize_low_level.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026-present Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -7,6 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ +; Some portions generated by Copilot (Opus 5). ; ; ;/**************************************************************************/ @@ -20,7 +22,6 @@ ;/**************************************************************************/ ; ; - IMPORT _tx_thread_system_stack_ptr IMPORT _tx_initialize_unused_memory IMPORT _tx_timer_interrupt IMPORT __main @@ -137,12 +138,6 @@ _tx_initialize_low_level ADDS r1, r1, #4 ; STR r1, [r0] ; Setup first unused memory pointer ; -; /* Setup Vector Table Offset Register. */ -; - LDR r0, =0xE000ED08 ; Build address of NVIC registers - LDR r1, =__tx_vectors ; Pickup address of vector table - STR r1, [r0] ; Set vector table address -; ; /* Enable the cycle count register. */ ; ; LDR r0, =0xE0001000 ; Build address of DWT register @@ -151,21 +146,6 @@ _tx_initialize_low_level ; ORRS r1, r1, r2 ; Set the CYCCNTENA bit ; STR r1, [r0] ; Enable the cycle count register ; -; /* Setup Vector Table Offset Register. */ -; - LDR r0, =0xE000E000 ; Build address of NVIC registers - LDR r2, =0xD08 ; Offset to vector base register - ADD r0, r0, r2 ; Build vector base register - LDR r1, =__tx_vectors ; Pickup address of vector table - STR r1, [r0] ; Set vector table address -; -; /* Set system stack pointer from vector value. */ -; - LDR r0, =_tx_thread_system_stack_ptr ; Build address of system stack pointer - LDR r1, =__tx_vectors ; Pickup address of vector table - LDR r1, [r1] ; Pickup reset stack pointer - STR r1, [r0] ; Save system stack pointer -; ; /* Configure SysTick. */ ; LDR r0, =0xE000E000 ; Build address of NVIC registers diff --git a/ports/cortex_m0/ac6/example_build/sample_threadx/tx_initialize_low_level.S b/ports/cortex_m0/ac6/example_build/sample_threadx/tx_initialize_low_level.S index 7aad3a308..c3a7a2fe9 100644 --- a/ports/cortex_m0/ac6/example_build/sample_threadx/tx_initialize_low_level.S +++ b/ports/cortex_m0/ac6/example_build/sample_threadx/tx_initialize_low_level.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * Copyright (c) 2026-present Eclipse ThreadX contributors @ * @ * This program and the accompanying materials are made available under the @ * terms of the MIT License which is available at @@ -7,6 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ +// Some portions generated by Copilot (Opus 5). @ // Some portions generated by GitHub Copilot (Claude Sonnet 4.6). @ @ @@ -21,7 +23,6 @@ @/**************************************************************************/ @ @ - .global _tx_thread_system_stack_ptr .global _tx_initialize_unused_memory .global _tx_thread_context_save .global _tx_thread_context_restore @@ -94,21 +95,6 @@ _tx_initialize_low_level: @ ORRS r1, r1, r2 @ Set the CYCCNTENA bit @ STR r1, [r0] @ Enable the cycle count register @ -@ /* Setup Vector Table Offset Register. */ -@ - LDR r0, =0xE000E000 @ Build address of NVIC registers - LDR r2, =0xD08 @ Offset to vector base register - ADD r0, r0, r2 @ Build vector base register - LDR r1, =vector_table @ Pickup address of vector table - STR r1, [r0] @ Set vector table address -@ -@ /* Set system stack pointer from vector value. */ -@ - LDR r0, =_tx_thread_system_stack_ptr @ Build address of system stack pointer - LDR r1, =vector_table @ Pickup address of vector table - LDR r1, [r1] @ Pickup reset stack pointer - STR r1, [r0] @ Save system stack pointer -@ @ /* Configure SysTick for 100Hz clock, or 16384 cycles if no reference. */ @ LDR r0, =0xE000E000 @ Build address of NVIC registers diff --git a/ports/cortex_m0/gnu/example_build/tx_initialize_low_level.S b/ports/cortex_m0/gnu/example_build/tx_initialize_low_level.S index 36738f3db..0bf70f4a0 100644 --- a/ports/cortex_m0/gnu/example_build/tx_initialize_low_level.S +++ b/ports/cortex_m0/gnu/example_build/tx_initialize_low_level.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * Copyright (c) 2026-present Eclipse ThreadX contributors @ * @ * This program and the accompanying materials are made available under the @ * terms of the MIT License which is available at @@ -7,6 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ +// Some portions generated by Copilot (Opus 5). @ @ @/**************************************************************************/ @@ -30,13 +32,11 @@ @#include "tx_timer.h" @ @ - .global _tx_thread_system_stack_ptr .global _tx_initialize_unused_memory .global __RAM_segment_used_end__ .global _tx_thread_context_save .global _tx_thread_context_restore .global _tx_timer_interrupt - .global _vectors @ @ SYSTEM_CLOCK = 8000000 @@ -105,21 +105,6 @@ _tx_initialize_low_level: @ ORRS r1, r1, r2 @ Set the CYCCNTENA bit @ STR r1, [r0] @ Enable the cycle count register @ -@ /* Setup Vector Table Offset Register. */ -@ - LDR r0, =0xE000E000 @ Build address of NVIC registers - LDR r2, =0xD08 @ Offset to vector base register - ADD r0, r0, r2 @ Build vector base register - LDR r1, =_vectors @ Pickup address of vector table - STR r1, [r0] @ Set vector table address -@ -@ /* Set system stack pointer from vector value. */ -@ - LDR r0, =_tx_thread_system_stack_ptr @ Build address of system stack pointer - LDR r1, =_vectors @ Pickup address of vector table - LDR r1, [r1] @ Pickup reset stack pointer - STR r1, [r0] @ Save system stack pointer -@ @ /* Configure SysTick for 100Hz clock, or 16384 cycles if no reference. */ @ LDR r0, =0xE000E000 @ Build address of NVIC registers diff --git a/ports/cortex_m0/iar/example_build/tx_initialize_low_level.s b/ports/cortex_m0/iar/example_build/tx_initialize_low_level.s index 991f7809a..aa5bec7ba 100644 --- a/ports/cortex_m0/iar/example_build/tx_initialize_low_level.s +++ b/ports/cortex_m0/iar/example_build/tx_initialize_low_level.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026-present Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -7,6 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ +; Some portions generated by Copilot (Opus 5). ; ; ;/**************************************************************************/ @@ -20,10 +22,8 @@ ;/**************************************************************************/ ; ; - EXTERN _tx_thread_system_stack_ptr EXTERN _tx_initialize_unused_memory EXTERN _tx_timer_interrupt - EXTERN __vector_table EXTERN _tx_execution_isr_enter EXTERN _tx_execution_isr_exit ; @@ -100,21 +100,6 @@ _tx_initialize_low_level: ; ORRS r1, r1, r2 ; Set the CYCCNTENA bit ; STR r1, [r0] ; Enable the cycle count register ; -; /* Setup Vector Table Offset Register. */ -; - LDR r0, =0xE000E000 ; Build address of NVIC registers - LDR r2, =0xD08 ; Offset to vector base register - ADD r0, r0, r2 ; Build vector base register - LDR r1, =__vector_table ; Pickup address of vector table - STR r1, [r0] ; Set vector table address -; -; /* Set system stack pointer from vector value. */ -; - LDR r0, =_tx_thread_system_stack_ptr ; Build address of system stack pointer - LDR r1, =__vector_table ; Pickup address of vector table - LDR r1, [r1] ; Pickup reset stack pointer - STR r1, [r0] ; Save system stack pointer -; ; /* Configure SysTick. */ ; LDR r0, =0xE000E000 ; Build address of NVIC registers diff --git a/ports/cortex_m0/keil/example_build/tx_initialize_low_level.s b/ports/cortex_m0/keil/example_build/tx_initialize_low_level.s index 3a585477f..0c2206ad8 100644 --- a/ports/cortex_m0/keil/example_build/tx_initialize_low_level.s +++ b/ports/cortex_m0/keil/example_build/tx_initialize_low_level.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026-present Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -7,6 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ +; Some portions generated by Copilot (Opus 5). ; ; ;/**************************************************************************/ @@ -20,7 +22,6 @@ ;/**************************************************************************/ ; ; - IMPORT _tx_thread_system_stack_ptr IMPORT _tx_initialize_unused_memory IMPORT _tx_timer_interrupt IMPORT __main @@ -137,12 +138,6 @@ _tx_initialize_low_level ADDS r1, r1, #4 ; STR r1, [r0] ; Setup first unused memory pointer ; -; /* Setup Vector Table Offset Register. */ -; - LDR r0, =0xE000ED08 ; Build address of NVIC registers - LDR r1, =__tx_vectors ; Pickup address of vector table - STR r1, [r0] ; Set vector table address -; ; /* Enable the cycle count register. */ ; ; LDR r0, =0xE0001000 ; Build address of DWT register @@ -151,21 +146,6 @@ _tx_initialize_low_level ; ORRS r1, r1, r2 ; Set the CYCCNTENA bit ; STR r1, [r0] ; Enable the cycle count register ; -; /* Setup Vector Table Offset Register. */ -; - LDR r0, =0xE000E000 ; Build address of NVIC registers - LDR r2, =0xD08 ; Offset to vector base register - ADD r0, r0, r2 ; Build vector base register - LDR r1, =__tx_vectors ; Pickup address of vector table - STR r1, [r0] ; Set vector table address -; -; /* Set system stack pointer from vector value. */ -; - LDR r0, =_tx_thread_system_stack_ptr ; Build address of system stack pointer - LDR r1, =__tx_vectors ; Pickup address of vector table - LDR r1, [r1] ; Pickup reset stack pointer - STR r1, [r0] ; Save system stack pointer -; ; /* Configure SysTick. */ ; LDR r0, =0xE000E000 ; Build address of NVIC registers diff --git a/ports/cortex_m23/ac6/example_build/tx_initialize_low_level.S b/ports/cortex_m23/ac6/example_build/tx_initialize_low_level.S index 1625f570d..bbb2b2491 100644 --- a/ports/cortex_m23/ac6/example_build/tx_initialize_low_level.S +++ b/ports/cortex_m23/ac6/example_build/tx_initialize_low_level.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -87,23 +88,12 @@ _tx_initialize_low_level: ADDS r1, r1, #4 // STR r1, [r0] // Setup first unused memory pointer - /* Setup Vector Table Offset Register. */ - LDR r0, =0xE000ED08 // Build address of NVIC registers - LDR r1, =__Vectors // Pickup address of vector table - STR r1, [r0] // Set vector table address - /* Enable the cycle count register. */ // LDR r0, =0xE0001000 // Build address of DWT register // LDR r1, [r0] // Pickup the current value // ORR r1, r1, #1 // Set the CYCCNTENA bit // STR r1, [r0] // Enable the cycle count register - /* Set system stack pointer from vector value. */ - LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer - LDR r1, =__Vectors // Pickup address of vector table - LDR r1, [r1] // Pickup reset stack pointer - STR r1, [r0] // Save system stack pointer - /* Configure SysTick. */ LDR r0, =0xE000E000 // Build address of NVIC registers MOV r1, #0 // Build value for SysTick reset diff --git a/ports/cortex_m23/gnu/src/tx_initialize_low_level.S b/ports/cortex_m23/gnu/src/tx_initialize_low_level.S index 54e29e4ea..602d30b7f 100644 --- a/ports/cortex_m23/gnu/src/tx_initialize_low_level.S +++ b/ports/cortex_m23/gnu/src/tx_initialize_low_level.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -87,11 +88,6 @@ _tx_initialize_low_level: ADDS r1, r1, #4 // STR r1, [r0] // Setup first unused memory pointer - /* Setup Vector Table Offset Register. */ - LDR r0, =0xE000ED08 // Build address of NVIC registers - LDR r1, =_vectors // Pickup address of vector table - STR r1, [r0] // Set vector table address - // /* Enable the cycle count register. */ // // LDR r0, =0xE0001000 // Build address of DWT register @@ -99,12 +95,6 @@ _tx_initialize_low_level: // ORR r1, r1, #1 // Set the CYCCNTENA bit // STR r1, [r0] // Enable the cycle count register - /* Set system stack pointer from vector value. */ - LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer - LDR r1, =_vectors // Pickup address of vector table - LDR r1, [r1] // Pickup reset stack pointer - STR r1, [r0] // Save system stack pointer - /* Configure SysTick. */ LDR r0, =0xE000E000 // Build address of NVIC registers MOVS r1, #0 // Build value for SysTick reset diff --git a/ports/cortex_m23/iar/src/tx_initialize_low_level.s b/ports/cortex_m23/iar/src/tx_initialize_low_level.s index 90849145d..14b78e58a 100644 --- a/ports/cortex_m23/iar/src/tx_initialize_low_level.s +++ b/ports/cortex_m23/iar/src/tx_initialize_low_level.s @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -20,11 +21,9 @@ /**************************************************************************/ /**************************************************************************/ - EXTERN _tx_thread_system_stack_ptr EXTERN _tx_initialize_unused_memory EXTERN _tx_timer_interrupt EXTERN __main - EXTERN __vector_table EXTERN _tx_thread_current_ptr EXTERN _tx_thread_stack_error_handler @@ -85,23 +84,12 @@ _tx_initialize_low_level: LDR r1, =__tx_free_memory_start // Build first free address STR r1, [r0] // Setup first unused memory pointer - /* Setup Vector Table Offset Register. */ - LDR r0, =0xE000ED08 // Build address of NVIC registers - LDR r1, =__vector_table // Pickup address of vector table - STR r1, [r0] // Set vector table address - /* Enable the cycle count register. */ // LDR r0, =0xE0001000 // Build address of DWT register // LDR r1, [r0] // Pickup the current value // ORR r1, r1, #1 // Set the CYCCNTENA bit // STR r1, [r0] // Enable the cycle count register - /* Set system stack pointer from vector value. */ - LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer - LDR r1, =__vector_table // Pickup address of vector table - LDR r1, [r1] // Pickup reset stack pointer - STR r1, [r0] // Save system stack pointer - /* Configure SysTick. */ LDR r0, =0xE000E000 // Build address of NVIC registers MOV r1, #0 // Build value for SysTick reset diff --git a/ports/cortex_m3/ac5/example_build/tx_initialize_low_level.s b/ports/cortex_m3/ac5/example_build/tx_initialize_low_level.s index cb0b26054..b8da8e000 100644 --- a/ports/cortex_m3/ac5/example_build/tx_initialize_low_level.s +++ b/ports/cortex_m3/ac5/example_build/tx_initialize_low_level.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026-present Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -7,6 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ +; Some portions generated by Copilot (Opus 5). ; ; ;/**************************************************************************/ @@ -20,7 +22,6 @@ ;/**************************************************************************/ ; ; - IMPORT _tx_thread_system_stack_ptr IMPORT _tx_initialize_unused_memory IMPORT _tx_timer_interrupt IMPORT __main @@ -139,12 +140,6 @@ _tx_initialize_low_level ADD r1, r1, #4 ; STR r1, [r0] ; Setup first unused memory pointer ; -; /* Setup Vector Table Offset Register. */ -; - MOV r0, #0xE000E000 ; Build address of NVIC registers - LDR r1, =__tx_vectors ; Pickup address of vector table - STR r1, [r0, #0xD08] ; Set vector table address -; ; /* Enable the cycle count register. */ ; ; LDR r0, =0xE0001000 ; Build address of DWT register @@ -152,13 +147,6 @@ _tx_initialize_low_level ; ORR r1, r1, #1 ; Set the CYCCNTENA bit ; STR r1, [r0] ; Enable the cycle count register ; -; /* Set system stack pointer from vector value. */ -; - LDR r0, =_tx_thread_system_stack_ptr ; Build address of system stack pointer - LDR r1, =__tx_vectors ; Pickup address of vector table - LDR r1, [r1] ; Pickup reset stack pointer - STR r1, [r0] ; Save system stack pointer -; ; /* Configure SysTick for 100Hz clock, or 16384 cycles if no reference. */ ; MOV r0, #0xE000E000 ; Build address of NVIC registers diff --git a/ports/cortex_m3/ac6/example_build/sample_threadx/tx_initialize_low_level.S b/ports/cortex_m3/ac6/example_build/sample_threadx/tx_initialize_low_level.S index 325d21b30..54a671128 100644 --- a/ports/cortex_m3/ac6/example_build/sample_threadx/tx_initialize_low_level.S +++ b/ports/cortex_m3/ac6/example_build/sample_threadx/tx_initialize_low_level.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * Copyright (c) 2026-present Eclipse ThreadX contributors @ * @ * This program and the accompanying materials are made available under the @ * terms of the MIT License which is available at @@ -7,6 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ +// Some portions generated by Copilot (Opus 5). @ @ @/**************************************************************************/ @@ -20,7 +22,6 @@ @/**************************************************************************/ @ @ - .global _tx_thread_system_stack_ptr .global _tx_initialize_unused_memory .global _tx_timer_interrupt .global __main @@ -93,19 +94,6 @@ _tx_initialize_low_level: ADD r1, r1, #4 @ STR r1, [r0] @ Setup first unused memory pointer @ -@ /* Setup Vector Table Offset Register. */ -@ - MOV r0, #0xE000E000 @ Build address of NVIC registers - LDR r1, =vector_table @ Pickup address of vector table - STR r1, [r0, #0xD08] @ Set vector table address -@ -@ /* Set system stack pointer from vector value. */ -@ - LDR r0, =_tx_thread_system_stack_ptr @ Build address of system stack pointer - LDR r1, =vector_table @ Pickup address of vector table - LDR r1, [r1] @ Pickup reset stack pointer - STR r1, [r0] @ Save system stack pointer -@ @ /* Enable the cycle count register. */ @ LDR r0, =0xE0001000 @ Build address of DWT register diff --git a/ports/cortex_m3/ghs/example_build/tx_initialize_low_level.arm b/ports/cortex_m3/ghs/example_build/tx_initialize_low_level.arm index 96fa7fa9e..47beffbc2 100644 --- a/ports/cortex_m3/ghs/example_build/tx_initialize_low_level.arm +++ b/ports/cortex_m3/ghs/example_build/tx_initialize_low_level.arm @@ -1,5 +1,6 @@ /*************************************************************************** * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present Eclipse ThreadX contributors * * This program and the accompanying materials are made available under the * terms of the MIT License which is available at @@ -7,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +; Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -75,13 +77,6 @@ _tx_initialize_low_level: CPSID i ; Disable interrupts - /* Save the system stack pointer. */ - /* _tx_thread_system_stack_ptr = (VOID_PTR) (sp); */ - - LDR r1,=_tx_thread_system_stack_ptr ; Pickup address of system stack ptr - STR sp, [r1] ; Save system stack - - /* Save the first available memory address. */ /* _tx_initialize_unused_memory = (VOID_PTR) __ghsbegin_free_mem; */ @@ -98,15 +93,9 @@ _tx_initialize_low_level: STR r1, [r0] ; Enable the cycle count register - /* Setup Vector Table Offset Register. */ - - MOV r0, 0xE000E000 ; Build address of NVIC registers - LDR r1, =__vectors ; Pickup address of vector table - STR r1, [r0, 0xD08] ; Set vector table address - - /* Configure SysTick for 100Hz clock, or 16384 cycles if no reference. */ + MOV r0, 0xE000E000 ; Build address of NVIC registers MOV r1, 0 ; Build value for SysTick reset STR r1, [r0, 0x10] ; Reset SysTick Control STR r1, [r0, 0x18] ; Reset SysTick Counter Value diff --git a/ports/cortex_m3/gnu/example_build/tx_initialize_low_level.S b/ports/cortex_m3/gnu/example_build/tx_initialize_low_level.S index 4bf5d3281..d5bc168f6 100644 --- a/ports/cortex_m3/gnu/example_build/tx_initialize_low_level.S +++ b/ports/cortex_m3/gnu/example_build/tx_initialize_low_level.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -19,12 +20,10 @@ /**************************************************************************/ /**************************************************************************/ - .global _tx_thread_system_stack_ptr .global _tx_initialize_unused_memory .global __RAM_segment_used_end__ .global _tx_timer_interrupt .global __main - .global _vectors .global __tx_NMIHandler // NMI .global __tx_BadHandler // HardFault .global __tx_SVCallHandler // SVCall @@ -89,17 +88,6 @@ _tx_initialize_low_level: ADD r1, r1, #4 // STR r1, [r0] // Setup first unused memory pointer - /* Setup Vector Table Offset Register. */ - MOV r0, #0xE000E000 // Build address of NVIC registers - LDR r1, =_vectors // Pickup address of vector table - STR r1, [r0, #0xD08] // Set vector table address - - /* Set system stack pointer from vector value. */ - LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer - LDR r1, =_vectors // Pickup address of vector table - LDR r1, [r1] // Pickup reset stack pointer - STR r1, [r0] // Save system stack pointer - /* Enable the cycle count register. */ LDR r0, =0xE0001000 // Build address of DWT register LDR r1, [r0] // Pickup the current value diff --git a/ports/cortex_m3/iar/example_build/tx_initialize_low_level.s b/ports/cortex_m3/iar/example_build/tx_initialize_low_level.s index ef1f8f9ef..2c985dbb1 100644 --- a/ports/cortex_m3/iar/example_build/tx_initialize_low_level.s +++ b/ports/cortex_m3/iar/example_build/tx_initialize_low_level.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026-present Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -7,6 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ +; Some portions generated by Copilot (Opus 5). ; ; ;/**************************************************************************/ @@ -20,10 +22,8 @@ ;/**************************************************************************/ ; ; - EXTERN _tx_thread_system_stack_ptr EXTERN _tx_initialize_unused_memory EXTERN _tx_timer_interrupt - EXTERN __vector_table EXTERN _tx_execution_isr_enter EXTERN _tx_execution_isr_exit ; @@ -97,19 +97,6 @@ _tx_initialize_low_level: ORR r1, r1, #1 ; Set the CYCCNTENA bit STR r1, [r0] ; Enable the cycle count register ; -; /* Setup Vector Table Offset Register. */ -; - MOV r0, #0xE000E000 ; Build address of NVIC registers - LDR r1, =__vector_table ; Pickup address of vector table - STR r1, [r0, #0xD08] ; Set vector table address -; -; /* Set system stack pointer from vector value. */ -; - LDR r0, =_tx_thread_system_stack_ptr ; Build address of system stack pointer - LDR r1, =__vector_table ; Pickup address of vector table - LDR r1, [r1] ; Pickup reset stack pointer - STR r1, [r0] ; Save system stack pointer -; ; /* Configure SysTick. */ ; MOV r0, #0xE000E000 ; Build address of NVIC registers diff --git a/ports/cortex_m3/keil/example_build/tx_initialize_low_level.s b/ports/cortex_m3/keil/example_build/tx_initialize_low_level.s index adde4604c..62ea64d02 100644 --- a/ports/cortex_m3/keil/example_build/tx_initialize_low_level.s +++ b/ports/cortex_m3/keil/example_build/tx_initialize_low_level.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026-present Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -7,6 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ +; Some portions generated by Copilot (Opus 5). ; ; ;/**************************************************************************/ @@ -20,7 +22,6 @@ ;/**************************************************************************/ ; ; - IMPORT _tx_thread_system_stack_ptr IMPORT _tx_initialize_unused_memory IMPORT _tx_timer_interrupt IMPORT __main @@ -138,12 +139,6 @@ _tx_initialize_low_level ADD r1, r1, #4 ; STR r1, [r0] ; Setup first unused memory pointer ; -; /* Setup Vector Table Offset Register. */ -; - MOV r0, #0xE000E000 ; Build address of NVIC registers - LDR r1, =__tx_vectors ; Pickup address of vector table - STR r1, [r0, #0xD08] ; Set vector table address -; ; /* Enable the cycle count register. */ ; ; LDR r0, =0xE0001000 ; Build address of DWT register @@ -151,13 +146,6 @@ _tx_initialize_low_level ; ORR r1, r1, #1 ; Set the CYCCNTENA bit ; STR r1, [r0] ; Enable the cycle count register ; -; /* Set system stack pointer from vector value. */ -; - LDR r0, =_tx_thread_system_stack_ptr ; Build address of system stack pointer - LDR r1, =__tx_vectors ; Pickup address of vector table - LDR r1, [r1] ; Pickup reset stack pointer - STR r1, [r0] ; Save system stack pointer -; ; /* Configure SysTick for 100Hz clock, or 16384 cycles if no reference. */ ; MOV r0, #0xE000E000 ; Build address of NVIC registers diff --git a/ports/cortex_m33/ac6/example_build/tx_initialize_low_level.S b/ports/cortex_m33/ac6/example_build/tx_initialize_low_level.S index b32c5ac45..f9bd71c62 100644 --- a/ports/cortex_m33/ac6/example_build/tx_initialize_low_level.S +++ b/ports/cortex_m33/ac6/example_build/tx_initialize_low_level.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -84,23 +85,12 @@ _tx_initialize_low_level: ADD r1, r1, #4 // STR r1, [r0] // Setup first unused memory pointer - /* Setup Vector Table Offset Register. */ - MOV r0, #0xE000E000 // Build address of NVIC registers - LDR r1, =__Vectors // Pickup address of vector table - STR r1, [r0, #0xD08] // Set vector table address - /* Enable the cycle count register. */ LDR r0, =0xE0001000 // Build address of DWT register LDR r1, [r0] // Pickup the current value ORR r1, r1, #1 // Set the CYCCNTENA bit STR r1, [r0] // Enable the cycle count register - /* Set system stack pointer from vector value. */ - LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer - LDR r1, =__Vectors // Pickup address of vector table - LDR r1, [r1] // Pickup reset stack pointer - STR r1, [r0] // Save system stack pointer - /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers MOV r1, #0 // Build value for SysTick reset diff --git a/ports/cortex_m33/ac6/src/tx_initialize_low_level.S b/ports/cortex_m33/ac6/src/tx_initialize_low_level.S index e74425a43..d38ae7156 100644 --- a/ports/cortex_m33/ac6/src/tx_initialize_low_level.S +++ b/ports/cortex_m33/ac6/src/tx_initialize_low_level.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -87,23 +88,12 @@ _tx_initialize_low_level: ADD r1, r1, #4 // STR r1, [r0] // Setup first unused memory pointer - /* Setup Vector Table Offset Register. */ - MOV r0, #0xE000E000 // Build address of NVIC registers - LDR r1, =__Vectors // Pickup address of vector table - STR r1, [r0, #0xD08] // Set vector table address - /* Enable the cycle count register. */ LDR r0, =0xE0001000 // Build address of DWT register LDR r1, [r0] // Pickup the current value ORR r1, r1, #1 // Set the CYCCNTENA bit STR r1, [r0] // Enable the cycle count register - /* Set system stack pointer from vector value. */ - LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer - LDR r1, =__Vectors // Pickup address of vector table - LDR r1, [r1] // Pickup reset stack pointer - STR r1, [r0] // Save system stack pointer - /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers MOV r1, #0 // Build value for SysTick reset diff --git a/ports/cortex_m33/gnu/example_build/tx_initialize_low_level.S b/ports/cortex_m33/gnu/example_build/tx_initialize_low_level.S index 0ddfba102..fe965cd69 100644 --- a/ports/cortex_m33/gnu/example_build/tx_initialize_low_level.S +++ b/ports/cortex_m33/gnu/example_build/tx_initialize_low_level.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -87,23 +88,12 @@ _tx_initialize_low_level: ADD r1, r1, #4 // STR r1, [r0] // Setup first unused memory pointer - /* Setup Vector Table Offset Register. */ - MOV r0, #0xE000E000 // Build address of NVIC registers - LDR r1, =_vectors // Pickup address of vector table - STR r1, [r0, #0xD08] // Set vector table address - /* Enable the cycle count register. */ LDR r0, =0xE0001000 // Build address of DWT register LDR r1, [r0] // Pickup the current value ORR r1, r1, #1 // Set the CYCCNTENA bit STR r1, [r0] // Enable the cycle count register - /* Set system stack pointer from vector value. */ - LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer - LDR r1, =_vectors // Pickup address of vector table - LDR r1, [r1] // Pickup reset stack pointer - STR r1, [r0] // Save system stack pointer - /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers MOV r1, #0 // Build value for SysTick reset diff --git a/ports/cortex_m33/iar/src/tx_initialize_low_level.s b/ports/cortex_m33/iar/src/tx_initialize_low_level.s index 17d29846e..0bcff9134 100644 --- a/ports/cortex_m33/iar/src/tx_initialize_low_level.s +++ b/ports/cortex_m33/iar/src/tx_initialize_low_level.s @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -24,11 +25,9 @@ #include "tx_user.h" #endif - EXTERN _tx_thread_system_stack_ptr EXTERN _tx_initialize_unused_memory EXTERN _tx_timer_interrupt EXTERN __main - EXTERN __vector_table EXTERN _tx_thread_current_ptr EXTERN _tx_thread_stack_error_handler @@ -89,23 +88,12 @@ _tx_initialize_low_level: LDR r1, =__tx_free_memory_start // Build first free address STR r1, [r0] // Setup first unused memory pointer - /* Setup Vector Table Offset Register. */ - MOV r0, #0xE000E000 // Build address of NVIC registers - LDR r1, =__vector_table // Pickup address of vector table - STR r1, [r0, #0xD08] // Set vector table address - /* Enable the cycle count register. */ // LDR r0, =0xE0001000 // Build address of DWT register // LDR r1, [r0] // Pickup the current value // ORR r1, r1, #1 // Set the CYCCNTENA bit // STR r1, [r0] // Enable the cycle count register - /* Set system stack pointer from vector value. */ - LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer - LDR r1, =__vector_table // Pickup address of vector table - LDR r1, [r1] // Pickup reset stack pointer - STR r1, [r0] // Save system stack pointer - /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers MOV r1, #0 // Build value for SysTick reset diff --git a/ports/cortex_m4/ac5/example_build/tx_initialize_low_level.s b/ports/cortex_m4/ac5/example_build/tx_initialize_low_level.s index c08bd94e4..706914071 100644 --- a/ports/cortex_m4/ac5/example_build/tx_initialize_low_level.s +++ b/ports/cortex_m4/ac5/example_build/tx_initialize_low_level.s @@ -1,4 +1,5 @@ ;/**************************************************************************/ +; Some portions generated by Copilot (Opus 5). ;/* */ ;/* Copyright (c) 2024 Microsoft Corporation. */ ;/* */ @@ -16,7 +17,6 @@ ;/**************************************************************************/ ; ; - IMPORT _tx_thread_system_stack_ptr IMPORT _tx_initialize_unused_memory IMPORT _tx_thread_context_save IMPORT _tx_thread_context_restore @@ -143,12 +143,6 @@ _tx_initialize_low_level ADD r1, r1, #4 ; STR r1, [r0] ; Setup first unused memory pointer ; -; /* Setup Vector Table Offset Register. */ -; - MOV r0, #0xE000E000 ; Build address of NVIC registers - LDR r1, =__tx_vectors ; Pickup address of vector table - STR r1, [r0, #0xD08] ; Set vector table address -; ; /* Enable the cycle count register. */ ; ; LDR r0, =0xE0001000 ; Build address of DWT register @@ -156,13 +150,6 @@ _tx_initialize_low_level ; ORR r1, r1, #1 ; Set the CYCCNTENA bit ; STR r1, [r0] ; Enable the cycle count register ; -; /* Set system stack pointer from vector value. */ -; - LDR r0, =_tx_thread_system_stack_ptr ; Build address of system stack pointer - LDR r1, =__tx_vectors ; Pickup address of vector table - LDR r1, [r1] ; Pickup reset stack pointer - STR r1, [r0] ; Save system stack pointer -; ; /* Configure SysTick. */ ; MOV r0, #0xE000E000 ; Build address of NVIC registers diff --git a/ports/cortex_m4/ac6/example_build/sample_threadx/tx_initialize_low_level.S b/ports/cortex_m4/ac6/example_build/sample_threadx/tx_initialize_low_level.S index 9bada308d..a049386b1 100644 --- a/ports/cortex_m4/ac6/example_build/sample_threadx/tx_initialize_low_level.S +++ b/ports/cortex_m4/ac6/example_build/sample_threadx/tx_initialize_low_level.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * Copyright (c) 2026-present Eclipse ThreadX contributors @ * @ * This program and the accompanying materials are made available under the @ * terms of the MIT License which is available at @@ -7,6 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ +// Some portions generated by Copilot (Opus 5). @ @ @/**************************************************************************/ @@ -20,7 +22,6 @@ @/**************************************************************************/ @ @ - .global _tx_thread_system_stack_ptr .global _tx_initialize_unused_memory .global _tx_timer_interrupt .global __main @@ -93,19 +94,6 @@ _tx_initialize_low_level: ADD r1, r1, #4 @ STR r1, [r0] @ Setup first unused memory pointer @ -@ /* Setup Vector Table Offset Register. */ -@ - MOV r0, #0xE000E000 @ Build address of NVIC registers - LDR r1, =vector_table @ Pickup address of vector table - STR r1, [r0, #0xD08] @ Set vector table address -@ -@ /* Set system stack pointer from vector value. */ -@ - LDR r0, =_tx_thread_system_stack_ptr @ Build address of system stack pointer - LDR r1, =vector_table @ Pickup address of vector table - LDR r1, [r1] @ Pickup reset stack pointer - STR r1, [r0] @ Save system stack pointer -@ @ /* Enable the cycle count register. */ @ LDR r0, =0xE0001000 @ Build address of DWT register diff --git a/ports/cortex_m4/ghs/example_build/tx_initialize_low_level.arm b/ports/cortex_m4/ghs/example_build/tx_initialize_low_level.arm index bf96627de..1de645edd 100644 --- a/ports/cortex_m4/ghs/example_build/tx_initialize_low_level.arm +++ b/ports/cortex_m4/ghs/example_build/tx_initialize_low_level.arm @@ -1,5 +1,6 @@ /*************************************************************************** * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present Eclipse ThreadX contributors * * This program and the accompanying materials are made available under the * terms of the MIT License which is available at @@ -7,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +; Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -75,13 +77,6 @@ _tx_initialize_low_level: CPSID i ; Disable interrupts - /* Save the system stack pointer. */ - /* _tx_thread_system_stack_ptr = (VOID_PTR) (sp); */ - - LDR r1,=_tx_thread_system_stack_ptr ; Pickup address of system stack ptr - STR sp, [r1] ; Save system stack - - /* Save the first available memory address. */ /* _tx_initialize_unused_memory = (VOID_PTR) __ghsbegin_free_mem; */ @@ -98,15 +93,9 @@ _tx_initialize_low_level: STR r1, [r0] ; Enable the cycle count register - /* Setup Vector Table Offset Register. */ - - MOV r0, 0xE000E000 ; Build address of NVIC registers - LDR r1, =__vectors ; Pickup address of vector table - STR r1, [r0, 0xD08] ; Set vector table address - - /* Configure SysTick for 100Hz clock, or 16384 cycles if no reference. */ + MOV r0, 0xE000E000 ; Build address of NVIC registers MOV r1, 0 ; Build value for SysTick reset STR r1, [r0, 0x10] ; Reset SysTick Control STR r1, [r0, 0x18] ; Reset SysTick Counter Value diff --git a/ports/cortex_m4/gnu/example_build/tx_initialize_low_level.S b/ports/cortex_m4/gnu/example_build/tx_initialize_low_level.S index 39399ebc4..e714dee70 100644 --- a/ports/cortex_m4/gnu/example_build/tx_initialize_low_level.S +++ b/ports/cortex_m4/gnu/example_build/tx_initialize_low_level.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * Copyright (c) 2026-present Eclipse ThreadX contributors @ * @ * This program and the accompanying materials are made available under the @ * terms of the MIT License which is available at @@ -7,6 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ +// Some portions generated by Copilot (Opus 5). @ @ @/**************************************************************************/ @@ -20,14 +22,12 @@ @/**************************************************************************/ @ @ - .global _tx_thread_system_stack_ptr .global _tx_initialize_unused_memory .global __RAM_segment_used_end__ .global _tx_timer_interrupt .global __main .global __tx_SVCallHandler .global __tx_PendSVHandler - .global _vectors .global __tx_NMIHandler @ NMI .global __tx_BadHandler @ HardFault .global __tx_SVCallHandler @ SVCall @@ -95,19 +95,6 @@ _tx_initialize_low_level: ADD r1, r1, #4 @ STR r1, [r0] @ Setup first unused memory pointer @ -@ /* Setup Vector Table Offset Register. */ -@ - MOV r0, #0xE000E000 @ Build address of NVIC registers - LDR r1, =_vectors @ Pickup address of vector table - STR r1, [r0, #0xD08] @ Set vector table address -@ -@ /* Set system stack pointer from vector value. */ -@ - LDR r0, =_tx_thread_system_stack_ptr @ Build address of system stack pointer - LDR r1, =_vectors @ Pickup address of vector table - LDR r1, [r1] @ Pickup reset stack pointer - STR r1, [r0] @ Save system stack pointer -@ @ /* Enable the cycle count register. */ @ LDR r0, =0xE0001000 @ Build address of DWT register diff --git a/ports/cortex_m4/iar/example_build/tx_initialize_low_level.s b/ports/cortex_m4/iar/example_build/tx_initialize_low_level.s index 8e3f7d85d..044339c05 100644 --- a/ports/cortex_m4/iar/example_build/tx_initialize_low_level.s +++ b/ports/cortex_m4/iar/example_build/tx_initialize_low_level.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026-present Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -7,6 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ +; Some portions generated by Copilot (Opus 5). ; ; ;/**************************************************************************/ @@ -20,10 +22,8 @@ ;/**************************************************************************/ ; ; - EXTERN _tx_thread_system_stack_ptr EXTERN _tx_initialize_unused_memory EXTERN _tx_timer_interrupt - EXTERN __vector_table EXTERN _tx_execution_isr_enter EXTERN _tx_execution_isr_exit ; @@ -97,19 +97,6 @@ _tx_initialize_low_level: ORR r1, r1, #1 ; Set the CYCCNTENA bit STR r1, [r0] ; Enable the cycle count register ; -; /* Setup Vector Table Offset Register. */ -; - MOV r0, #0xE000E000 ; Build address of NVIC registers - LDR r1, =__vector_table ; Pickup address of vector table - STR r1, [r0, #0xD08] ; Set vector table address -; -; /* Set system stack pointer from vector value. */ -; - LDR r0, =_tx_thread_system_stack_ptr ; Build address of system stack pointer - LDR r1, =__vector_table ; Pickup address of vector table - LDR r1, [r1] ; Pickup reset stack pointer - STR r1, [r0] ; Save system stack pointer -; ; /* Configure SysTick. */ ; MOV r0, #0xE000E000 ; Build address of NVIC registers diff --git a/ports/cortex_m4/keil/example_build/tx_initialize_low_level.s b/ports/cortex_m4/keil/example_build/tx_initialize_low_level.s index 4bce73a43..015d2c73e 100644 --- a/ports/cortex_m4/keil/example_build/tx_initialize_low_level.s +++ b/ports/cortex_m4/keil/example_build/tx_initialize_low_level.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026-present Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -7,6 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ +; Some portions generated by Copilot (Opus 5). ; ; ;/**************************************************************************/ @@ -30,7 +32,6 @@ ;#include "tx_timer.h" ; ; - IMPORT _tx_thread_system_stack_ptr IMPORT _tx_initialize_unused_memory IMPORT _tx_thread_context_save IMPORT _tx_thread_context_restore @@ -158,12 +159,6 @@ _tx_initialize_low_level ADD r1, r1, #4 ; STR r1, [r0] ; Setup first unused memory pointer ; -; /* Setup Vector Table Offset Register. */ -; - MOV r0, #0xE000E000 ; Build address of NVIC registers - LDR r1, =__tx_vectors ; Pickup address of vector table - STR r1, [r0, #0xD08] ; Set vector table address -; ; /* Enable the cycle count register. */ ; ; LDR r0, =0xE0001000 ; Build address of DWT register @@ -171,13 +166,6 @@ _tx_initialize_low_level ; ORR r1, r1, #1 ; Set the CYCCNTENA bit ; STR r1, [r0] ; Enable the cycle count register ; -; /* Set system stack pointer from vector value. */ -; - LDR r0, =_tx_thread_system_stack_ptr ; Build address of system stack pointer - LDR r1, =__tx_vectors ; Pickup address of vector table - LDR r1, [r1] ; Pickup reset stack pointer - STR r1, [r0] ; Save system stack pointer -; ; /* Configure SysTick. */ ; MOV r0, #0xE000E000 ; Build address of NVIC registers diff --git a/ports/cortex_m52/ac6/src/tx_initialize_low_level.S b/ports/cortex_m52/ac6/src/tx_initialize_low_level.S index 0e1af6b5c..d7921ee30 100644 --- a/ports/cortex_m52/ac6/src/tx_initialize_low_level.S +++ b/ports/cortex_m52/ac6/src/tx_initialize_low_level.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -87,23 +88,12 @@ _tx_initialize_low_level: ADD r1, r1, #4 // STR r1, [r0] // Setup first unused memory pointer - /* Setup Vector Table Offset Register. */ - MOV r0, #0xE000E000 // Build address of NVIC registers - LDR r1, =__Vectors // Pickup address of vector table - STR r1, [r0, #0xD08] // Set vector table address - /* Enable the cycle count register. */ LDR r0, =0xE0001000 // Build address of DWT register LDR r1, [r0] // Pickup the current value ORR r1, r1, #1 // Set the CYCCNTENA bit STR r1, [r0] // Enable the cycle count register - /* Set system stack pointer from vector value. */ - LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer - LDR r1, =__Vectors // Pickup address of vector table - LDR r1, [r1] // Pickup reset stack pointer - STR r1, [r0] // Save system stack pointer - /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers MOV r1, #0 // Build value for SysTick reset diff --git a/ports/cortex_m52/iar/src/tx_initialize_low_level.s b/ports/cortex_m52/iar/src/tx_initialize_low_level.s index 2cb79d4a5..12ea8649a 100644 --- a/ports/cortex_m52/iar/src/tx_initialize_low_level.s +++ b/ports/cortex_m52/iar/src/tx_initialize_low_level.s @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -24,11 +25,9 @@ #include "tx_user.h" #endif - EXTERN _tx_thread_system_stack_ptr EXTERN _tx_initialize_unused_memory EXTERN _tx_timer_interrupt EXTERN __main - EXTERN __vector_table EXTERN _tx_thread_current_ptr EXTERN _tx_thread_stack_error_handler @@ -89,23 +88,12 @@ _tx_initialize_low_level: LDR r1, =__tx_free_memory_start // Build first free address STR r1, [r0] // Setup first unused memory pointer - /* Setup Vector Table Offset Register. */ - MOV r0, #0xE000E000 // Build address of NVIC registers - LDR r1, =__vector_table // Pickup address of vector table - STR r1, [r0, #0xD08] // Set vector table address - /* Enable the cycle count register. */ // LDR r0, =0xE0001000 // Build address of DWT register // LDR r1, [r0] // Pickup the current value // ORR r1, r1, #1 // Set the CYCCNTENA bit // STR r1, [r0] // Enable the cycle count register - /* Set system stack pointer from vector value. */ - LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer - LDR r1, =__vector_table // Pickup address of vector table - LDR r1, [r1] // Pickup reset stack pointer - STR r1, [r0] // Save system stack pointer - /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers MOV r1, #0 // Build value for SysTick reset diff --git a/ports/cortex_m55/ac6/example_build/tx_initialize_low_level.S b/ports/cortex_m55/ac6/example_build/tx_initialize_low_level.S index 6e7e9eedd..b6ea3dcf9 100644 --- a/ports/cortex_m55/ac6/example_build/tx_initialize_low_level.S +++ b/ports/cortex_m55/ac6/example_build/tx_initialize_low_level.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -84,23 +85,12 @@ _tx_initialize_low_level: ADD r1, r1, #4 // STR r1, [r0] // Setup first unused memory pointer - /* Setup Vector Table Offset Register. */ - MOV r0, #0xE000E000 // Build address of NVIC registers - LDR r1, =__Vectors // Pickup address of vector table - STR r1, [r0, #0xD08] // Set vector table address - /* Enable the cycle count register. */ LDR r0, =0xE0001000 // Build address of DWT register LDR r1, [r0] // Pickup the current value ORR r1, r1, #1 // Set the CYCCNTENA bit STR r1, [r0] // Enable the cycle count register - /* Set system stack pointer from vector value. */ - LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer - LDR r1, =__Vectors // Pickup address of vector table - LDR r1, [r1] // Pickup reset stack pointer - STR r1, [r0] // Save system stack pointer - /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers MOV r1, #0 // Build value for SysTick reset diff --git a/ports/cortex_m55/ac6/src/tx_initialize_low_level.S b/ports/cortex_m55/ac6/src/tx_initialize_low_level.S index 45f180127..8e80b625f 100644 --- a/ports/cortex_m55/ac6/src/tx_initialize_low_level.S +++ b/ports/cortex_m55/ac6/src/tx_initialize_low_level.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -87,23 +88,12 @@ _tx_initialize_low_level: ADD r1, r1, #4 // STR r1, [r0] // Setup first unused memory pointer - /* Setup Vector Table Offset Register. */ - MOV r0, #0xE000E000 // Build address of NVIC registers - LDR r1, =__Vectors // Pickup address of vector table - STR r1, [r0, #0xD08] // Set vector table address - /* Enable the cycle count register. */ LDR r0, =0xE0001000 // Build address of DWT register LDR r1, [r0] // Pickup the current value ORR r1, r1, #1 // Set the CYCCNTENA bit STR r1, [r0] // Enable the cycle count register - /* Set system stack pointer from vector value. */ - LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer - LDR r1, =__Vectors // Pickup address of vector table - LDR r1, [r1] // Pickup reset stack pointer - STR r1, [r0] // Save system stack pointer - /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers MOV r1, #0 // Build value for SysTick reset diff --git a/ports/cortex_m55/gnu/example_build/tx_initialize_low_level.S b/ports/cortex_m55/gnu/example_build/tx_initialize_low_level.S index 0a8d5363a..c87d00a32 100644 --- a/ports/cortex_m55/gnu/example_build/tx_initialize_low_level.S +++ b/ports/cortex_m55/gnu/example_build/tx_initialize_low_level.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -87,23 +88,12 @@ _tx_initialize_low_level: ADD r1, r1, #4 // STR r1, [r0] // Setup first unused memory pointer - /* Setup Vector Table Offset Register. */ - MOV r0, #0xE000E000 // Build address of NVIC registers - LDR r1, =_vectors // Pickup address of vector table - STR r1, [r0, #0xD08] // Set vector table address - /* Enable the cycle count register. */ LDR r0, =0xE0001000 // Build address of DWT register LDR r1, [r0] // Pickup the current value ORR r1, r1, #1 // Set the CYCCNTENA bit STR r1, [r0] // Enable the cycle count register - /* Set system stack pointer from vector value. */ - LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer - LDR r1, =_vectors // Pickup address of vector table - LDR r1, [r1] // Pickup reset stack pointer - STR r1, [r0] // Save system stack pointer - /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers MOV r1, #0 // Build value for SysTick reset diff --git a/ports/cortex_m55/iar/src/tx_initialize_low_level.s b/ports/cortex_m55/iar/src/tx_initialize_low_level.s index faf658178..be4e8ae25 100644 --- a/ports/cortex_m55/iar/src/tx_initialize_low_level.s +++ b/ports/cortex_m55/iar/src/tx_initialize_low_level.s @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -24,11 +25,9 @@ #include "tx_user.h" #endif - EXTERN _tx_thread_system_stack_ptr EXTERN _tx_initialize_unused_memory EXTERN _tx_timer_interrupt EXTERN __main - EXTERN __vector_table EXTERN _tx_thread_current_ptr EXTERN _tx_thread_stack_error_handler @@ -89,23 +88,12 @@ _tx_initialize_low_level: LDR r1, =__tx_free_memory_start // Build first free address STR r1, [r0] // Setup first unused memory pointer - /* Setup Vector Table Offset Register. */ - MOV r0, #0xE000E000 // Build address of NVIC registers - LDR r1, =__vector_table // Pickup address of vector table - STR r1, [r0, #0xD08] // Set vector table address - /* Enable the cycle count register. */ // LDR r0, =0xE0001000 // Build address of DWT register // LDR r1, [r0] // Pickup the current value // ORR r1, r1, #1 // Set the CYCCNTENA bit // STR r1, [r0] // Enable the cycle count register - /* Set system stack pointer from vector value. */ - LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer - LDR r1, =__vector_table // Pickup address of vector table - LDR r1, [r1] // Pickup reset stack pointer - STR r1, [r0] // Save system stack pointer - /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers MOV r1, #0 // Build value for SysTick reset diff --git a/ports/cortex_m7/ac5/example_build/tx_initialize_low_level.s b/ports/cortex_m7/ac5/example_build/tx_initialize_low_level.s index 7f3e86907..94e13b01f 100644 --- a/ports/cortex_m7/ac5/example_build/tx_initialize_low_level.s +++ b/ports/cortex_m7/ac5/example_build/tx_initialize_low_level.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026-present Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -7,6 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ +; Some portions generated by Copilot (Opus 5). ; ; ;/**************************************************************************/ @@ -20,7 +22,6 @@ ;/**************************************************************************/ ; ; - IMPORT _tx_thread_system_stack_ptr IMPORT _tx_initialize_unused_memory IMPORT _tx_thread_context_save IMPORT _tx_thread_context_restore @@ -148,12 +149,6 @@ _tx_initialize_low_level ADD r1, r1, #4 ; STR r1, [r0] ; Setup first unused memory pointer ; -; /* Setup Vector Table Offset Register. */ -; - MOV r0, #0xE000E000 ; Build address of NVIC registers - LDR r1, =__tx_vectors ; Pickup address of vector table - STR r1, [r0, #0xD08] ; Set vector table address -; ; /* Enable the cycle count register. */ ; ; LDR r0, =0xE0001000 ; Build address of DWT register @@ -161,13 +156,6 @@ _tx_initialize_low_level ; ORR r1, r1, #1 ; Set the CYCCNTENA bit ; STR r1, [r0] ; Enable the cycle count register ; -; /* Set system stack pointer from vector value. */ -; - LDR r0, =_tx_thread_system_stack_ptr ; Build address of system stack pointer - LDR r1, =__tx_vectors ; Pickup address of vector table - LDR r1, [r1] ; Pickup reset stack pointer - STR r1, [r0] ; Save system stack pointer -; ; /* Configure SysTick. */ ; MOV r0, #0xE000E000 ; Build address of NVIC registers diff --git a/ports/cortex_m7/ac6/example_build/sample_threadx/tx_initialize_low_level.S b/ports/cortex_m7/ac6/example_build/sample_threadx/tx_initialize_low_level.S index 0e50bc488..4095c8516 100644 --- a/ports/cortex_m7/ac6/example_build/sample_threadx/tx_initialize_low_level.S +++ b/ports/cortex_m7/ac6/example_build/sample_threadx/tx_initialize_low_level.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * Copyright (c) 2026-present Eclipse ThreadX contributors @ * @ * This program and the accompanying materials are made available under the @ * terms of the MIT License which is available at @@ -7,6 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ +// Some portions generated by Copilot (Opus 5). @ @ @/**************************************************************************/ @@ -20,7 +22,6 @@ @/**************************************************************************/ @ @ - .global _tx_thread_system_stack_ptr .global _tx_initialize_unused_memory .global _tx_timer_interrupt .global __main @@ -93,19 +94,6 @@ _tx_initialize_low_level: ADD r1, r1, #4 @ STR r1, [r0] @ Setup first unused memory pointer @ -@ /* Setup Vector Table Offset Register. */ -@ - MOV r0, #0xE000E000 @ Build address of NVIC registers - LDR r1, =vector_table @ Pickup address of vector table - STR r1, [r0, #0xD08] @ Set vector table address -@ -@ /* Set system stack pointer from vector value. */ -@ - LDR r0, =_tx_thread_system_stack_ptr @ Build address of system stack pointer - LDR r1, =vector_table @ Pickup address of vector table - LDR r1, [r1] @ Pickup reset stack pointer - STR r1, [r0] @ Save system stack pointer -@ @ /* Enable the cycle count register. */ @ LDR r0, =0xE0001000 @ Build address of DWT register diff --git a/ports/cortex_m7/ghs/example_build/tx_initialize_low_level.arm b/ports/cortex_m7/ghs/example_build/tx_initialize_low_level.arm index fc6e19fe8..b98fa9745 100644 --- a/ports/cortex_m7/ghs/example_build/tx_initialize_low_level.arm +++ b/ports/cortex_m7/ghs/example_build/tx_initialize_low_level.arm @@ -1,5 +1,6 @@ /*************************************************************************** * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present Eclipse ThreadX contributors * * This program and the accompanying materials are made available under the * terms of the MIT License which is available at @@ -7,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +; Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -75,13 +77,6 @@ _tx_initialize_low_level: CPSID i ; Disable interrupts - /* Save the system stack pointer. */ - /* _tx_thread_system_stack_ptr = (VOID_PTR) (sp); */ - - LDR r1,=_tx_thread_system_stack_ptr ; Pickup address of system stack ptr - STR sp, [r1] ; Save system stack - - /* Save the first available memory address. */ /* _tx_initialize_unused_memory = (VOID_PTR) __ghsbegin_free_mem; */ @@ -98,15 +93,9 @@ _tx_initialize_low_level: STR r1, [r0] ; Enable the cycle count register - /* Setup Vector Table Offset Register. */ - - MOV r0, 0xE000E000 ; Build address of NVIC registers - LDR r1, =__vectors ; Pickup address of vector table - STR r1, [r0, 0xD08] ; Set vector table address - - /* Configure SysTick for 100Hz clock, or 16384 cycles if no reference. */ + MOV r0, 0xE000E000 ; Build address of NVIC registers MOV r1, 0 ; Build value for SysTick reset STR r1, [r0, 0x10] ; Reset SysTick Control STR r1, [r0, 0x18] ; Reset SysTick Counter Value diff --git a/ports/cortex_m7/gnu/example_build/tx_initialize_low_level.S b/ports/cortex_m7/gnu/example_build/tx_initialize_low_level.S index 2b6d9af63..478d8f156 100644 --- a/ports/cortex_m7/gnu/example_build/tx_initialize_low_level.S +++ b/ports/cortex_m7/gnu/example_build/tx_initialize_low_level.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -19,12 +20,10 @@ /**************************************************************************/ /**************************************************************************/ - .global _tx_thread_system_stack_ptr .global _tx_initialize_unused_memory .global __RAM_segment_used_end__ .global _tx_timer_interrupt .global __main - .global _vectors .global __tx_NMIHandler // NMI .global __tx_BadHandler // HardFault .global __tx_SVCallHandler // SVCall @@ -89,17 +88,6 @@ _tx_initialize_low_level: ADD r1, r1, #4 // STR r1, [r0] // Setup first unused memory pointer - /* Setup Vector Table Offset Register. */ - MOV r0, #0xE000E000 // Build address of NVIC registers - LDR r1, =_vectors // Pickup address of vector table - STR r1, [r0, #0xD08] // Set vector table address - - /* Set system stack pointer from vector value. */ - LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer - LDR r1, =_vectors // Pickup address of vector table - LDR r1, [r1] // Pickup reset stack pointer - STR r1, [r0] // Save system stack pointer - /* Enable the cycle count register. */ LDR r0, =0xE0001000 // Build address of DWT register LDR r1, [r0] // Pickup the current value diff --git a/ports/cortex_m7/iar/example_build/tx_initialize_low_level.s b/ports/cortex_m7/iar/example_build/tx_initialize_low_level.s index 6e886e7ff..e9f14b2b9 100644 --- a/ports/cortex_m7/iar/example_build/tx_initialize_low_level.s +++ b/ports/cortex_m7/iar/example_build/tx_initialize_low_level.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026-present Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -7,6 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ +; Some portions generated by Copilot (Opus 5). ; ; ;/**************************************************************************/ @@ -20,10 +22,8 @@ ;/**************************************************************************/ ; ; - EXTERN _tx_thread_system_stack_ptr EXTERN _tx_initialize_unused_memory EXTERN _tx_timer_interrupt - EXTERN __vector_table EXTERN _tx_execution_isr_enter EXTERN _tx_execution_isr_exit ; @@ -97,19 +97,6 @@ _tx_initialize_low_level: ORR r1, r1, #1 ; Set the CYCCNTENA bit STR r1, [r0] ; Enable the cycle count register ; -; /* Setup Vector Table Offset Register. */ -; - MOV r0, #0xE000E000 ; Build address of NVIC registers - LDR r1, =__vector_table ; Pickup address of vector table - STR r1, [r0, #0xD08] ; Set vector table address -; -; /* Set system stack pointer from vector value. */ -; - LDR r0, =_tx_thread_system_stack_ptr ; Build address of system stack pointer - LDR r1, =__vector_table ; Pickup address of vector table - LDR r1, [r1] ; Pickup reset stack pointer - STR r1, [r0] ; Save system stack pointer -; ; /* Configure SysTick. */ ; MOV r0, #0xE000E000 ; Build address of NVIC registers diff --git a/ports/cortex_m85/ac6/src/tx_initialize_low_level.S b/ports/cortex_m85/ac6/src/tx_initialize_low_level.S index 776f8760e..453eae27d 100644 --- a/ports/cortex_m85/ac6/src/tx_initialize_low_level.S +++ b/ports/cortex_m85/ac6/src/tx_initialize_low_level.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -87,23 +88,12 @@ _tx_initialize_low_level: ADD r1, r1, #4 // STR r1, [r0] // Setup first unused memory pointer - /* Setup Vector Table Offset Register. */ - MOV r0, #0xE000E000 // Build address of NVIC registers - LDR r1, =__Vectors // Pickup address of vector table - STR r1, [r0, #0xD08] // Set vector table address - /* Enable the cycle count register. */ LDR r0, =0xE0001000 // Build address of DWT register LDR r1, [r0] // Pickup the current value ORR r1, r1, #1 // Set the CYCCNTENA bit STR r1, [r0] // Enable the cycle count register - /* Set system stack pointer from vector value. */ - LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer - LDR r1, =__Vectors // Pickup address of vector table - LDR r1, [r1] // Pickup reset stack pointer - STR r1, [r0] // Save system stack pointer - /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers MOV r1, #0 // Build value for SysTick reset diff --git a/ports/cortex_m85/gnu/example_build/tx_initialize_low_level.S b/ports/cortex_m85/gnu/example_build/tx_initialize_low_level.S index 317d1d391..3190cd117 100644 --- a/ports/cortex_m85/gnu/example_build/tx_initialize_low_level.S +++ b/ports/cortex_m85/gnu/example_build/tx_initialize_low_level.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -87,23 +88,12 @@ _tx_initialize_low_level: ADD r1, r1, #4 // STR r1, [r0] // Setup first unused memory pointer - /* Setup Vector Table Offset Register. */ - MOV r0, #0xE000E000 // Build address of NVIC registers - LDR r1, =_vectors // Pickup address of vector table - STR r1, [r0, #0xD08] // Set vector table address - /* Enable the cycle count register. */ LDR r0, =0xE0001000 // Build address of DWT register LDR r1, [r0] // Pickup the current value ORR r1, r1, #1 // Set the CYCCNTENA bit STR r1, [r0] // Enable the cycle count register - /* Set system stack pointer from vector value. */ - LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer - LDR r1, =_vectors // Pickup address of vector table - LDR r1, [r1] // Pickup reset stack pointer - STR r1, [r0] // Save system stack pointer - /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers MOV r1, #0 // Build value for SysTick reset diff --git a/ports/cortex_m85/iar/src/tx_initialize_low_level.s b/ports/cortex_m85/iar/src/tx_initialize_low_level.s index 4935842a2..c75e6546e 100644 --- a/ports/cortex_m85/iar/src/tx_initialize_low_level.s +++ b/ports/cortex_m85/iar/src/tx_initialize_low_level.s @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -24,11 +25,9 @@ #include "tx_user.h" #endif - EXTERN _tx_thread_system_stack_ptr EXTERN _tx_initialize_unused_memory EXTERN _tx_timer_interrupt EXTERN __main - EXTERN __vector_table EXTERN _tx_thread_current_ptr EXTERN _tx_thread_stack_error_handler @@ -89,23 +88,12 @@ _tx_initialize_low_level: LDR r1, =__tx_free_memory_start // Build first free address STR r1, [r0] // Setup first unused memory pointer - /* Setup Vector Table Offset Register. */ - MOV r0, #0xE000E000 // Build address of NVIC registers - LDR r1, =__vector_table // Pickup address of vector table - STR r1, [r0, #0xD08] // Set vector table address - /* Enable the cycle count register. */ // LDR r0, =0xE0001000 // Build address of DWT register // LDR r1, [r0] // Pickup the current value // ORR r1, r1, #1 // Set the CYCCNTENA bit // STR r1, [r0] // Enable the cycle count register - /* Set system stack pointer from vector value. */ - LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer - LDR r1, =__vector_table // Pickup address of vector table - LDR r1, [r1] // Pickup reset stack pointer - STR r1, [r0] // Save system stack pointer - /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers MOV r1, #0 // Build value for SysTick reset diff --git a/ports_arch/ARMv7-M/threadx/ac5/example_build/tx_initialize_low_level.s b/ports_arch/ARMv7-M/threadx/ac5/example_build/tx_initialize_low_level.s index af05fba7b..4b7611af8 100644 --- a/ports_arch/ARMv7-M/threadx/ac5/example_build/tx_initialize_low_level.s +++ b/ports_arch/ARMv7-M/threadx/ac5/example_build/tx_initialize_low_level.s @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -20,7 +21,6 @@ /**************************************************************************/ /**************************************************************************/ - IMPORT _tx_thread_system_stack_ptr IMPORT _tx_initialize_unused_memory IMPORT _tx_thread_context_save IMPORT _tx_thread_context_restore @@ -151,17 +151,6 @@ _tx_initialize_low_level ADD r1, r1, #4 // Add 4 to get to next free word STR r1, [r0] // Setup first unused memory pointer - /* Setup Vector Table Offset Register. */ - MOV r0, #0xE000E000 // Build address of NVIC registers - LDR r1, =__tx_vectors // Pickup address of vector table - STR r1, [r0, #0xD08] // Set vector table address - - /* Set system stack pointer from vector value. */ - LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer - LDR r1, =__tx_vectors // Pickup address of vector table - LDR r1, [r1] // Pickup reset stack pointer - STR r1, [r0] // Save system stack pointer - #ifndef TX_NO_TIMER /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers diff --git a/ports_arch/ARMv7-M/threadx/ac6/example_build/sample_threadx/tx_initialize_low_level.S b/ports_arch/ARMv7-M/threadx/ac6/example_build/sample_threadx/tx_initialize_low_level.S index 617d62de4..9b89b732e 100644 --- a/ports_arch/ARMv7-M/threadx/ac6/example_build/sample_threadx/tx_initialize_low_level.S +++ b/ports_arch/ARMv7-M/threadx/ac6/example_build/sample_threadx/tx_initialize_low_level.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -20,7 +21,6 @@ /**************************************************************************/ /**************************************************************************/ - .global _tx_thread_system_stack_ptr .global _tx_initialize_unused_memory #ifndef TX_NO_TIMER .global _tx_timer_interrupt @@ -93,17 +93,6 @@ _tx_initialize_low_level: ADD r1, r1, #4 // STR r1, [r0] // Setup first unused memory pointer - /* Setup Vector Table Offset Register. */ - MOV r0, #0xE000E000 // Build address of NVIC registers - LDR r1, =vector_table // Pickup address of vector table - STR r1, [r0, #0xD08] // Set vector table address - - /* Set system stack pointer from vector value. */ - LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer - LDR r1, =vector_table // Pickup address of vector table - LDR r1, [r1] // Pickup reset stack pointer - STR r1, [r0] // Save system stack pointer - #ifndef TX_NO_TIMER /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers diff --git a/ports_arch/ARMv7-M/threadx/ghs/example_build/tx_initialize_low_level.arm b/ports_arch/ARMv7-M/threadx/ghs/example_build/tx_initialize_low_level.arm index fc6e19fe8..b98fa9745 100644 --- a/ports_arch/ARMv7-M/threadx/ghs/example_build/tx_initialize_low_level.arm +++ b/ports_arch/ARMv7-M/threadx/ghs/example_build/tx_initialize_low_level.arm @@ -1,5 +1,6 @@ /*************************************************************************** * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present Eclipse ThreadX contributors * * This program and the accompanying materials are made available under the * terms of the MIT License which is available at @@ -7,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +; Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -75,13 +77,6 @@ _tx_initialize_low_level: CPSID i ; Disable interrupts - /* Save the system stack pointer. */ - /* _tx_thread_system_stack_ptr = (VOID_PTR) (sp); */ - - LDR r1,=_tx_thread_system_stack_ptr ; Pickup address of system stack ptr - STR sp, [r1] ; Save system stack - - /* Save the first available memory address. */ /* _tx_initialize_unused_memory = (VOID_PTR) __ghsbegin_free_mem; */ @@ -98,15 +93,9 @@ _tx_initialize_low_level: STR r1, [r0] ; Enable the cycle count register - /* Setup Vector Table Offset Register. */ - - MOV r0, 0xE000E000 ; Build address of NVIC registers - LDR r1, =__vectors ; Pickup address of vector table - STR r1, [r0, 0xD08] ; Set vector table address - - /* Configure SysTick for 100Hz clock, or 16384 cycles if no reference. */ + MOV r0, 0xE000E000 ; Build address of NVIC registers MOV r1, 0 ; Build value for SysTick reset STR r1, [r0, 0x10] ; Reset SysTick Control STR r1, [r0, 0x18] ; Reset SysTick Counter Value diff --git a/ports_arch/ARMv7-M/threadx/gnu/example_build/tx_initialize_low_level.S b/ports_arch/ARMv7-M/threadx/gnu/example_build/tx_initialize_low_level.S index 41cde1638..220b8b6de 100644 --- a/ports_arch/ARMv7-M/threadx/gnu/example_build/tx_initialize_low_level.S +++ b/ports_arch/ARMv7-M/threadx/gnu/example_build/tx_initialize_low_level.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -20,12 +21,10 @@ /**************************************************************************/ /**************************************************************************/ - .global _tx_thread_system_stack_ptr .global _tx_initialize_unused_memory .global __RAM_segment_used_end__ .global _tx_timer_interrupt .global __main - .global _vectors .global __tx_NMIHandler // NMI .global __tx_BadHandler // HardFault .global __tx_SVCallHandler // SVCall @@ -90,17 +89,6 @@ _tx_initialize_low_level: ADD r1, r1, #4 // STR r1, [r0] // Setup first unused memory pointer - /* Setup Vector Table Offset Register. */ - MOV r0, #0xE000E000 // Build address of NVIC registers - LDR r1, =_vectors // Pickup address of vector table - STR r1, [r0, #0xD08] // Set vector table address - - /* Set system stack pointer from vector value. */ - LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer - LDR r1, =_vectors // Pickup address of vector table - LDR r1, [r1] // Pickup reset stack pointer - STR r1, [r0] // Save system stack pointer - #ifndef TX_NO_TIMER /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers diff --git a/ports_arch/ARMv7-M/threadx/iar/example_build/tx_initialize_low_level.s b/ports_arch/ARMv7-M/threadx/iar/example_build/tx_initialize_low_level.s index dd4bfce4a..c7734a377 100644 --- a/ports_arch/ARMv7-M/threadx/iar/example_build/tx_initialize_low_level.s +++ b/ports_arch/ARMv7-M/threadx/iar/example_build/tx_initialize_low_level.s @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -20,10 +21,8 @@ /**************************************************************************/ /**************************************************************************/ - EXTERN _tx_thread_system_stack_ptr EXTERN _tx_initialize_unused_memory EXTERN _tx_timer_interrupt - EXTERN __vector_table EXTERN _tx_execution_isr_enter EXTERN _tx_execution_isr_exit @@ -84,17 +83,6 @@ _tx_initialize_low_level: LDR r2, =_tx_initialize_unused_memory // Build address of unused memory pointer STR r0, [r2, #0] // Save first free memory address - /* Setup Vector Table Offset Register. */ - MOV r0, #0xE000E000 // Build address of NVIC registers - LDR r1, =__vector_table // Pickup address of vector table - STR r1, [r0, #0xD08] // Set vector table address - - /* Set system stack pointer from vector value. */ - LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer - LDR r1, =__vector_table // Pickup address of vector table - LDR r1, [r1] // Pickup reset stack pointer - STR r1, [r0] // Save system stack pointer - #ifndef TX_NO_TIMER /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers diff --git a/ports_arch/ARMv8-M/threadx/ac6/src/tx_initialize_low_level.S b/ports_arch/ARMv8-M/threadx/ac6/src/tx_initialize_low_level.S index e57c6b39e..417bd9330 100644 --- a/ports_arch/ARMv8-M/threadx/ac6/src/tx_initialize_low_level.S +++ b/ports_arch/ARMv8-M/threadx/ac6/src/tx_initialize_low_level.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -87,23 +88,12 @@ _tx_initialize_low_level: ADD r1, r1, #4 // STR r1, [r0] // Setup first unused memory pointer - /* Setup Vector Table Offset Register. */ - MOV r0, #0xE000E000 // Build address of NVIC registers - LDR r1, =__Vectors // Pickup address of vector table - STR r1, [r0, #0xD08] // Set vector table address - /* Enable the cycle count register. */ LDR r0, =0xE0001000 // Build address of DWT register LDR r1, [r0] // Pickup the current value ORR r1, r1, #1 // Set the CYCCNTENA bit STR r1, [r0] // Enable the cycle count register - /* Set system stack pointer from vector value. */ - LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer - LDR r1, =__Vectors // Pickup address of vector table - LDR r1, [r1] // Pickup reset stack pointer - STR r1, [r0] // Save system stack pointer - /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers MOV r1, #0 // Build value for SysTick reset diff --git a/ports_arch/ARMv8-M/threadx/iar/src/tx_initialize_low_level.s b/ports_arch/ARMv8-M/threadx/iar/src/tx_initialize_low_level.s index a79f1963a..e074ce8ea 100644 --- a/ports_arch/ARMv8-M/threadx/iar/src/tx_initialize_low_level.s +++ b/ports_arch/ARMv8-M/threadx/iar/src/tx_initialize_low_level.s @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -24,11 +25,9 @@ #include "tx_user.h" #endif - EXTERN _tx_thread_system_stack_ptr EXTERN _tx_initialize_unused_memory EXTERN _tx_timer_interrupt EXTERN __main - EXTERN __vector_table EXTERN _tx_thread_current_ptr EXTERN _tx_thread_stack_error_handler @@ -89,23 +88,12 @@ _tx_initialize_low_level: LDR r1, =__tx_free_memory_start // Build first free address STR r1, [r0] // Setup first unused memory pointer - /* Setup Vector Table Offset Register. */ - MOV r0, #0xE000E000 // Build address of NVIC registers - LDR r1, =__vector_table // Pickup address of vector table - STR r1, [r0, #0xD08] // Set vector table address - /* Enable the cycle count register. */ // LDR r0, =0xE0001000 // Build address of DWT register // LDR r1, [r0] // Pickup the current value // ORR r1, r1, #1 // Set the CYCCNTENA bit // STR r1, [r0] // Enable the cycle count register - /* Set system stack pointer from vector value. */ - LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer - LDR r1, =__vector_table // Pickup address of vector table - LDR r1, [r1] // Pickup reset stack pointer - STR r1, [r0] // Save system stack pointer - /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers MOV r1, #0 // Build value for SysTick reset diff --git a/ports_module/cortex_m0+/ac6/example_build/sample_threadx/tx_initialize_low_level.S b/ports_module/cortex_m0+/ac6/example_build/sample_threadx/tx_initialize_low_level.S index a5de014ac..db06ba6e1 100644 --- a/ports_module/cortex_m0+/ac6/example_build/sample_threadx/tx_initialize_low_level.S +++ b/ports_module/cortex_m0+/ac6/example_build/sample_threadx/tx_initialize_low_level.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -21,7 +22,6 @@ /**************************************************************************/ - .global _tx_thread_system_stack_ptr .global _tx_initialize_unused_memory .global _tx_timer_interrupt .global __main @@ -93,19 +93,6 @@ _tx_initialize_low_level: ADDS r1, r1, #4 // STR r1, [r0] // Setup first unused memory pointer - /* Setup Vector Table Offset Register. */ - - LDR r0, =0xE000ED08 // Build address of NVIC registers - LDR r1, =vector_table // Pickup address of vector table - STR r1, [r0] // Set vector table address - - /* Set system stack pointer from vector value. */ - - LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer - LDR r1, =vector_table // Pickup address of vector table - LDR r1, [r1] // Pickup reset stack pointer - STR r1, [r0] // Save system stack pointer - /* Enable the cycle count register. */ LDR r0, =0xE0001000 // Build address of DWT register diff --git a/ports_module/cortex_m0+/ac6/example_build/sample_threadx_module_manager/tx_initialize_low_level.S b/ports_module/cortex_m0+/ac6/example_build/sample_threadx_module_manager/tx_initialize_low_level.S index da703cce3..e72056098 100644 --- a/ports_module/cortex_m0+/ac6/example_build/sample_threadx_module_manager/tx_initialize_low_level.S +++ b/ports_module/cortex_m0+/ac6/example_build/sample_threadx_module_manager/tx_initialize_low_level.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -21,7 +22,6 @@ /**************************************************************************/ - .global _tx_thread_system_stack_ptr .global _tx_initialize_unused_memory .global _tx_timer_interrupt .global __main @@ -93,20 +93,6 @@ _tx_initialize_low_level: ADDS r1, r1, #4 // STR r1, [r0] // Setup first unused memory pointer - /* Setup Vector Table Offset Register. */ - - LDR r0, =0xE000E000 // Build address of NVIC registers - LDR r1, =vector_table // Pickup address of vector table - LDR r2, =0xD08 - STR r1, [r0, r2] // Set vector table address - - /* Set system stack pointer from vector value. */ - - LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer - LDR r1, =vector_table // Pickup address of vector table - LDR r1, [r1] // Pickup reset stack pointer - STR r1, [r0] // Save system stack pointer - /* Enable the cycle count register. */ LDR r0, =0xE0001000 // Build address of DWT register diff --git a/ports_module/cortex_m0+/gnu/example_build/sample_threadx/tx_initialize_low_level.S b/ports_module/cortex_m0+/gnu/example_build/sample_threadx/tx_initialize_low_level.S index 436ee0496..d229d6830 100644 --- a/ports_module/cortex_m0+/gnu/example_build/sample_threadx/tx_initialize_low_level.S +++ b/ports_module/cortex_m0+/gnu/example_build/sample_threadx/tx_initialize_low_level.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -21,12 +22,10 @@ /**************************************************************************/ - .global _tx_thread_system_stack_ptr .global _tx_initialize_unused_memory .global __RAM_segment_used_end__ .global _tx_timer_interrupt .global __main - .global _vectors .global __tx_NMIHandler // NMI .global __tx_BadHandler // HardFault .global __tx_SVCallHandler // SVCall @@ -95,19 +94,6 @@ _tx_initialize_low_level: ADDS r1, r1, #4 // STR r1, [r0] // Setup first unused memory pointer - /* Setup Vector Table Offset Register. */ - - LDR r0, =0xE000ED08 // Build address of NVIC registers - LDR r1, =_vectors // Pickup address of vector table - STR r1, [r0] // Set vector table address - - /* Set system stack pointer from vector value. */ - - LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer - LDR r1, =_vectors // Pickup address of vector table - LDR r1, [r1] // Pickup reset stack pointer - STR r1, [r0] // Save system stack pointer - /* Enable the cycle count register. */ LDR r0, =0xE0001000 // Build address of DWT register diff --git a/ports_module/cortex_m0+/gnu/example_build/sample_threadx_module_manager/tx_initialize_low_level.S b/ports_module/cortex_m0+/gnu/example_build/sample_threadx_module_manager/tx_initialize_low_level.S index 667452cfd..46ea9c3a5 100644 --- a/ports_module/cortex_m0+/gnu/example_build/sample_threadx_module_manager/tx_initialize_low_level.S +++ b/ports_module/cortex_m0+/gnu/example_build/sample_threadx_module_manager/tx_initialize_low_level.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -21,12 +22,10 @@ /**************************************************************************/ - .global _tx_thread_system_stack_ptr .global _tx_initialize_unused_memory .global __RAM_segment_used_end__ .global _tx_timer_interrupt .global __main - .global _vectors .global __tx_NMIHandler // NMI .global __tx_BadHandler // HardFault .global __tx_SVCallHandler // SVCall @@ -95,19 +94,6 @@ _tx_initialize_low_level: ADDS r1, r1, #4 // STR r1, [r0] // Setup first unused memory pointer - /* Setup Vector Table Offset Register. */ - - LDR r0, =0xE000ED08 // Build address of NVIC registers - LDR r1, =_vectors // Pickup address of vector table - STR r1, [r0] // Set vector table address - - /* Set system stack pointer from vector value. */ - - LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer - LDR r1, =_vectors // Pickup address of vector table - LDR r1, [r1] // Pickup reset stack pointer - STR r1, [r0] // Save system stack pointer - /* Enable the cycle count register. */ LDR r0, =0xE0001000 // Build address of DWT register diff --git a/ports_module/cortex_m0+/iar/example_build/tx_initialize_low_level.s b/ports_module/cortex_m0+/iar/example_build/tx_initialize_low_level.s index 44be0ae66..35c3393ff 100644 --- a/ports_module/cortex_m0+/iar/example_build/tx_initialize_low_level.s +++ b/ports_module/cortex_m0+/iar/example_build/tx_initialize_low_level.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026-present Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -7,6 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ +; Some portions generated by Copilot (Opus 5). ; ; ;/**************************************************************************/ @@ -30,10 +32,8 @@ ;#include "tx_timer.h" ; ; - EXTERN _tx_thread_system_stack_ptr EXTERN _tx_initialize_unused_memory EXTERN _tx_timer_interrupt - EXTERN __vector_table EXTERN _tx_execution_isr_enter EXTERN _tx_execution_isr_exit ; @@ -99,19 +99,6 @@ _tx_initialize_low_level: ADDS r1, r1, #4 // STR r1, [r0] // Setup first unused memory pointer - /* Setup Vector Table Offset Register. */ - - LDR r0, =0xE000ED08 // Build address of NVIC registers - LDR r1, =__vector_table // Pickup address of vector table - STR r1, [r0] // Set vector table address - - /* Set system stack pointer from vector value. */ - - LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer - LDR r1, =__vector_table // Pickup address of vector table - LDR r1, [r1] // Pickup reset stack pointer - STR r1, [r0] // Save system stack pointer - /* Enable the cycle count register. */ LDR r0, =0xE0001000 // Build address of DWT register diff --git a/ports_module/cortex_m23/ac6/example_build/tx_initialize_low_level.S b/ports_module/cortex_m23/ac6/example_build/tx_initialize_low_level.S index 2bc0c4602..4c6ae772d 100644 --- a/ports_module/cortex_m23/ac6/example_build/tx_initialize_low_level.S +++ b/ports_module/cortex_m23/ac6/example_build/tx_initialize_low_level.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -84,23 +85,12 @@ _tx_initialize_low_level: ADDS r1, r1, #4 // STR r1, [r0] // Setup first unused memory pointer - /* Setup Vector Table Offset Register. */ - LDR r0, =0xE000ED08 // Build address of NVIC registers - LDR r1, =__Vectors // Pickup address of vector table - STR r1, [r0] // Set vector table address - /* Enable the cycle count register. */ // LDR r0, =0xE0001000 // Build address of DWT register // LDR r1, [r0] // Pickup the current value // ORR r1, r1, #1 // Set the CYCCNTENA bit // STR r1, [r0] // Enable the cycle count register - /* Set system stack pointer from vector value. */ - LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer - LDR r1, =__Vectors // Pickup address of vector table - LDR r1, [r1] // Pickup reset stack pointer - STR r1, [r0] // Save system stack pointer - /* Configure SysTick. */ LDR r0, =0xE000E000 // Build address of NVIC registers MOV r1, #0 // Build value for SysTick reset diff --git a/ports_module/cortex_m23/gnu/module_manager/src/tx_initialize_low_level.S b/ports_module/cortex_m23/gnu/module_manager/src/tx_initialize_low_level.S index 5e356aeb9..56dffa862 100644 --- a/ports_module/cortex_m23/gnu/module_manager/src/tx_initialize_low_level.S +++ b/ports_module/cortex_m23/gnu/module_manager/src/tx_initialize_low_level.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). // Some portions generated by Claude Code (Opus 5). @@ -87,11 +88,6 @@ _tx_initialize_low_level: ADDS r1, r1, #4 // STR r1, [r0] // Setup first unused memory pointer - /* Setup Vector Table Offset Register. */ - LDR r0, =0xE000ED08 // Build address of NVIC registers - LDR r1, =__Vectors // Pickup address of vector table - STR r1, [r0] // Set vector table address - // /* Enable the cycle count register. */ // // LDR r0, =0xE0001000 // Build address of DWT register @@ -99,12 +95,6 @@ _tx_initialize_low_level: // ORR r1, r1, #1 // Set the CYCCNTENA bit // STR r1, [r0] // Enable the cycle count register - /* Set system stack pointer from vector value. */ - LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer - LDR r1, =__Vectors // Pickup address of vector table - LDR r1, [r1] // Pickup reset stack pointer - STR r1, [r0] // Save system stack pointer - /* Configure SysTick. */ LDR r0, =0xE000E000 // Build address of NVIC registers MOVS r1, #0 // Build value for SysTick reset diff --git a/ports_module/cortex_m23/iar/example_build/tx_initialize_low_level.s b/ports_module/cortex_m23/iar/example_build/tx_initialize_low_level.s index 90849145d..14b78e58a 100644 --- a/ports_module/cortex_m23/iar/example_build/tx_initialize_low_level.s +++ b/ports_module/cortex_m23/iar/example_build/tx_initialize_low_level.s @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -20,11 +21,9 @@ /**************************************************************************/ /**************************************************************************/ - EXTERN _tx_thread_system_stack_ptr EXTERN _tx_initialize_unused_memory EXTERN _tx_timer_interrupt EXTERN __main - EXTERN __vector_table EXTERN _tx_thread_current_ptr EXTERN _tx_thread_stack_error_handler @@ -85,23 +84,12 @@ _tx_initialize_low_level: LDR r1, =__tx_free_memory_start // Build first free address STR r1, [r0] // Setup first unused memory pointer - /* Setup Vector Table Offset Register. */ - LDR r0, =0xE000ED08 // Build address of NVIC registers - LDR r1, =__vector_table // Pickup address of vector table - STR r1, [r0] // Set vector table address - /* Enable the cycle count register. */ // LDR r0, =0xE0001000 // Build address of DWT register // LDR r1, [r0] // Pickup the current value // ORR r1, r1, #1 // Set the CYCCNTENA bit // STR r1, [r0] // Enable the cycle count register - /* Set system stack pointer from vector value. */ - LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer - LDR r1, =__vector_table // Pickup address of vector table - LDR r1, [r1] // Pickup reset stack pointer - STR r1, [r0] // Save system stack pointer - /* Configure SysTick. */ LDR r0, =0xE000E000 // Build address of NVIC registers MOV r1, #0 // Build value for SysTick reset diff --git a/ports_module/cortex_m3/ac5/example_build/tx_initialize_low_level.S b/ports_module/cortex_m3/ac5/example_build/tx_initialize_low_level.S index 0d415dc59..2b1a96a71 100644 --- a/ports_module/cortex_m3/ac5/example_build/tx_initialize_low_level.S +++ b/ports_module/cortex_m3/ac5/example_build/tx_initialize_low_level.S @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026-present Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -7,6 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ +; Some portions generated by Copilot (Opus 5). ; ; ;/**************************************************************************/ @@ -30,7 +32,6 @@ ;#include "tx_timer.h" ; ; - IMPORT _tx_thread_system_stack_ptr IMPORT _tx_initialize_unused_memory IMPORT _tx_thread_context_save IMPORT _tx_thread_context_restore @@ -162,12 +163,6 @@ _tx_initialize_low_level ADD r1, r1, #4 ; STR r1, [r0] ; Setup first unused memory pointer ; -; /* Setup Vector Table Offset Register. */ -; - MOV r0, #0xE000E000 ; Build address of NVIC registers - LDR r1, =__tx_vectors ; Pickup address of vector table - STR r1, [r0, #0xD08] ; Set vector table address -; ; /* Enable the cycle count register. */ ; ; LDR r0, =0xE0001000 ; Build address of DWT register @@ -175,13 +170,6 @@ _tx_initialize_low_level ; ORR r1, r1, #1 ; Set the CYCCNTENA bit ; STR r1, [r0] ; Enable the cycle count register ; -; /* Set system stack pointer from vector value. */ -; - LDR r0, =_tx_thread_system_stack_ptr ; Build address of system stack pointer - LDR r1, =__tx_vectors ; Pickup address of vector table - LDR r1, [r1] ; Pickup reset stack pointer - STR r1, [r0] ; Save system stack pointer -; ; /* Configure SysTick. */ ; MOV r0, #0xE000E000 ; Build address of NVIC registers diff --git a/ports_module/cortex_m3/ac6/example_build/sample_threadx/tx_initialize_low_level.S b/ports_module/cortex_m3/ac6/example_build/sample_threadx/tx_initialize_low_level.S index 5cf5b418d..6f9f6cc70 100644 --- a/ports_module/cortex_m3/ac6/example_build/sample_threadx/tx_initialize_low_level.S +++ b/ports_module/cortex_m3/ac6/example_build/sample_threadx/tx_initialize_low_level.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -21,7 +22,6 @@ /**************************************************************************/ - .global _tx_thread_system_stack_ptr .global _tx_initialize_unused_memory .global _tx_timer_interrupt .global __main @@ -93,19 +93,6 @@ _tx_initialize_low_level: ADD r1, r1, #4 // STR r1, [r0] // Setup first unused memory pointer - /* Setup Vector Table Offset Register. */ - - MOV r0, #0xE000E000 // Build address of NVIC registers - LDR r1, =vector_table // Pickup address of vector table - STR r1, [r0, #0xD08] // Set vector table address - - /* Set system stack pointer from vector value. */ - - LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer - LDR r1, =vector_table // Pickup address of vector table - LDR r1, [r1] // Pickup reset stack pointer - STR r1, [r0] // Save system stack pointer - /* Enable the cycle count register. */ LDR r0, =0xE0001000 // Build address of DWT register diff --git a/ports_module/cortex_m3/ac6/example_build/sample_threadx_module_manager/tx_initialize_low_level.S b/ports_module/cortex_m3/ac6/example_build/sample_threadx_module_manager/tx_initialize_low_level.S index 376b15c02..2a748d08d 100644 --- a/ports_module/cortex_m3/ac6/example_build/sample_threadx_module_manager/tx_initialize_low_level.S +++ b/ports_module/cortex_m3/ac6/example_build/sample_threadx_module_manager/tx_initialize_low_level.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -21,7 +22,6 @@ /**************************************************************************/ - .global _tx_thread_system_stack_ptr .global _tx_initialize_unused_memory .global _tx_timer_interrupt .global __main @@ -93,19 +93,6 @@ _tx_initialize_low_level: ADD r1, r1, #4 // STR r1, [r0] // Setup first unused memory pointer - /* Setup Vector Table Offset Register. */ - - MOV r0, #0xE000E000 // Build address of NVIC registers - LDR r1, =vector_table // Pickup address of vector table - STR r1, [r0, #0xD08] // Set vector table address - - /* Set system stack pointer from vector value. */ - - LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer - LDR r1, =vector_table // Pickup address of vector table - LDR r1, [r1] // Pickup reset stack pointer - STR r1, [r0] // Save system stack pointer - /* Enable the cycle count register. */ LDR r0, =0xE0001000 // Build address of DWT register diff --git a/ports_module/cortex_m3/gnu/example_build/tx_initialize_low_level.S b/ports_module/cortex_m3/gnu/example_build/tx_initialize_low_level.S index 278dd9b39..63737c9cc 100644 --- a/ports_module/cortex_m3/gnu/example_build/tx_initialize_low_level.S +++ b/ports_module/cortex_m3/gnu/example_build/tx_initialize_low_level.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -21,12 +22,10 @@ /**************************************************************************/ - .global _tx_thread_system_stack_ptr .global _tx_initialize_unused_memory .global __RAM_segment_used_end__ .global _tx_timer_interrupt .global __main - .global _vectors .global __tx_NMIHandler @ NMI .global __tx_BadHandler @ HardFault .global __tx_DBGHandler @ Monitor @@ -90,17 +89,6 @@ _tx_initialize_low_level: ADD r1, r1, #4 @ STR r1, [r0] @ Setup first unused memory pointer - /* Setup Vector Table Offset Register. */ - MOV r0, #0xE000E000 @ Build address of NVIC registers - LDR r1, =_vectors @ Pickup address of vector table - STR r1, [r0, #0xD08] @ Set vector table address - - /* Set system stack pointer from vector value. */ - LDR r0, =_tx_thread_system_stack_ptr @ Build address of system stack pointer - LDR r1, =_vectors @ Pickup address of vector table - LDR r1, [r1] @ Pickup reset stack pointer - STR r1, [r0] @ Save system stack pointer - /* Enable the cycle count register. */ LDR r0, =0xE0001000 @ Build address of DWT register LDR r1, [r0] @ Pickup the current value diff --git a/ports_module/cortex_m3/iar/example_build/tx_initialize_low_level.s b/ports_module/cortex_m3/iar/example_build/tx_initialize_low_level.s index d31fbb338..29ca88bbb 100644 --- a/ports_module/cortex_m3/iar/example_build/tx_initialize_low_level.s +++ b/ports_module/cortex_m3/iar/example_build/tx_initialize_low_level.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026-present Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -7,6 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ +; Some portions generated by Copilot (Opus 5). ; ; ;/**************************************************************************/ @@ -30,10 +32,8 @@ ;#include "tx_timer.h" ; ; - EXTERN _tx_thread_system_stack_ptr EXTERN _tx_initialize_unused_memory EXTERN _tx_timer_interrupt - EXTERN __vector_table EXTERN _tx_execution_isr_enter EXTERN _tx_execution_isr_exit ; @@ -107,19 +107,6 @@ _tx_initialize_low_level: ORR r1, r1, #1 ; Set the CYCCNTENA bit STR r1, [r0] ; Enable the cycle count register ; -; /* Setup Vector Table Offset Register. */ -; - MOV r0, #0xE000E000 ; Build address of NVIC registers - LDR r1, =__vector_table ; Pickup address of vector table - STR r1, [r0, #0xD08] ; Set vector table address -; -; /* Set system stack pointer from vector value. */ -; - LDR r0, =_tx_thread_system_stack_ptr ; Build address of system stack pointer - LDR r1, =__vector_table ; Pickup address of vector table - LDR r1, [r1] ; Pickup reset stack pointer - STR r1, [r0] ; Save system stack pointer -; ; /* Configure SysTick. */ ; MOV r0, #0xE000E000 ; Build address of NVIC registers diff --git a/ports_module/cortex_m33/ac6/example_build/tx_initialize_low_level.S b/ports_module/cortex_m33/ac6/example_build/tx_initialize_low_level.S index 4043e1103..f4a34575a 100644 --- a/ports_module/cortex_m33/ac6/example_build/tx_initialize_low_level.S +++ b/ports_module/cortex_m33/ac6/example_build/tx_initialize_low_level.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -84,23 +85,12 @@ _tx_initialize_low_level: ADD r1, r1, #4 // STR r1, [r0] // Setup first unused memory pointer - /* Setup Vector Table Offset Register. */ - MOV r0, #0xE000E000 // Build address of NVIC registers - LDR r1, =__Vectors // Pickup address of vector table - STR r1, [r0, #0xD08] // Set vector table address - /* Enable the cycle count register. */ LDR r0, =0xE0001000 // Build address of DWT register LDR r1, [r0] // Pickup the current value ORR r1, r1, #1 // Set the CYCCNTENA bit STR r1, [r0] // Enable the cycle count register - /* Set system stack pointer from vector value. */ - LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer - LDR r1, =__Vectors // Pickup address of vector table - LDR r1, [r1] // Pickup reset stack pointer - STR r1, [r0] // Save system stack pointer - /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers MOV r1, #0 // Build value for SysTick reset diff --git a/ports_module/cortex_m33/gnu/module_manager/src/tx_initialize_low_level.S b/ports_module/cortex_m33/gnu/module_manager/src/tx_initialize_low_level.S index dd10aeffd..d735825e5 100644 --- a/ports_module/cortex_m33/gnu/module_manager/src/tx_initialize_low_level.S +++ b/ports_module/cortex_m33/gnu/module_manager/src/tx_initialize_low_level.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -84,23 +85,12 @@ _tx_initialize_low_level: ADD r1, r1, #4 // STR r1, [r0] // Setup first unused memory pointer - /* Setup Vector Table Offset Register. */ - MOV r0, #0xE000E000 // Build address of NVIC registers - LDR r1, =_vectors // Pickup address of vector table - STR r1, [r0, #0xD08] // Set vector table address - /* Enable the cycle count register. */ LDR r0, =0xE0001000 // Build address of DWT register LDR r1, [r0] // Pickup the current value ORR r1, r1, #1 // Set the CYCCNTENA bit STR r1, [r0] // Enable the cycle count register - /* Set system stack pointer from vector value. */ - LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer - LDR r1, =_vectors // Pickup address of vector table - LDR r1, [r1] // Pickup reset stack pointer - STR r1, [r0] // Save system stack pointer - /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers MOV r1, #0 // Build value for SysTick reset diff --git a/ports_module/cortex_m33/iar/example_build/tx_initialize_low_level.s b/ports_module/cortex_m33/iar/example_build/tx_initialize_low_level.s index 048e0a8b1..4f4ae82c4 100644 --- a/ports_module/cortex_m33/iar/example_build/tx_initialize_low_level.s +++ b/ports_module/cortex_m33/iar/example_build/tx_initialize_low_level.s @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -20,11 +21,9 @@ /**************************************************************************/ /**************************************************************************/ - EXTERN _tx_thread_system_stack_ptr EXTERN _tx_initialize_unused_memory EXTERN _tx_timer_interrupt EXTERN __main - EXTERN __vector_table EXTERN _tx_thread_current_ptr EXTERN _tx_thread_stack_error_handler @@ -85,23 +84,12 @@ _tx_initialize_low_level: LDR r1, =__tx_free_memory_start // Build first free address STR r1, [r0] // Setup first unused memory pointer - /* Setup Vector Table Offset Register. */ - MOV r0, #0xE000E000 // Build address of NVIC registers - LDR r1, =__vector_table // Pickup address of vector table - STR r1, [r0, #0xD08] // Set vector table address - /* Enable the cycle count register. */ // LDR r0, =0xE0001000 // Build address of DWT register // LDR r1, [r0] // Pickup the current value // ORR r1, r1, #1 // Set the CYCCNTENA bit // STR r1, [r0] // Enable the cycle count register - /* Set system stack pointer from vector value. */ - LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer - LDR r1, =__vector_table // Pickup address of vector table - LDR r1, [r1] // Pickup reset stack pointer - STR r1, [r0] // Save system stack pointer - /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers MOV r1, #0 // Build value for SysTick reset diff --git a/ports_module/cortex_m4/ac5/example_build/tx_initialize_low_level.S b/ports_module/cortex_m4/ac5/example_build/tx_initialize_low_level.S index 49b4f75c5..f14e718ea 100644 --- a/ports_module/cortex_m4/ac5/example_build/tx_initialize_low_level.S +++ b/ports_module/cortex_m4/ac5/example_build/tx_initialize_low_level.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -20,7 +21,6 @@ /**************************************************************************/ /**************************************************************************/ - IMPORT _tx_thread_system_stack_ptr IMPORT _tx_initialize_unused_memory IMPORT _tx_thread_context_save IMPORT _tx_thread_context_restore @@ -148,12 +148,6 @@ _tx_initialize_low_level ADD r1, r1, #4 // STR r1, [r0] // Setup first unused memory pointer - /* Setup Vector Table Offset Register. */ - - MOV r0, #0xE000E000 // Build address of NVIC registers - LDR r1, =__tx_vectors // Pickup address of vector table - STR r1, [r0, #0xD08] // Set vector table address - /* Enable the cycle count register. */ // LDR r0, =0xE0001000 // Build address of DWT register @@ -161,13 +155,6 @@ _tx_initialize_low_level // ORR r1, r1, #1 // Set the CYCCNTENA bit // STR r1, [r0] // Enable the cycle count register - /* Set system stack pointer from vector value. */ - - LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer - LDR r1, =__tx_vectors // Pickup address of vector table - LDR r1, [r1] // Pickup reset stack pointer - STR r1, [r0] // Save system stack pointer - /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers diff --git a/ports_module/cortex_m4/ac6/example_build/sample_threadx/tx_initialize_low_level.S b/ports_module/cortex_m4/ac6/example_build/sample_threadx/tx_initialize_low_level.S index fdf439916..aa03c18dd 100644 --- a/ports_module/cortex_m4/ac6/example_build/sample_threadx/tx_initialize_low_level.S +++ b/ports_module/cortex_m4/ac6/example_build/sample_threadx/tx_initialize_low_level.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -21,7 +22,6 @@ /**************************************************************************/ - .global _tx_thread_system_stack_ptr .global _tx_initialize_unused_memory .global _tx_timer_interrupt .global __main @@ -93,19 +93,6 @@ _tx_initialize_low_level: ADD r1, r1, #4 // STR r1, [r0] // Setup first unused memory pointer - /* Setup Vector Table Offset Register. */ - - MOV r0, #0xE000E000 // Build address of NVIC registers - LDR r1, =vector_table // Pickup address of vector table - STR r1, [r0, #0xD08] // Set vector table address - - /* Set system stack pointer from vector value. */ - - LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer - LDR r1, =vector_table // Pickup address of vector table - LDR r1, [r1] // Pickup reset stack pointer - STR r1, [r0] // Save system stack pointer - /* Enable the cycle count register. */ LDR r0, =0xE0001000 // Build address of DWT register diff --git a/ports_module/cortex_m4/ac6/example_build/sample_threadx_module_manager/tx_initialize_low_level.S b/ports_module/cortex_m4/ac6/example_build/sample_threadx_module_manager/tx_initialize_low_level.S index 61e40d2ec..36a865d1f 100644 --- a/ports_module/cortex_m4/ac6/example_build/sample_threadx_module_manager/tx_initialize_low_level.S +++ b/ports_module/cortex_m4/ac6/example_build/sample_threadx_module_manager/tx_initialize_low_level.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -21,7 +22,6 @@ /**************************************************************************/ - .global _tx_thread_system_stack_ptr .global _tx_initialize_unused_memory .global _tx_timer_interrupt .global __main @@ -93,12 +93,6 @@ _tx_initialize_low_level: ADD r1, r1, #4 // STR r1, [r0] // Setup first unused memory pointer - /* Setup Vector Table Offset Register. */ - - MOV r0, #0xE000E000 // Build address of NVIC registers - LDR r1, =vector_table // Pickup address of vector table - STR r1, [r0, #0xD08] // Set vector table address - /* Enable the cycle count register. */ // LDR r0, =0xE0001000 // Build address of DWT register @@ -106,13 +100,6 @@ _tx_initialize_low_level: // ORR r1, r1, #1 // Set the CYCCNTENA bit // STR r1, [r0] // Enable the cycle count register - /* Set system stack pointer from vector value. */ - - LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer - LDR r1, =vector_table // Pickup address of vector table - LDR r1, [r1] // Pickup reset stack pointer - STR r1, [r0] // Save system stack pointer - /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers diff --git a/ports_module/cortex_m4/gnu/example_build/tx_initialize_low_level.S b/ports_module/cortex_m4/gnu/example_build/tx_initialize_low_level.S index 85a88c699..6bb27823b 100644 --- a/ports_module/cortex_m4/gnu/example_build/tx_initialize_low_level.S +++ b/ports_module/cortex_m4/gnu/example_build/tx_initialize_low_level.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -21,12 +22,10 @@ /**************************************************************************/ - .global _tx_thread_system_stack_ptr .global _tx_initialize_unused_memory .global __RAM_segment_used_end__ .global _tx_timer_interrupt .global __main - .global _vectors .global __tx_NMIHandler // NMI .global __tx_BadHandler // HardFault .global __tx_DBGHandler // Monitor @@ -92,12 +91,6 @@ _tx_initialize_low_level: ADD r1, r1, #4 // STR r1, [r0] // Setup first unused memory pointer - /* Setup Vector Table Offset Register. */ - - MOV r0, #0xE000E000 // Build address of NVIC registers - LDR r1, =_vectors // Pickup address of vector table - STR r1, [r0, #0xD08] // Set vector table address - /* Enable the cycle count register. */ // LDR r0, =0xE0001000 // Build address of DWT register @@ -105,13 +98,6 @@ _tx_initialize_low_level: // ORR r1, r1, #1 // Set the CYCCNTENA bit // STR r1, [r0] // Enable the cycle count register - /* Set system stack pointer from vector value. */ - - LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer - LDR r1, =_vectors // Pickup address of vector table - LDR r1, [r1] // Pickup reset stack pointer - STR r1, [r0] // Save system stack pointer - /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers diff --git a/ports_module/cortex_m4/iar/example_build/tx_initialize_low_level.s b/ports_module/cortex_m4/iar/example_build/tx_initialize_low_level.s index 55e9fc409..ba580eae5 100644 --- a/ports_module/cortex_m4/iar/example_build/tx_initialize_low_level.s +++ b/ports_module/cortex_m4/iar/example_build/tx_initialize_low_level.s @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -21,10 +22,8 @@ /**************************************************************************/ - EXTERN _tx_thread_system_stack_ptr EXTERN _tx_initialize_unused_memory EXTERN _tx_timer_interrupt - EXTERN __vector_table EXTERN _tx_execution_isr_enter EXTERN _tx_execution_isr_exit @@ -87,12 +86,6 @@ _tx_initialize_low_level: LDR r1, =__tx_free_memory_start // Build first free address STR r1, [r0] // Setup first unused memory pointer - /* Setup Vector Table Offset Register. */ - - MOV r0, #0xE000E000 // Build address of NVIC registers - LDR r1, =__vector_table // Pickup address of vector table - STR r1, [r0, #0xD08] // Set vector table address - /* Enable the cycle count register. */ // LDR r0, =0xE0001000 // Build address of DWT register @@ -100,13 +93,6 @@ _tx_initialize_low_level: // ORR r1, r1, #1 // Set the CYCCNTENA bit // STR r1, [r0] // Enable the cycle count register - /* Set system stack pointer from vector value. */ - - LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer - LDR r1, =__vector_table // Pickup address of vector table - LDR r1, [r1] // Pickup reset stack pointer - STR r1, [r0] // Save system stack pointer - /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers diff --git a/ports_module/cortex_m7/ac5/example_build/tx_initialize_low_level.S b/ports_module/cortex_m7/ac5/example_build/tx_initialize_low_level.S index 7ab4b4509..20957edde 100644 --- a/ports_module/cortex_m7/ac5/example_build/tx_initialize_low_level.S +++ b/ports_module/cortex_m7/ac5/example_build/tx_initialize_low_level.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -20,7 +21,6 @@ /**************************************************************************/ /**************************************************************************/ - IMPORT _tx_thread_system_stack_ptr IMPORT _tx_initialize_unused_memory IMPORT _tx_thread_context_save IMPORT _tx_thread_context_restore @@ -148,12 +148,6 @@ _tx_initialize_low_level ADD r1, r1, #4 // STR r1, [r0] // Setup first unused memory pointer - /* Setup Vector Table Offset Register. */ - - MOV r0, #0xE000E000 // Build address of NVIC registers - LDR r1, =__tx_vectors // Pickup address of vector table - STR r1, [r0, #0xD08] // Set vector table address - /* Enable the cycle count register. */ // LDR r0, =0xE0001000 // Build address of DWT register @@ -161,13 +155,6 @@ _tx_initialize_low_level // ORR r1, r1, #1 // Set the CYCCNTENA bit // STR r1, [r0] // Enable the cycle count register - /* Set system stack pointer from vector value. */ - - LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer - LDR r1, =__tx_vectors // Pickup address of vector table - LDR r1, [r1] // Pickup reset stack pointer - STR r1, [r0] // Save system stack pointer - /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers diff --git a/ports_module/cortex_m7/ac6/example_build/sample_threadx/tx_initialize_low_level.S b/ports_module/cortex_m7/ac6/example_build/sample_threadx/tx_initialize_low_level.S index 813d25770..af0d05cbb 100644 --- a/ports_module/cortex_m7/ac6/example_build/sample_threadx/tx_initialize_low_level.S +++ b/ports_module/cortex_m7/ac6/example_build/sample_threadx/tx_initialize_low_level.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -21,7 +22,6 @@ /**************************************************************************/ - .global _tx_thread_system_stack_ptr .global _tx_initialize_unused_memory .global _tx_timer_interrupt .global __main @@ -93,19 +93,6 @@ _tx_initialize_low_level: ADD r1, r1, #4 // STR r1, [r0] // Setup first unused memory pointer - /* Setup Vector Table Offset Register. */ - - MOV r0, #0xE000E000 // Build address of NVIC registers - LDR r1, =vector_table // Pickup address of vector table - STR r1, [r0, #0xD08] // Set vector table address - - /* Set system stack pointer from vector value. */ - - LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer - LDR r1, =vector_table // Pickup address of vector table - LDR r1, [r1] // Pickup reset stack pointer - STR r1, [r0] // Save system stack pointer - /* Enable the cycle count register. */ LDR r0, =0xE0001000 // Build address of DWT register diff --git a/ports_module/cortex_m7/ac6/example_build/sample_threadx_module_manager/tx_initialize_low_level.S b/ports_module/cortex_m7/ac6/example_build/sample_threadx_module_manager/tx_initialize_low_level.S index c5715b945..98e9b5375 100644 --- a/ports_module/cortex_m7/ac6/example_build/sample_threadx_module_manager/tx_initialize_low_level.S +++ b/ports_module/cortex_m7/ac6/example_build/sample_threadx_module_manager/tx_initialize_low_level.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -21,7 +22,6 @@ /**************************************************************************/ - .global _tx_thread_system_stack_ptr .global _tx_initialize_unused_memory .global _tx_timer_interrupt .global __main @@ -93,12 +93,6 @@ _tx_initialize_low_level: ADD r1, r1, #4 // STR r1, [r0] // Setup first unused memory pointer - /* Setup Vector Table Offset Register. */ - - MOV r0, #0xE000E000 // Build address of NVIC registers - LDR r1, =vector_table // Pickup address of vector table - STR r1, [r0, #0xD08] // Set vector table address - /* Enable the cycle count register. */ // LDR r0, =0xE0001000 // Build address of DWT register @@ -106,13 +100,6 @@ _tx_initialize_low_level: // ORR r1, r1, #1 // Set the CYCCNTENA bit // STR r1, [r0] // Enable the cycle count register - /* Set system stack pointer from vector value. */ - - LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer - LDR r1, =vector_table // Pickup address of vector table - LDR r1, [r1] // Pickup reset stack pointer - STR r1, [r0] // Save system stack pointer - /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers diff --git a/ports_module/cortex_m7/gnu/example_build/tx_initialize_low_level.S b/ports_module/cortex_m7/gnu/example_build/tx_initialize_low_level.S index 01c8814be..1d0d2cea7 100644 --- a/ports_module/cortex_m7/gnu/example_build/tx_initialize_low_level.S +++ b/ports_module/cortex_m7/gnu/example_build/tx_initialize_low_level.S @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -21,12 +22,10 @@ /**************************************************************************/ - .global _tx_thread_system_stack_ptr .global _tx_initialize_unused_memory .global __RAM_segment_used_end__ .global _tx_timer_interrupt .global __main - .global _vectors .global __tx_NMIHandler // NMI .global __tx_BadHandler // HardFault .global __tx_DBGHandler // Monitor @@ -92,12 +91,6 @@ _tx_initialize_low_level: ADD r1, r1, #4 // STR r1, [r0] // Setup first unused memory pointer - /* Setup Vector Table Offset Register. */ - - MOV r0, #0xE000E000 // Build address of NVIC registers - LDR r1, =_vectors // Pickup address of vector table - STR r1, [r0, #0xD08] // Set vector table address - /* Enable the cycle count register. */ // LDR r0, =0xE0001000 // Build address of DWT register @@ -105,13 +98,6 @@ _tx_initialize_low_level: // ORR r1, r1, #1 // Set the CYCCNTENA bit // STR r1, [r0] // Enable the cycle count register - /* Set system stack pointer from vector value. */ - - LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer - LDR r1, =_vectors // Pickup address of vector table - LDR r1, [r1] // Pickup reset stack pointer - STR r1, [r0] // Save system stack pointer - /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers diff --git a/ports_module/cortex_m7/iar/example_build/tx_initialize_low_level.s b/ports_module/cortex_m7/iar/example_build/tx_initialize_low_level.s index 6919b6e10..631f41670 100644 --- a/ports_module/cortex_m7/iar/example_build/tx_initialize_low_level.s +++ b/ports_module/cortex_m7/iar/example_build/tx_initialize_low_level.s @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -21,10 +22,8 @@ /**************************************************************************/ - EXTERN _tx_thread_system_stack_ptr EXTERN _tx_initialize_unused_memory EXTERN _tx_timer_interrupt - EXTERN __vector_table EXTERN _tx_execution_isr_enter EXTERN _tx_execution_isr_exit @@ -87,12 +86,6 @@ _tx_initialize_low_level: LDR r1, =__tx_free_memory_start // Build first free address STR r1, [r0] // Setup first unused memory pointer - /* Setup Vector Table Offset Register. */ - - MOV r0, #0xE000E000 // Build address of NVIC registers - LDR r1, =__vector_table // Pickup address of vector table - STR r1, [r0, #0xD08] // Set vector table address - /* Enable the cycle count register. */ // LDR r0, =0xE0001000 // Build address of DWT register @@ -100,13 +93,6 @@ _tx_initialize_low_level: // ORR r1, r1, #1 // Set the CYCCNTENA bit // STR r1, [r0] // Enable the cycle count register - /* Set system stack pointer from vector value. */ - - LDR r0, =_tx_thread_system_stack_ptr // Build address of system stack pointer - LDR r1, =__vector_table // Pickup address of vector table - LDR r1, [r1] // Pickup reset stack pointer - STR r1, [r0] // Save system stack pointer - /* Configure SysTick. */ MOV r0, #0xE000E000 // Build address of NVIC registers From a8c84593ddd7bc2f80c8abf605deb08729ed00b3 Mon Sep 17 00:00:00 2001 From: tardigrade Date: Thu, 10 Sep 2026 02:00:23 +0530 Subject: [PATCH 121/181] Added ARMv7-A SMP Linux build scripts(A5,A7,A9) (#674) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ports: add Linux build scripts for Cortex-A5 SMP * ports: fix Cortex-A5 SMP sample linking on Linux * ports: add Linux build scripts for Cortex-A7 and A9 SMP * ports: fix Cortex-A7 SMP assembly source path * wip: add ATFE selection to Armv7 SMP scripts * ports: complete Armv7 SMP Linux toolchain support * ports: add local startup for Armv7 SMP samples * ports: add license headers to Armv7 SMP scripts * Dropped the preprocessing flag the file extension now carries Two lines named assembly sources that #672 renamed. That change moved twenty-nine files under gnu trees from .s to .S, because GAS runs the C preprocessor on .S and not on .s: in a .s file every # line is a comment, so a #define is never substituted and an #if/#else pair emits both arms. Four files were silently doing the wrong thing as a result, including ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_unprotect.s, which ignored all four of its own feature macros. These scripts had worked around the same defect with -x assembler-with-cpp rather than hitting it, which was correct when they were written. With the rename the flag is redundant and the lowercase names no longer resolve, so cortex_a5_smp/build_threadx.sh failed with "cc1: fatal error: tx_initialize_low_level.s: No such file or directory". The other seven references to those two files across these three scripts already named them with a capital S. Verified with the pinned Arm GNU 14.3.rel1 rather than the 13.2 that a distro package supplies: build_threadx.sh and build_threadx_sample.sh both succeed for a5, a7 and a9, all three link a sample_threadx.out, and scripts/check_gcc.sh passes end to end with its example stage reading 45 of 45, up from 42. Assisted-by: Claude Opus 5 --------- Co-authored-by: Frédéric Desbiens --- .../gnu/example_build/build_threadx.sh | 295 ++++++++++++++++++ .../gnu/example_build/build_threadx_sample.sh | 56 ++++ .../cortex_a5_smp/gnu/example_build/crt0.S | 101 ++++++ .../gnu/example_build/build_threadx.sh | 295 ++++++++++++++++++ .../gnu/example_build/build_threadx_sample.sh | 54 ++++ .../cortex_a7_smp/gnu/example_build/crt0.S | 101 ++++++ .../gnu/example_build/build_threadx.sh | 295 ++++++++++++++++++ .../gnu/example_build/build_threadx_sample.sh | 54 ++++ .../cortex_a9_smp/gnu/example_build/crt0.S | 101 ++++++ 9 files changed, 1352 insertions(+) create mode 100755 ports_smp/cortex_a5_smp/gnu/example_build/build_threadx.sh create mode 100755 ports_smp/cortex_a5_smp/gnu/example_build/build_threadx_sample.sh create mode 100644 ports_smp/cortex_a5_smp/gnu/example_build/crt0.S create mode 100755 ports_smp/cortex_a7_smp/gnu/example_build/build_threadx.sh create mode 100755 ports_smp/cortex_a7_smp/gnu/example_build/build_threadx_sample.sh create mode 100644 ports_smp/cortex_a7_smp/gnu/example_build/crt0.S create mode 100755 ports_smp/cortex_a9_smp/gnu/example_build/build_threadx.sh create mode 100755 ports_smp/cortex_a9_smp/gnu/example_build/build_threadx_sample.sh create mode 100644 ports_smp/cortex_a9_smp/gnu/example_build/crt0.S diff --git a/ports_smp/cortex_a5_smp/gnu/example_build/build_threadx.sh b/ports_smp/cortex_a5_smp/gnu/example_build/build_threadx.sh new file mode 100755 index 000000000..88c68def6 --- /dev/null +++ b/ports_smp/cortex_a5_smp/gnu/example_build/build_threadx.sh @@ -0,0 +1,295 @@ +#!/bin/sh +############################################################################## +# 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 +############################################################################## + +set -e +cd "$(dirname "$0")" + +# this script builds the ThreadX library for the Cortex-A5 SMP port using +# GNU toolchain or llvm/clang toolchain (defaults to GNU). +: "${TOOLCHAIN:=gnu}" + +case "${TOOLCHAIN}" in + gnu) + CC="arm-none-eabi-gcc" + AR="arm-none-eabi-ar" + TARGET_FLAGS="" + ;; + atfe) + CC="${ATFE_CLANG:-clang}" + case "${CC}" in + */*) AR="$(dirname "${CC}")/llvm-ar" ;; + *) AR="llvm-ar" ;; + esac + TARGET_FLAGS="--target=arm-none-eabi" + ;; + *) + echo "Unknown TOOLCHAIN: ${TOOLCHAIN}" >&2 + exit 1 + ;; +esac + +rm -f tx.a +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 tx_initialize_low_level.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 ../src/tx_thread_context_restore.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 ../src/tx_thread_context_save.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 ../src/tx_thread_interrupt_control.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 ../src/tx_thread_interrupt_disable.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 ../src/tx_thread_interrupt_restore.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 ../src/tx_thread_irq_nesting_end.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 ../src/tx_thread_irq_nesting_start.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 ../src/tx_thread_schedule.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 ../src/tx_thread_smp_core_get.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 ../src/tx_thread_smp_core_preempt.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 ../src/tx_thread_smp_current_state_get.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 ../src/tx_thread_smp_current_thread_get.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 ../src/tx_thread_smp_initialize_wait.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 ../src/tx_thread_smp_low_level_initialize.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 ../src/tx_thread_smp_protect.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 ../src/tx_thread_smp_time_get.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 ../src/tx_thread_smp_unprotect.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 ../src/tx_thread_stack_build.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 ../src/tx_thread_system_return.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 ../src/tx_thread_vectored_context_save.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 ../src/tx_timer_interrupt.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_allocate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_pool_cleanup.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_pool_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_pool_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_pool_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_pool_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_pool_performance_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_pool_performance_system_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_pool_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_release.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_allocate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_cleanup.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_performance_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_performance_system_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_search.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_release.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_cleanup.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_performance_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_performance_system_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_set.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_set_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_initialize_high_level.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_initialize_kernel_enter.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_initialize_kernel_setup.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_cleanup.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_performance_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_performance_system_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_priority_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_put.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_cleanup.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_flush.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_front_send.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_performance_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_performance_system_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_receive.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_send.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_send_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_ceiling_put.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_cleanup.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_performance_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_performance_system_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_put.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_put_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_entry_exit_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_identify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_performance_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_performance_system_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_preemption_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_priority_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_relinquish.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_reset.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_resume.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_shell_entry.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_sleep.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_stack_analyze.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_stack_error_handler.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_stack_error_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_suspend.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_system_preempt_check.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_system_resume.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_system_suspend.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_terminate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_time_slice.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_time_slice_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_timeout.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_wait_abort.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_time_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_time_set.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_activate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_deactivate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_expiration_process.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_performance_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_performance_system_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_system_activate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_system_deactivate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_thread_entry.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_enable.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_disable.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_interrupt_control.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_isr_enter_insert.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_isr_exit_insert.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_object_register.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_object_unregister.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_user_event_insert.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_buffer_full_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_event_filter.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_event_unfilter.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_block_allocate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_block_pool_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_block_pool_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_block_pool_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_block_pool_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_block_release.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_byte_allocate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_byte_pool_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_byte_pool_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_byte_pool_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_byte_pool_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_byte_release.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_event_flags_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_event_flags_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_event_flags_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_event_flags_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_event_flags_set.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_event_flags_set_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_mutex_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_mutex_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_mutex_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_mutex_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_mutex_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_mutex_put.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_flush.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_front_send.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_receive.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_send.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_send_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_semaphore_ceiling_put.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_semaphore_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_semaphore_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_semaphore_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_semaphore_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_semaphore_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_semaphore_put.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_semaphore_put_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_entry_exit_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_preemption_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_priority_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_relinquish.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_reset.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_resume.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_suspend.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_terminate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_time_slice_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_wait_abort.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_timer_activate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_timer_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_timer_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_timer_deactivate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_timer_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_timer_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_smp_current_state_set.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_smp_debug_entry_insert.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_smp_high_level_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_smp_rebalance_execute_list.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_smp_core_exclude.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_smp_core_exclude_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_smp_core_exclude.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_smp_core_exclude_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_smp_utilities.c +"${AR}" -r tx.a tx_thread_stack_build.o tx_thread_schedule.o tx_thread_system_return.o tx_thread_context_save.o tx_thread_context_restore.o tx_timer_interrupt.o tx_thread_interrupt_control.o +"${AR}" -r tx.a tx_initialize_low_level.o tx_thread_interrupt_disable.o +"${AR}" -r tx.a tx_thread_interrupt_restore.o tx_thread_irq_nesting_end.o tx_thread_irq_nesting_start.o +"${AR}" -r tx.a tx_block_allocate.o tx_block_pool_cleanup.o tx_block_pool_create.o tx_block_pool_delete.o tx_block_pool_info_get.o +"${AR}" -r tx.a tx_block_pool_initialize.o tx_block_pool_performance_info_get.o tx_block_pool_performance_system_info_get.o tx_block_pool_prioritize.o +"${AR}" -r tx.a tx_block_release.o tx_byte_allocate.o tx_byte_pool_cleanup.o tx_byte_pool_create.o tx_byte_pool_delete.o tx_byte_pool_info_get.o +"${AR}" -r tx.a tx_byte_pool_initialize.o tx_byte_pool_performance_info_get.o tx_byte_pool_performance_system_info_get.o tx_byte_pool_prioritize.o +"${AR}" -r tx.a tx_byte_pool_search.o tx_byte_release.o tx_event_flags_cleanup.o tx_event_flags_create.o tx_event_flags_delete.o tx_event_flags_get.o +"${AR}" -r tx.a tx_event_flags_info_get.o tx_event_flags_initialize.o tx_event_flags_performance_info_get.o tx_event_flags_performance_system_info_get.o +"${AR}" -r tx.a tx_event_flags_set.o tx_event_flags_set_notify.o tx_initialize_high_level.o tx_initialize_kernel_enter.o tx_initialize_kernel_setup.o +"${AR}" -r tx.a tx_mutex_cleanup.o tx_mutex_create.o tx_mutex_delete.o tx_mutex_get.o tx_mutex_info_get.o tx_mutex_initialize.o tx_mutex_performance_info_get.o +"${AR}" -r tx.a tx_mutex_performance_system_info_get.o tx_mutex_prioritize.o tx_mutex_priority_change.o tx_mutex_put.o tx_queue_cleanup.o tx_queue_create.o +"${AR}" -r tx.a tx_queue_delete.o tx_queue_flush.o tx_queue_front_send.o tx_queue_info_get.o tx_queue_initialize.o tx_queue_performance_info_get.o +"${AR}" -r tx.a tx_queue_performance_system_info_get.o tx_queue_prioritize.o tx_queue_receive.o tx_queue_send.o tx_queue_send_notify.o tx_semaphore_ceiling_put.o +"${AR}" -r tx.a tx_semaphore_cleanup.o tx_semaphore_create.o tx_semaphore_delete.o tx_semaphore_get.o tx_semaphore_info_get.o tx_semaphore_initialize.o +"${AR}" -r tx.a tx_semaphore_performance_info_get.o tx_semaphore_performance_system_info_get.o tx_semaphore_prioritize.o tx_semaphore_put.o tx_semaphore_put_notify.o +"${AR}" -r tx.a tx_thread_create.o tx_thread_delete.o tx_thread_entry_exit_notify.o tx_thread_identify.o tx_thread_info_get.o tx_thread_initialize.o +"${AR}" -r tx.a tx_thread_performance_info_get.o tx_thread_performance_system_info_get.o tx_thread_preemption_change.o tx_thread_priority_change.o tx_thread_relinquish.o +"${AR}" -r tx.a tx_thread_reset.o tx_thread_resume.o tx_thread_shell_entry.o tx_thread_sleep.o tx_thread_stack_analyze.o tx_thread_stack_error_handler.o +"${AR}" -r tx.a tx_thread_stack_error_notify.o tx_thread_suspend.o tx_thread_system_preempt_check.o tx_thread_system_resume.o tx_thread_system_suspend.o +"${AR}" -r tx.a tx_thread_terminate.o tx_thread_time_slice.o tx_thread_time_slice_change.o tx_thread_timeout.o tx_thread_wait_abort.o tx_time_get.o +"${AR}" -r tx.a tx_time_set.o tx_timer_activate.o tx_timer_change.o tx_timer_create.o tx_timer_deactivate.o tx_timer_delete.o tx_timer_expiration_process.o +"${AR}" -r tx.a tx_timer_info_get.o tx_timer_initialize.o tx_timer_performance_info_get.o tx_timer_performance_system_info_get.o tx_timer_system_activate.o +"${AR}" -r tx.a tx_timer_system_deactivate.o tx_timer_thread_entry.o tx_trace_enable.o tx_trace_disable.o tx_trace_initialize.o tx_trace_interrupt_control.o +"${AR}" -r tx.a tx_trace_isr_enter_insert.o tx_trace_isr_exit_insert.o tx_trace_object_register.o tx_trace_object_unregister.o tx_trace_user_event_insert.o +"${AR}" -r tx.a tx_trace_buffer_full_notify.o tx_trace_event_filter.o tx_trace_event_unfilter.o +"${AR}" -r tx.a txe_block_allocate.o txe_block_pool_create.o txe_block_pool_delete.o txe_block_pool_info_get.o txe_block_pool_prioritize.o txe_block_release.o +"${AR}" -r tx.a txe_byte_allocate.o txe_byte_pool_create.o txe_byte_pool_delete.o txe_byte_pool_info_get.o txe_byte_pool_prioritize.o txe_byte_release.o +"${AR}" -r tx.a txe_event_flags_create.o txe_event_flags_delete.o txe_event_flags_get.o txe_event_flags_info_get.o txe_event_flags_set.o +"${AR}" -r tx.a txe_event_flags_set_notify.o txe_mutex_create.o txe_mutex_delete.o txe_mutex_get.o txe_mutex_info_get.o txe_mutex_prioritize.o +"${AR}" -r tx.a txe_mutex_put.o txe_queue_create.o txe_queue_delete.o txe_queue_flush.o txe_queue_front_send.o txe_queue_info_get.o txe_queue_prioritize.o +"${AR}" -r tx.a txe_queue_receive.o txe_queue_send.o txe_queue_send_notify.o txe_semaphore_ceiling_put.o txe_semaphore_create.o txe_semaphore_delete.o +"${AR}" -r tx.a txe_semaphore_get.o txe_semaphore_info_get.o txe_semaphore_prioritize.o txe_semaphore_put.o txe_semaphore_put_notify.o txe_thread_create.o +"${AR}" -r tx.a txe_thread_delete.o txe_thread_entry_exit_notify.o txe_thread_info_get.o txe_thread_preemption_change.o txe_thread_priority_change.o +"${AR}" -r tx.a txe_thread_relinquish.o txe_thread_reset.o txe_thread_resume.o txe_thread_suspend.o txe_thread_terminate.o txe_thread_time_slice_change.o +"${AR}" -r tx.a txe_thread_wait_abort.o txe_timer_activate.o txe_timer_change.o txe_timer_create.o txe_timer_deactivate.o txe_timer_delete.o txe_timer_info_get.o +"${AR}" -r tx.a tx_thread_smp_current_state_set.o tx_thread_smp_debug_entry_insert.o tx_thread_smp_high_level_initialize.o +"${AR}" -r tx.a tx_thread_smp_rebalance_execute_list.o tx_thread_smp_core_exclude.o tx_thread_smp_core_exclude_get.o +"${AR}" -r tx.a tx_timer_smp_core_exclude.o tx_timer_smp_core_exclude_get.o tx_thread_smp_utilities.o +"${AR}" -r tx.a tx_thread_smp_core_get.o tx_thread_smp_core_preempt.o tx_thread_smp_current_state_get.o tx_thread_smp_current_thread_get.o tx_thread_smp_initialize_wait.o +"${AR}" -r tx.a tx_thread_smp_low_level_initialize.o tx_thread_smp_protect.o tx_thread_smp_time_get.o tx_thread_smp_unprotect.o diff --git a/ports_smp/cortex_a5_smp/gnu/example_build/build_threadx_sample.sh b/ports_smp/cortex_a5_smp/gnu/example_build/build_threadx_sample.sh new file mode 100755 index 000000000..7ed4946eb --- /dev/null +++ b/ports_smp/cortex_a5_smp/gnu/example_build/build_threadx_sample.sh @@ -0,0 +1,56 @@ +#!/bin/sh +############################################################################## +# 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 +############################################################################## + +set -e +cd "$(dirname "$0")" + +# this script builds the ThreadX sample image for the Cortex-A5 SMP port using +# GNU toolchain or llvm/clang toolchain (defaults to GNU). +: "${TOOLCHAIN:=gnu}" +case "${TOOLCHAIN}" in + gnu) + CC="arm-none-eabi-gcc" + TARGET_FLAGS="" + # GNU and Clang use different driver syntax for selecting the program's + # entry-point symbol. + ENTRY_FLAG="-e Vectors" + # Bare-metal C libraries require syscall support. GNU uses newlib's nosys stubs + # while ATFE requires a semihost library. + SYSCALL_LIB="--specs=nosys.specs" + ;; + atfe) + CC="${ATFE_CLANG:-clang}" + TARGET_FLAGS="--target=arm-none-eabi" + ENTRY_FLAG="-Wl,--entry=Vectors" + SYSCALL_LIB="-lsemihost" + ;; + *) + echo "Unknown TOOLCHAIN: ${TOOLCHAIN}" >&2 + exit 1 + ;; +esac + +"${CC}" ${TARGET_FLAGS} -c -g -I../../../../common_smp/inc -I../inc -mcpu=cortex-a5 sample_threadx.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 startup.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 crt0.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 MP_GIC.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 MP_SCU.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 MP_Mutexes.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 MP_PrivateTimer.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a5 v7.S +"${CC}" ${TARGET_FLAGS} -g -mcpu=cortex-a5 -nostartfiles \ + -T sample_threadx.ld \ + ${ENTRY_FLAG} \ + ${SYSCALL_LIB} \ + -o sample_threadx.out \ + MP_PrivateTimer.o MP_GIC.o MP_Mutexes.o MP_SCU.o \ + sample_threadx.o startup.o crt0.o v7.o tx.a \ + -Wl,-M > sample_threadx.map diff --git a/ports_smp/cortex_a5_smp/gnu/example_build/crt0.S b/ports_smp/cortex_a5_smp/gnu/example_build/crt0.S new file mode 100644 index 000000000..abc817d5c --- /dev/null +++ b/ports_smp/cortex_a5_smp/gnu/example_build/crt0.S @@ -0,0 +1,101 @@ + + .syntax unified +#if defined(THUMB_MODE) + .thumb +#else + .arm +#endif + +/* .text is used instead of .section .text so it works with arm-aout too. */ + .text + .align 0 + +#if defined(THUMB_MODE) + .thumb_func +#endif + .global _mainCRTStartup +_mainCRTStartup: +#if defined(THUMB_MODE) + .thumb_func +#endif + .global _start +_start: +#if defined(THUMB_MODE) + .thumb_func +#endif + .global start +start: + +/* Start by setting up a stack */ + /* Set up the stack pointer to a fixed value */ + ldr r3, .LC0 + mov sp, r3 + /* Setup a default stack-limit in case the code has been + compiled with "-mapcs-stack-check". Hard-wiring this value + is not ideal, since there is currently no support for + checking that the heap and stack have not collided, or that + this default 64k is enough for the program being executed. + However, it ensures that this simple crt0 world will not + immediately cause an overflow event: */ + sub sl, sp, #64 << 10 /* Still assumes 256bytes below sl */ + mov a2, #0 /* Second arg: fill value */ + mov fp, a2 /* Null frame pointer */ + mov r7, a2 /* Null frame pointer for Thumb */ + + ldr a1, .LC1 /* First arg: start of memory block */ + ldr a3, .LC2 + sub a3, a3, a1 /* Third arg: length of block */ + + + + bl memset + mov r0, #0 /* no arguments */ + mov r1, #0 /* no argv either */ +#ifdef __USES_INITFINI__ + /* Some arm/elf targets use the .init and .fini sections + to create constructors and destructors, and for these + targets we need to call the _init function and arrange + for _fini to be called at program exit. */ + mov r4, r0 + mov r5, r1 +/* ldr r0, .Lfini */ + bl atexit +/* bl init */ + mov r0, r4 + mov r1, r5 +#endif + bl main + + bl exit /* Should not return. */ + + + /* For Thumb, constants must be after the code since only + positive offsets are supported for PC relative addresses. */ + + .align 0 +.LC0: +.LC1: + .word __bss_start__ +.LC2: + .word __bss_end__ +/* +#ifdef __USES_INITFINI__ +.Lfini: + .word _fini +#endif */ + /* Return ... */ + bx lr + + .global _fini + .type _fini,function +_fini: + BX lr // Return to caller + +/* Workspace for Angel calls. */ + .data +/* Data returned by monitor SWI. */ +.global __stack_base__ +HeapBase: .word 0 +HeapLimit: .word 0 +__stack_base__: .word 0 +StackLimit: .word 0 diff --git a/ports_smp/cortex_a7_smp/gnu/example_build/build_threadx.sh b/ports_smp/cortex_a7_smp/gnu/example_build/build_threadx.sh new file mode 100755 index 000000000..2f27e278c --- /dev/null +++ b/ports_smp/cortex_a7_smp/gnu/example_build/build_threadx.sh @@ -0,0 +1,295 @@ +#!/bin/sh +############################################################################## +# 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 +############################################################################## + +set -e +cd "$(dirname "$0")" + +# this script builds the ThreadX library for the Cortex-A7 SMP port using +# GNU toolchain or llvm/clang toolchain (defaults to GNU). +: "${TOOLCHAIN:=gnu}" + +case "${TOOLCHAIN}" in + gnu) + CC="arm-none-eabi-gcc" + AR="arm-none-eabi-ar" + TARGET_FLAGS="" + ;; + atfe) + CC="${ATFE_CLANG:-clang}" + case "${CC}" in + */*) AR="$(dirname "${CC}")/llvm-ar" ;; + *) AR="llvm-ar" ;; + esac + TARGET_FLAGS="--target=arm-none-eabi" + ;; + *) + echo "Unknown TOOLCHAIN: ${TOOLCHAIN}" >&2 + exit 1 + ;; +esac + +rm -f tx.a +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 tx_initialize_low_level.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 ../src/tx_thread_stack_build.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 ../src/tx_thread_schedule.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 ../src/tx_thread_system_return.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 ../src/tx_thread_context_save.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 ../src/tx_thread_context_restore.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 ../src/tx_thread_interrupt_control.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 ../src/tx_timer_interrupt.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 ../src/tx_thread_interrupt_disable.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 ../src/tx_thread_interrupt_restore.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 ../src/tx_thread_irq_nesting_end.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 ../src/tx_thread_irq_nesting_start.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 ../src/tx_thread_vectored_context_save.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 ../src/tx_thread_smp_core_get.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 ../src/tx_thread_smp_core_preempt.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 ../src/tx_thread_smp_current_state_get.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 ../src/tx_thread_smp_current_thread_get.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 ../src/tx_thread_smp_initialize_wait.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 ../src/tx_thread_smp_low_level_initialize.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 ../src/tx_thread_smp_protect.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 ../src/tx_thread_smp_time_get.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 ../src/tx_thread_smp_unprotect.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_allocate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_pool_cleanup.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_pool_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_pool_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_pool_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_pool_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_pool_performance_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_pool_performance_system_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_pool_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_release.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_allocate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_cleanup.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_performance_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_performance_system_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_search.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_release.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_cleanup.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_performance_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_performance_system_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_set.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_set_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_initialize_high_level.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_initialize_kernel_enter.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_initialize_kernel_setup.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_cleanup.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_performance_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_performance_system_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_priority_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_put.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_cleanup.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_flush.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_front_send.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_performance_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_performance_system_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_receive.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_send.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_send_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_ceiling_put.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_cleanup.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_performance_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_performance_system_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_put.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_put_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_entry_exit_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_identify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_performance_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_performance_system_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_preemption_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_priority_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_relinquish.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_reset.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_resume.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_shell_entry.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_sleep.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_stack_analyze.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_stack_error_handler.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_stack_error_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_suspend.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_system_preempt_check.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_system_resume.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_system_suspend.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_terminate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_time_slice.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_time_slice_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_timeout.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_wait_abort.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_time_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_time_set.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_activate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_deactivate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_expiration_process.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_performance_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_performance_system_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_system_activate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_system_deactivate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_thread_entry.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_enable.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_disable.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_interrupt_control.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_isr_enter_insert.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_isr_exit_insert.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_object_register.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_object_unregister.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_user_event_insert.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_buffer_full_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_event_filter.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_event_unfilter.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_block_allocate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_block_pool_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_block_pool_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_block_pool_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_block_pool_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_block_release.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_byte_allocate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_byte_pool_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_byte_pool_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_byte_pool_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_byte_pool_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_byte_release.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_event_flags_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_event_flags_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_event_flags_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_event_flags_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_event_flags_set.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_event_flags_set_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_mutex_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_mutex_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_mutex_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_mutex_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_mutex_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_mutex_put.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_flush.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_front_send.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_receive.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_send.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_send_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_semaphore_ceiling_put.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_semaphore_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_semaphore_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_semaphore_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_semaphore_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_semaphore_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_semaphore_put.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_semaphore_put_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_entry_exit_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_preemption_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_priority_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_relinquish.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_reset.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_resume.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_suspend.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_terminate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_time_slice_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_wait_abort.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_timer_activate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_timer_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_timer_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_timer_deactivate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_timer_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_timer_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_smp_current_state_set.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_smp_debug_entry_insert.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_smp_high_level_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_smp_rebalance_execute_list.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_smp_core_exclude.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_smp_core_exclude_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_smp_core_exclude.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_smp_core_exclude_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_smp_utilities.c +"${AR}" -r tx.a tx_thread_stack_build.o tx_thread_schedule.o tx_thread_system_return.o tx_thread_context_save.o tx_thread_context_restore.o tx_timer_interrupt.o tx_thread_interrupt_control.o +"${AR}" -r tx.a tx_initialize_low_level.o tx_thread_interrupt_disable.o +"${AR}" -r tx.a tx_thread_interrupt_restore.o tx_thread_irq_nesting_end.o tx_thread_irq_nesting_start.o +"${AR}" -r tx.a tx_block_allocate.o tx_block_pool_cleanup.o tx_block_pool_create.o tx_block_pool_delete.o tx_block_pool_info_get.o +"${AR}" -r tx.a tx_block_pool_initialize.o tx_block_pool_performance_info_get.o tx_block_pool_performance_system_info_get.o tx_block_pool_prioritize.o +"${AR}" -r tx.a tx_block_release.o tx_byte_allocate.o tx_byte_pool_cleanup.o tx_byte_pool_create.o tx_byte_pool_delete.o tx_byte_pool_info_get.o +"${AR}" -r tx.a tx_byte_pool_initialize.o tx_byte_pool_performance_info_get.o tx_byte_pool_performance_system_info_get.o tx_byte_pool_prioritize.o +"${AR}" -r tx.a tx_byte_pool_search.o tx_byte_release.o tx_event_flags_cleanup.o tx_event_flags_create.o tx_event_flags_delete.o tx_event_flags_get.o +"${AR}" -r tx.a tx_event_flags_info_get.o tx_event_flags_initialize.o tx_event_flags_performance_info_get.o tx_event_flags_performance_system_info_get.o +"${AR}" -r tx.a tx_event_flags_set.o tx_event_flags_set_notify.o tx_initialize_high_level.o tx_initialize_kernel_enter.o tx_initialize_kernel_setup.o +"${AR}" -r tx.a tx_mutex_cleanup.o tx_mutex_create.o tx_mutex_delete.o tx_mutex_get.o tx_mutex_info_get.o tx_mutex_initialize.o tx_mutex_performance_info_get.o +"${AR}" -r tx.a tx_mutex_performance_system_info_get.o tx_mutex_prioritize.o tx_mutex_priority_change.o tx_mutex_put.o tx_queue_cleanup.o tx_queue_create.o +"${AR}" -r tx.a tx_queue_delete.o tx_queue_flush.o tx_queue_front_send.o tx_queue_info_get.o tx_queue_initialize.o tx_queue_performance_info_get.o +"${AR}" -r tx.a tx_queue_performance_system_info_get.o tx_queue_prioritize.o tx_queue_receive.o tx_queue_send.o tx_queue_send_notify.o tx_semaphore_ceiling_put.o +"${AR}" -r tx.a tx_semaphore_cleanup.o tx_semaphore_create.o tx_semaphore_delete.o tx_semaphore_get.o tx_semaphore_info_get.o tx_semaphore_initialize.o +"${AR}" -r tx.a tx_semaphore_performance_info_get.o tx_semaphore_performance_system_info_get.o tx_semaphore_prioritize.o tx_semaphore_put.o tx_semaphore_put_notify.o +"${AR}" -r tx.a tx_thread_create.o tx_thread_delete.o tx_thread_entry_exit_notify.o tx_thread_identify.o tx_thread_info_get.o tx_thread_initialize.o +"${AR}" -r tx.a tx_thread_performance_info_get.o tx_thread_performance_system_info_get.o tx_thread_preemption_change.o tx_thread_priority_change.o tx_thread_relinquish.o +"${AR}" -r tx.a tx_thread_reset.o tx_thread_resume.o tx_thread_shell_entry.o tx_thread_sleep.o tx_thread_stack_analyze.o tx_thread_stack_error_handler.o +"${AR}" -r tx.a tx_thread_stack_error_notify.o tx_thread_suspend.o tx_thread_system_preempt_check.o tx_thread_system_resume.o tx_thread_system_suspend.o +"${AR}" -r tx.a tx_thread_terminate.o tx_thread_time_slice.o tx_thread_time_slice_change.o tx_thread_timeout.o tx_thread_wait_abort.o tx_time_get.o +"${AR}" -r tx.a tx_time_set.o tx_timer_activate.o tx_timer_change.o tx_timer_create.o tx_timer_deactivate.o tx_timer_delete.o tx_timer_expiration_process.o +"${AR}" -r tx.a tx_timer_info_get.o tx_timer_initialize.o tx_timer_performance_info_get.o tx_timer_performance_system_info_get.o tx_timer_system_activate.o +"${AR}" -r tx.a tx_timer_system_deactivate.o tx_timer_thread_entry.o tx_trace_enable.o tx_trace_disable.o tx_trace_initialize.o tx_trace_interrupt_control.o +"${AR}" -r tx.a tx_trace_isr_enter_insert.o tx_trace_isr_exit_insert.o tx_trace_object_register.o tx_trace_object_unregister.o tx_trace_user_event_insert.o +"${AR}" -r tx.a tx_trace_buffer_full_notify.o tx_trace_event_filter.o tx_trace_event_unfilter.o +"${AR}" -r tx.a txe_block_allocate.o txe_block_pool_create.o txe_block_pool_delete.o txe_block_pool_info_get.o txe_block_pool_prioritize.o txe_block_release.o +"${AR}" -r tx.a txe_byte_allocate.o txe_byte_pool_create.o txe_byte_pool_delete.o txe_byte_pool_info_get.o txe_byte_pool_prioritize.o txe_byte_release.o +"${AR}" -r tx.a txe_event_flags_create.o txe_event_flags_delete.o txe_event_flags_get.o txe_event_flags_info_get.o txe_event_flags_set.o +"${AR}" -r tx.a txe_event_flags_set_notify.o txe_mutex_create.o txe_mutex_delete.o txe_mutex_get.o txe_mutex_info_get.o txe_mutex_prioritize.o +"${AR}" -r tx.a txe_mutex_put.o txe_queue_create.o txe_queue_delete.o txe_queue_flush.o txe_queue_front_send.o txe_queue_info_get.o txe_queue_prioritize.o +"${AR}" -r tx.a txe_queue_receive.o txe_queue_send.o txe_queue_send_notify.o txe_semaphore_ceiling_put.o txe_semaphore_create.o txe_semaphore_delete.o +"${AR}" -r tx.a txe_semaphore_get.o txe_semaphore_info_get.o txe_semaphore_prioritize.o txe_semaphore_put.o txe_semaphore_put_notify.o txe_thread_create.o +"${AR}" -r tx.a txe_thread_delete.o txe_thread_entry_exit_notify.o txe_thread_info_get.o txe_thread_preemption_change.o txe_thread_priority_change.o +"${AR}" -r tx.a txe_thread_relinquish.o txe_thread_reset.o txe_thread_resume.o txe_thread_suspend.o txe_thread_terminate.o txe_thread_time_slice_change.o +"${AR}" -r tx.a txe_thread_wait_abort.o txe_timer_activate.o txe_timer_change.o txe_timer_create.o txe_timer_deactivate.o txe_timer_delete.o txe_timer_info_get.o +"${AR}" -r tx.a tx_thread_smp_current_state_set.o tx_thread_smp_debug_entry_insert.o tx_thread_smp_high_level_initialize.o +"${AR}" -r tx.a tx_thread_smp_rebalance_execute_list.o tx_thread_smp_core_exclude.o tx_thread_smp_core_exclude_get.o +"${AR}" -r tx.a tx_timer_smp_core_exclude.o tx_timer_smp_core_exclude_get.o tx_thread_smp_utilities.o +"${AR}" -r tx.a tx_thread_smp_core_get.o tx_thread_smp_core_preempt.o tx_thread_smp_current_state_get.o tx_thread_smp_current_thread_get.o tx_thread_smp_initialize_wait.o +"${AR}" -r tx.a tx_thread_smp_low_level_initialize.o tx_thread_smp_protect.o tx_thread_smp_time_get.o tx_thread_smp_unprotect.o diff --git a/ports_smp/cortex_a7_smp/gnu/example_build/build_threadx_sample.sh b/ports_smp/cortex_a7_smp/gnu/example_build/build_threadx_sample.sh new file mode 100755 index 000000000..c3475fab1 --- /dev/null +++ b/ports_smp/cortex_a7_smp/gnu/example_build/build_threadx_sample.sh @@ -0,0 +1,54 @@ +#!/bin/sh +############################################################################## +# 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 +############################################################################## + +set -e +cd "$(dirname "$0")" + +# this script builds the ThreadX sample image for the Cortex-A7 SMP port using +# GNU toolchain or llvm/clang toolchain (defaults to GNU). +: "${TOOLCHAIN:=gnu}" +case "${TOOLCHAIN}" in + gnu) + CC="arm-none-eabi-gcc" + TARGET_FLAGS="" + # GNU and Clang use different driver syntax for selecting the program's + # entry-point symbol. + ENTRY_FLAG="-e Vectors" + # Bare-metal C libraries require syscall support. GNU uses newlib's nosys stubs + # while ATFE requires a semihost library. + SYSCALL_LIB="--specs=nosys.specs" + ;; + atfe) + CC="${ATFE_CLANG:-clang}" + TARGET_FLAGS="--target=arm-none-eabi" + ENTRY_FLAG="-Wl,--entry=Vectors" + SYSCALL_LIB="-lsemihost" + ;; + *) + echo "Unknown TOOLCHAIN: ${TOOLCHAIN}" >&2 + exit 1 + ;; +esac + +"${CC}" ${TARGET_FLAGS} -c -g -I../../../../common_smp/inc -I../inc -mcpu=cortex-a7 sample_threadx.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 startup.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 crt0.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 MP_GIC.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 MP_Mutexes.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a7 v7.S +"${CC}" ${TARGET_FLAGS} -g -mcpu=cortex-a7 -nostartfiles \ + -T sample_threadx.ld \ + ${SYSCALL_LIB} \ + ${ENTRY_FLAG} \ + -o sample_threadx.out \ + MP_GIC.o MP_Mutexes.o \ + sample_threadx.o startup.o crt0.o v7.o tx.a \ + -Wl,-M > sample_threadx.map diff --git a/ports_smp/cortex_a7_smp/gnu/example_build/crt0.S b/ports_smp/cortex_a7_smp/gnu/example_build/crt0.S new file mode 100644 index 000000000..abc817d5c --- /dev/null +++ b/ports_smp/cortex_a7_smp/gnu/example_build/crt0.S @@ -0,0 +1,101 @@ + + .syntax unified +#if defined(THUMB_MODE) + .thumb +#else + .arm +#endif + +/* .text is used instead of .section .text so it works with arm-aout too. */ + .text + .align 0 + +#if defined(THUMB_MODE) + .thumb_func +#endif + .global _mainCRTStartup +_mainCRTStartup: +#if defined(THUMB_MODE) + .thumb_func +#endif + .global _start +_start: +#if defined(THUMB_MODE) + .thumb_func +#endif + .global start +start: + +/* Start by setting up a stack */ + /* Set up the stack pointer to a fixed value */ + ldr r3, .LC0 + mov sp, r3 + /* Setup a default stack-limit in case the code has been + compiled with "-mapcs-stack-check". Hard-wiring this value + is not ideal, since there is currently no support for + checking that the heap and stack have not collided, or that + this default 64k is enough for the program being executed. + However, it ensures that this simple crt0 world will not + immediately cause an overflow event: */ + sub sl, sp, #64 << 10 /* Still assumes 256bytes below sl */ + mov a2, #0 /* Second arg: fill value */ + mov fp, a2 /* Null frame pointer */ + mov r7, a2 /* Null frame pointer for Thumb */ + + ldr a1, .LC1 /* First arg: start of memory block */ + ldr a3, .LC2 + sub a3, a3, a1 /* Third arg: length of block */ + + + + bl memset + mov r0, #0 /* no arguments */ + mov r1, #0 /* no argv either */ +#ifdef __USES_INITFINI__ + /* Some arm/elf targets use the .init and .fini sections + to create constructors and destructors, and for these + targets we need to call the _init function and arrange + for _fini to be called at program exit. */ + mov r4, r0 + mov r5, r1 +/* ldr r0, .Lfini */ + bl atexit +/* bl init */ + mov r0, r4 + mov r1, r5 +#endif + bl main + + bl exit /* Should not return. */ + + + /* For Thumb, constants must be after the code since only + positive offsets are supported for PC relative addresses. */ + + .align 0 +.LC0: +.LC1: + .word __bss_start__ +.LC2: + .word __bss_end__ +/* +#ifdef __USES_INITFINI__ +.Lfini: + .word _fini +#endif */ + /* Return ... */ + bx lr + + .global _fini + .type _fini,function +_fini: + BX lr // Return to caller + +/* Workspace for Angel calls. */ + .data +/* Data returned by monitor SWI. */ +.global __stack_base__ +HeapBase: .word 0 +HeapLimit: .word 0 +__stack_base__: .word 0 +StackLimit: .word 0 diff --git a/ports_smp/cortex_a9_smp/gnu/example_build/build_threadx.sh b/ports_smp/cortex_a9_smp/gnu/example_build/build_threadx.sh new file mode 100755 index 000000000..8050c7756 --- /dev/null +++ b/ports_smp/cortex_a9_smp/gnu/example_build/build_threadx.sh @@ -0,0 +1,295 @@ +#!/bin/sh +############################################################################## +# 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 +############################################################################## + +set -e +cd "$(dirname "$0")" + +# this script builds the ThreadX library for the Cortex-A9 SMP port using +# GNU toolchain or llvm/clang toolchain (defaults to GNU). +: "${TOOLCHAIN:=gnu}" + +case "${TOOLCHAIN}" in + gnu) + CC="arm-none-eabi-gcc" + AR="arm-none-eabi-ar" + TARGET_FLAGS="" + ;; + atfe) + CC="${ATFE_CLANG:-clang}" + case "${CC}" in + */*) AR="$(dirname "${CC}")/llvm-ar" ;; + *) AR="llvm-ar" ;; + esac + TARGET_FLAGS="--target=arm-none-eabi" + ;; + *) + echo "Unknown TOOLCHAIN: ${TOOLCHAIN}" >&2 + exit 1 + ;; +esac + +rm -f tx.a +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 tx_initialize_low_level.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 ../src/tx_thread_context_restore.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 ../src/tx_thread_context_save.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 ../src/tx_thread_interrupt_control.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 ../src/tx_thread_interrupt_disable.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 ../src/tx_thread_interrupt_restore.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 ../src/tx_thread_irq_nesting_end.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 ../src/tx_thread_irq_nesting_start.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 ../src/tx_thread_schedule.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 ../src/tx_thread_smp_core_get.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 ../src/tx_thread_smp_core_preempt.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 ../src/tx_thread_smp_current_state_get.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 ../src/tx_thread_smp_current_thread_get.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 ../src/tx_thread_smp_initialize_wait.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 ../src/tx_thread_smp_low_level_initialize.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 ../src/tx_thread_smp_protect.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 ../src/tx_thread_smp_time_get.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 ../src/tx_thread_smp_unprotect.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 ../src/tx_thread_stack_build.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 ../src/tx_thread_system_return.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 ../src/tx_thread_vectored_context_save.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 ../src/tx_timer_interrupt.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_allocate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_pool_cleanup.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_pool_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_pool_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_pool_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_pool_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_pool_performance_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_pool_performance_system_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_pool_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_block_release.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_allocate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_cleanup.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_performance_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_performance_system_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_pool_search.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_byte_release.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_cleanup.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_performance_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_performance_system_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_set.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_event_flags_set_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_initialize_high_level.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_initialize_kernel_enter.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_initialize_kernel_setup.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_cleanup.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_performance_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_performance_system_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_priority_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_mutex_put.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_cleanup.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_flush.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_front_send.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_performance_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_performance_system_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_receive.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_send.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_queue_send_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_ceiling_put.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_cleanup.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_performance_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_performance_system_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_put.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_semaphore_put_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_entry_exit_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_identify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_performance_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_performance_system_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_preemption_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_priority_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_relinquish.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_reset.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_resume.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_shell_entry.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_sleep.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_stack_analyze.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_stack_error_handler.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_stack_error_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_suspend.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_system_preempt_check.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_system_resume.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_system_suspend.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_terminate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_time_slice.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_time_slice_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_timeout.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_wait_abort.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_time_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_time_set.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_activate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_deactivate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_expiration_process.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_performance_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_performance_system_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_system_activate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_system_deactivate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_thread_entry.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_enable.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_disable.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_interrupt_control.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_isr_enter_insert.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_isr_exit_insert.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_object_register.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_object_unregister.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_user_event_insert.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_buffer_full_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_event_filter.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_trace_event_unfilter.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_block_allocate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_block_pool_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_block_pool_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_block_pool_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_block_pool_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_block_release.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_byte_allocate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_byte_pool_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_byte_pool_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_byte_pool_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_byte_pool_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_byte_release.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_event_flags_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_event_flags_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_event_flags_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_event_flags_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_event_flags_set.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_event_flags_set_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_mutex_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_mutex_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_mutex_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_mutex_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_mutex_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_mutex_put.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_flush.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_front_send.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_receive.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_send.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_queue_send_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_semaphore_ceiling_put.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_semaphore_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_semaphore_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_semaphore_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_semaphore_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_semaphore_prioritize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_semaphore_put.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_semaphore_put_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_entry_exit_notify.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_preemption_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_priority_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_relinquish.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_reset.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_resume.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_suspend.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_terminate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_time_slice_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_thread_wait_abort.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_timer_activate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_timer_change.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_timer_create.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_timer_deactivate.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_timer_delete.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/txe_timer_info_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_smp_current_state_set.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_smp_debug_entry_insert.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_smp_high_level_initialize.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_smp_rebalance_execute_list.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_smp_core_exclude.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_smp_core_exclude_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_smp_core_exclude.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_timer_smp_core_exclude_get.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 -I../../../../common_smp/inc -I../inc ../../../../common_smp/src/tx_thread_smp_utilities.c +"${AR}" -r tx.a tx_thread_stack_build.o tx_thread_schedule.o tx_thread_system_return.o tx_thread_context_save.o tx_thread_context_restore.o tx_timer_interrupt.o tx_thread_interrupt_control.o +"${AR}" -r tx.a tx_initialize_low_level.o tx_thread_interrupt_disable.o +"${AR}" -r tx.a tx_thread_interrupt_restore.o tx_thread_irq_nesting_end.o tx_thread_irq_nesting_start.o +"${AR}" -r tx.a tx_block_allocate.o tx_block_pool_cleanup.o tx_block_pool_create.o tx_block_pool_delete.o tx_block_pool_info_get.o +"${AR}" -r tx.a tx_block_pool_initialize.o tx_block_pool_performance_info_get.o tx_block_pool_performance_system_info_get.o tx_block_pool_prioritize.o +"${AR}" -r tx.a tx_block_release.o tx_byte_allocate.o tx_byte_pool_cleanup.o tx_byte_pool_create.o tx_byte_pool_delete.o tx_byte_pool_info_get.o +"${AR}" -r tx.a tx_byte_pool_initialize.o tx_byte_pool_performance_info_get.o tx_byte_pool_performance_system_info_get.o tx_byte_pool_prioritize.o +"${AR}" -r tx.a tx_byte_pool_search.o tx_byte_release.o tx_event_flags_cleanup.o tx_event_flags_create.o tx_event_flags_delete.o tx_event_flags_get.o +"${AR}" -r tx.a tx_event_flags_info_get.o tx_event_flags_initialize.o tx_event_flags_performance_info_get.o tx_event_flags_performance_system_info_get.o +"${AR}" -r tx.a tx_event_flags_set.o tx_event_flags_set_notify.o tx_initialize_high_level.o tx_initialize_kernel_enter.o tx_initialize_kernel_setup.o +"${AR}" -r tx.a tx_mutex_cleanup.o tx_mutex_create.o tx_mutex_delete.o tx_mutex_get.o tx_mutex_info_get.o tx_mutex_initialize.o tx_mutex_performance_info_get.o +"${AR}" -r tx.a tx_mutex_performance_system_info_get.o tx_mutex_prioritize.o tx_mutex_priority_change.o tx_mutex_put.o tx_queue_cleanup.o tx_queue_create.o +"${AR}" -r tx.a tx_queue_delete.o tx_queue_flush.o tx_queue_front_send.o tx_queue_info_get.o tx_queue_initialize.o tx_queue_performance_info_get.o +"${AR}" -r tx.a tx_queue_performance_system_info_get.o tx_queue_prioritize.o tx_queue_receive.o tx_queue_send.o tx_queue_send_notify.o tx_semaphore_ceiling_put.o +"${AR}" -r tx.a tx_semaphore_cleanup.o tx_semaphore_create.o tx_semaphore_delete.o tx_semaphore_get.o tx_semaphore_info_get.o tx_semaphore_initialize.o +"${AR}" -r tx.a tx_semaphore_performance_info_get.o tx_semaphore_performance_system_info_get.o tx_semaphore_prioritize.o tx_semaphore_put.o tx_semaphore_put_notify.o +"${AR}" -r tx.a tx_thread_create.o tx_thread_delete.o tx_thread_entry_exit_notify.o tx_thread_identify.o tx_thread_info_get.o tx_thread_initialize.o +"${AR}" -r tx.a tx_thread_performance_info_get.o tx_thread_performance_system_info_get.o tx_thread_preemption_change.o tx_thread_priority_change.o tx_thread_relinquish.o +"${AR}" -r tx.a tx_thread_reset.o tx_thread_resume.o tx_thread_shell_entry.o tx_thread_sleep.o tx_thread_stack_analyze.o tx_thread_stack_error_handler.o +"${AR}" -r tx.a tx_thread_stack_error_notify.o tx_thread_suspend.o tx_thread_system_preempt_check.o tx_thread_system_resume.o tx_thread_system_suspend.o +"${AR}" -r tx.a tx_thread_terminate.o tx_thread_time_slice.o tx_thread_time_slice_change.o tx_thread_timeout.o tx_thread_wait_abort.o tx_time_get.o +"${AR}" -r tx.a tx_time_set.o tx_timer_activate.o tx_timer_change.o tx_timer_create.o tx_timer_deactivate.o tx_timer_delete.o tx_timer_expiration_process.o +"${AR}" -r tx.a tx_timer_info_get.o tx_timer_initialize.o tx_timer_performance_info_get.o tx_timer_performance_system_info_get.o tx_timer_system_activate.o +"${AR}" -r tx.a tx_timer_system_deactivate.o tx_timer_thread_entry.o tx_trace_enable.o tx_trace_disable.o tx_trace_initialize.o tx_trace_interrupt_control.o +"${AR}" -r tx.a tx_trace_isr_enter_insert.o tx_trace_isr_exit_insert.o tx_trace_object_register.o tx_trace_object_unregister.o tx_trace_user_event_insert.o +"${AR}" -r tx.a tx_trace_buffer_full_notify.o tx_trace_event_filter.o tx_trace_event_unfilter.o +"${AR}" -r tx.a txe_block_allocate.o txe_block_pool_create.o txe_block_pool_delete.o txe_block_pool_info_get.o txe_block_pool_prioritize.o txe_block_release.o +"${AR}" -r tx.a txe_byte_allocate.o txe_byte_pool_create.o txe_byte_pool_delete.o txe_byte_pool_info_get.o txe_byte_pool_prioritize.o txe_byte_release.o +"${AR}" -r tx.a txe_event_flags_create.o txe_event_flags_delete.o txe_event_flags_get.o txe_event_flags_info_get.o txe_event_flags_set.o +"${AR}" -r tx.a txe_event_flags_set_notify.o txe_mutex_create.o txe_mutex_delete.o txe_mutex_get.o txe_mutex_info_get.o txe_mutex_prioritize.o +"${AR}" -r tx.a txe_mutex_put.o txe_queue_create.o txe_queue_delete.o txe_queue_flush.o txe_queue_front_send.o txe_queue_info_get.o txe_queue_prioritize.o +"${AR}" -r tx.a txe_queue_receive.o txe_queue_send.o txe_queue_send_notify.o txe_semaphore_ceiling_put.o txe_semaphore_create.o txe_semaphore_delete.o +"${AR}" -r tx.a txe_semaphore_get.o txe_semaphore_info_get.o txe_semaphore_prioritize.o txe_semaphore_put.o txe_semaphore_put_notify.o txe_thread_create.o +"${AR}" -r tx.a txe_thread_delete.o txe_thread_entry_exit_notify.o txe_thread_info_get.o txe_thread_preemption_change.o txe_thread_priority_change.o +"${AR}" -r tx.a txe_thread_relinquish.o txe_thread_reset.o txe_thread_resume.o txe_thread_suspend.o txe_thread_terminate.o txe_thread_time_slice_change.o +"${AR}" -r tx.a txe_thread_wait_abort.o txe_timer_activate.o txe_timer_change.o txe_timer_create.o txe_timer_deactivate.o txe_timer_delete.o txe_timer_info_get.o +"${AR}" -r tx.a tx_thread_smp_current_state_set.o tx_thread_smp_debug_entry_insert.o tx_thread_smp_high_level_initialize.o +"${AR}" -r tx.a tx_thread_smp_rebalance_execute_list.o tx_thread_smp_core_exclude.o tx_thread_smp_core_exclude_get.o +"${AR}" -r tx.a tx_timer_smp_core_exclude.o tx_timer_smp_core_exclude_get.o tx_thread_smp_utilities.o +"${AR}" -r tx.a tx_thread_smp_core_get.o tx_thread_smp_core_preempt.o tx_thread_smp_current_state_get.o tx_thread_smp_current_thread_get.o tx_thread_smp_initialize_wait.o +"${AR}" -r tx.a tx_thread_smp_low_level_initialize.o tx_thread_smp_protect.o tx_thread_smp_time_get.o tx_thread_smp_unprotect.o diff --git a/ports_smp/cortex_a9_smp/gnu/example_build/build_threadx_sample.sh b/ports_smp/cortex_a9_smp/gnu/example_build/build_threadx_sample.sh new file mode 100755 index 000000000..429876225 --- /dev/null +++ b/ports_smp/cortex_a9_smp/gnu/example_build/build_threadx_sample.sh @@ -0,0 +1,54 @@ +#!/bin/sh +############################################################################## +# 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 +############################################################################## + +set -e +cd "$(dirname "$0")" + +# this script builds the ThreadX sample image for the Cortex-A9 SMP port using +# GNU toolchain or llvm/clang toolchain (defaults to GNU). +: "${TOOLCHAIN:=gnu}" +case "${TOOLCHAIN}" in + gnu) + CC="arm-none-eabi-gcc" + TARGET_FLAGS="" # GNU and Clang use different driver syntax for selecting the program's + # entry-point symbol. + ENTRY_FLAG="-e Vectors" + # Bare-metal C libraries require syscall support. GNU uses newlib's nosys stubs + # while ATFE requires a semihost library. + SYSCALL_LIB="--specs=nosys.specs" + ;; + atfe) + CC="${ATFE_CLANG:-clang}" + TARGET_FLAGS="--target=arm-none-eabi" + ENTRY_FLAG="-Wl,--entry=Vectors" + SYSCALL_LIB="-lsemihost" + ;; + *) + echo "Unknown TOOLCHAIN: ${TOOLCHAIN}" >&2 + exit 1 + ;; +esac + +"${CC}" ${TARGET_FLAGS} -c -g -I../../../../common_smp/inc -I../inc -mcpu=cortex-a9 sample_threadx.c +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 startup.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 crt0.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 MP_GIC.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 MP_SCU.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 MP_Mutexes.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 MP_PrivateTimer.S +"${CC}" ${TARGET_FLAGS} -c -g -mcpu=cortex-a9 v7.S +"${CC}" ${TARGET_FLAGS} -g -mcpu=cortex-a9 -nostartfiles \ + -T sample_threadx.ld \ + ${ENTRY_FLAG} \ + ${SYSCALL_LIB} \ + -o sample_threadx.out MP_PrivateTimer.o MP_GIC.o MP_Mutexes.o MP_SCU.o \ + sample_threadx.o startup.o crt0.o v7.o tx.a \ + -Wl,-M > sample_threadx.map diff --git a/ports_smp/cortex_a9_smp/gnu/example_build/crt0.S b/ports_smp/cortex_a9_smp/gnu/example_build/crt0.S new file mode 100644 index 000000000..abc817d5c --- /dev/null +++ b/ports_smp/cortex_a9_smp/gnu/example_build/crt0.S @@ -0,0 +1,101 @@ + + .syntax unified +#if defined(THUMB_MODE) + .thumb +#else + .arm +#endif + +/* .text is used instead of .section .text so it works with arm-aout too. */ + .text + .align 0 + +#if defined(THUMB_MODE) + .thumb_func +#endif + .global _mainCRTStartup +_mainCRTStartup: +#if defined(THUMB_MODE) + .thumb_func +#endif + .global _start +_start: +#if defined(THUMB_MODE) + .thumb_func +#endif + .global start +start: + +/* Start by setting up a stack */ + /* Set up the stack pointer to a fixed value */ + ldr r3, .LC0 + mov sp, r3 + /* Setup a default stack-limit in case the code has been + compiled with "-mapcs-stack-check". Hard-wiring this value + is not ideal, since there is currently no support for + checking that the heap and stack have not collided, or that + this default 64k is enough for the program being executed. + However, it ensures that this simple crt0 world will not + immediately cause an overflow event: */ + sub sl, sp, #64 << 10 /* Still assumes 256bytes below sl */ + mov a2, #0 /* Second arg: fill value */ + mov fp, a2 /* Null frame pointer */ + mov r7, a2 /* Null frame pointer for Thumb */ + + ldr a1, .LC1 /* First arg: start of memory block */ + ldr a3, .LC2 + sub a3, a3, a1 /* Third arg: length of block */ + + + + bl memset + mov r0, #0 /* no arguments */ + mov r1, #0 /* no argv either */ +#ifdef __USES_INITFINI__ + /* Some arm/elf targets use the .init and .fini sections + to create constructors and destructors, and for these + targets we need to call the _init function and arrange + for _fini to be called at program exit. */ + mov r4, r0 + mov r5, r1 +/* ldr r0, .Lfini */ + bl atexit +/* bl init */ + mov r0, r4 + mov r1, r5 +#endif + bl main + + bl exit /* Should not return. */ + + + /* For Thumb, constants must be after the code since only + positive offsets are supported for PC relative addresses. */ + + .align 0 +.LC0: +.LC1: + .word __bss_start__ +.LC2: + .word __bss_end__ +/* +#ifdef __USES_INITFINI__ +.Lfini: + .word _fini +#endif */ + /* Return ... */ + bx lr + + .global _fini + .type _fini,function +_fini: + BX lr // Return to caller + +/* Workspace for Angel calls. */ + .data +/* Data returned by monitor SWI. */ +.global __stack_base__ +HeapBase: .word 0 +HeapLimit: .word 0 +__stack_base__: .word 0 +StackLimit: .word 0 From 7f6e4962338eaf6491a120f96175b19d70d4eb48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Wed, 9 Sep 2026 17:17:37 -0400 Subject: [PATCH 122/181] Added the missing VFP enable field to the Cortex-R5/AC5 thread control block, which VFP builds were writing over the FileX pointer (#715) The Cortex-R5/AC5 port defines TX_THREAD_EXTENSION_2 as empty while its assembly reads and writes the per-thread VFP enable flag at [thread, #144]. With TX_ENABLE_VFP_SUPPORT that offset lands on tx_thread_filex_ptr, so tx_thread_vfp_enable corrupted the FileX pointer and lazy save/restore tested an unrelated value. Defined TX_THREAD_EXTENSION_2 as ULONG tx_thread_vfp_enable, matching the Armv7-A ports and the Cortex-R4/R5 GNU and AC6 ports fixed earlier, and added tx_port_offset_check.c so a future layout change breaks the build instead of silently retargeting the accesses. The offset was measured at 144 for this port and asserted. Fixes #382 Assisted-by: Copilot (Opus 5) --- ports/cortex_r5/ac5/inc/tx_port.h | 13 ++- .../cortex_r5/ac5/src/tx_port_offset_check.c | 87 +++++++++++++++++++ 2 files changed, 99 insertions(+), 1 deletion(-) create mode 100644 ports/cortex_r5/ac5/src/tx_port_offset_check.c diff --git a/ports/cortex_r5/ac5/inc/tx_port.h b/ports/cortex_r5/ac5/inc/tx_port.h index 3fa525784..d1c69fba3 100644 --- a/ports/cortex_r5/ac5/inc/tx_port.h +++ b/ports/cortex_r5/ac5/inc/tx_port.h @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -183,7 +185,16 @@ typedef unsigned short USHORT; #define TX_THREAD_EXTENSION_0 #define TX_THREAD_EXTENSION_1 -#define TX_THREAD_EXTENSION_2 + +/* TX_THREAD_EXTENSION_2 carries the per-thread VFP enable flag that the lazy + floating-point save and restore in tx_thread_schedule, tx_thread_system_return + and tx_thread_context_restore reads and writes as [thread, #144]. Without it + a TX_ENABLE_VFP_SUPPORT build has no such member and those accesses land on + tx_thread_filex_ptr instead. Defined unconditionally, matching the Armv7-A + ports: the offset is hard-coded in assembly, so a conditional member would + move every following field and be correct in only one configuration. */ + +#define TX_THREAD_EXTENSION_2 ULONG tx_thread_vfp_enable; #define TX_THREAD_EXTENSION_3 diff --git a/ports/cortex_r5/ac5/src/tx_port_offset_check.c b/ports/cortex_r5/ac5/src/tx_port_offset_check.c new file mode 100644 index 000000000..11eaa2539 --- /dev/null +++ b/ports/cortex_r5/ac5/src/tx_port_offset_check.c @@ -0,0 +1,87 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Copilot (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Port Specific */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +/**************************************************************************/ +/* */ +/* PORT SPECIFIC C INFORMATION RELEASE */ +/* */ +/* tx_port_offset_check.c Cortex-R5/AC5 */ +/* */ +/* DESCRIPTION */ +/* */ +/* Compile-time verification of the TX_THREAD structure offsets that */ +/* this port's assembly reaches by hard-coded displacement. The file */ +/* emits no code; it exists purely so that a layout change becomes a */ +/* build failure. */ +/* */ +/* Why this is needed: tx_thread_schedule.s, */ +/* tx_thread_system_return.s and tx_thread_context_restore.s read and */ +/* write the per-thread VFP enable flag as [thread, #144]. Nothing in */ +/* the toolchain connects that literal to the C structure, so adding a */ +/* member, enabling an option that adds one, or reordering the port */ +/* extensions would silently retarget those accesses at an unrelated */ +/* field -- corrupting thread state in a way that is extremely hard to */ +/* diagnose from the symptom. The offset was measured at 144 for the */ +/* default build and is asserted here. */ +/* */ +/* NOTE: this port has no CMake build of its own, so this file takes */ +/* effect only in builds that compile everything under src/. It is */ +/* still worthwhile: it emits no code, costs nothing, and protects every */ +/* build that does pick it up. */ +/* */ +/* A negative array dimension is used rather than _Static_assert */ +/* because this project targets C99, where _Static_assert does not */ +/* exist. If an assertion below fails, the compiler reports a negative */ +/* or zero-sized array for the named typedef. */ +/* */ +/**************************************************************************/ + +#include "tx_api.h" +#include + +/* Offset of the VFP enable flag as encoded in this port's assembly. + Overridable only so that the assertion itself can be tested. */ + +#ifndef TX_PORT_VFP_ENABLE_OFFSET +#define TX_PORT_VFP_ENABLE_OFFSET 144 +#endif + +typedef char +tx_port_assert_vfp_enable_offset_is_144[ + (offsetof(TX_THREAD, tx_thread_vfp_enable) == TX_PORT_VFP_ENABLE_OFFSET) + ? 1 : -1]; + +/* The stack pointer is read as [thread, #8] by tx_thread_schedule.S and + written by tx_thread_system_return.s, and the run counter as + [thread, #4]. Assert those too, since they are on the context-switch + critical path. */ + +typedef char +tx_port_assert_stack_ptr_offset_is_8[ + (offsetof(TX_THREAD, tx_thread_stack_ptr) == 8) ? 1 : -1]; + +typedef char +tx_port_assert_run_count_offset_is_4[ + (offsetof(TX_THREAD, tx_thread_run_count) == 4) ? 1 : -1]; From 5e9d046b12ea52d13646bd7755a813491c1a76c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Thu, 10 Sep 2026 07:25:37 -0400 Subject: [PATCH 123/181] Compiled the module manager C sources with GCC, as clang already did (#716) #689 added the module manager stage to check_clang.sh alone. The GCC half was never written, so the module manager C stayed unbuilt by the project's declared default compiler: 28 files of portable module manager under common_modules, plus the three to nine per-port files under ports_module//gnu/module_manager/src, across nine Arm module ports. The stage is deliberately check_clang.sh's, port for port and header for header, because a port covered by one check and not the other implies a parity the checks list does not have. The same two details the ports dictate carry over: an SMP port's control blocks come from common_smp rather than common, and the TrustZone ports need -mcmse for their cmse_nonsecure_entry functions to be honoured rather than ignored. The clang-only waiver does not: GCC implements the optimize attribute that tx_thread_secure_stack.c carries, so nothing needs suppressing for that file. One divergence is forced by the toolchain. txm_module_manager_absolute_load.c carries a #pragma message steering callers to the extended entry point, and the C stages treat any compiler output as a failure. check_clang.sh silences it with -Wno-#pragma-messages; GCC has no equivalent, and neither -Wno-pragmas nor any other -W option suppresses the note -- verified with 14.3.rel1. The note is therefore filtered out of the stage's output instead, together with the source quote GCC prints beneath it. The filter stops at the next line that begins a diagnostic of its own, so an error immediately following a waived note is still reported; that case is what the injected-defect run below checks. The workflow needed no trigger change: #689 added common_modules/** to both path lists in advance, for the stage that had yet to arrive. Its header comment is brought in line with what the workflow now runs. Verified with the toolchain CI pins, arm-gnu-toolchain 14.3.rel1, both triples. The full script passes and every port compiles every file, matching the counts check_clang.sh reports for the same nine ports: cortex_a35 31/31 cortex_a35_smp 31/31 cortex_a7 34/34 cortex_m0+ 33/33 cortex_m23 37/37 cortex_m3 33/33 cortex_m33 37/37 cortex_m4 33/33 cortex_m7 33/33 Verified that the stage fails as intended by injecting defects into a throwaway worktree: one in common_modules on the line straight after the waived pragma note, reported under all nine ports, and one in a single port's own source, reported only under that port. Assisted-by: Claude Code (Opus 5) --- .github/workflows/gcc_check.yml | 14 ++-- scripts/check_gcc.sh | 109 ++++++++++++++++++++++++++++++-- 2 files changed, 112 insertions(+), 11 deletions(-) diff --git a/.github/workflows/gcc_check.yml b/.github/workflows/gcc_check.yml index eabbd0a7e..f26cf5704 100644 --- a/.github/workflows/gcc_check.yml +++ b/.github/workflows/gcc_check.yml @@ -1,10 +1,11 @@ name: gcc_check -# Builds the Arm ports with the Arm GNU toolchain, in five stages: assemble +# Builds the Arm ports with the Arm GNU toolchain, in six stages: assemble # every assembly source of every Arm gnu port, assemble again the parts guarded # by feature macros, compile the common C sources for one core per architecture -# profile, then link the example builds, both the script-driven ones and those -# driven by CMake. +# profile, compile the module manager C sources once per Arm module port, then +# link the example builds, both the script-driven ones and those driven by +# CMake. # # Why this exists: GCC is the project's declared default compiler (AGENTS.md, # "The default compiler for the project is GCC 14 on Linux") and until this @@ -13,9 +14,10 @@ name: gcc_check # guarded than the GNU one, on ports whose directory is literally named gnu. # # What it covers: 840 assembly sources across 40 port families, 469 of them -# again behind feature macros, common/src for nine cores, 42 script-driven -# example links and the five Cortex-R52 CMake images. Every skip is printed by -# name with a reason -- run scripts/check_gcc.sh --help, or read its header. +# again behind feature macros, common/src for nine cores, 302 module manager C +# files across the nine Arm module ports, 42 script-driven example links and +# the five Cortex-R52 CMake images. Every skip is printed by name with a reason +# -- run scripts/check_gcc.sh --help, or read its header. # # What it does not cover: it compiles and links and **executes nothing**. The # Cortex-R52 FVP ctest suite is not part of it. RISC-V, MIPS, RX and ARC are diff --git a/scripts/check_gcc.sh b/scripts/check_gcc.sh index ae603ea61..190d50f8b 100755 --- a/scripts/check_gcc.sh +++ b/scripts/check_gcc.sh @@ -14,13 +14,13 @@ # SPDX-License-Identifier: MIT and CC0-1.0 ############################################################################## -# Builds the Arm ports with the GNU toolchain, in six stages: assemble every +# Builds the Arm ports with the GNU toolchain, in seven stages: assemble every # assembly source of every Arm gnu port, assemble again the parts guarded by # feature macros, compile the common C sources for one core per architecture -# profile, link the example builds, both the script-driven ones and those -# driven by CMake, and finally assert that the option combinations the -# Cortex-R52 port refuses are in fact refused. Only the linking stages need a -# target C library. +# profile, compile the module manager C sources once per Arm module port, link +# the example builds, both the script-driven ones and those driven by CMake, +# and finally assert that the option combinations the Cortex-R52 port refuses +# are in fact refused. Only the linking stages need a target C library. # # scripts/check_gcc.sh # both drivers from PATH # scripts/check_gcc.sh --arm-none-eabi /path/to/toolchain/bin \ @@ -93,6 +93,25 @@ done say() { [ "$quiet" -eq 1 ] || echo "$@"; } fail() { echo " FAIL: $*"; } +# The C stages treat any compiler output as a failure, and a #pragma message is +# a deliberate notice to callers rather than a defect in the file that carries +# it -- txm_module_manager_absolute_load.c deprecates itself in favour of the +# extended entry point, and the module manager stage compiles it once per port. +# +# check_clang.sh suppresses these at the compiler with -Wno-#pragma-messages. +# GCC has no equivalent: the note is unconditional, and neither -Wno-pragmas +# nor any other -W option silences it -- verified with 14.3.rel1. So it is +# filtered out of the output here instead, along with the source quote and +# caret GCC prints beneath it. The skip ends at the next line that starts a +# diagnostic of its own, so an error following a waived note is still reported. +strip_pragma_messages() { + awk ' + /note: .#pragma message:/ { skip = 1; next } + skip && /^ *[0-9]* *\|/ { next } + { skip = 0; print } + ' +} + # Accept either the driver itself or the directory holding it, since a # toolchain is unpacked as a tree and naming its bin directory is the natural # thing to reach for. Resolve to an absolute path: the example stages run the @@ -420,6 +439,86 @@ if [ "$asm_only" -eq 0 ]; then done fi +# -------------------------------------------------------------------------- +if [ "$asm_only" -eq 0 ]; then + say "" + say "== Module manager C sources, one per Arm module port ==" + + # #689 added this stage to check_clang.sh alone, so the module manager C + # stayed unbuilt by the project's declared default compiler: 28 files of + # portable module manager under common_modules, plus the three to nine + # per-port files under ports_module//gnu/module_manager/src. This is + # the GCC half, and it is deliberately the same stage -- same ports, same + # headers, same counts -- because a port covered by one check and not the + # other implies a parity the checks list does not have. + # + # Each module port ships its own tx_port.h and txm_module_port.h, carrying + # the control-block extensions the dispatch code needs, so a port is + # compiled against its own headers rather than the base port's. + module_skipped="" + for dir in ports_module/*/gnu/module_manager/src; do + [ -d "$dir" ] || continue + core="$(echo "$dir" | cut -d/ -f2)" + spec="${PORT_TARGET[$core]:-}" + if [ -z "$spec" ]; then + module_skipped="$module_skipped $core" + continue + fi + + inc="ports_module/$core/gnu/inc" + if [ ! -f "$inc/tx_port.h" ] || [ ! -f "$inc/txm_module_port.h" ]; then + module_skipped="$module_skipped $core(headers)" + continue + fi + + # shellcheck disable=SC2086 + set -- $spec + target="$1"; cpu="$2"; shift 2; extra="$*" + CC="$(cc_for "$target")" + + # An SMP port's control blocks come from common_smp; pairing it with the + # single-core headers hides _tx_thread_smp_protect behind an implicit + # declaration instead of compiling the port that is actually shipped. + case "$core" in + *_smp) kernel_inc="common_smp/inc" ;; + *) kernel_inc="common/inc" ;; + esac + + # The TrustZone ports carry cmse_nonsecure_entry, which needs -mcmse to + # be honoured rather than ignored. + port_extra="" + if [ -f "$inc/tx_secure_interface.h" ]; then + port_extra="-mcmse" + fi + + count=0; bad=0 + for src in common_modules/module_manager/src/*.c "$dir"/*.c; do + [ -f "$src" ] || continue + count=$((count + 1)) + output="$("$CC" -mcpu="$cpu" $extra $port_extra \ + -I"$inc" -I"$kernel_inc" -Icommon_modules/inc \ + -Icommon_modules/module_manager/inc \ + -c "$src" -o /dev/null 2>&1 | strip_pragma_messages)" + if [ -n "$output" ]; then + fail "$core: $src" + # Show the error lines when there are any, and otherwise + # whatever the compiler did say -- a FAIL with nothing under it + # sends the reader off to reproduce the command by hand. + if echo "$output" | grep -q "error:"; then + echo "$output" | grep "error:" | head -3 | sed 's/^/ /' + else + echo "$output" | head -3 | sed 's/^/ /' + fi + bad=$((bad + 1)); failures=$((failures + 1)) + fi + done + say " $core: $((count - bad)) of $count compiled" + done + if [ -n "$module_skipped" ]; then + say " no target mapping, skipped:$module_skipped" + fi +fi + # -------------------------------------------------------------------------- if [ "$no_examples" -eq 0 ]; then say "" From 39277cf026e3a235375529fefcddf279f0c8b6fe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Thu, 10 Sep 2026 07:55:11 -0400 Subject: [PATCH 124/181] Stated the compiler and coverage requirements directly, and said who the pinned toolchain default serves (#718) * Stated the compiler and coverage requirements instead of citing a file no contributor can open Seven comments across five files cited a maintainer-local document as the source for two project requirements: that GCC 14 on Linux is the default compiler, and that the coverage target is 100%. That document is not part of this repository and is not published anywhere, so the citation gave a reader nothing to follow -- it named a source they cannot open, in place of simply stating the requirement. Both requirements are real and both stay. Only the pointer goes: each comment now states the requirement on its own terms, which is what the surrounding prose was already doing everywhere else. cmake/cortex_r52.cmake the pinned reference toolchain scripts/check_gcc.sh why the script exists .github/workflows/gcc_check.yml why the workflow exists, and the GCC_VERSION pin .github/workflows/r52_fvp.yml the GCC_VERSION pin .github/workflows/regression_template.yml the coverage floor, twice Comments only; no behaviour changes. Two paragraphs are rewrapped where the shorter text left a ragged line. Verified that scripts/check_gcc.sh still parses and prints its help from the header range it slices, and that cmake/cortex_r52.cmake still configures the Cortex-R52 build. Assisted-by: Claude Code (Opus 5) * Said who the pinned toolchain default in the CMake toolchain files serves Both cmake/cortex_r52.cmake and cmake/cortex_m52.cmake default ARM_TOOLCHAIN_PATH to a toolchains directory under the user's home, guarded by an EXISTS check. Nothing said whether CI relies on that, and the natural reading is that it does. It does not. The three workflows that install a toolchain unpack it into the workspace and cache it there, and r52_fvp.yml puts that directory on PATH before configuring; scripts/check_gcc.sh passes -DARM_TOOLCHAIN_PATH at each of its three CMake call sites. On a runner the guarded directory is absent, the EXISTS check falls through, and the compiler comes from PATH. The default only ever fires on a developer machine, where it is what makes a no-flag build work. Both comments now say that, so the default is not mistaken for a CI dependency and not removed as dead code. cortex_r52.cmake carries the explanation and cortex_m52.cmake refers to it, matching the cross-reference already there. The r52 comment also claimed absolute paths mean "the build does not depend on PATH ordering", which is only true where the pinned directory exists -- in CI the build depends on PATH and nothing else. Qualified accordingly. Comments only; no behaviour changes. Verified that both toolchain files still configure, and that the fall-through is real: with HOME pointed at a directory holding no toolchains, cortex_r52.cmake configures against the arm-none-eabi-gcc found on PATH. Assisted-by: Claude Code (Opus 5) --- .github/workflows/gcc_check.yml | 14 +++++++------- .github/workflows/r52_fvp.yml | 2 +- .github/workflows/regression_template.yml | 8 ++++---- cmake/cortex_m52.cmake | 4 ++++ cmake/cortex_r52.cmake | 18 ++++++++++++++---- scripts/check_gcc.sh | 13 ++++++------- 6 files changed, 36 insertions(+), 23 deletions(-) diff --git a/.github/workflows/gcc_check.yml b/.github/workflows/gcc_check.yml index f26cf5704..3eda52fa2 100644 --- a/.github/workflows/gcc_check.yml +++ b/.github/workflows/gcc_check.yml @@ -7,11 +7,11 @@ name: gcc_check # link the example builds, both the script-driven ones and those driven by # CMake. # -# Why this exists: GCC is the project's declared default compiler (AGENTS.md, -# "The default compiler for the project is GCC 14 on Linux") and until this -# workflow landed, nothing in CI compiled a line of any port with it. The only -# cross-compilation check that ran was clang_check, so the LLVM path was better -# guarded than the GNU one, on ports whose directory is literally named gnu. +# Why this exists: GCC 14 on Linux is the project's default compiler, it is +# what the gnu ports exist for, and until this workflow landed, nothing in CI +# compiled a line of any port with it. The only cross-compilation check that +# ran was clang_check, so the LLVM path was better guarded than the GNU one, +# on ports whose directory is literally named gnu. # # What it covers: 840 assembly sources across 40 port families, 469 of them # again behind feature macros, common/src for nine cores, 302 module manager C @@ -94,8 +94,8 @@ jobs: env: # Pinned deliberately, as the runner image is: a toolchain upgrade should # be a reviewable commit rather than something that changes underneath the - # ports. 14.3.rel1 matches AGENTS.md's GCC 14 default and the version - # cortex_m already pins. + # ports. 14.3.rel1 is the GCC 14 the project builds against, and the + # version cortex_m already pins. # Releases: https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads GCC_VERSION: 14.3.rel1 diff --git a/.github/workflows/r52_fvp.yml b/.github/workflows/r52_fvp.yml index 8adc1c2be..60861d49b 100644 --- a/.github/workflows/r52_fvp.yml +++ b/.github/workflows/r52_fvp.yml @@ -75,7 +75,7 @@ jobs: # Pinned deliberately. Matches gcc_check.yml and ci_cortex_m.yml so all # three share one cache entry rather than each holding its own copy of # the same archive; change them together or the sharing silently stops. - # 14.3.rel1 is AGENTS.md's declared GCC 14 default. + # 14.3.rel1 is the project's GCC 14 default. GCC_VERSION: 14.3.rel1 # Where the Armv8-R AEM FVP comes from. diff --git a/.github/workflows/regression_template.yml b/.github/workflows/regression_template.yml index ad2d42aa7..267b1b585 100644 --- a/.github/workflows/regression_template.yml +++ b/.github/workflows/regression_template.yml @@ -54,7 +54,7 @@ on: # rate, and not the lower of the two. Probed on the same run: the # ThreadX report at 100.00% lines and 77.67% branches passes a floor of # 99. Worth knowing, because branch coverage is around 78% in both - # suites while AGENTS.md asks for 100%, and a floor set from the + # suites while the project asks for 100%, and a floor set from the # headline line figure says nothing about it. # # Each suite sets its own in regression_test.yml, because they do not @@ -157,9 +157,9 @@ jobs: # ! opens a YAML tag, and the expression will not parse without it. # # fail_below_min turns the summary into a gate. Until now coverage could - # fall from any figure to any other and no check went red, against an - # AGENTS.md that asks for 100% -- a stated requirement measured with a - # gauge that could not fail. + # fall from any figure to any other and no check went red, against a + # project target of 100% -- a stated requirement measured with a gauge + # that could not fail. # # One thing the floor does not defend, and it is the likeliest way for # coverage to break: an empty report reads as 100%. gcovr writes diff --git a/cmake/cortex_m52.cmake b/cmake/cortex_m52.cmake index be25f62dd..4ba987d6d 100644 --- a/cmake/cortex_m52.cmake +++ b/cmake/cortex_m52.cmake @@ -29,6 +29,10 @@ include(${CMAKE_CURRENT_LIST_DIR}/arm-none-eabi.cmake) # reject the port outright. Override with -DARM_TOOLCHAIN_PATH= to build with a different compiler. The check leaves PATH # alone when the pinned directory is absent. +# +# As in cortex_r52.cmake, the default below serves local builds and nothing +# else -- no CI job has that directory, so on a runner the EXISTS check falls +# through and the compiler comes from PATH. See the longer note there. if(NOT DEFINED ARM_TOOLCHAIN_PATH) set(ARM_TOOLCHAIN_PATH "$ENV{HOME}/toolchains/arm-gnu-toolchain-14.3.rel1-x86_64-arm-none-eabi/bin") diff --git a/cmake/cortex_r52.cmake b/cmake/cortex_r52.cmake index ea599c682..a9e7aee61 100644 --- a/cmake/cortex_r52.cmake +++ b/cmake/cortex_r52.cmake @@ -30,10 +30,20 @@ set(SPEC_FLAGS "--specs=nosys.specs") include(${CMAKE_CURRENT_LIST_DIR}/arm-none-eabi.cmake) -# Pin the reference cross toolchain (see AGENTS.md, "Compiler"). Absolute paths -# are used deliberately so the build does not depend on PATH ordering. Override -# with -DARM_TOOLCHAIN_PATH= to build with a -# different compiler -- for example the advisory newest-compiler lane. +# Pin the project's reference cross toolchain, GCC 14 for Arm. An absolute +# path is used deliberately, so that a build on a machine which has it does not +# depend on PATH ordering. Override with -DARM_TOOLCHAIN_PATH= to build with a different compiler -- for example the +# advisory newest-compiler lane. +# +# The default below serves local builds and nothing else. It fires only on a +# machine that already has that directory, and no CI job does: the workflows +# unpack the toolchain into the workspace and put it on PATH, and +# scripts/check_gcc.sh passes -DARM_TOOLCHAIN_PATH at every CMake call site. +# On a runner the EXISTS check therefore falls through and the compiler comes +# from PATH. Do not read the default as something CI depends on -- and do not +# remove it as dead code either, because it is what makes a no-flag build work +# on a developer machine. if(NOT DEFINED ARM_TOOLCHAIN_PATH) set(ARM_TOOLCHAIN_PATH "$ENV{HOME}/toolchains/arm-gnu-toolchain-14.3.rel1-x86_64-arm-none-eabi/bin") diff --git a/scripts/check_gcc.sh b/scripts/check_gcc.sh index 190d50f8b..e714a5c13 100755 --- a/scripts/check_gcc.sh +++ b/scripts/check_gcc.sh @@ -37,13 +37,12 @@ # # Exit status is 0 when everything builds and 1 otherwise. # -# Why this exists: GCC is the project's declared default compiler (AGENTS.md, -# "The default compiler for the project is GCC 14 on Linux"), it is what the -# gnu ports exist for, and it is what nearly every downstream user builds with -# -- and until this script landed, nothing in CI compiled a line of any port -# with it. The only cross-compilation check that ran was the LLVM one, so the -# ATfE path was better guarded than the GNU one, on ports whose directory is -# literally named gnu. +# Why this exists: GCC 14 on Linux is the project's default compiler, it is +# what the gnu ports exist for, and it is what nearly every downstream user +# builds with -- and until this script landed, nothing in CI compiled a line +# of any port with it. The only cross-compilation check that ran was the LLVM +# one, so the ATfE path was better guarded than the GNU one, on ports whose +# directory is literally named gnu. # # This is the companion to scripts/check_clang.sh and deliberately mirrors it # stage for stage. They are two scripts rather than one with a --toolchain flag From 42f1d2bcf0d5946b008bacdda09ce0f8ce115a3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Thu, 10 Sep 2026 09:06:13 -0400 Subject: [PATCH 125/181] Pointed the SMP coverage comment at the pull request that made its measurements (#719) The paragraph explaining why the SMP floor sits at 99 rather than 100 ended with a bare reference that resolves to nothing a reader of this repository can open. It named a source outside the tree in place of one inside it. The real source is #677: it wrote the four tests that closed 53 of the 64 lines, took the measurements the paragraph quotes -- the 180,003 windows with zero handovers, and the three remaining lines in tx_thread_smp_utilities.c -- and raised the floor from 98 to 99. Citing it gives the next reader somewhere to go. This is the same correction #718 made across five other files; this line was missed because it sits in regression_test.yml rather than the template. Comment only; no behaviour change. Assisted-by: Claude Code (Opus 5) --- .github/workflows/regression_test.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/regression_test.yml b/.github/workflows/regression_test.yml index 014ceec9a..0de8aa822 100644 --- a/.github/workflows/regression_test.yml +++ b/.github/workflows/regression_test.yml @@ -77,7 +77,8 @@ jobs: # three are in tx_thread_smp_utilities.c: one is a range guard placed # after the shift it is meant to guard, so reaching it needs undefined # behaviour, and two are a priority-inheritance branch that needs the - # mutex owner genuinely executing on another core. See T17. + # mutex owner genuinely executing on another core. See #677, which + # made these measurements and raised the floor. coverage_thresholds: '99 100' freertos: permissions: From 18abe103afccb2f67e8b8b1da338090d464fc675 Mon Sep 17 00:00:00 2001 From: Akif Ejaz Date: Thu, 10 Sep 2026 18:08:11 +0500 Subject: [PATCH 126/181] Enabled the RISC-V regression suite in CI for QEMU targets (#717) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Enable the RISC-V regression suite in CI The riscv: job in regression_test.yml has been present but commented out since the RISC-V CI infrastructure landed (scripts/install_riscv.sh, scripts/build_tx_riscv.sh, scripts/test_tx_riscv.sh, and the CMake tree under test/tx/cmake/riscv/). It has been gated on a note that read 're-enable when RISC-V CI is ready', with no other blocker recorded. The suite is ready. A local run of scripts/build_tx_riscv.sh followed by scripts/test_tx_riscv.sh against upstream/dev builds every RISC-V target and passes every registered test across all ten build configurations: RV32 (five configs): 5 * 95 = 475 tests, 0 failures, 0 timeouts. RV64 (five configs): 5 * 96 = 480 tests, 0 failures, 0 timeouts. The extra RV64 test is threadx_riscv_new_thread_fpu_state_test, which lives beside test/tx/cmake/riscv/regression/CMakeLists.txt and is added only when THREADX_ARCH is risc-v64 -- the RV32 stack builder still leaves the mstatus slot of the frame unwritten. Every test runs on qemu-system-riscv32 / qemu-system-riscv64 with -machine virt, and each configuration completes in roughly thirteen to fifteen seconds. The job is wired the same way the ThreadX, SMP and FreeRTOS suites are: it calls .github/workflows/regression_template.yml with the RISC-V install/build/test scripts and the RISC-V cmake_path, sets result_affix: RISC-V so its check name and artifacts are named, and carries skip_deploy: true because coverage publishing stays on the Linux suites for now. skip_coverage: true is kept because the CMake configurations under test/tx/cmake/riscv match the Linux suite's minus the coverage instrumentation, so gcovr has nothing to read -- the same reason the FreeRTOS lane sets it. The regression_test.yml triggers were not touched, so the RISC-V suite now runs on push and pull_request to master and dev alongside the other three suites. * Said why the RISC-V suite collects no coverage, instead of implying a missing build configuration The comment added with the job read "No coverage build configuration for the RISC-V suite yet". Both halves of what followed are true -- the configurations under test/tx/cmake/riscv are the Linux suite's minus the coverage one, and gcovr has nothing to read -- but "yet" points the next reader at a fix that would not work. Coverage here is not one missing default_build_coverage entry. These tests are bare-metal images run under QEMU with -bios none, and test/tx/cmake/riscv/bsp/syscalls.c has _write to the UART, _exit through the sifive_test device, and stubs for _close, _fstat, _isatty, _lseek, _read and _sbrk -- but no _open. gcov emits a .gcda by opening a path, so instrumenting these builds produces nothing regardless of how they are configured. Nor is the template's TX_COVERAGE=OFF what holds coverage off: test/tx/cmake/riscv is its own top-level project and never declares that option, so the value is inert there. Getting a figure out of this suite needs a transport off the target -- gcov's dump routines over the UART the BSP already drives, or semihosting. Worth stating plainly in a project that asks for 100% coverage, rather than leaving a reader to discover it after adding a configuration that cannot help. Comment only; the job's inputs are unchanged. Assisted-by: Claude Code (Opus 5) --------- Co-authored-by: Frédéric Desbiens --- .github/workflows/regression_test.yml | 50 +++++++++++++++++---------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/.github/workflows/regression_test.yml b/.github/workflows/regression_test.yml index 0de8aa822..7b5724ac5 100644 --- a/.github/workflows/regression_test.yml +++ b/.github/workflows/regression_test.yml @@ -98,24 +98,38 @@ jobs: # No coverage build configuration yet; the suite covers the creation # paths of the layer rather than all of it. skip_coverage: true - # riscv: disabled — re-enable when RISC-V CI is ready - # riscv: - # permissions: - # contents: read - # issues: read - # checks: write - # pull-requests: write - # pages: write - # id-token: write - # uses: ./.github/workflows/regression_template.yml - # with: - # install_script: ./scripts/install_riscv.sh - # build_script: ./scripts/build_tx_riscv.sh - # test_script: ./scripts/test_tx_riscv.sh - # cmake_path: ./test/tx/cmake/riscv - # result_affix: RISC-V - # skip_deploy: true - # skip_coverage: true + riscv: + permissions: + contents: read + issues: read + checks: write + pull-requests: write + pages: write + id-token: write + uses: ./.github/workflows/regression_template.yml + with: + install_script: ./scripts/install_riscv.sh + build_script: ./scripts/build_tx_riscv.sh + test_script: ./scripts/test_tx_riscv.sh + cmake_path: ./test/tx/cmake/riscv + result_affix: RISC-V + skip_deploy: true + # No coverage from this suite, and not for want of a build configuration. + # These tests are bare-metal images run under QEMU with -bios none, and + # test/tx/cmake/riscv/bsp/syscalls.c gives them _write to the UART, _exit + # through the sifive_test device, and stubs for _close, _fstat, _isatty, + # _lseek, _read and _sbrk -- but no _open. gcov emits a .gcda by opening + # a path, so instrumenting these builds would produce nothing to read. + # + # test/tx/cmake/riscv/CMakeLists.txt is its own top-level project and does + # not declare the TX_COVERAGE option that test/tx/cmake and test/smp/cmake + # do, so the OFF the template exports is inert here rather than the thing + # holding coverage off. + # + # Collecting it therefore needs a transport off the target -- gcov's dump + # routines over the UART the BSP already drives, or semihosting -- and not + # a default_build_coverage entry beside the other five configurations. + skip_coverage: true deploy: # Publishing the coverage report stays on master. Adding dev to this # workflow's triggers was meant to run the suites on the branch the pull From 6c84e61d194c456789a847e63477576a893e738a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Thu, 10 Sep 2026 09:28:44 -0400 Subject: [PATCH 127/181] Gave install_riscv.sh the network hardening install.sh already had, and shared it between them (#721) install.sh grew a retry loop, per-command timeouts and a deliberately non-gating apt-get update after this runner pool cost several whole runs: a mirror going silent for two hours, and a Hash Sum mismatch from a third-party repository the project does not even use turning builds red. Those lessons were local to that one file. install_riscv.sh had none of them, and #717 puts it on every pull request's critical path. Under set -e its bare apt-get update was a single point of failure for the whole suite -- the precise case install.sh downgrades to a warning on purpose -- and its two wget calls, each fetching about 500 MB, had no retry and no timeout. Rather than copy the helpers and let them drift again, they move to tx_ci_common.sh and both scripts source it, following the arrangement scripts/tx_windows_common.ps1 already uses on the Windows side. install.sh keeps its behaviour exactly: same APT_OPTIONS, same 120-second TIMEOUT, same three-attempt retry, and the comments explaining each of them travel with the code they explain. Two things are new: - TIMEOUT_LONG, 180 seconds, for a single large download. Sized against the 39 seconds each tarball took on 10 Sep 2026 and deliberately not larger: the install step is capped at ten minutes, and a per-attempt timeout able to swallow that cap would leave the retry loop no turn to take, which is the failure mode the apt comment already records. - fetch(), which verifies a SHA-256 before anything is unpacked. Both digests were taken from the releases API and then checked against the bytes the CDN actually serves. This is not an independent trust root -- expected value and file come from the same host -- but it pins the bytes, so a deleted and re-pushed tag or a replaced asset stops the build instead of being picked up silently. Also verifies qemu-system-riscv32 alongside riscv64. run.sh selects one per architecture, so both are worth failing on here rather than at the first test. Verified locally: retry returns 0 on success and 1 after three attempts; fetch accepts a correct digest and, on a wrong one, fails and removes the partial file; the source line resolves from the repository root, from an absolute path and through a symlink; and both recorded digests match the bytes served for the pinned tag. Assisted-by: Claude Code (Opus 5) --- scripts/install.sh | 53 +++--------------- scripts/install_riscv.sh | 43 +++++++++++++-- scripts/tx_ci_common.sh | 113 +++++++++++++++++++++++++++++++++++++++ 3 files changed, 158 insertions(+), 51 deletions(-) create mode 100644 scripts/tx_ci_common.sh diff --git a/scripts/install.sh b/scripts/install.sh index 84279c4e4..cb80c8993 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -16,53 +16,12 @@ # Remove large folder to save space rm -rf /opt/hostedtoolcache -# Everything below reaches the network, and on this runner pool that is not -# dependable. apt-get update stalled seven times in a single day, once for more -# than two hours, each time with the Azure mirror returning nothing and the -# fallback to archive.ubuntu.com then going silent. Nothing here bounded a fetch -# and nothing retried one, so a mirror being down cost a whole run rather than a -# few seconds. Worse, this script has no set -e, so a failed update did not stop -# the install that follows: it went on to install from whatever index it already -# had, and the run failed later somewhere less obvious. -# -# Each command is wrapped in timeout rather than left to bound itself. apt's own -# Acquire timeouts were tried first and did not help: a run still sat inside a -# single apt-get update for nine and a half minutes without producing a line, -# having got as far as fetching noble-security InRelease, so the retry loop never -# got a turn and the step timeout was what eventually killed it. Whatever apt is -# waiting on there, it is not something Acquire::http::Timeout covers. timeout -# does not care where the wait is. -# -# The Acquire options are kept anyway, since they make a slow mirror give up -# sooner. The loop covers a mirror that is down rather than merely slow. The -# explicit exits stop a failed fetch from being carried forward into a build, -# with one deliberate exception noted at the update below. -APT_OPTIONS=(-o Acquire::Retries=3 - -o Acquire::http::Timeout=20 - -o Acquire::https::Timeout=20) - -# Two minutes per attempt, killed outright if it ignores the first signal. Three -# attempts plus backoff bounds a command at about six and a half minutes, and a -# command that exhausts its attempts exits rather than letting the next one run. -# -# timeout goes under sudo, not over it, so that it signals apt itself. Signalling -# sudo instead risks the kill landing on sudo while apt carries on holding the -# dpkg lock, which would leave every retry failing for a different reason than -# the one being retried. -TIMEOUT=(timeout --kill-after=10 120) - -retry() { - local attempt - for attempt in 1 2 3; do - if "$@"; then - return 0 - fi - echo "install.sh: '$*' failed or timed out on attempt ${attempt}" - sleep $((attempt * 10)) - done - echo "install.sh: '$*' failed after 3 attempts" - return 1 -} +# The network helpers -- retry, TIMEOUT, TIMEOUT_LONG and APT_OPTIONS -- live in +# tx_ci_common.sh, alongside the comments recording why each of them is shaped +# the way it is. They were defined here until the RISC-V suite was enabled in +# CI, which put a second install script on every pull request's critical path +# with none of them. +. "$(dirname "$(realpath "$0")")/tx_ci_common.sh" # THE UPDATE IS NOT THE GATE, AND IT MUST NOT BE. apt-get update fails if ANY # configured repository serves a bad index, including ones this project does diff --git a/scripts/install_riscv.sh b/scripts/install_riscv.sh index 41642e704..428476258 100755 --- a/scripts/install_riscv.sh +++ b/scripts/install_riscv.sh @@ -13,23 +13,55 @@ # Install RISC-V bare-metal cross-compiler toolchain and QEMU for CI. set -e +# retry, TIMEOUT, TIMEOUT_LONG, APT_OPTIONS and fetch. Shared with install.sh, +# which is where they were written and where the reasons for their shape are +# recorded. +. "$(dirname "$(realpath "$0")")/tx_ci_common.sh" + +# The release tag is pinned so that what CI compiles with is answerable from the +# repository, and the digests pin the bytes behind the tag. A tag can be deleted +# and re-pushed and a release asset can be replaced; either would be picked up +# silently without these. Both digests were taken from the releases API and then +# checked against the bytes the CDN actually serves, 10 Sep 2026. Moving the tag +# means refreshing all three lines together. RELEASE_TAG="2026.04.26" BASE_URL="https://github.com/riscv-collab/riscv-gnu-toolchain/releases/download/${RELEASE_TAG}" # Use ubuntu-24.04 binaries to match ubuntu-latest runners. RV32_TARBALL="riscv32-elf-ubuntu-24.04-gcc.tar.xz" +RV32_SHA256="73c9a5adbb38b779312e5b3fc10d624484364ef1f870314571ae92c486ba9917" RV64_TARBALL="riscv64-elf-ubuntu-24.04-gcc.tar.xz" +RV64_SHA256="4a66a329653c9cfb869b826cae6d70c603bedcc1e13d419d3e3e92b99e0816b1" echo "=== Installing QEMU and build tools ===" -sudo apt-get update -qq -sudo apt-get install -y -qq qemu-system-misc ninja-build cmake + +# The update warns rather than gates, for the reason install.sh sets out at +# length: apt-get update fails if ANY configured repository serves a bad index, +# including the third-party ones the runner image carries and this project does +# not use. The install below is the gate, and it still fails hard on a package +# it cannot get. Under set -e a bare update would have ended the job -- and with +# the RISC-V suite running on every pull request, ended it for everybody. +if ! retry sudo "${TIMEOUT[@]}" apt-get "${APT_OPTIONS[@]}" update; then + echo "" + echo "install_riscv.sh: apt-get update did not fully succeed." + echo "install_riscv.sh: continuing, because a repository this project does" + echo "install_riscv.sh: not use can fail an update. The install below is" + echo "install_riscv.sh: the real gate." + echo "" +fi +retry sudo "${TIMEOUT[@]}" apt-get "${APT_OPTIONS[@]}" install -y \ + qemu-system-misc \ + ninja-build \ + cmake || exit 1 echo "=== Downloading RISC-V GCC toolchain (${RELEASE_TAG}) ===" # Both tarballs extract into riscv/ with non-overlapping prefixes # (riscv32-unknown-elf-* and riscv64-unknown-elf-*). -for tarball in "$RV32_TARBALL" "$RV64_TARBALL"; do +for spec in "${RV32_TARBALL}:${RV32_SHA256}" "${RV64_TARBALL}:${RV64_SHA256}"; do + tarball="${spec%%:*}" + sha256="${spec##*:}" echo "Downloading ${tarball} ..." - wget --no-verbose "${BASE_URL}/${tarball}" -O "/tmp/${tarball}" + fetch "${BASE_URL}/${tarball}" "/tmp/${tarball}" "${sha256}" || exit 1 sudo tar xJf "/tmp/${tarball}" -C /opt rm "/tmp/${tarball}" done @@ -40,4 +72,7 @@ echo "$TOOLCHAIN_BIN" >> "$GITHUB_PATH" echo "=== Verifying installation ===" "$TOOLCHAIN_BIN/riscv32-unknown-elf-gcc" --version | head -1 "$TOOLCHAIN_BIN/riscv64-unknown-elf-gcc" --version | head -1 +# Both QEMU system emulators are used -- run.sh selects one per architecture -- +# so both are worth failing on here rather than at the first test. +qemu-system-riscv32 --version | head -1 qemu-system-riscv64 --version | head -1 diff --git a/scripts/tx_ci_common.sh b/scripts/tx_ci_common.sh new file mode 100644 index 000000000..4aff48195 --- /dev/null +++ b/scripts/tx_ci_common.sh @@ -0,0 +1,113 @@ +############################################################################## +# 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. +# +# AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +# The AI-generated portions may be considered public domain (CC0-1.0) +# and not subject to the project's licence. The human contributor has +# reviewed and verified that the code is correct. +# +# SPDX-License-Identifier: MIT and CC0-1.0 +############################################################################## + +# Network helpers shared by the CI install scripts. Sourced, not executed -- +# there is no shebang, and nothing happens here beyond defining APT_OPTIONS, +# TIMEOUT, TIMEOUT_LONG, retry and fetch. +# +# They lived in install.sh until the RISC-V suite was enabled in CI, at which +# point a second install script was on every pull request's critical path with +# none of them. The lessons below were paid for once; a script that reaches the +# network in this project should not have to learn them again. +# +# The two callers differ in one way worth knowing: install_riscv.sh runs under +# set -e and install.sh does not. That is why install.sh spells out `|| exit 1` +# on the calls that must stop it -- without that, a failed fetch there would be +# carried forward into a build that then failed somewhere less obvious. + +# Everything the install scripts do reaches the network, and on this runner pool +# that is not dependable. apt-get update stalled seven times in a single day, +# once for more than two hours, each time with the Azure mirror returning +# nothing and the fallback to archive.ubuntu.com then going silent. Nothing +# bounded a fetch and nothing retried one, so a mirror being down cost a whole +# run rather than a few seconds. +# +# The Acquire options make a slow mirror give up sooner. The retry loop below +# covers a mirror that is down rather than merely slow. +APT_OPTIONS=(-o Acquire::Retries=3 + -o Acquire::http::Timeout=20 + -o Acquire::https::Timeout=20) + +# Two minutes per attempt, killed outright if it ignores the first signal. Three +# attempts plus backoff bounds a command at about six and a half minutes. +# +# Each command is wrapped in timeout rather than left to bound itself. apt's own +# Acquire timeouts were tried first and did not help: a run still sat inside a +# single apt-get update for nine and a half minutes without producing a line, +# having got as far as fetching noble-security InRelease, so the retry loop never +# got a turn and the step timeout was what eventually killed it. Whatever apt is +# waiting on there, it is not something Acquire::http::Timeout covers. timeout +# does not care where the wait is. +# +# timeout goes under sudo, not over it, so that it signals apt itself. Signalling +# sudo instead risks the kill landing on sudo while apt carries on holding the +# dpkg lock, which would leave every retry failing for a different reason than +# the one being retried. +TIMEOUT=(timeout --kill-after=10 120) + +# Three minutes, for a single large download rather than a package operation. +# The two RISC-V toolchain tarballs are about 500 MB each and took 39 seconds +# apiece on 10 Sep 2026, so this is a margin of roughly four and a half. +# +# It is deliberately not larger. The install step in regression_template.yml is +# capped at ten minutes, and a per-attempt timeout long enough to swallow that +# cap would leave the retry loop below with no turn to take -- which is the +# exact failure the TIMEOUT comment above records apt producing. Three attempts +# at three minutes plus backoff still does not fit inside ten, so the step +# timeout remains the outer backstop for a server that is genuinely down; what +# the retries buy is recovery from the transient case, which is the common one, +# and a log that says which attempt failed rather than a bare cancelled step. +TIMEOUT_LONG=(timeout --kill-after=10 180) + +retry() { + local attempt + for attempt in 1 2 3; do + if "$@"; then + return 0 + fi + echo "tx_ci_common: '$*' failed or timed out on attempt ${attempt}" + sleep $((attempt * 10)) + done + echo "tx_ci_common: '$*' failed after 3 attempts" + return 1 +} + +# fetch +# +# Downloads with retries and verifies the digest before the caller is allowed to +# unpack anything. --tries=1 hands retrying to the loop above rather than letting +# wget retry inside a single timeout window and burn it. +# +# The digest is not an independent trust root: it is checked against bytes from +# the same host that publishes the expected value, so it does not prove the +# release was not tampered with at source. What it does buy is that the bytes +# are pinned. A tag can be deleted and re-pushed and an asset can be replaced, +# and today either would be picked up silently; with this, the build stops and +# says which file failed and what it got. +fetch() { + local url=$1 + local dest=$2 + local sha=$3 + + retry "${TIMEOUT_LONG[@]}" wget --no-verbose --tries=1 "$url" -O "$dest" || return 1 + + if ! echo "${sha} ${dest}" | sha256sum --check --status; then + echo "tx_ci_common: checksum mismatch for ${url}" >&2 + echo "tx_ci_common: expected ${sha}" >&2 + echo "tx_ci_common: actual $(sha256sum "$dest" | cut -d' ' -f1)" >&2 + rm -f "$dest" + return 1 + fi +} From d56f96f37f7242df00bc714e6e7ea54285beafb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Thu, 10 Sep 2026 09:31:58 -0400 Subject: [PATCH 128/181] Refreshed the reason gcc_check leaves RISC-V out (#722) The header explained the exclusion by saying RISC-V "is not regressing" and that adding it would widen the toolchain download. The second half is still true; the first read as though nothing in CI exercised the family at all, which stopped being the case with #717. RISC-V is now the best-covered of the four excluded families rather than the least: regression_test.yml builds both ports and runs 955 tests on them under QEMU -- 475 on RV32 and 480 on RV64, across five build configurations each -- which is more than a compile-and-link check could establish. That is a stronger argument for leaving it out of this workflow than the original, so the sentence now makes it. The download figure is kept and quantified: the two bare-metal toolchains this workflow would have to fetch are about 500 MB apiece. Comment only; no behaviour change. scripts/check_gcc.sh names the same four families but states the exclusion without giving a reason for it, so it needs no matching edit. Assisted-by: Claude Code (Opus 5) --- .github/workflows/gcc_check.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/gcc_check.yml b/.github/workflows/gcc_check.yml index 3eda52fa2..cd340a0e9 100644 --- a/.github/workflows/gcc_check.yml +++ b/.github/workflows/gcc_check.yml @@ -21,8 +21,11 @@ name: gcc_check # # What it does not cover: it compiles and links and **executes nothing**. The # Cortex-R52 FVP ctest suite is not part of it. RISC-V, MIPS, RX and ARC are -# outside it entirely -- RISC-V deliberately, as both its ports do assemble and -# adding them widens the toolchain download for a family that is not regressing. +# outside it entirely -- RISC-V deliberately, and now for a stronger reason +# than when this was written: regression_test.yml builds both its ports and +# runs 955 tests on them under QEMU, which is more than a compile check could +# say. Adding them here would widen this workflow's toolchain download by about +# a gigabyte to re-prove a subset of that. # # It does not supersede cortex_m. That workflow builds four ports *through # CMake*, which is the only thing exercising cmake/cortex_m*.cmake and the From 9ee198a2d67698e6c7db4cbe47374add909766d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Thu, 10 Sep 2026 11:02:42 -0400 Subject: [PATCH 129/181] Made the stack analyze binary search require several consecutive fill words, so unwritten holes in a used stack no longer cause the highest stack pointer to be under-reported (#720) The binary search in _tx_thread_stack_analyze() accepted a probe location as unused as soon as a single word still held TX_STACK_FILL. A word inside an otherwise used region that simply was never written - the padding of a partially initialized local array, for example - therefore made the search move away from the real boundary and report far less stack usage than the thread had actually consumed, which in turn kept the stack guard from firing. The probe now walks down from the candidate location and requires TX_THREAD_STACK_ANALYZE_FILL_WORDS consecutive fill words before it treats the location as unused, stopping early at the lowest location already known to hold the fill pattern. The new macro defaults to eight words and can be overridden in tx_port.h; setting it to one restores the previous behavior. Holes shorter than the configured run no longer mislead the search, and the result is unchanged for stacks that contain no such holes. Assisted-by: Copilot (Opus 5) --- common/inc/tx_api.h | 13 ++++++ common/src/tx_thread_stack_analyze.c | 50 +++++++++++++++++++++++- common_smp/inc/tx_api.h | 13 ++++++ common_smp/src/tx_thread_stack_analyze.c | 50 +++++++++++++++++++++++- 4 files changed, 122 insertions(+), 4 deletions(-) diff --git a/common/inc/tx_api.h b/common/inc/tx_api.h index 321e70a9b..bf9de8565 100644 --- a/common/inc/tx_api.h +++ b/common/inc/tx_api.h @@ -1843,6 +1843,19 @@ UINT _tx_trace_interrupt_control(UINT new_posture); #endif +/* Define the number of consecutive stack fill pattern words the thread stack analyze function must + observe, working towards the lowest address of the stack, before it accepts a probe location as + unused. A value of one restores the original behavior, where a single word that happens to still + hold the fill pattern - an unwritten hole inside an otherwise used region, such as the padding of + a partially initialized local array - can make the binary search stop early and under-report the + stack usage. Larger values make the result more accurate at the cost of a few additional reads + per binary search iteration. This can be re-defined in tx_port.h. */ + +#ifndef TX_THREAD_STACK_ANALYZE_FILL_WORDS +#define TX_THREAD_STACK_ANALYZE_FILL_WORDS ((ULONG) 8) +#endif + + /* Add a default macro that can be re-defined in tx_port.h to add processing to the initialize kernel enter function. By default, this is simply defined as whitespace. */ diff --git a/common/src/tx_thread_stack_analyze.c b/common/src/tx_thread_stack_analyze.c index 080d00522..e3023f13d 100644 --- a/common/src/tx_thread_stack_analyze.c +++ b/common/src/tx_thread_stack_analyze.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -70,6 +72,9 @@ TX_INTERRUPT_SAVE_AREA ULONG *stack_ptr; ULONG *stack_lowest; ULONG *stack_highest; +ULONG *probe_ptr; +ULONG probe_count; +UINT fill_present; ULONG size; @@ -110,8 +115,49 @@ ULONG size; size = (ULONG) (TX_ULONG_POINTER_DIF(stack_highest, stack_lowest))/((ULONG) 2); stack_ptr = TX_ULONG_POINTER_ADD(stack_lowest, size); - /* Determine if the pattern is still there. */ - if (*stack_ptr != TX_STACK_FILL) + /* Determine if the pattern is still there. To avoid stopping on an + unwritten hole inside an otherwise used region, require several + consecutive fill words, working towards the lowest address. The scan + stops at the lowest known fill location, since everything at or below + that point is already known to hold the fill pattern. */ + fill_present = TX_TRUE; + probe_ptr = stack_ptr; + probe_count = TX_THREAD_STACK_ANALYZE_FILL_WORDS; + while (probe_count != ((ULONG) 0)) + { + + /* Determine if this word still holds the fill pattern. */ + if (*probe_ptr != TX_STACK_FILL) + { + + /* No, the probe location is in use. */ + fill_present = TX_FALSE; + probe_count = ((ULONG) 0); + } + else + { + + /* Yes, account for this word. */ + probe_count--; + + /* Determine if the lowest known fill location has been reached. */ + if (probe_ptr <= stack_lowest) + { + + /* Yes, nothing further to check. */ + probe_count = ((ULONG) 0); + } + else + { + + /* Position to the previous word in the stack. */ + probe_ptr = TX_ULONG_POINTER_SUB(probe_ptr, 1); + } + } + } + + /* Determine if the probe location is in use. */ + if (fill_present == TX_FALSE) { /* Update the stack highest, since we need to look in the upper half now. */ diff --git a/common_smp/inc/tx_api.h b/common_smp/inc/tx_api.h index 7d0ccbe54..679bfe679 100644 --- a/common_smp/inc/tx_api.h +++ b/common_smp/inc/tx_api.h @@ -1853,6 +1853,19 @@ UINT _tx_trace_interrupt_control(UINT new_posture); #endif +/* Define the number of consecutive stack fill pattern words the thread stack analyze function must + observe, working towards the lowest address of the stack, before it accepts a probe location as + unused. A value of one restores the original behavior, where a single word that happens to still + hold the fill pattern - an unwritten hole inside an otherwise used region, such as the padding of + a partially initialized local array - can make the binary search stop early and under-report the + stack usage. Larger values make the result more accurate at the cost of a few additional reads + per binary search iteration. This can be re-defined in tx_port.h. */ + +#ifndef TX_THREAD_STACK_ANALYZE_FILL_WORDS +#define TX_THREAD_STACK_ANALYZE_FILL_WORDS ((ULONG) 8) +#endif + + /* Add a default macro that can be re-defined in tx_port.h to add processing to the initialize kernel enter function. By default, this is simply defined as whitespace. */ diff --git a/common_smp/src/tx_thread_stack_analyze.c b/common_smp/src/tx_thread_stack_analyze.c index 080d00522..e3023f13d 100644 --- a/common_smp/src/tx_thread_stack_analyze.c +++ b/common_smp/src/tx_thread_stack_analyze.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -70,6 +72,9 @@ TX_INTERRUPT_SAVE_AREA ULONG *stack_ptr; ULONG *stack_lowest; ULONG *stack_highest; +ULONG *probe_ptr; +ULONG probe_count; +UINT fill_present; ULONG size; @@ -110,8 +115,49 @@ ULONG size; size = (ULONG) (TX_ULONG_POINTER_DIF(stack_highest, stack_lowest))/((ULONG) 2); stack_ptr = TX_ULONG_POINTER_ADD(stack_lowest, size); - /* Determine if the pattern is still there. */ - if (*stack_ptr != TX_STACK_FILL) + /* Determine if the pattern is still there. To avoid stopping on an + unwritten hole inside an otherwise used region, require several + consecutive fill words, working towards the lowest address. The scan + stops at the lowest known fill location, since everything at or below + that point is already known to hold the fill pattern. */ + fill_present = TX_TRUE; + probe_ptr = stack_ptr; + probe_count = TX_THREAD_STACK_ANALYZE_FILL_WORDS; + while (probe_count != ((ULONG) 0)) + { + + /* Determine if this word still holds the fill pattern. */ + if (*probe_ptr != TX_STACK_FILL) + { + + /* No, the probe location is in use. */ + fill_present = TX_FALSE; + probe_count = ((ULONG) 0); + } + else + { + + /* Yes, account for this word. */ + probe_count--; + + /* Determine if the lowest known fill location has been reached. */ + if (probe_ptr <= stack_lowest) + { + + /* Yes, nothing further to check. */ + probe_count = ((ULONG) 0); + } + else + { + + /* Position to the previous word in the stack. */ + probe_ptr = TX_ULONG_POINTER_SUB(probe_ptr, 1); + } + } + } + + /* Determine if the probe location is in use. */ + if (fill_present == TX_FALSE) { /* Update the stack highest, since we need to look in the upper half now. */ From 70741198e9f6831acf52257913d1bb9c7a5a2720 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Thu, 10 Sep 2026 12:04:40 -0400 Subject: [PATCH 130/181] Refused thread delete and reset while an exit transition is in progress (#724) _tx_thread_shell_entry and _tx_thread_terminate both publish a thread's terminal state -- TX_COMPLETED or TX_TERMINATED -- and then call that thread's exit notification callback, before the thread has been detached from the ready list and before either service has finished with the pointer it holds to the control block. That terminal state is exactly the state _tx_thread_delete and _tx_thread_reset accept as authorization to invalidate or rebuild the control block, and neither service tested whether the transition producing it had finished. A callback could therefore delete the thread it was called for -- and then lawfully recreate it over the same memory, since delete exists to permit that -- while the scheduler was still linked to the old incarnation. tx_thread_create zeroes the whole control block and can auto-start the new one, so the old priority list is left heading at a block whose own priority field names a different list, with the old priority's map bit set behind nothing. Alternatively a callback could reset a terminated thread, which moves it out of the terminal state, and then resume it: the interrupted- suspension logic in _tx_thread_system_resume refuses to void a suspension only while the state is still terminal, so with the reset allowed first the resume clears the suspending flag and restores TX_READY, the outer service then finds the flag clear and skips the removal, and tx_thread_terminate returns TX_SUCCESS for a thread that is runnable again. Interrupt masking does not close the window, because the kernel restores the prior posture before invoking the callback deliberately. On SMP TX_RESTORE also releases the global protection, so the target can be executing on another core while its callback runs -- and a reset there memsets the stack a live core is running on. On the Linux, Win32 and Win64 host simulation ports the consequence is more immediate than corruption: TX_THREAD_DELETE_PORT_COMPLETION cancels and joins the host thread backing the deleted thread, so a callback-side delete of the completing thread destroys the host thread the callback is running on. The fix marks the transition and has the two services refuse a marked target, returning the errors they already document, TX_DELETE_ERROR and TX_NOT_DONE. The refusal is transient and the same call succeeds once the transition has completed, so no documented lifecycle is lost; and it is in the core services rather than the _txe_ wrappers, so disabling error checking cannot disable it. Refusing the reset is also what closes the resume path, without touching _tx_thread_system_resume: its existing terminal-state test is sufficient once nothing can turn the terminal state into TX_SUSPENDED from inside the window. tx_thread_suspending is the marker, rather than a new control-block field. It already means "a suspension is in progress" and is already true across the callback in the two interruptable paths, so no field is added, the public structure is unchanged, and sizeof(TX_THREAD) is unchanged -- which matters, because the Module Manager's object handling depends on the sizes of the control blocks. Widening its lifetime was checked against every reader rather than assumed. There are four: two in _tx_thread_system_suspend and two in _tx_thread_system_resume. In every window this change widens, the state is TX_COMPLETED or TX_TERMINATED, and both resume readers already refuse to void a suspension for exactly those two states, so their behaviour is unchanged; and no suspension routine is called on the target in those windows, so the suspend readers never see them. No suspension-initiating service can set the marker again inside a window either: every one of them acts on a thread that is ready or suspended. Three sites needed changing beyond the two refusals, and the shape of each was decided by where the marker can safely be cleared: - The non-ready branch of _tx_thread_terminate cleared the marker before the terminated extension and the callback, which is what left them free to act on a control block the service still had mutex-release processing to do against. The clear moves to the common tail, after the last dereference of the target, and becomes the single clear site for the whole service. In the interruptable ready branch the flag is already false there, because _tx_thread_system_suspend cleared it when it detached the thread, so the tail store is a second store of a value the flag already holds -- cheaper than testing for it, and it keeps one clear site. - Under TX_NOT_INTERRUPTABLE neither path set the marker at all, because that configuration does not use the interruptable suspension path that sets it. Both now set it before the callback. Interrupts being disabled there does not help: the callback is reached by a direct call. - In the TX_NOT_INTERRUPTABLE completion path the marker is cleared before _tx_thread_system_ni_suspend rather than after it. That call returns to the scheduler for a thread that is the current thread, which a completing thread is, and does not come back; clearing afterwards would leave a normally completed thread marked for ever and therefore permanently undeletable. Nothing is lost by clearing early there, because everything from that point to the detachment runs with interrupts disabled and calls no application code. The change is the same change twice. All four files are byte-for-byte identical between common and common_smp at this commit and stay so after it, so common_smp was written by copying rather than by repeating the edits. tx_thread_system_suspend.c and tx_thread_system_resume.c, which do differ between the kernels, are deliberately untouched. Tests. The in-tree regression test goes to both trees and is byte-for-byte identical between them. It drives seven scenarios: terminating a ready non-current target with two peers ready at the same priority, with the callback attempting the delete and recreating the block if it succeeded; the same with the callback attempting the reset and then the resume; terminating a target suspended on a semaphore while owning a mutex, which is the non-ready branch; natural completion alone at its priority, including the safe post-completion reset, terminate, delete and recreate at another priority; self termination; a benign callback, whose notification count and ordering are unchanged; and the state and boundary cases, where the new refusal must not fire. It measures rather than describes. The callback records the published state, the marker, and the status of every lifecycle service it can reach, calling the core service as well as the wrapper wherever a refusal is expected. A snapshot taken under interrupt lockout -- which is the global SMP protection on an SMP port -- checks that every ready list agrees with the control blocks it heads, that the priority map agrees with the lists, and that each execute pointer is a member of the list its own priority field names. Every walk is bounded, so a corrupted ring costs an assertion and not a hang, and no test in the suite can hang. Expectations are counted inside a scenario and gated between scenarios, so a failing kernel reports how much it failed by without being driven further into its own corruption. The consequences are demonstrated from the terminator's context rather than the completing thread's, which is what makes the pre-fix behaviour an assertion instead of a wedged simulator. Compiled against the unfixed sources the test fails 9 of the 24 expectations it reaches in the uniprocessor tree and 10 of 24 in the SMP tree, and the failures are the finding: the callback-side delete succeeds, the recreate succeeds, the consistency snapshot disagrees, the target is neither terminal nor detached when the service returns, and a peer has left the ready ring the recreated block hijacked. The SMP tree gets a second test for the case that needs concurrency. The victim is excluded to core 1 and spins there without relinquishing while the controller, excluded to core 0, terminates it, so the callback runs on one core while the target executes on another. The callback-side reset and delete must both be refused, and a sentinel written into the unused low end of the victim's stack must survive -- a reset would have memset the whole stack before rebuilding the frame. Every wait is bounded, and if the remote precondition cannot be established the test says so and drops only the assertions that depend on it rather than reporting a pass it did not earn; measured over twenty consecutive runs it established the precondition every time. TX_NOT_INTERRUPTABLE and TX_DISABLE_ERROR_CHECKING are not among the five build configurations either tree compiles, and each tree builds the whole library once per configuration, so neither can be reached from inside the suites. The lines this change adds under TX_NOT_INTERRUPTABLE are therefore in no configuration the trees build, and they are where the permanent- undeletability failure mode lives, so they get their own harness rather than a compile check: the four sources plus the two error wrappers are compiled directly into a test executable, once per combination, with recorders standing behind the scheduler services they call. That is what makes the marker's value at the moment of detachment directly observable. It runs 66 expectations under TX_NOT_INTERRUPTABLE, 66 under that with error checking disabled, 45 under that with notification disabled, and 63 under error checking disabled alone; against the unfixed sources those fail 25, 22, 6 and 20 respectively. The harness lives in the uniprocessor tree only, because the four sources are identical between the kernels and the shim replaces the very primitive the SMP port differs in, so a second copy would compile the same text under the same macros. It is deliberately left out of the coverage instrumentation, since the same source under different feature macros has a different line set and merging those would confuse the union rather than add to it. Results. Both suites pass in all five configurations with GCC 14: 103 of 103 in the uniprocessor tree, up from 98, and 116 of 116 in the SMP tree, up from 114. Merged line coverage is 100% in the uniprocessor tree and 5172 of 5183 in the SMP tree, whose eleven uncovered lines are the same eleven that were uncovered before this change and are in tx_byte_pool_search and tx_thread_smp_utilities; all four changed files are at 100% line coverage in both trees, and SMP branch coverage rises from 2819 of 3548 to 2831 of 3556. Cross-compiled with arm-none-eabi-gcc at -Wall -Wextra for Cortex-M4 against common and for Cortex-A7 SMP against common_smp, all four files produce no diagnostics at all and an identical warning set to before the change, under -std=gnu99 and -std=c99 alike -- unlike the module ports, -std=c99 does not fail on these base ports, and even -Wconversion is clean. No MISRA deviation is required: explicit comparisons to TX_TRUE, existing ThreadX types, single-entry and single-exit control flow, no goto, and two added constant-time tests that change no real-time complexity. Assisted-by: Claude Code (Opus 5) --- common/src/tx_thread_delete.c | 27 + common/src/tx_thread_reset.c | 24 + common/src/tx_thread_shell_entry.c | 22 + common/src/tx_thread_terminate.c | 47 +- common_smp/src/tx_thread_delete.c | 27 + common_smp/src/tx_thread_reset.c | 24 + common_smp/src/tx_thread_shell_entry.c | 22 + common_smp/src/tx_thread_terminate.c | 47 +- test/smp/cmake/regression/CMakeLists.txt | 2 + test/smp/regression/testcontrol.c | 4 + ...adx_smp_thread_exit_callback_remote_test.c | 514 ++++++ ...adx_thread_exit_callback_transition_test.c | 1375 +++++++++++++++++ test/tx/cmake/CMakeLists.txt | 9 + test/tx/cmake/regression/CMakeLists.txt | 1 + .../tx/cmake/thread_transition/CMakeLists.txt | 115 ++ test/tx/regression/testcontrol.c | 2 + ...adx_thread_exit_callback_transition_test.c | 1375 +++++++++++++++++ ...adx_thread_transition_configuration_test.c | 607 ++++++++ ...threadx_thread_transition_host_test_port.h | 120 ++ 19 files changed, 4336 insertions(+), 28 deletions(-) create mode 100644 test/smp/regression/threadx_smp_thread_exit_callback_remote_test.c create mode 100644 test/smp/regression/threadx_thread_exit_callback_transition_test.c create mode 100644 test/tx/cmake/thread_transition/CMakeLists.txt create mode 100644 test/tx/regression/threadx_thread_exit_callback_transition_test.c create mode 100644 test/tx/thread_transition/threadx_thread_transition_configuration_test.c create mode 100644 test/tx/thread_transition/threadx_thread_transition_host_test_port.h diff --git a/common/src/tx_thread_delete.c b/common/src/tx_thread_delete.c index 510f6565e..e73fdd319 100644 --- a/common/src/tx_thread_delete.c +++ b/common/src/tx_thread_delete.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Claude Code (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -95,6 +97,31 @@ UINT status; } } + /* The state is terminal, but a terminal state on its own is not authorization to + release the control block. Both paths that produce one -- thread completion in + _tx_thread_shell_entry and thread termination in _tx_thread_terminate -- publish + TX_COMPLETED or TX_TERMINATED, and then run this thread's exit notification + callback, before the thread has been detached from the ready list and before + those services have finished with the pointer they hold to it. The suspending + flag is set for exactly that interval, so a thread whose flag is still set is + part-way through the transition. */ + if (status == TX_SUCCESS) + { + + /* Is the completion or termination transition still in progress? */ + if (thread_ptr -> tx_thread_suspending == TX_TRUE) + { + + /* Restore interrupts. */ + TX_RESTORE + + /* Yes, refuse the delete rather than unlink a thread the scheduler is + still holding. The condition is transient: the caller may retry once + the transition has finished. */ + status = TX_DELETE_ERROR; + } + } + /* Determine if the delete operation is okay. */ if (status == TX_SUCCESS) { diff --git a/common/src/tx_thread_reset.c b/common/src/tx_thread_reset.c index da56daf57..e87de26be 100644 --- a/common/src/tx_thread_reset.c +++ b/common/src/tx_thread_reset.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Claude Code (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -104,6 +106,28 @@ UINT status; status = TX_NOT_DONE; } } + + /* The state is terminal, but a terminal state on its own is not authorization + to rebuild the stack and move the thread back to TX_SUSPENDED. Both paths + that produce one -- thread completion in _tx_thread_shell_entry and thread + termination in _tx_thread_terminate -- publish TX_COMPLETED or + TX_TERMINATED, and then run this thread's exit notification callback, before + the thread has been detached from the ready list. The suspending flag is + set for exactly that interval. Resetting inside it would also defeat the + protection _tx_thread_system_resume relies on, which refuses to cancel a + suspension only while the state is still terminal. */ + if (status == TX_SUCCESS) + { + + /* Is the completion or termination transition still in progress? */ + if (thread_ptr -> tx_thread_suspending == TX_TRUE) + { + + /* Yes, refuse the reset. The condition is transient: the caller may + retry once the transition has finished. */ + status = TX_NOT_DONE; + } + } } /* Is the request valid? */ diff --git a/common/src/tx_thread_shell_entry.c b/common/src/tx_thread_shell_entry.c index 45fe9d6da..c079f18e1 100644 --- a/common/src/tx_thread_shell_entry.c +++ b/common/src/tx_thread_shell_entry.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Claude Code (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -134,6 +136,17 @@ VOID (*entry_exit_notify)(TX_THREAD *notify_thread_ptr, UINT type); #ifdef TX_NOT_INTERRUPTABLE + /* Set the suspending flag, so that the completion transition is marked as in + progress for the same interval it is marked in the interruptable + configuration below. Nothing in this configuration needs the flag to cancel + an interrupted suspension -- interrupts stay disabled through the whole + transition -- but the notification callback and the completion extension + below are application code, reached by a direct call, and interrupt lockout + does not stop either of them from calling a thread lifecycle service on this + same control block. The flag is what _tx_thread_delete and _tx_thread_reset + test in order to refuse one. */ + thread_ptr -> tx_thread_suspending = TX_TRUE; + #ifndef TX_DISABLE_NOTIFY_CALLBACKS /* Determine if an application callback routine is specified. */ @@ -148,6 +161,15 @@ VOID (*entry_exit_notify)(TX_THREAD *notify_thread_ptr, UINT type); /* Perform any additional activities for tool or user purpose. */ TX_THREAD_COMPLETED_EXTENSION(thread_ptr) + /* Clear the suspending flag. It has to be cleared here rather than after the + call below, because _tx_thread_system_ni_suspend returns to the scheduler for + a thread that is the current thread, which this one is, and so does not come + back. Clearing it afterwards would leave a normally completed thread marked + as transitioning for ever and therefore permanently undeletable. Clearing it + here loses nothing: everything from this point to the detachment runs with + interrupts disabled and calls no application code. */ + thread_ptr -> tx_thread_suspending = TX_FALSE; + /* Call actual non-interruptable thread suspension routine. */ _tx_thread_system_ni_suspend(thread_ptr, ((ULONG) 0)); diff --git a/common/src/tx_thread_terminate.c b/common/src/tx_thread_terminate.c index 86e34baeb..05ec91a1f 100644 --- a/common/src/tx_thread_terminate.c +++ b/common/src/tx_thread_terminate.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Claude Code (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -133,6 +135,16 @@ ULONG suspension_sequence; #ifdef TX_NOT_INTERRUPTABLE + /* Set the suspending flag, so that the termination transition is marked + as in progress for the same interval it is marked in the interruptable + configuration below. Nothing in this configuration needs the flag to + cancel an interrupted suspension -- interrupts stay disabled through + the whole transition -- but the notification callback below is + application code, reached by a direct call, and interrupt lockout does + not stop it from calling a thread lifecycle service on this same + control block. The flag is cleared in the common tail below. */ + thread_ptr -> tx_thread_suspending = TX_TRUE; + #ifndef TX_DISABLE_NOTIFY_CALLBACKS /* Determine if an application callback routine is specified. */ @@ -225,20 +237,13 @@ ULONG suspension_sequence; (suspend_cleanup)(thread_ptr, suspension_sequence); } -#ifndef TX_NOT_INTERRUPTABLE - - /* Disable interrupts. */ - TX_DISABLE -#endif - - /* Clear the suspending flag. */ - thread_ptr -> tx_thread_suspending = TX_FALSE; - -#ifndef TX_NOT_INTERRUPTABLE - - /* Restore interrupts. */ - TX_RESTORE -#endif + /* The suspending flag deliberately stays set here. It used to be + cleared at this point, which left the terminated extension and the + notification callback below -- both application code -- free to delete + or reset this control block while this service still held a pointer to + it and still had mutex-release processing to do. It is now cleared + once, in the common tail below, after the last dereference of the + target. */ /* Perform any additional activities for tool or user purpose. */ TX_THREAD_TERMINATED_EXTENSION(thread_ptr) @@ -282,6 +287,20 @@ ULONG suspension_sequence; TX_DISABLE #endif + /* Clear the suspending flag. This is the one place the end of the + termination transition is published, and it is reached from both branches + above, after the notification callback and after the mutex-release + processing, which is the last thing in this service to dereference the + target. Until this store, _tx_thread_delete and _tx_thread_reset refuse + the target. In the interruptable ready branch the flag is already false, + because _tx_thread_system_suspend cleared it when it detached the thread, + so this is a second store of a value the flag already holds; that is + cheaper than testing for it and it keeps the transition to a single clear + site. No suspension-initiating service can have set it again in between: + every one of them acts on a thread that is ready or suspended, and this + thread is terminated. */ + thread_ptr -> tx_thread_suspending = TX_FALSE; + /* Enable preemption. */ _tx_thread_preempt_disable--; diff --git a/common_smp/src/tx_thread_delete.c b/common_smp/src/tx_thread_delete.c index 510f6565e..e73fdd319 100644 --- a/common_smp/src/tx_thread_delete.c +++ b/common_smp/src/tx_thread_delete.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Claude Code (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -95,6 +97,31 @@ UINT status; } } + /* The state is terminal, but a terminal state on its own is not authorization to + release the control block. Both paths that produce one -- thread completion in + _tx_thread_shell_entry and thread termination in _tx_thread_terminate -- publish + TX_COMPLETED or TX_TERMINATED, and then run this thread's exit notification + callback, before the thread has been detached from the ready list and before + those services have finished with the pointer they hold to it. The suspending + flag is set for exactly that interval, so a thread whose flag is still set is + part-way through the transition. */ + if (status == TX_SUCCESS) + { + + /* Is the completion or termination transition still in progress? */ + if (thread_ptr -> tx_thread_suspending == TX_TRUE) + { + + /* Restore interrupts. */ + TX_RESTORE + + /* Yes, refuse the delete rather than unlink a thread the scheduler is + still holding. The condition is transient: the caller may retry once + the transition has finished. */ + status = TX_DELETE_ERROR; + } + } + /* Determine if the delete operation is okay. */ if (status == TX_SUCCESS) { diff --git a/common_smp/src/tx_thread_reset.c b/common_smp/src/tx_thread_reset.c index da56daf57..e87de26be 100644 --- a/common_smp/src/tx_thread_reset.c +++ b/common_smp/src/tx_thread_reset.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Claude Code (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -104,6 +106,28 @@ UINT status; status = TX_NOT_DONE; } } + + /* The state is terminal, but a terminal state on its own is not authorization + to rebuild the stack and move the thread back to TX_SUSPENDED. Both paths + that produce one -- thread completion in _tx_thread_shell_entry and thread + termination in _tx_thread_terminate -- publish TX_COMPLETED or + TX_TERMINATED, and then run this thread's exit notification callback, before + the thread has been detached from the ready list. The suspending flag is + set for exactly that interval. Resetting inside it would also defeat the + protection _tx_thread_system_resume relies on, which refuses to cancel a + suspension only while the state is still terminal. */ + if (status == TX_SUCCESS) + { + + /* Is the completion or termination transition still in progress? */ + if (thread_ptr -> tx_thread_suspending == TX_TRUE) + { + + /* Yes, refuse the reset. The condition is transient: the caller may + retry once the transition has finished. */ + status = TX_NOT_DONE; + } + } } /* Is the request valid? */ diff --git a/common_smp/src/tx_thread_shell_entry.c b/common_smp/src/tx_thread_shell_entry.c index 45fe9d6da..c079f18e1 100644 --- a/common_smp/src/tx_thread_shell_entry.c +++ b/common_smp/src/tx_thread_shell_entry.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Claude Code (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -134,6 +136,17 @@ VOID (*entry_exit_notify)(TX_THREAD *notify_thread_ptr, UINT type); #ifdef TX_NOT_INTERRUPTABLE + /* Set the suspending flag, so that the completion transition is marked as in + progress for the same interval it is marked in the interruptable + configuration below. Nothing in this configuration needs the flag to cancel + an interrupted suspension -- interrupts stay disabled through the whole + transition -- but the notification callback and the completion extension + below are application code, reached by a direct call, and interrupt lockout + does not stop either of them from calling a thread lifecycle service on this + same control block. The flag is what _tx_thread_delete and _tx_thread_reset + test in order to refuse one. */ + thread_ptr -> tx_thread_suspending = TX_TRUE; + #ifndef TX_DISABLE_NOTIFY_CALLBACKS /* Determine if an application callback routine is specified. */ @@ -148,6 +161,15 @@ VOID (*entry_exit_notify)(TX_THREAD *notify_thread_ptr, UINT type); /* Perform any additional activities for tool or user purpose. */ TX_THREAD_COMPLETED_EXTENSION(thread_ptr) + /* Clear the suspending flag. It has to be cleared here rather than after the + call below, because _tx_thread_system_ni_suspend returns to the scheduler for + a thread that is the current thread, which this one is, and so does not come + back. Clearing it afterwards would leave a normally completed thread marked + as transitioning for ever and therefore permanently undeletable. Clearing it + here loses nothing: everything from this point to the detachment runs with + interrupts disabled and calls no application code. */ + thread_ptr -> tx_thread_suspending = TX_FALSE; + /* Call actual non-interruptable thread suspension routine. */ _tx_thread_system_ni_suspend(thread_ptr, ((ULONG) 0)); diff --git a/common_smp/src/tx_thread_terminate.c b/common_smp/src/tx_thread_terminate.c index 86e34baeb..05ec91a1f 100644 --- a/common_smp/src/tx_thread_terminate.c +++ b/common_smp/src/tx_thread_terminate.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Claude Code (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -133,6 +135,16 @@ ULONG suspension_sequence; #ifdef TX_NOT_INTERRUPTABLE + /* Set the suspending flag, so that the termination transition is marked + as in progress for the same interval it is marked in the interruptable + configuration below. Nothing in this configuration needs the flag to + cancel an interrupted suspension -- interrupts stay disabled through + the whole transition -- but the notification callback below is + application code, reached by a direct call, and interrupt lockout does + not stop it from calling a thread lifecycle service on this same + control block. The flag is cleared in the common tail below. */ + thread_ptr -> tx_thread_suspending = TX_TRUE; + #ifndef TX_DISABLE_NOTIFY_CALLBACKS /* Determine if an application callback routine is specified. */ @@ -225,20 +237,13 @@ ULONG suspension_sequence; (suspend_cleanup)(thread_ptr, suspension_sequence); } -#ifndef TX_NOT_INTERRUPTABLE - - /* Disable interrupts. */ - TX_DISABLE -#endif - - /* Clear the suspending flag. */ - thread_ptr -> tx_thread_suspending = TX_FALSE; - -#ifndef TX_NOT_INTERRUPTABLE - - /* Restore interrupts. */ - TX_RESTORE -#endif + /* The suspending flag deliberately stays set here. It used to be + cleared at this point, which left the terminated extension and the + notification callback below -- both application code -- free to delete + or reset this control block while this service still held a pointer to + it and still had mutex-release processing to do. It is now cleared + once, in the common tail below, after the last dereference of the + target. */ /* Perform any additional activities for tool or user purpose. */ TX_THREAD_TERMINATED_EXTENSION(thread_ptr) @@ -282,6 +287,20 @@ ULONG suspension_sequence; TX_DISABLE #endif + /* Clear the suspending flag. This is the one place the end of the + termination transition is published, and it is reached from both branches + above, after the notification callback and after the mutex-release + processing, which is the last thing in this service to dereference the + target. Until this store, _tx_thread_delete and _tx_thread_reset refuse + the target. In the interruptable ready branch the flag is already false, + because _tx_thread_system_suspend cleared it when it detached the thread, + so this is a second store of a value the flag already holds; that is + cheaper than testing for it and it keeps the transition to a single clear + site. No suspension-initiating service can have set it again in between: + every one of them acts on a thread that is ready or suspended, and this + thread is terminated. */ + thread_ptr -> tx_thread_suspending = TX_FALSE; + /* Enable preemption. */ _tx_thread_preempt_disable--; diff --git a/test/smp/cmake/regression/CMakeLists.txt b/test/smp/cmake/regression/CMakeLists.txt index af33ca3f0..dd1d48a30 100644 --- a/test/smp/cmake/regression/CMakeLists.txt +++ b/test/smp/cmake/regression/CMakeLists.txt @@ -115,6 +115,8 @@ set(regression_test_cases ${SOURCE_DIR}/threadx_thread_sleep_terminate_test.c ${SOURCE_DIR}/threadx_thread_stack_checking_test.c ${SOURCE_DIR}/threadx_thread_terminate_delete_test.c + ${SOURCE_DIR}/threadx_thread_exit_callback_transition_test.c + ${SOURCE_DIR}/threadx_smp_thread_exit_callback_remote_test.c ${SOURCE_DIR}/threadx_thread_time_slice_change_test.c ${SOURCE_DIR}/threadx_thread_wait_abort_and_isr_test.c ${SOURCE_DIR}/threadx_thread_wait_abort_test.c diff --git a/test/smp/regression/testcontrol.c b/test/smp/regression/testcontrol.c index c0ba34636..59d8e69a7 100644 --- a/test/smp/regression/testcontrol.c +++ b/test/smp/regression/testcontrol.c @@ -240,6 +240,8 @@ void threadx_thread_simple_sleep_non_clear_application_define(void *); void threadx_thread_sleep_for_100ticks_application_define(void *); void threadx_thread_multiple_sleep_application_define(void *); void threadx_thread_terminate_delete_application_define(void *); +void threadx_thread_exit_callback_transition_application_define(void *); +void threadx_smp_thread_exit_callback_remote_application_define(void *); void threadx_thread_preemption_change_application_define(void *); void threadx_thread_priority_change_application_define(void *); void threadx_thread_time_slice_change_application_define(void *); @@ -384,6 +386,8 @@ TEST_ENTRY test_control_tests[] = threadx_thread_sleep_for_100ticks_application_define, threadx_thread_multiple_sleep_application_define, threadx_thread_terminate_delete_application_define, + threadx_thread_exit_callback_transition_application_define, + threadx_smp_thread_exit_callback_remote_application_define, threadx_thread_priority_change_application_define, diff --git a/test/smp/regression/threadx_smp_thread_exit_callback_remote_test.c b/test/smp/regression/threadx_smp_thread_exit_callback_remote_test.c new file mode 100644 index 000000000..488c28226 --- /dev/null +++ b/test/smp/regression/threadx_smp_thread_exit_callback_remote_test.c @@ -0,0 +1,514 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/* Define the ThreadX SMP thread exit callback remote-core termination test. + + This is the SMP-specific half of the exit-callback transition coverage. The + deterministic cases are in threadx_thread_exit_callback_transition_test, + which confines every thread it drives to core 0 precisely so that they + cannot be made flaky by concurrency; this test supplies the case that needs + it. + + The victim is excluded from every core but core 1 and spins there without + relinquishing, so it is genuinely executing on another core when the + controller -- excluded to core 0 -- terminates it. _tx_thread_terminate + publishes TX_TERMINATED, releases the global SMP protection at TX_RESTORE, + and calls the victim's exit notification callback in the controller's + context on core 0. On an unfixed kernel a callback-side reset of the victim + succeeds at that point, and _tx_thread_reset both memsets the victim's stack + to the fill pattern and rebuilds its initial frame -- over the stack a live + core is running on. + + What is measured: + + - that the victim really was mapped to and executing on another core when + termination began, which is the precondition; if it cannot be + established within a bounded wait the test says so and drops only the + assertions that depend on it, rather than reporting a pass it did not + earn or spinning until something changes, + - that the callback-side delete and reset are refused, from the wrapper + and from the core service alike, + - that the victim's stack is untouched, checked with a sentinel written + into the unused low end of the stack, which a reset's fill would erase, + - that after the service returns the victim is in no core's execute slot + and on no ready list. + + Every wait is bounded and every list walk is bounded, so neither a failing + kernel nor an unlucky schedule can turn this into a hang. */ + +#include +#include "tx_api.h" +#include "tx_thread.h" + + +#define CONTROLLER_PRIORITY 10 +#define VICTIM_PRIORITY 20 + +/* The core the victim is pinned to, and the exclusion maps that pin it there + and the controller to core 0. */ + +#define VICTIM_CORE 1 +#define EXCLUDE_ALL_BUT_CORE_0 0xE +#define EXCLUDE_ALL_BUT_CORE_1 0xD + +/* Bound on the wait for the victim to be mapped to its core. */ + +#define REMOTE_WAIT_TICKS 200 + +/* Sentinel written into the unused low end of the victim's stack. A reset + memsets the whole stack to the fill pattern before rebuilding the frame, so + the sentinel is gone if a reset ran. Its offset keeps it clear of both the + frame a downward-growing stack builds at the top and the stack-checking + pattern the kernel inspects at the very bottom. */ + +#define SENTINEL_OFFSET 64 +#define SENTINEL_WORDS 8 +#define SENTINEL_VALUE 0xA5A5A5A5UL + +#define READY_RING_LIMIT 32 + +#define PROBE_NOT_ATTEMPTED 0xFFFFFFFFUL + +#define FAILED_TAG_LIMIT 16 + + +static TX_THREAD controller; +static TX_THREAD victim; + +static CHAR *victim_stack; + +static volatile ULONG victim_spins = 0; +static volatile UINT victim_run = TX_FALSE; + +static UINT probe_state; +static UINT probe_suspending; +static UINT probe_core_mapped; +static UINT probe_delete_status = PROBE_NOT_ATTEMPTED; +static UINT probe_core_delete_status = PROBE_NOT_ATTEMPTED; +static UINT probe_reset_status = PROBE_NOT_ATTEMPTED; +static UINT probe_core_reset_status = PROBE_NOT_ATTEMPTED; +static UINT probe_ran = TX_FALSE; +static UINT remote_confirmed = TX_FALSE; +static UINT sentinel_intact_after = TX_FALSE; + +static unsigned long expectations_checked = 0; +static unsigned long expectations_failed = 0; +static UINT first_failure = 0; +static UINT failed_tags[FAILED_TAG_LIMIT]; +static UINT failed_tag_count = 0; + + +/* Define thread prototypes. */ + +static void controller_entry(ULONG thread_input); +static void victim_entry(ULONG thread_input); + + +/* Prototype for test control return. */ + +void test_control_return(UINT status); + + +static void expect(UINT condition, UINT tag) +{ + + expectations_checked++; + + if (condition != TX_TRUE) + { + + expectations_failed++; + + if (first_failure == 0) + { + first_failure = tag; + } + + if (failed_tag_count < FAILED_TAG_LIMIT) + { + failed_tags[failed_tag_count] = tag; + failed_tag_count++; + } + } +} + + +static void expect_status(UINT actual, UINT wanted, UINT tag) +{ + + if (actual == wanted) + { + expect(TX_TRUE, tag); + } + else + { + expect(TX_FALSE, tag); + } +} + + +static void write_sentinel(void) +{ + +ULONG *words; +UINT index; + + + words = (ULONG *) (victim_stack + SENTINEL_OFFSET); + + for (index = 0; index < SENTINEL_WORDS; index++) + { + words[index] = SENTINEL_VALUE; + } +} + + +static UINT sentinel_intact(void) +{ + +ULONG *words; +UINT index; +UINT intact; + + + words = (ULONG *) (victim_stack + SENTINEL_OFFSET); + intact = TX_TRUE; + + for (index = 0; index < SENTINEL_WORDS; index++) + { + if (words[index] != SENTINEL_VALUE) + { + intact = TX_FALSE; + } + } + + return(intact); +} + + +/* Report whether thread_ptr appears in any core's execute slot or on any ready + list. Both walks are bounded. */ + +static UINT fully_detached(TX_THREAD *thread_ptr) +{ + +TX_INTERRUPT_SAVE_AREA + +TX_THREAD *walk_ptr; +TX_THREAD *head_ptr; +UINT priority; +UINT steps; +UINT core; +UINT detached; + + + detached = TX_TRUE; + + TX_DISABLE + + for (core = 0; core < ((UINT) TX_THREAD_SMP_MAX_CORES); core++) + { + if (_tx_thread_execute_ptr[core] == thread_ptr) + { + detached = TX_FALSE; + } + } + + for (priority = 0; priority < ((UINT) TX_MAX_PRIORITIES); priority++) + { + + head_ptr = _tx_thread_priority_list[priority]; + walk_ptr = head_ptr; + steps = 0; + + while ((walk_ptr != TX_NULL) && (steps < READY_RING_LIMIT)) + { + + if (walk_ptr == thread_ptr) + { + detached = TX_FALSE; + } + + walk_ptr = walk_ptr -> tx_thread_ready_next; + steps++; + + if (walk_ptr == head_ptr) + { + walk_ptr = TX_NULL; + } + } + } + + TX_RESTORE + + return(detached); +} + + +static void entry_exit_notify(TX_THREAD *thread_ptr, UINT type) +{ + + if (thread_ptr != &victim) + { + return; + } + + if (type != TX_THREAD_EXIT) + { + return; + } + + probe_ran = TX_TRUE; + probe_state = thread_ptr -> tx_thread_state; + probe_suspending = thread_ptr -> tx_thread_suspending; + probe_core_mapped = thread_ptr -> tx_thread_smp_core_mapped; + + /* The delete first, then the reset. Each core service is called only if + its wrapper already refused, so that a kernel which allows the operation + is not asked to perform it twice. */ + + probe_delete_status = tx_thread_delete(thread_ptr); + + if (probe_delete_status != TX_SUCCESS) + { + + probe_core_delete_status = _tx_thread_delete(thread_ptr); + + if (probe_core_delete_status != TX_SUCCESS) + { + + probe_reset_status = tx_thread_reset(thread_ptr); + + if (probe_reset_status != TX_SUCCESS) + { + probe_core_reset_status = _tx_thread_reset(thread_ptr); + } + } + } +} + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_smp_thread_exit_callback_remote_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + pointer = (CHAR *) first_unused_memory; + + status = tx_thread_create(&controller, "controller", controller_entry, 0, + pointer, TEST_STACK_SIZE_PRINTF, + CONTROLLER_PRIORITY, CONTROLLER_PRIORITY, + TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + victim_stack = pointer; + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + status += tx_thread_smp_core_exclude(&controller, EXCLUDE_ALL_BUT_CORE_0); + + if (status != TX_SUCCESS) + { + + printf("Running SMP Thread Exit Callback Remote Test............... ERROR #1\n"); + test_control_return(1); + } +} + + +static void controller_entry(ULONG thread_input) +{ + +UINT status; +UINT notify_status; +UINT index; +ULONG waited; +ULONG spins_before; + + + (void) thread_input; + + printf("Running SMP Thread Exit Callback Remote Test............... "); + + victim_run = TX_TRUE; + + status = tx_thread_create(&victim, "victim", victim_entry, 0, + victim_stack, TEST_STACK_SIZE_PRINTF, + VICTIM_PRIORITY, VICTIM_PRIORITY, + TX_NO_TIME_SLICE, TX_DONT_START); + + status += tx_thread_smp_core_exclude(&victim, EXCLUDE_ALL_BUT_CORE_1); + + notify_status = tx_thread_entry_exit_notify(&victim, entry_exit_notify); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + if (notify_status != TX_SUCCESS) + { + status = notify_status; + } +#else + + if (notify_status != TX_FEATURE_NOT_ENABLED) + { + status = notify_status; + } +#endif + + expect_status(status, TX_SUCCESS, 10); + + /* The sentinel goes in after the create, because the create fills the whole + stack with the pattern the stack-checking configurations inspect. */ + write_sentinel(); + expect(sentinel_intact(), 11); + + if (expectations_failed == 0) + { + expect_status(tx_thread_resume(&victim), TX_SUCCESS, 12); + } + + /* Wait, bounded, for the victim to be both mapped to its core and selected + to execute there, and for it to have actually spun. Those three + together are the precondition this test exists for. */ + + waited = 0; + + while ((waited < REMOTE_WAIT_TICKS) && (remote_confirmed == TX_FALSE)) + { + + if ((_tx_thread_execute_ptr[VICTIM_CORE] == &victim) && + (victim.tx_thread_smp_core_mapped == ((UINT) VICTIM_CORE)) && + (victim_spins > 0)) + { + remote_confirmed = TX_TRUE; + } + else + { + tx_thread_sleep(1); + waited++; + } + } + + /* Confirm it is still spinning, so that the termination below really does + start against a running remote thread rather than a stalled one. */ + + spins_before = victim_spins; + + if (remote_confirmed == TX_TRUE) + { + tx_thread_sleep(2); + expect(((victim_spins > spins_before) ? TX_TRUE : TX_FALSE), 13); + } + else + { + + /* Say so rather than assert it. The refusal assertions below do not + depend on the victim being remote, so they still run; the ones that + do are dropped, and this line records that the environment did not + provide the precondition. */ + printf("(remote precondition not established in %u ticks; remote-only checks skipped) ", + (UINT) REMOTE_WAIT_TICKS); + } + + if (expectations_failed == 0) + { + + expect_status(tx_thread_terminate(&victim), TX_SUCCESS, 20); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + expect(probe_ran, 21); + expect_status(probe_state, TX_TERMINATED, 22); + + /* The transition marker is set across the callback, which is what the + two refusals below rest on. */ + expect_status(probe_suspending, TX_TRUE, 23); + + expect_status(probe_delete_status, TX_DELETE_ERROR, 24); + expect_status(probe_core_delete_status, TX_DELETE_ERROR, 25); + expect_status(probe_reset_status, TX_NOT_DONE, 26); + expect_status(probe_core_reset_status, TX_NOT_DONE, 27); + + if (remote_confirmed == TX_TRUE) + { + + /* The callback saw the victim still mapped to the remote core. */ + expect_status(probe_core_mapped, (UINT) VICTIM_CORE, 28); + } +#endif + + /* The reset was refused, so nothing memset the stack a live core was + running on. */ + sentinel_intact_after = sentinel_intact(); + expect_status(sentinel_intact_after, TX_TRUE, 29); + + /* And the termination completed: the marker is clear, and the victim is + in no core's execute slot and on no ready list. */ + expect_status(victim.tx_thread_state, TX_TERMINATED, 30); + expect_status(victim.tx_thread_suspending, TX_FALSE, 31); + expect(fully_detached(&victim), 32); + } + + /* The victim's loop exits on this, for the case where it is still between + the terminate and its core acting on the preemption. */ + victim_run = TX_FALSE; + + if (expectations_failed == 0) + { + expect_status(tx_thread_delete(&victim), TX_SUCCESS, 40); + } + + if (expectations_failed != 0) + { + + printf("ERROR #%u (%lu of %lu expectations failed:", + first_failure, expectations_failed, expectations_checked); + + for (index = 0; index < failed_tag_count; index++) + { + printf(" %u", failed_tags[index]); + } + + printf(")\n"); + fflush(stdout); + test_control_return(1); + } + else + { + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + +static void victim_entry(ULONG thread_input) +{ + + (void) thread_input; + + /* Spin without relinquishing, so this thread occupies its core rather than + yielding it. */ + while (victim_run == TX_TRUE) + { + victim_spins++; + } +} diff --git a/test/smp/regression/threadx_thread_exit_callback_transition_test.c b/test/smp/regression/threadx_thread_exit_callback_transition_test.c new file mode 100644 index 000000000..c931085c5 --- /dev/null +++ b/test/smp/regression/threadx_thread_exit_callback_transition_test.c @@ -0,0 +1,1375 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/* This test covers the completion and termination transitions that a thread's + TX_THREAD_EXIT notification callback runs inside. + + _tx_thread_shell_entry and _tx_thread_terminate both publish the terminal + state -- TX_COMPLETED or TX_TERMINATED -- and then call the thread's exit + notification callback, before the thread has been detached from the ready + list and before either service has finished with the pointer it holds to + the control block. That terminal state is the same state _tx_thread_delete + and _tx_thread_reset accept as authorization to invalidate or rebuild the + control block, so a callback used to be able to delete the object -- and + then lawfully recreate it over the same memory -- while the scheduler was + still linked to the old incarnation, or to reset a terminated thread and + resume it back onto the ready list after termination had reported success. + + The tx_thread_suspending flag marks the transition for exactly its + duration, and delete and reset now refuse a target whose flag is still set. + The refusal is transient: TX_DELETE_ERROR and TX_NOT_DONE are errors those + two services already document, and the same call succeeds once the + transition has finished. + + What the test measures, in every scenario: + + 1. what the callback observes -- the published state, the transition + flag, and the status of each lifecycle service it can reach, + 2. that the scheduler's ready lists, priority map and execute pointer + stay consistent with the control blocks they point at, taken as one + snapshot under interrupt lockout so that the reading is not itself a + race, + 3. that the documented behaviour still works afterwards: the same delete + and reset succeed once the transition has completed, so nothing has + become permanently undeletable. + + The consequences are demonstrated rather than described, and deliberately + from the terminator's context rather than the completing thread's: + + - scenario A has the callback recreate the control block if its delete + unexpectedly succeeded, at a lower priority, so that the outcome is an + assertable disagreement -- the old priority list still heading at a + control block whose own priority field names a different list -- rather + than a fault; + - scenario B has the callback reset and then resume the target, so that a + kernel which allows the reset is caught reporting a successful + termination for a thread that is runnable again. + + Both run while the victim is a ready thread that is not the current thread. + That ordering is not cosmetic. On the Linux, Win32 and Win64 host + simulation ports TX_THREAD_DELETE_PORT_COMPLETION cancels and joins the + host thread backing the deleted thread, so a callback-side delete of the + *completing* thread destroys the host thread the callback is running on and + wedges the simulator instead of reaching an assertion. The completion + scenarios therefore come last, and the scenario gate below stops the run + before them if anything earlier has already failed. + + Every list walk is bounded, so a corrupted ring costs an assertion and not + a hang. Expectations are counted rather than short-circuited within a + scenario, so a failing kernel reports how much it failed by; progression + between scenarios is gated on there being no failures yet, so a kernel that + has already corrupted the scheduler is not driven further into it. */ + +#include +#include "tx_api.h" +#include "tx_thread.h" + + +/* Priorities. The controller sits above every thread it drives. The victim + shares its priority with two peers, so that both the multi-member and the + single-member ready-ring unlink paths are reached. RECREATE_PRIORITY is + below VICTIM_PRIORITY on purpose: see the note in the callback. */ + +#define CONTROLLER_PRIORITY 10 +#define VICTIM_PRIORITY 20 +#define RECREATE_PRIORITY 21 + +/* Upper bound on a ready-ring walk. The suite never has this many threads at + one priority, so exceeding it means the ring is broken rather than long. */ + +#define READY_RING_LIMIT 32 + +/* Sentinel for a probe slot the callback did not reach. */ + +#define PROBE_NOT_ATTEMPTED 0xFFFFFFFFUL + + +static unsigned long controller_counter = 0; +static unsigned long victim_counter = 0; +static unsigned long peer_a_counter = 0; +static unsigned long peer_b_counter = 0; +static unsigned long replacement_counter = 0; +static unsigned long callback_entry_counter = 0; +static unsigned long callback_exit_counter = 0; + +static TX_THREAD controller; +static TX_THREAD victim; +static TX_THREAD peer_a; +static TX_THREAD peer_b; +static TX_SEMAPHORE victim_semaphore; +static TX_MUTEX victim_mutex; + +static CHAR *victim_stack; +static CHAR *replacement_stack; + +/* What the victim's entry function should do before it returns. */ + +static volatile UINT victim_hold = TX_FALSE; +static volatile UINT victim_self_terminate = TX_FALSE; +static volatile UINT victim_take_mutex = TX_FALSE; +static volatile UINT victim_wait_semaphore = TX_FALSE; +static volatile UINT peers_run = TX_FALSE; + +/* What the exit callback should attempt the next time it runs. Independent + flags rather than one mode, because a delete that unexpectedly succeeds + destroys the object and would mask the reset measurement behind it. */ + +static volatile UINT probe_delete_enabled = TX_FALSE; +static volatile UINT probe_reset_enabled = TX_FALSE; +static volatile UINT probe_misc_enabled = TX_FALSE; +static volatile UINT probe_reuse_enabled = TX_FALSE; + +/* What the callback saw the last time it probed. */ + +static UINT probe_state; +static UINT probe_suspending; +static UINT probe_delete_status; +static UINT probe_core_delete_status; +static UINT probe_reset_status; +static UINT probe_core_reset_status; +static UINT probe_resume_status; +static UINT probe_suspend_status; +static UINT probe_terminate_status; +static UINT probe_create_status; +static UINT probe_consistent; +static UINT probe_ran; +static UINT delete_succeeded; + +/* Ordering witness for the notification pair. Entry and exit counts cannot + simply be compared: a victim created with TX_DONT_START never reports an + entry, and an incarnation that is reset and terminated again reports a + second exit with no second entry. What must hold is that an exit for a + thread that ran is preceded by that thread's entry. */ + +static UINT last_notify_type = PROBE_NOT_ATTEMPTED; +static UINT exit_saw_entry_first = TX_FALSE; + +/* Expectation accounting. */ + +#define FAILED_TAG_LIMIT 32 + +static unsigned long expectations_checked = 0; +static unsigned long expectations_failed = 0; +static UINT first_failure = 0; +static UINT failed_tags[FAILED_TAG_LIMIT]; +static UINT failed_tag_count = 0; + + +/* Define task prototypes. */ + +static void controller_entry(ULONG thread_input); +static void victim_entry(ULONG thread_input); +static void peer_entry(ULONG thread_input); +static void replacement_entry(ULONG thread_input); + + +/* Prototype for test control return. */ + +void test_control_return(UINT status); + + +/* Record one expectation. tag identifies it in the failure report; the first + failing tag is the number the suite prints, so tags are allocated in the + order the expectations are written. */ + +static void expect(UINT condition, UINT tag) +{ + + expectations_checked++; + + if (condition != TX_TRUE) + { + + expectations_failed++; + + if (first_failure == 0) + { + first_failure = tag; + } + + /* Keep the tags, so that a failing kernel reports which expectations + it failed rather than only the first and a total. */ + if (failed_tag_count < FAILED_TAG_LIMIT) + { + failed_tags[failed_tag_count] = tag; + failed_tag_count++; + } + } +} + + +static void expect_status(UINT actual, UINT wanted, UINT tag) +{ + + if (actual == wanted) + { + expect(TX_TRUE, tag); + } + else + { + expect(TX_FALSE, tag); + } +} + + +static void expect_pointer(void *actual, void *wanted, UINT tag) +{ + + if (actual == wanted) + { + expect(TX_TRUE, tag); + } + else + { + expect(TX_FALSE, tag); + } +} + + +static void expect_count(unsigned long actual, unsigned long wanted, UINT tag) +{ + + if (actual == wanted) + { + expect(TX_TRUE, tag); + } + else + { + expect(TX_FALSE, tag); + } +} + + +/* Walk one ready ring and report whether thread_ptr is a member of it. The + walk is bounded, so a ring that does not close is reported as a + non-membership rather than spun on for ever. */ + +static UINT ready_ring_contains(UINT priority, TX_THREAD *thread_ptr) +{ + +TX_THREAD *walk_ptr; +TX_THREAD *head_ptr; +UINT steps; +UINT found; + + + found = TX_FALSE; + head_ptr = _tx_thread_priority_list[priority]; + walk_ptr = head_ptr; + steps = 0; + + while ((walk_ptr != TX_NULL) && (steps < READY_RING_LIMIT) && (found == TX_FALSE)) + { + + if (walk_ptr == thread_ptr) + { + found = TX_TRUE; + } + + walk_ptr = walk_ptr -> tx_thread_ready_next; + steps++; + + /* The ring has closed. */ + if (walk_ptr == head_ptr) + { + walk_ptr = TX_NULL; + } + } + + return(found); +} + + +/* Take one snapshot of the scheduler's ready structures and check that they + agree with the control blocks they point at. + + This is the assertion the pre-fix behaviour fails. A callback that deletes + the victim and recreates it at another priority leaves the old priority list + heading at that control block while the block's own priority field names the + new list, and leaves the old priority's map bit set with nothing behind it. + Neither disagreement needs a fault to be visible. + + The whole snapshot is taken under interrupt lockout -- which is the global + SMP protection on an SMP port -- so that reading the scheduler's state is + not itself a race against another core. + + transitioning names the one thread that is allowed to be on a ready list + without being ready, which is precisely the thread whose completion or + termination transition is in progress: the terminal state is published + before the detachment, so inside the callback the victim is legitimately a + TX_COMPLETED or TX_TERMINATED member of its ready ring. That single + exemption is from the state clause only. Every other clause, and in + particular the clause that requires a ready-list member to agree that this + is its priority -- the one a callback-side delete and recreate breaks -- + still applies to it. */ + +static UINT scheduler_consistent_except(TX_THREAD *transitioning) +{ + +TX_INTERRUPT_SAVE_AREA + +TX_THREAD *head_ptr; +TX_THREAD *walk_ptr; +TX_THREAD *execute_ptr; +UINT priority; +UINT steps; +UINT consistent; +#ifdef TX_THREAD_SMP_MAX_CORES +UINT core; +#endif + + + consistent = TX_TRUE; + + TX_DISABLE + + for (priority = 0; priority < ((UINT) TX_MAX_PRIORITIES); priority++) + { + + head_ptr = _tx_thread_priority_list[priority]; + +#if TX_MAX_PRIORITIES <= 32 + + /* A priority with a ready list must have its map bit set, and a + priority with no ready list must not. */ + if (head_ptr == TX_NULL) + { + if ((_tx_thread_priority_maps[0] & (((ULONG) 1) << priority)) != ((ULONG) 0)) + { + consistent = TX_FALSE; + } + } + else + { + if ((_tx_thread_priority_maps[0] & (((ULONG) 1) << priority)) == ((ULONG) 0)) + { + consistent = TX_FALSE; + } + } +#endif + + walk_ptr = head_ptr; + steps = 0; + + while ((walk_ptr != TX_NULL) && (steps < READY_RING_LIMIT)) + { + + /* Every thread on a ready list must be a live thread, must be + ready, and must agree that this is its priority. */ + if (walk_ptr -> tx_thread_id != TX_THREAD_ID) + { + consistent = TX_FALSE; + } + + if ((walk_ptr -> tx_thread_state != TX_READY) && (walk_ptr != transitioning)) + { + consistent = TX_FALSE; + } + + if (walk_ptr -> tx_thread_priority != priority) + { + consistent = TX_FALSE; + } + + /* The ring must be doubly linked. */ + if (walk_ptr -> tx_thread_ready_next -> tx_thread_ready_previous != walk_ptr) + { + consistent = TX_FALSE; + } + + walk_ptr = walk_ptr -> tx_thread_ready_next; + steps++; + + if (walk_ptr == head_ptr) + { + walk_ptr = TX_NULL; + } + } + + /* A ring that did not close inside the bound is broken. */ + if (walk_ptr != TX_NULL) + { + consistent = TX_FALSE; + } + } + + /* Whatever the scheduler has selected to execute must be a member of the + ready list that its own priority field names. */ +#ifdef TX_THREAD_SMP_MAX_CORES + + for (core = 0; core < ((UINT) TX_THREAD_SMP_MAX_CORES); core++) + { + + execute_ptr = _tx_thread_execute_ptr[core]; + + if (execute_ptr != TX_NULL) + { + if (ready_ring_contains(execute_ptr -> tx_thread_priority, execute_ptr) == TX_FALSE) + { + consistent = TX_FALSE; + } + } + } +#else + + execute_ptr = _tx_thread_execute_ptr; + + if (execute_ptr != TX_NULL) + { + if (ready_ring_contains(execute_ptr -> tx_thread_priority, execute_ptr) == TX_FALSE) + { + consistent = TX_FALSE; + } + } +#endif + + TX_RESTORE + + return(consistent); +} + + +static UINT scheduler_consistent(void) +{ + return(scheduler_consistent_except(TX_NULL)); +} + + +/* Report whether thread_ptr is absent from every ready list and from every + execute slot, which is what a completed or terminated thread must be once + its transition has finished. */ + +static UINT fully_detached(TX_THREAD *thread_ptr) +{ + +TX_INTERRUPT_SAVE_AREA + +UINT priority; +UINT detached; +#ifdef TX_THREAD_SMP_MAX_CORES +UINT core; +#endif + + + detached = TX_TRUE; + + TX_DISABLE + + for (priority = 0; priority < ((UINT) TX_MAX_PRIORITIES); priority++) + { + if (ready_ring_contains(priority, thread_ptr) == TX_TRUE) + { + detached = TX_FALSE; + } + } + +#ifdef TX_THREAD_SMP_MAX_CORES + + for (core = 0; core < ((UINT) TX_THREAD_SMP_MAX_CORES); core++) + { + if (_tx_thread_execute_ptr[core] == thread_ptr) + { + detached = TX_FALSE; + } + } +#else + + if (_tx_thread_execute_ptr == thread_ptr) + { + detached = TX_FALSE; + } +#endif + + TX_RESTORE + + return(detached); +} + + +static void arm_probe(UINT probe_delete, UINT probe_reset, UINT probe_misc, UINT probe_reuse) +{ + + probe_state = PROBE_NOT_ATTEMPTED; + probe_suspending = PROBE_NOT_ATTEMPTED; + probe_delete_status = PROBE_NOT_ATTEMPTED; + probe_core_delete_status = PROBE_NOT_ATTEMPTED; + probe_reset_status = PROBE_NOT_ATTEMPTED; + probe_core_reset_status = PROBE_NOT_ATTEMPTED; + probe_resume_status = PROBE_NOT_ATTEMPTED; + probe_suspend_status = PROBE_NOT_ATTEMPTED; + probe_terminate_status = PROBE_NOT_ATTEMPTED; + probe_create_status = PROBE_NOT_ATTEMPTED; + probe_consistent = PROBE_NOT_ATTEMPTED; + probe_ran = TX_FALSE; + delete_succeeded = TX_FALSE; + + probe_delete_enabled = probe_delete; + probe_reset_enabled = probe_reset; + probe_misc_enabled = probe_misc; + probe_reuse_enabled = probe_reuse; +} + + +/* The exit notification callback. Everything it learns is recorded for the + controller to check; it prints nothing and it never suspends, so it obeys + the one restriction the manual places on a notification callback. */ + +static void entry_exit_notify(TX_THREAD *thread_ptr, UINT type) +{ + + /* Only the victim's notifications are of interest. Its control block is + reused across scenarios, so the pointer is the identity. */ + if (thread_ptr != &victim) + { + return; + } + + if (type == TX_THREAD_ENTRY) + { + callback_entry_counter++; + last_notify_type = TX_THREAD_ENTRY; + return; + } + + if (type != TX_THREAD_EXIT) + { + return; + } + + callback_exit_counter++; + + if (last_notify_type == TX_THREAD_ENTRY) + { + exit_saw_entry_first = TX_TRUE; + } + + last_notify_type = TX_THREAD_EXIT; + + if ((probe_delete_enabled == TX_FALSE) && (probe_reset_enabled == TX_FALSE) && + (probe_misc_enabled == TX_FALSE)) + { + return; + } + + probe_ran = TX_TRUE; + + /* What the kernel has published about the thread at this point. */ + probe_state = thread_ptr -> tx_thread_state; + probe_suspending = thread_ptr -> tx_thread_suspending; + + /* None of the services below has a suspension option, which is the only + thing the manual forbids a callback from using, so every one of them is + reachable from here. + + Where a service is expected to refuse, the core service is called after + the _txe_ wrapper as well. The wrapper is what an ordinary build + reaches; the core service is what a TX_DISABLE_ERROR_CHECKING build + reaches directly, and the refusal has to live there so that disabling + error checking cannot disable it. The core call is made only when the + wrapper already refused, so that a kernel which allows the operation is + not asked to perform it twice. */ + + if (probe_delete_enabled == TX_TRUE) + { + + probe_delete_status = tx_thread_delete(thread_ptr); + + if (probe_delete_status == TX_SUCCESS) + { + delete_succeeded = TX_TRUE; + } + else + { + + probe_core_delete_status = _tx_thread_delete(thread_ptr); + + if (probe_core_delete_status == TX_SUCCESS) + { + delete_succeeded = TX_TRUE; + } + } + + /* Recreate the control block only if the delete unexpectedly + succeeded. On a fixed kernel this never runs. On an unfixed one it + is the lawful next step after a successful delete, and it is what + turns the window into an observable inconsistency: tx_thread_create + zeroes the whole control block, and the auto-start then links it + onto RECREATE_PRIORITY's ready list while the old incarnation is + still the head of VICTIM_PRIORITY's. + + RECREATE_PRIORITY is the lower of the two so that the stale head is + the one the scheduler selects from, and so that the ring at the new + priority has a single member. Recreating at the same priority would + instead have the auto-start write through the control block's + freshly zeroed ready_previous pointer, which is a fault rather than + an assertion. */ + if ((delete_succeeded == TX_TRUE) && (probe_reuse_enabled == TX_TRUE)) + { + probe_create_status = tx_thread_create(thread_ptr, "replacement", + replacement_entry, 0, + replacement_stack, + TEST_STACK_SIZE_PRINTF, + RECREATE_PRIORITY, RECREATE_PRIORITY, + TX_NO_TIME_SLICE, TX_AUTO_START); + } + } + + if ((probe_reset_enabled == TX_TRUE) && (delete_succeeded == TX_FALSE)) + { + + probe_reset_status = tx_thread_reset(thread_ptr); + + if (probe_reset_status != TX_SUCCESS) + { + probe_core_reset_status = _tx_thread_reset(thread_ptr); + } + + /* Follow the reset with the resume that the reset would have unlocked. + On a fixed kernel the state is still terminal and the resume is + refused. On an unfixed one the reset has moved the state to + TX_SUSPENDED, the resume finds a suspending thread whose state is no + longer terminal, clears the flag and puts the thread back on the + ready list -- and the outer service then skips the removal and + reports success for a termination that did not happen. */ + probe_resume_status = tx_thread_resume(thread_ptr); + } + + if ((probe_misc_enabled == TX_TRUE) && (delete_succeeded == TX_FALSE)) + { + probe_suspend_status = tx_thread_suspend(thread_ptr); + probe_terminate_status = tx_thread_terminate(thread_ptr); + } + + probe_consistent = scheduler_consistent_except(thread_ptr); +} + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_thread_exit_callback_transition_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + status = tx_thread_create(&controller, "controller", controller_entry, 0, + pointer, TEST_STACK_SIZE_PRINTF, + CONTROLLER_PRIORITY, CONTROLLER_PRIORITY, + TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + status += tx_thread_create(&peer_a, "peer a", peer_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + VICTIM_PRIORITY, VICTIM_PRIORITY, + TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + status += tx_thread_create(&peer_b, "peer b", peer_entry, 2, + pointer, TEST_STACK_SIZE_PRINTF, + VICTIM_PRIORITY, VICTIM_PRIORITY, + TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* The victim's control block is created and destroyed repeatedly, so its + two stacks are set aside here rather than per scenario. */ + victim_stack = pointer; + pointer = pointer + TEST_STACK_SIZE_PRINTF; + replacement_stack = pointer; + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + status += tx_semaphore_create(&victim_semaphore, "victim semaphore", 0); + status += tx_mutex_create(&victim_mutex, "victim mutex", TX_INHERIT); + + if (status != TX_SUCCESS) + { + + printf("Running Thread Exit Callback Transition Test............... ERROR #1\n"); + test_control_return(1); + } + +#ifdef TX_THREAD_SMP_MAX_CORES + + /* Confine every thread this test drives to core 0. The measurements below + are of global scheduler structures at chosen moments, and letting the + peers and the victim run on other cores would make them a race against + the test rather than a property of it. A victim executing on a + different core when termination begins is deliberately covered by a + separate SMP test, so that the deterministic cases here cannot be made + flaky by it. */ + status = tx_thread_smp_core_exclude(&controller, 0xE); + status += tx_thread_smp_core_exclude(&peer_a, 0xE); + status += tx_thread_smp_core_exclude(&peer_b, 0xE); + + if (status != TX_SUCCESS) + { + + printf("Running Thread Exit Callback Transition Test............... ERROR #2\n"); + test_control_return(1); + } +#endif +} + + +/* Create the victim over its own control block, with the exit callback + registered. The notify status is folded into the result according to what + the configuration supports. */ + +static UINT create_victim(UINT priority, UINT auto_start) +{ + +UINT status; +UINT notify_status; + + + status = tx_thread_create(&victim, "victim", victim_entry, 0, + victim_stack, TEST_STACK_SIZE_PRINTF, + priority, priority, TX_NO_TIME_SLICE, auto_start); + + notify_status = tx_thread_entry_exit_notify(&victim, entry_exit_notify); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + if (notify_status != TX_SUCCESS) + { + status = notify_status; + } +#else + + /* Notification is compiled out, so the registration is expected to be + refused and the callback never runs. */ + if (notify_status != TX_FEATURE_NOT_ENABLED) + { + status = notify_status; + } +#endif + +#ifdef TX_THREAD_SMP_MAX_CORES + + if (status == TX_SUCCESS) + { + status = tx_thread_smp_core_exclude(&victim, 0xE); + } +#endif + + return(status); +} + + +/* The gate between scenarios. A kernel that has already failed an expectation + has, in these scenarios, already left the scheduler inconsistent, and + driving it further would report nothing more while risking a wedge instead + of a verdict. */ + +static UINT ok_so_far(void) +{ + +UINT result; + + + result = TX_FALSE; + + if (expectations_failed == 0) + { + result = TX_TRUE; + } + + return(result); +} + + +static void controller_entry(ULONG thread_input) +{ + +ULONG expected_exits; +ULONG expected_entries; +UINT index; + + + (void) thread_input; + + controller_counter++; + expected_exits = 0; + expected_entries = 0; + + /* Inform user. */ + printf("Running Thread Exit Callback Transition Test............... "); + + /* The scheduler must be self-consistent before anything is measured, so + that a later failure is attributable to this test. */ + expect(scheduler_consistent(), 10); + + /* ------------------------------------------------------------------- */ + /* Scenario A: terminate a ready target that is not the current thread, */ + /* with two peers ready at the same priority. The callback attempts */ + /* the delete, and recreates the control block if it succeeded. */ + /* ------------------------------------------------------------------- */ + + if (ok_so_far() == TX_TRUE) + { + + peers_run = TX_TRUE; + victim_hold = TX_TRUE; + + expect_status(tx_thread_resume(&peer_a), TX_SUCCESS, 11); + expect_status(tx_thread_resume(&peer_b), TX_SUCCESS, 12); + + arm_probe(TX_TRUE, TX_FALSE, TX_FALSE, TX_TRUE); + + expect_status(create_victim(VICTIM_PRIORITY, TX_AUTO_START), TX_SUCCESS, 13); + } + + if (ok_so_far() == TX_TRUE) + { + + /* Let the victim and both peers become ready and start spinning, so + that the victim's unlink is from a multi-member ring. */ + tx_thread_sleep(3); + + expect_status(victim.tx_thread_state, TX_READY, 14); + expect(ready_ring_contains(VICTIM_PRIORITY, &victim), 15); + expect(ready_ring_contains(VICTIM_PRIORITY, &peer_a), 16); + expect(ready_ring_contains(VICTIM_PRIORITY, &peer_b), 17); + } + + if (ok_so_far() == TX_TRUE) + { + + expect_status(tx_thread_terminate(&victim), TX_SUCCESS, 18); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + expect(probe_ran, 19); + + /* The callback runs after the terminal state has been published, and + inside the transition, which is what the flag records. */ + expect_status(probe_state, TX_TERMINATED, 20); + expect_status(probe_suspending, TX_TRUE, 21); + + /* Both the wrapper and the core service must refuse. */ + expect_status(probe_delete_status, TX_DELETE_ERROR, 22); + expect_status(probe_core_delete_status, TX_DELETE_ERROR, 23); + + /* So the recreate never happened and nothing is inconsistent. */ + expect_status(delete_succeeded, TX_FALSE, 24); + expect_status(probe_create_status, PROBE_NOT_ATTEMPTED, 25); + expect_status(probe_consistent, TX_TRUE, 26); + expect_count(replacement_counter, 0, 27); +#endif + + /* After the service returns the termination is complete: the state is + terminal, the marker is clear, the target is on no ready list and in + no execute slot, and the peers are undisturbed. */ + expect_status(victim.tx_thread_state, TX_TERMINATED, 28); + expect_status(victim.tx_thread_suspending, TX_FALSE, 29); + expect(fully_detached(&victim), 30); + expect(ready_ring_contains(VICTIM_PRIORITY, &peer_a), 31); + expect(ready_ring_contains(VICTIM_PRIORITY, &peer_b), 32); + expect(scheduler_consistent(), 33); + } + + if (ok_so_far() == TX_TRUE) + { + + arm_probe(TX_FALSE, TX_FALSE, TX_FALSE, TX_FALSE); + + /* The documented behaviour is available again. */ + expect_status(tx_thread_delete(&victim), TX_SUCCESS, 34); + } + + /* ------------------------------------------------------------------- */ + /* Scenario B: the same termination, but the callback attempts a reset */ + /* and then the resume that a successful reset would have unlocked. */ + /* */ + /* This is the leg where the transition check is the only thing */ + /* standing between the callback and a reset of a thread that is still */ + /* on the ready list. Without it the reset succeeds, the resume */ + /* clears the suspending flag and restores TX_READY, the outer service */ + /* then finds the flag clear and skips the removal, and */ + /* tx_thread_terminate returns TX_SUCCESS for a runnable thread. */ + /* ------------------------------------------------------------------- */ + + if (ok_so_far() == TX_TRUE) + { + + arm_probe(TX_FALSE, TX_TRUE, TX_FALSE, TX_FALSE); + + expect_status(create_victim(VICTIM_PRIORITY, TX_AUTO_START), TX_SUCCESS, 40); + } + + if (ok_so_far() == TX_TRUE) + { + + tx_thread_sleep(3); + + expect_status(victim.tx_thread_state, TX_READY, 41); + expect_status(tx_thread_terminate(&victim), TX_SUCCESS, 42); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + expect(probe_ran, 43); + expect_status(probe_state, TX_TERMINATED, 44); + expect_status(probe_suspending, TX_TRUE, 45); + + /* The discriminating leg. The target is not the current thread and + its published state is terminal, so both of the conditions the + service tested before this fix are satisfied. */ + expect_status(probe_reset_status, TX_NOT_DONE, 46); + expect_status(probe_core_reset_status, TX_NOT_DONE, 47); + + /* With the reset refused, the state is still terminal, so the resume + cannot reach the branch that would void the termination. */ + expect_status(probe_resume_status, TX_RESUME_ERROR, 48); + expect_status(probe_consistent, TX_TRUE, 49); +#endif + + /* And the termination stands. A kernel that let the callback reset + and resume the target arrives here with the victim ready to run. */ + expect_status(victim.tx_thread_state, TX_TERMINATED, 50); + expect_status(victim.tx_thread_suspending, TX_FALSE, 51); + expect(fully_detached(&victim), 52); + expect(scheduler_consistent(), 53); + } + + if (ok_so_far() == TX_TRUE) + { + + arm_probe(TX_FALSE, TX_FALSE, TX_FALSE, TX_FALSE); + + expect_status(tx_thread_reset(&victim), TX_SUCCESS, 54); + expect_status(tx_thread_terminate(&victim), TX_SUCCESS, 55); + expect_status(tx_thread_delete(&victim), TX_SUCCESS, 56); + } + + /* Retire the peers, so that the ring drops to a single member and then to + none, and check consistency across both unlinks. */ + + if (ok_so_far() == TX_TRUE) + { + + peers_run = TX_FALSE; + tx_thread_sleep(3); + + expect_status(peer_a.tx_thread_state, TX_COMPLETED, 57); + expect_status(peer_b.tx_thread_state, TX_COMPLETED, 58); + expect(scheduler_consistent(), 59); + expect_status(tx_thread_delete(&peer_a), TX_SUCCESS, 60); + expect_status(tx_thread_delete(&peer_b), TX_SUCCESS, 61); + } + + /* ------------------------------------------------------------------- */ + /* Scenario C: terminate a target suspended on an object, so that the */ + /* non-ready branch of _tx_thread_terminate runs -- suspension cleanup, */ + /* the terminated extension, the callback, and mutex release, in that */ + /* order. That branch used to clear the marker before the callback */ + /* rather than after the last dereference of the target. */ + /* ------------------------------------------------------------------- */ + + if (ok_so_far() == TX_TRUE) + { + + arm_probe(TX_TRUE, TX_TRUE, TX_FALSE, TX_FALSE); + victim_hold = TX_FALSE; + victim_take_mutex = TX_TRUE; + victim_wait_semaphore = TX_TRUE; + + expect_status(create_victim(VICTIM_PRIORITY, TX_AUTO_START), TX_SUCCESS, 70); + } + + if (ok_so_far() == TX_TRUE) + { + + /* Let the victim take the mutex and suspend on the semaphore. */ + tx_thread_sleep(3); + + expect_status(victim.tx_thread_state, TX_SEMAPHORE_SUSP, 71); + expect_pointer(victim_mutex.tx_mutex_owner, &victim, 72); + } + + if (ok_so_far() == TX_TRUE) + { + + expect_status(tx_thread_terminate(&victim), TX_SUCCESS, 73); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + expect(probe_ran, 74); + expect_status(probe_state, TX_TERMINATED, 75); + + /* The discriminating leg for this branch. The marker used to be + cleared before this point, which left the callback free to delete or + reset a control block that the service still had mutex-release + processing to do against. */ + expect_status(probe_suspending, TX_TRUE, 76); + expect_status(probe_delete_status, TX_DELETE_ERROR, 77); + expect_status(probe_core_delete_status, TX_DELETE_ERROR, 78); + expect_status(probe_reset_status, TX_NOT_DONE, 79); + expect_status(probe_core_reset_status, TX_NOT_DONE, 80); + expect_status(probe_resume_status, TX_RESUME_ERROR, 81); + expect_status(delete_succeeded, TX_FALSE, 82); + expect_status(probe_consistent, TX_TRUE, 83); +#endif + + /* The marker is cleared at the safe point, after the mutex release, + and the mutex the terminated thread owned has been given up. The + value of the flag during the release itself is not observable from + application code; what is observable is that there is exactly one + clear site and that it sits downstream of the release. */ + expect_status(victim.tx_thread_suspending, TX_FALSE, 84); + expect_pointer(victim_mutex.tx_mutex_owner, TX_NULL, 85); + expect_count((unsigned long) victim_semaphore.tx_semaphore_suspended_count, 0, 86); + expect(fully_detached(&victim), 87); + expect(scheduler_consistent(), 88); + } + + if (ok_so_far() == TX_TRUE) + { + + arm_probe(TX_FALSE, TX_FALSE, TX_FALSE, TX_FALSE); + + expect_status(tx_thread_delete(&victim), TX_SUCCESS, 89); + } + + /* ------------------------------------------------------------------- */ + /* Scenario D: natural completion, victim alone at its priority. */ + /* */ + /* The callback here runs on the completing thread itself, so a */ + /* callback-side delete that succeeds destroys the host thread on the */ + /* simulation ports. This scenario is therefore placed after the ones */ + /* that reach an assertion, and the gate above stops the run before it */ + /* if any of them has already failed. */ + /* ------------------------------------------------------------------- */ + + if (ok_so_far() == TX_TRUE) + { + + arm_probe(TX_TRUE, TX_TRUE, TX_TRUE, TX_FALSE); + victim_take_mutex = TX_FALSE; + victim_wait_semaphore = TX_FALSE; + + expect_status(create_victim(VICTIM_PRIORITY, TX_AUTO_START), TX_SUCCESS, 100); + } + + if (ok_so_far() == TX_TRUE) + { + + /* Let the victim run to completion, so that its callback runs inside + the completion transition. */ + tx_thread_sleep(3); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + expect(probe_ran, 101); + expect_status(probe_state, TX_COMPLETED, 102); + expect_status(probe_suspending, TX_TRUE, 103); + expect_status(probe_delete_status, TX_DELETE_ERROR, 104); + expect_status(probe_core_delete_status, TX_DELETE_ERROR, 105); + + /* Reset of the running thread is refused for two independent reasons + here -- it is the current thread, and its transition is in progress + -- so this leg is a guard rather than a discriminator. Scenario B + is where the transition check is the only thing refusing a reset. */ + expect_status(probe_reset_status, TX_NOT_DONE, 106); + expect_status(probe_core_reset_status, TX_NOT_DONE, 107); + + /* A completed thread is neither resumable nor suspendable, and + terminating one is a documented no-op. */ + expect_status(probe_resume_status, TX_RESUME_ERROR, 108); + expect_status(probe_suspend_status, TX_SUSPEND_ERROR, 109); + expect_status(probe_terminate_status, TX_SUCCESS, 110); + expect_status(delete_succeeded, TX_FALSE, 111); + expect_status(probe_consistent, TX_TRUE, 112); +#endif + + /* The transition has finished, so the calls the callback was refused + must succeed. The refusal is transient and nothing has become + permanently undeletable. */ + expect_status(victim.tx_thread_state, TX_COMPLETED, 113); + expect_status(victim.tx_thread_suspending, TX_FALSE, 114); + expect(fully_detached(&victim), 115); + expect(scheduler_consistent(), 116); + expect(((victim_counter > 0) ? TX_TRUE : TX_FALSE), 117); + } + + if (ok_so_far() == TX_TRUE) + { + + arm_probe(TX_FALSE, TX_FALSE, TX_FALSE, TX_FALSE); + + /* Reset, so that the documented reset of a completed thread is covered + on a target whose transition has finished, and so that the + reset/terminate/delete order is exercised on this branch too. */ + expect_status(tx_thread_reset(&victim), TX_SUCCESS, 118); + expect_status(victim.tx_thread_state, TX_SUSPENDED, 119); + expect_status(tx_thread_delete(&victim), TX_DELETE_ERROR, 120); + expect_status(tx_thread_terminate(&victim), TX_SUCCESS, 121); + expect_status(victim.tx_thread_suspending, TX_FALSE, 122); + expect_status(tx_thread_delete(&victim), TX_SUCCESS, 123); + } + + /* A safe post-completion recreate at a different priority, which is the + lifecycle the callback was refused, performed at the point it is + legitimate. It exercises the priority map and the list heads for a + recreate that moves priority as well as for one that does not. */ + + if (ok_so_far() == TX_TRUE) + { + + expect_status(create_victim(RECREATE_PRIORITY, TX_AUTO_START), TX_SUCCESS, 124); + + tx_thread_sleep(3); + + expect_status(victim.tx_thread_state, TX_COMPLETED, 125); + expect(scheduler_consistent(), 126); + expect_status(tx_thread_delete(&victim), TX_SUCCESS, 127); + } + + /* ------------------------------------------------------------------- */ + /* Scenario E: self termination. The callback fires once, in the */ + /* victim's own context, the lifecycle mutation is refused there too, */ + /* and another thread can complete the lifecycle afterwards. */ + /* ------------------------------------------------------------------- */ + + if (ok_so_far() == TX_TRUE) + { + + victim_self_terminate = TX_TRUE; + expected_exits = callback_exit_counter; + + arm_probe(TX_TRUE, TX_TRUE, TX_FALSE, TX_FALSE); + + expect_status(create_victim(VICTIM_PRIORITY, TX_AUTO_START), TX_SUCCESS, 130); + } + + if (ok_so_far() == TX_TRUE) + { + + tx_thread_sleep(3); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Exactly one exit notification, even though the thread terminated + itself from inside its own entry function. */ + expect_count(callback_exit_counter, expected_exits + 1, 131); + expect_status(probe_state, TX_TERMINATED, 132); + expect_status(probe_suspending, TX_TRUE, 133); + expect_status(probe_delete_status, TX_DELETE_ERROR, 134); + expect_status(probe_core_delete_status, TX_DELETE_ERROR, 135); + expect_status(probe_reset_status, TX_NOT_DONE, 136); + expect_status(delete_succeeded, TX_FALSE, 137); + expect_status(probe_consistent, TX_TRUE, 138); +#else + + expect_count(callback_exit_counter, expected_exits, 139); +#endif + + expect_status(victim.tx_thread_state, TX_TERMINATED, 140); + expect_status(victim.tx_thread_suspending, TX_FALSE, 141); + expect(fully_detached(&victim), 142); + } + + if (ok_so_far() == TX_TRUE) + { + + arm_probe(TX_FALSE, TX_FALSE, TX_FALSE, TX_FALSE); + + expect_status(tx_thread_reset(&victim), TX_SUCCESS, 143); + expect_status(tx_thread_terminate(&victim), TX_SUCCESS, 144); + expect_status(tx_thread_delete(&victim), TX_SUCCESS, 145); + expect(scheduler_consistent(), 146); + } + + /* ------------------------------------------------------------------- */ + /* Scenario F: a benign callback is unaffected. The notification */ + /* ordering and counts are what they were. */ + /* ------------------------------------------------------------------- */ + + if (ok_so_far() == TX_TRUE) + { + + victim_self_terminate = TX_FALSE; + expected_exits = callback_exit_counter; + expected_entries = callback_entry_counter; + exit_saw_entry_first = TX_FALSE; + last_notify_type = PROBE_NOT_ATTEMPTED; + + arm_probe(TX_FALSE, TX_FALSE, TX_FALSE, TX_FALSE); + + expect_status(create_victim(VICTIM_PRIORITY, TX_AUTO_START), TX_SUCCESS, 150); + } + + if (ok_so_far() == TX_TRUE) + { + + tx_thread_sleep(3); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* This incarnation ran and completed, so it reported exactly one entry + and one exit, and the entry came first. The transition marker has + changed neither how often notifications are delivered nor in what + order. */ + expect_count(callback_exit_counter, expected_exits + 1, 151); + expect_count(callback_entry_counter, expected_entries + 1, 152); + expect_status(exit_saw_entry_first, TX_TRUE, 153); +#else + + expect_count(callback_exit_counter, expected_exits, 154); + expect_count(callback_entry_counter, expected_entries, 155); +#endif + + expect_status(tx_thread_delete(&victim), TX_SUCCESS, 156); + expect(scheduler_consistent(), 157); + } + + /* ------------------------------------------------------------------- */ + /* Scenario G: state and boundary cases. A thread that never entered a */ + /* terminal state, and one that is already fully detached, behave as */ + /* documented -- the new refusal applies only while the marker is set. */ + /* ------------------------------------------------------------------- */ + + if (ok_so_far() == TX_TRUE) + { + + expect_status(create_victim(VICTIM_PRIORITY, TX_DONT_START), TX_SUCCESS, 170); + + /* Suspended, never run: neither state is terminal, so both services + are refused for the reason they always were, and the marker is not + set on a thread that is not transitioning. */ + expect_status(tx_thread_delete(&victim), TX_DELETE_ERROR, 171); + expect_status(tx_thread_reset(&victim), TX_NOT_DONE, 172); + expect_status(victim.tx_thread_suspending, TX_FALSE, 173); + + /* Terminated from a suspended state: deletable immediately, and + repeatedly resettable and re-terminable in between. */ + expect_status(tx_thread_terminate(&victim), TX_SUCCESS, 174); + expect_status(victim.tx_thread_suspending, TX_FALSE, 175); + expect_status(tx_thread_reset(&victim), TX_SUCCESS, 176); + expect_status(tx_thread_terminate(&victim), TX_SUCCESS, 177); + expect_status(tx_thread_terminate(&victim), TX_SUCCESS, 178); + expect_status(tx_thread_delete(&victim), TX_SUCCESS, 179); + expect(scheduler_consistent(), 180); + } + + if (expectations_failed != 0) + { + + printf("ERROR #%u (%lu of %lu expectations failed:", + first_failure, expectations_failed, expectations_checked); + + for (index = 0; index < failed_tag_count; index++) + { + printf(" %u", failed_tags[index]); + } + + if (expectations_failed > ((unsigned long) failed_tag_count)) + { + printf(" ..."); + } + + printf(")\n"); + fflush(stdout); + test_control_return(1); + } + else + { + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + +static void victim_entry(ULONG thread_input) +{ + + (void) thread_input; + + victim_counter++; + + if (victim_take_mutex == TX_TRUE) + { + tx_mutex_get(&victim_mutex, TX_NO_WAIT); + } + + if (victim_wait_semaphore == TX_TRUE) + { + + /* Suspend on an object, so that a termination takes the non-ready + branch and runs the suspension cleanup routine. */ + tx_semaphore_get(&victim_semaphore, TX_WAIT_FOREVER); + } + + if (victim_self_terminate == TX_TRUE) + { + + /* This does not return: the termination detaches this thread and the + preemption check at the end of the service switches away from it. */ + tx_thread_terminate(tx_thread_identify()); + } + + while (victim_hold == TX_TRUE) + { + + /* Stay ready, so that a terminate issued by another thread finds this + thread on the ready list. */ + tx_thread_relinquish(); + } + + /* Returning enters the completion transition. */ +} + + +static void peer_entry(ULONG thread_input) +{ + + if (thread_input == 1) + { + peer_a_counter++; + } + else + { + peer_b_counter++; + } + + while (peers_run == TX_TRUE) + { + + /* Stay ready at the victim's priority, so that the victim's ready ring + has more than one member. */ + tx_thread_relinquish(); + } +} + + +static void replacement_entry(ULONG thread_input) +{ + + (void) thread_input; + + replacement_counter++; + + /* Only reached on a kernel that let the callback recreate the control + block. Suspend rather than return, so that the run does not depend on a + second completion transition over a control block already known to be + inconsistent. */ + tx_thread_suspend(tx_thread_identify()); +} diff --git a/test/tx/cmake/CMakeLists.txt b/test/tx/cmake/CMakeLists.txt index b2f0ab1fe..235a28d2e 100644 --- a/test/tx/cmake/CMakeLists.txt +++ b/test/tx/cmake/CMakeLists.txt @@ -61,6 +61,15 @@ add_subdirectory(${CMAKE_CURRENT_LIST_DIR}/../../.. threadx) add_subdirectory(regression) add_subdirectory(samples) +# The two configurations this change has to reach, TX_NOT_INTERRUPTABLE and +# TX_DISABLE_ERROR_CHECKING, are not among the five above and cannot be reached +# from the regression suite, which links one library per configuration. This +# directory compiles the sources concerned directly. It is listed last rather than +# beside regression on purpose: every branch in the current fix set adds an +# add_subdirectory line immediately after regression, and putting a second one +# there turns a set of clean merges into a set of one-line conflicts. +add_subdirectory(thread_transition) + # Coverage # # The gate here used to be the build type alone, and only one of the five diff --git a/test/tx/cmake/regression/CMakeLists.txt b/test/tx/cmake/regression/CMakeLists.txt index 7a0296dc1..1479a93e0 100644 --- a/test/tx/cmake/regression/CMakeLists.txt +++ b/test/tx/cmake/regression/CMakeLists.txt @@ -98,6 +98,7 @@ set(regression_test_cases ${SOURCE_DIR}/threadx_thread_sleep_terminate_test.c ${SOURCE_DIR}/threadx_thread_stack_checking_test.c ${SOURCE_DIR}/threadx_thread_terminate_delete_test.c + ${SOURCE_DIR}/threadx_thread_exit_callback_transition_test.c ${SOURCE_DIR}/threadx_thread_time_slice_change_test.c ${SOURCE_DIR}/threadx_thread_wait_abort_and_isr_test.c ${SOURCE_DIR}/threadx_thread_wait_abort_test.c diff --git a/test/tx/cmake/thread_transition/CMakeLists.txt b/test/tx/cmake/thread_transition/CMakeLists.txt new file mode 100644 index 000000000..f414ed675 --- /dev/null +++ b/test/tx/cmake/thread_transition/CMakeLists.txt @@ -0,0 +1,115 @@ +cmake_minimum_required(VERSION 3.13 FATAL_ERROR) +cmake_policy(SET CMP0057 NEW) + +project(thread_transition_test LANGUAGES C) + +set(REPO_ROOT ${CMAKE_CURRENT_LIST_DIR}/../../../..) +set(SOURCE_DIR ${REPO_ROOT}/test/tx/thread_transition) + +# TX_NOT_INTERRUPTABLE and TX_DISABLE_ERROR_CHECKING are not among the five build +# configurations this tree compiles, and the tree builds the whole ThreadX library +# once per configuration, so neither can be reached from inside the regression +# suite. Both matter to the completion and termination transitions: +# +# - TX_NOT_INTERRUPTABLE selects a different transition, in which the exit +# notification callback runs with interrupts disabled and the interruptable +# suspension path -- which is what sets and clears the transition marker in the +# configurations the tree does build -- is not used at all. The marker is set +# and cleared there by stores that exist only in that configuration, and a +# marker left set would make a normally completed thread permanently +# undeletable. +# +# - TX_DISABLE_ERROR_CHECKING removes the _txe_ wrappers, so the public names bind +# straight to the core services. The refusal lives in the core services for that +# reason, and the way to show it is to call the public names in a build with no +# wrappers. +# +# So the four sources that change are compiled directly into a test executable, once +# per combination, with recorders standing behind the scheduler services they call. +# That is the same technique the module manager tests in this tree use, for the same +# reason: the code under test cannot be reached through the library the suite links. +# +# These executables are deliberately left out of the coverage instrumentation. The +# same source compiled under different feature macros has a different line set, and +# merging those into the union the coverage report takes would confuse the figure +# rather than add to it. The coverage figure belongs to the five configurations the +# tree builds, and every line this change adds outside a TX_NOT_INTERRUPTABLE guard +# is in them. + +set(transition_kernel_sources + ${REPO_ROOT}/common/src/tx_thread_shell_entry.c + ${REPO_ROOT}/common/src/tx_thread_terminate.c + ${REPO_ROOT}/common/src/tx_thread_delete.c + ${REPO_ROOT}/common/src/tx_thread_reset.c + ${REPO_ROOT}/common/src/txe_thread_delete.c + ${REPO_ROOT}/common/src/txe_thread_reset.c + ${REPO_ROOT}/common/src/txe_thread_terminate.c + ${REPO_ROOT}/common/src/tx_thread_initialize.c) + +set(transition_sources + ${SOURCE_DIR}/threadx_thread_transition_configuration_test.c + ${transition_kernel_sources}) + +# The shim goes on the kernel sources only, not on the test. It defines +# TX_SOURCE_CODE, which is what tells tx_api.h to leave the public service names +# unmapped so that internal sources can use the core names; the test needs the +# opposite, because calling the public names and letting tx_api.h decide what they +# bind to is exactly what the TX_DISABLE_ERROR_CHECKING configuration is here to +# demonstrate. +set_source_files_properties( + ${transition_kernel_sources} + DIRECTORY ${CMAKE_CURRENT_LIST_DIR} + PROPERTIES COMPILE_OPTIONS + "-include;${SOURCE_DIR}/threadx_thread_transition_host_test_port.h") + +# Each entry is a test-name suffix, a colon, and the feature macros that define the +# configuration, separated by "|". A semicolon cannot be used as that separator: it +# is CMake's own list separator, so the foreach below would iterate the macros +# instead of the configurations. +set(transition_configurations + "ni:TX_NOT_INTERRUPTABLE" + "ni_no_error_checking:TX_NOT_INTERRUPTABLE|TX_DISABLE_ERROR_CHECKING" + "ni_no_notify:TX_NOT_INTERRUPTABLE|TX_DISABLE_NOTIFY_CALLBACKS" + "no_error_checking:TX_DISABLE_ERROR_CHECKING") + +foreach(configuration ${transition_configurations}) + + string(REPLACE ":" ";" configuration_parts ${configuration}) + list(GET configuration_parts 0 configuration_name) + list(GET configuration_parts 1 configuration_macro_text) + string(REPLACE "|" ";" configuration_macros ${configuration_macro_text}) + + set(test_name threadx_thread_transition_${configuration_name}_test) + + add_executable(${test_name} ${transition_sources}) + + target_include_directories( + ${test_name} + PRIVATE ${SOURCE_DIR} + ${REPO_ROOT}/common/inc + ${REPO_ROOT}/ports/${THREADX_ARCH}/${THREADX_TOOLCHAIN}/inc) + + target_compile_definitions(${test_name} PRIVATE ${configuration_macros}) + + # This directory is configured once per build configuration of the tree, so + # these executables inherit whichever feature macros that configuration sets -- + # which is useful, since it means the two configurations above are also seen in + # combination with stack checking and with the other four. The one that cannot + # be inherited is event tracing: the trace macros in these sources reference the + # trace component's buffer and registry, and this harness links four kernel + # sources rather than the library, so the references would not resolve. The + # trace insertions in these same sources are covered by the tree's own + # trace_build configuration, where the whole library is linked, so nothing is + # lost by turning tracing off here. Event logging is turned off for the same + # reason; no configuration of the tree enables it. + # + # The -U flags have to reach the test source as well as the kernel sources, + # because TX_ENABLE_EVENT_TRACE is visible to tx_api.h and the two must agree on + # what the headers declare. Target compile options land after the directory's + # -D flags on the command line, which is what makes the -U effective. + target_compile_options(${test_name} PRIVATE -UTX_ENABLE_EVENT_TRACE + -UTX_ENABLE_EVENT_LOG) + + add_test(${CMAKE_BUILD_TYPE}::${test_name} ${test_name}) + +endforeach() diff --git a/test/tx/regression/testcontrol.c b/test/tx/regression/testcontrol.c index e2b3f7253..00e31d9b0 100644 --- a/test/tx/regression/testcontrol.c +++ b/test/tx/regression/testcontrol.c @@ -218,6 +218,7 @@ void threadx_thread_simple_sleep_non_clear_application_define(void *); void threadx_thread_sleep_for_100ticks_application_define(void *); void threadx_thread_multiple_sleep_application_define(void *); void threadx_thread_terminate_delete_application_define(void *); +void threadx_thread_exit_callback_transition_application_define(void *); void threadx_thread_preemption_change_application_define(void *); void threadx_thread_priority_change_application_define(void *); void threadx_thread_time_slice_change_application_define(void *); @@ -335,6 +336,7 @@ TEST_ENTRY test_control_tests[] = threadx_thread_sleep_for_100ticks_application_define, threadx_thread_multiple_sleep_application_define, threadx_thread_terminate_delete_application_define, + threadx_thread_exit_callback_transition_application_define, threadx_thread_priority_change_application_define, diff --git a/test/tx/regression/threadx_thread_exit_callback_transition_test.c b/test/tx/regression/threadx_thread_exit_callback_transition_test.c new file mode 100644 index 000000000..c931085c5 --- /dev/null +++ b/test/tx/regression/threadx_thread_exit_callback_transition_test.c @@ -0,0 +1,1375 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/* This test covers the completion and termination transitions that a thread's + TX_THREAD_EXIT notification callback runs inside. + + _tx_thread_shell_entry and _tx_thread_terminate both publish the terminal + state -- TX_COMPLETED or TX_TERMINATED -- and then call the thread's exit + notification callback, before the thread has been detached from the ready + list and before either service has finished with the pointer it holds to + the control block. That terminal state is the same state _tx_thread_delete + and _tx_thread_reset accept as authorization to invalidate or rebuild the + control block, so a callback used to be able to delete the object -- and + then lawfully recreate it over the same memory -- while the scheduler was + still linked to the old incarnation, or to reset a terminated thread and + resume it back onto the ready list after termination had reported success. + + The tx_thread_suspending flag marks the transition for exactly its + duration, and delete and reset now refuse a target whose flag is still set. + The refusal is transient: TX_DELETE_ERROR and TX_NOT_DONE are errors those + two services already document, and the same call succeeds once the + transition has finished. + + What the test measures, in every scenario: + + 1. what the callback observes -- the published state, the transition + flag, and the status of each lifecycle service it can reach, + 2. that the scheduler's ready lists, priority map and execute pointer + stay consistent with the control blocks they point at, taken as one + snapshot under interrupt lockout so that the reading is not itself a + race, + 3. that the documented behaviour still works afterwards: the same delete + and reset succeed once the transition has completed, so nothing has + become permanently undeletable. + + The consequences are demonstrated rather than described, and deliberately + from the terminator's context rather than the completing thread's: + + - scenario A has the callback recreate the control block if its delete + unexpectedly succeeded, at a lower priority, so that the outcome is an + assertable disagreement -- the old priority list still heading at a + control block whose own priority field names a different list -- rather + than a fault; + - scenario B has the callback reset and then resume the target, so that a + kernel which allows the reset is caught reporting a successful + termination for a thread that is runnable again. + + Both run while the victim is a ready thread that is not the current thread. + That ordering is not cosmetic. On the Linux, Win32 and Win64 host + simulation ports TX_THREAD_DELETE_PORT_COMPLETION cancels and joins the + host thread backing the deleted thread, so a callback-side delete of the + *completing* thread destroys the host thread the callback is running on and + wedges the simulator instead of reaching an assertion. The completion + scenarios therefore come last, and the scenario gate below stops the run + before them if anything earlier has already failed. + + Every list walk is bounded, so a corrupted ring costs an assertion and not + a hang. Expectations are counted rather than short-circuited within a + scenario, so a failing kernel reports how much it failed by; progression + between scenarios is gated on there being no failures yet, so a kernel that + has already corrupted the scheduler is not driven further into it. */ + +#include +#include "tx_api.h" +#include "tx_thread.h" + + +/* Priorities. The controller sits above every thread it drives. The victim + shares its priority with two peers, so that both the multi-member and the + single-member ready-ring unlink paths are reached. RECREATE_PRIORITY is + below VICTIM_PRIORITY on purpose: see the note in the callback. */ + +#define CONTROLLER_PRIORITY 10 +#define VICTIM_PRIORITY 20 +#define RECREATE_PRIORITY 21 + +/* Upper bound on a ready-ring walk. The suite never has this many threads at + one priority, so exceeding it means the ring is broken rather than long. */ + +#define READY_RING_LIMIT 32 + +/* Sentinel for a probe slot the callback did not reach. */ + +#define PROBE_NOT_ATTEMPTED 0xFFFFFFFFUL + + +static unsigned long controller_counter = 0; +static unsigned long victim_counter = 0; +static unsigned long peer_a_counter = 0; +static unsigned long peer_b_counter = 0; +static unsigned long replacement_counter = 0; +static unsigned long callback_entry_counter = 0; +static unsigned long callback_exit_counter = 0; + +static TX_THREAD controller; +static TX_THREAD victim; +static TX_THREAD peer_a; +static TX_THREAD peer_b; +static TX_SEMAPHORE victim_semaphore; +static TX_MUTEX victim_mutex; + +static CHAR *victim_stack; +static CHAR *replacement_stack; + +/* What the victim's entry function should do before it returns. */ + +static volatile UINT victim_hold = TX_FALSE; +static volatile UINT victim_self_terminate = TX_FALSE; +static volatile UINT victim_take_mutex = TX_FALSE; +static volatile UINT victim_wait_semaphore = TX_FALSE; +static volatile UINT peers_run = TX_FALSE; + +/* What the exit callback should attempt the next time it runs. Independent + flags rather than one mode, because a delete that unexpectedly succeeds + destroys the object and would mask the reset measurement behind it. */ + +static volatile UINT probe_delete_enabled = TX_FALSE; +static volatile UINT probe_reset_enabled = TX_FALSE; +static volatile UINT probe_misc_enabled = TX_FALSE; +static volatile UINT probe_reuse_enabled = TX_FALSE; + +/* What the callback saw the last time it probed. */ + +static UINT probe_state; +static UINT probe_suspending; +static UINT probe_delete_status; +static UINT probe_core_delete_status; +static UINT probe_reset_status; +static UINT probe_core_reset_status; +static UINT probe_resume_status; +static UINT probe_suspend_status; +static UINT probe_terminate_status; +static UINT probe_create_status; +static UINT probe_consistent; +static UINT probe_ran; +static UINT delete_succeeded; + +/* Ordering witness for the notification pair. Entry and exit counts cannot + simply be compared: a victim created with TX_DONT_START never reports an + entry, and an incarnation that is reset and terminated again reports a + second exit with no second entry. What must hold is that an exit for a + thread that ran is preceded by that thread's entry. */ + +static UINT last_notify_type = PROBE_NOT_ATTEMPTED; +static UINT exit_saw_entry_first = TX_FALSE; + +/* Expectation accounting. */ + +#define FAILED_TAG_LIMIT 32 + +static unsigned long expectations_checked = 0; +static unsigned long expectations_failed = 0; +static UINT first_failure = 0; +static UINT failed_tags[FAILED_TAG_LIMIT]; +static UINT failed_tag_count = 0; + + +/* Define task prototypes. */ + +static void controller_entry(ULONG thread_input); +static void victim_entry(ULONG thread_input); +static void peer_entry(ULONG thread_input); +static void replacement_entry(ULONG thread_input); + + +/* Prototype for test control return. */ + +void test_control_return(UINT status); + + +/* Record one expectation. tag identifies it in the failure report; the first + failing tag is the number the suite prints, so tags are allocated in the + order the expectations are written. */ + +static void expect(UINT condition, UINT tag) +{ + + expectations_checked++; + + if (condition != TX_TRUE) + { + + expectations_failed++; + + if (first_failure == 0) + { + first_failure = tag; + } + + /* Keep the tags, so that a failing kernel reports which expectations + it failed rather than only the first and a total. */ + if (failed_tag_count < FAILED_TAG_LIMIT) + { + failed_tags[failed_tag_count] = tag; + failed_tag_count++; + } + } +} + + +static void expect_status(UINT actual, UINT wanted, UINT tag) +{ + + if (actual == wanted) + { + expect(TX_TRUE, tag); + } + else + { + expect(TX_FALSE, tag); + } +} + + +static void expect_pointer(void *actual, void *wanted, UINT tag) +{ + + if (actual == wanted) + { + expect(TX_TRUE, tag); + } + else + { + expect(TX_FALSE, tag); + } +} + + +static void expect_count(unsigned long actual, unsigned long wanted, UINT tag) +{ + + if (actual == wanted) + { + expect(TX_TRUE, tag); + } + else + { + expect(TX_FALSE, tag); + } +} + + +/* Walk one ready ring and report whether thread_ptr is a member of it. The + walk is bounded, so a ring that does not close is reported as a + non-membership rather than spun on for ever. */ + +static UINT ready_ring_contains(UINT priority, TX_THREAD *thread_ptr) +{ + +TX_THREAD *walk_ptr; +TX_THREAD *head_ptr; +UINT steps; +UINT found; + + + found = TX_FALSE; + head_ptr = _tx_thread_priority_list[priority]; + walk_ptr = head_ptr; + steps = 0; + + while ((walk_ptr != TX_NULL) && (steps < READY_RING_LIMIT) && (found == TX_FALSE)) + { + + if (walk_ptr == thread_ptr) + { + found = TX_TRUE; + } + + walk_ptr = walk_ptr -> tx_thread_ready_next; + steps++; + + /* The ring has closed. */ + if (walk_ptr == head_ptr) + { + walk_ptr = TX_NULL; + } + } + + return(found); +} + + +/* Take one snapshot of the scheduler's ready structures and check that they + agree with the control blocks they point at. + + This is the assertion the pre-fix behaviour fails. A callback that deletes + the victim and recreates it at another priority leaves the old priority list + heading at that control block while the block's own priority field names the + new list, and leaves the old priority's map bit set with nothing behind it. + Neither disagreement needs a fault to be visible. + + The whole snapshot is taken under interrupt lockout -- which is the global + SMP protection on an SMP port -- so that reading the scheduler's state is + not itself a race against another core. + + transitioning names the one thread that is allowed to be on a ready list + without being ready, which is precisely the thread whose completion or + termination transition is in progress: the terminal state is published + before the detachment, so inside the callback the victim is legitimately a + TX_COMPLETED or TX_TERMINATED member of its ready ring. That single + exemption is from the state clause only. Every other clause, and in + particular the clause that requires a ready-list member to agree that this + is its priority -- the one a callback-side delete and recreate breaks -- + still applies to it. */ + +static UINT scheduler_consistent_except(TX_THREAD *transitioning) +{ + +TX_INTERRUPT_SAVE_AREA + +TX_THREAD *head_ptr; +TX_THREAD *walk_ptr; +TX_THREAD *execute_ptr; +UINT priority; +UINT steps; +UINT consistent; +#ifdef TX_THREAD_SMP_MAX_CORES +UINT core; +#endif + + + consistent = TX_TRUE; + + TX_DISABLE + + for (priority = 0; priority < ((UINT) TX_MAX_PRIORITIES); priority++) + { + + head_ptr = _tx_thread_priority_list[priority]; + +#if TX_MAX_PRIORITIES <= 32 + + /* A priority with a ready list must have its map bit set, and a + priority with no ready list must not. */ + if (head_ptr == TX_NULL) + { + if ((_tx_thread_priority_maps[0] & (((ULONG) 1) << priority)) != ((ULONG) 0)) + { + consistent = TX_FALSE; + } + } + else + { + if ((_tx_thread_priority_maps[0] & (((ULONG) 1) << priority)) == ((ULONG) 0)) + { + consistent = TX_FALSE; + } + } +#endif + + walk_ptr = head_ptr; + steps = 0; + + while ((walk_ptr != TX_NULL) && (steps < READY_RING_LIMIT)) + { + + /* Every thread on a ready list must be a live thread, must be + ready, and must agree that this is its priority. */ + if (walk_ptr -> tx_thread_id != TX_THREAD_ID) + { + consistent = TX_FALSE; + } + + if ((walk_ptr -> tx_thread_state != TX_READY) && (walk_ptr != transitioning)) + { + consistent = TX_FALSE; + } + + if (walk_ptr -> tx_thread_priority != priority) + { + consistent = TX_FALSE; + } + + /* The ring must be doubly linked. */ + if (walk_ptr -> tx_thread_ready_next -> tx_thread_ready_previous != walk_ptr) + { + consistent = TX_FALSE; + } + + walk_ptr = walk_ptr -> tx_thread_ready_next; + steps++; + + if (walk_ptr == head_ptr) + { + walk_ptr = TX_NULL; + } + } + + /* A ring that did not close inside the bound is broken. */ + if (walk_ptr != TX_NULL) + { + consistent = TX_FALSE; + } + } + + /* Whatever the scheduler has selected to execute must be a member of the + ready list that its own priority field names. */ +#ifdef TX_THREAD_SMP_MAX_CORES + + for (core = 0; core < ((UINT) TX_THREAD_SMP_MAX_CORES); core++) + { + + execute_ptr = _tx_thread_execute_ptr[core]; + + if (execute_ptr != TX_NULL) + { + if (ready_ring_contains(execute_ptr -> tx_thread_priority, execute_ptr) == TX_FALSE) + { + consistent = TX_FALSE; + } + } + } +#else + + execute_ptr = _tx_thread_execute_ptr; + + if (execute_ptr != TX_NULL) + { + if (ready_ring_contains(execute_ptr -> tx_thread_priority, execute_ptr) == TX_FALSE) + { + consistent = TX_FALSE; + } + } +#endif + + TX_RESTORE + + return(consistent); +} + + +static UINT scheduler_consistent(void) +{ + return(scheduler_consistent_except(TX_NULL)); +} + + +/* Report whether thread_ptr is absent from every ready list and from every + execute slot, which is what a completed or terminated thread must be once + its transition has finished. */ + +static UINT fully_detached(TX_THREAD *thread_ptr) +{ + +TX_INTERRUPT_SAVE_AREA + +UINT priority; +UINT detached; +#ifdef TX_THREAD_SMP_MAX_CORES +UINT core; +#endif + + + detached = TX_TRUE; + + TX_DISABLE + + for (priority = 0; priority < ((UINT) TX_MAX_PRIORITIES); priority++) + { + if (ready_ring_contains(priority, thread_ptr) == TX_TRUE) + { + detached = TX_FALSE; + } + } + +#ifdef TX_THREAD_SMP_MAX_CORES + + for (core = 0; core < ((UINT) TX_THREAD_SMP_MAX_CORES); core++) + { + if (_tx_thread_execute_ptr[core] == thread_ptr) + { + detached = TX_FALSE; + } + } +#else + + if (_tx_thread_execute_ptr == thread_ptr) + { + detached = TX_FALSE; + } +#endif + + TX_RESTORE + + return(detached); +} + + +static void arm_probe(UINT probe_delete, UINT probe_reset, UINT probe_misc, UINT probe_reuse) +{ + + probe_state = PROBE_NOT_ATTEMPTED; + probe_suspending = PROBE_NOT_ATTEMPTED; + probe_delete_status = PROBE_NOT_ATTEMPTED; + probe_core_delete_status = PROBE_NOT_ATTEMPTED; + probe_reset_status = PROBE_NOT_ATTEMPTED; + probe_core_reset_status = PROBE_NOT_ATTEMPTED; + probe_resume_status = PROBE_NOT_ATTEMPTED; + probe_suspend_status = PROBE_NOT_ATTEMPTED; + probe_terminate_status = PROBE_NOT_ATTEMPTED; + probe_create_status = PROBE_NOT_ATTEMPTED; + probe_consistent = PROBE_NOT_ATTEMPTED; + probe_ran = TX_FALSE; + delete_succeeded = TX_FALSE; + + probe_delete_enabled = probe_delete; + probe_reset_enabled = probe_reset; + probe_misc_enabled = probe_misc; + probe_reuse_enabled = probe_reuse; +} + + +/* The exit notification callback. Everything it learns is recorded for the + controller to check; it prints nothing and it never suspends, so it obeys + the one restriction the manual places on a notification callback. */ + +static void entry_exit_notify(TX_THREAD *thread_ptr, UINT type) +{ + + /* Only the victim's notifications are of interest. Its control block is + reused across scenarios, so the pointer is the identity. */ + if (thread_ptr != &victim) + { + return; + } + + if (type == TX_THREAD_ENTRY) + { + callback_entry_counter++; + last_notify_type = TX_THREAD_ENTRY; + return; + } + + if (type != TX_THREAD_EXIT) + { + return; + } + + callback_exit_counter++; + + if (last_notify_type == TX_THREAD_ENTRY) + { + exit_saw_entry_first = TX_TRUE; + } + + last_notify_type = TX_THREAD_EXIT; + + if ((probe_delete_enabled == TX_FALSE) && (probe_reset_enabled == TX_FALSE) && + (probe_misc_enabled == TX_FALSE)) + { + return; + } + + probe_ran = TX_TRUE; + + /* What the kernel has published about the thread at this point. */ + probe_state = thread_ptr -> tx_thread_state; + probe_suspending = thread_ptr -> tx_thread_suspending; + + /* None of the services below has a suspension option, which is the only + thing the manual forbids a callback from using, so every one of them is + reachable from here. + + Where a service is expected to refuse, the core service is called after + the _txe_ wrapper as well. The wrapper is what an ordinary build + reaches; the core service is what a TX_DISABLE_ERROR_CHECKING build + reaches directly, and the refusal has to live there so that disabling + error checking cannot disable it. The core call is made only when the + wrapper already refused, so that a kernel which allows the operation is + not asked to perform it twice. */ + + if (probe_delete_enabled == TX_TRUE) + { + + probe_delete_status = tx_thread_delete(thread_ptr); + + if (probe_delete_status == TX_SUCCESS) + { + delete_succeeded = TX_TRUE; + } + else + { + + probe_core_delete_status = _tx_thread_delete(thread_ptr); + + if (probe_core_delete_status == TX_SUCCESS) + { + delete_succeeded = TX_TRUE; + } + } + + /* Recreate the control block only if the delete unexpectedly + succeeded. On a fixed kernel this never runs. On an unfixed one it + is the lawful next step after a successful delete, and it is what + turns the window into an observable inconsistency: tx_thread_create + zeroes the whole control block, and the auto-start then links it + onto RECREATE_PRIORITY's ready list while the old incarnation is + still the head of VICTIM_PRIORITY's. + + RECREATE_PRIORITY is the lower of the two so that the stale head is + the one the scheduler selects from, and so that the ring at the new + priority has a single member. Recreating at the same priority would + instead have the auto-start write through the control block's + freshly zeroed ready_previous pointer, which is a fault rather than + an assertion. */ + if ((delete_succeeded == TX_TRUE) && (probe_reuse_enabled == TX_TRUE)) + { + probe_create_status = tx_thread_create(thread_ptr, "replacement", + replacement_entry, 0, + replacement_stack, + TEST_STACK_SIZE_PRINTF, + RECREATE_PRIORITY, RECREATE_PRIORITY, + TX_NO_TIME_SLICE, TX_AUTO_START); + } + } + + if ((probe_reset_enabled == TX_TRUE) && (delete_succeeded == TX_FALSE)) + { + + probe_reset_status = tx_thread_reset(thread_ptr); + + if (probe_reset_status != TX_SUCCESS) + { + probe_core_reset_status = _tx_thread_reset(thread_ptr); + } + + /* Follow the reset with the resume that the reset would have unlocked. + On a fixed kernel the state is still terminal and the resume is + refused. On an unfixed one the reset has moved the state to + TX_SUSPENDED, the resume finds a suspending thread whose state is no + longer terminal, clears the flag and puts the thread back on the + ready list -- and the outer service then skips the removal and + reports success for a termination that did not happen. */ + probe_resume_status = tx_thread_resume(thread_ptr); + } + + if ((probe_misc_enabled == TX_TRUE) && (delete_succeeded == TX_FALSE)) + { + probe_suspend_status = tx_thread_suspend(thread_ptr); + probe_terminate_status = tx_thread_terminate(thread_ptr); + } + + probe_consistent = scheduler_consistent_except(thread_ptr); +} + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_thread_exit_callback_transition_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + status = tx_thread_create(&controller, "controller", controller_entry, 0, + pointer, TEST_STACK_SIZE_PRINTF, + CONTROLLER_PRIORITY, CONTROLLER_PRIORITY, + TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + status += tx_thread_create(&peer_a, "peer a", peer_entry, 1, + pointer, TEST_STACK_SIZE_PRINTF, + VICTIM_PRIORITY, VICTIM_PRIORITY, + TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + status += tx_thread_create(&peer_b, "peer b", peer_entry, 2, + pointer, TEST_STACK_SIZE_PRINTF, + VICTIM_PRIORITY, VICTIM_PRIORITY, + TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* The victim's control block is created and destroyed repeatedly, so its + two stacks are set aside here rather than per scenario. */ + victim_stack = pointer; + pointer = pointer + TEST_STACK_SIZE_PRINTF; + replacement_stack = pointer; + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + status += tx_semaphore_create(&victim_semaphore, "victim semaphore", 0); + status += tx_mutex_create(&victim_mutex, "victim mutex", TX_INHERIT); + + if (status != TX_SUCCESS) + { + + printf("Running Thread Exit Callback Transition Test............... ERROR #1\n"); + test_control_return(1); + } + +#ifdef TX_THREAD_SMP_MAX_CORES + + /* Confine every thread this test drives to core 0. The measurements below + are of global scheduler structures at chosen moments, and letting the + peers and the victim run on other cores would make them a race against + the test rather than a property of it. A victim executing on a + different core when termination begins is deliberately covered by a + separate SMP test, so that the deterministic cases here cannot be made + flaky by it. */ + status = tx_thread_smp_core_exclude(&controller, 0xE); + status += tx_thread_smp_core_exclude(&peer_a, 0xE); + status += tx_thread_smp_core_exclude(&peer_b, 0xE); + + if (status != TX_SUCCESS) + { + + printf("Running Thread Exit Callback Transition Test............... ERROR #2\n"); + test_control_return(1); + } +#endif +} + + +/* Create the victim over its own control block, with the exit callback + registered. The notify status is folded into the result according to what + the configuration supports. */ + +static UINT create_victim(UINT priority, UINT auto_start) +{ + +UINT status; +UINT notify_status; + + + status = tx_thread_create(&victim, "victim", victim_entry, 0, + victim_stack, TEST_STACK_SIZE_PRINTF, + priority, priority, TX_NO_TIME_SLICE, auto_start); + + notify_status = tx_thread_entry_exit_notify(&victim, entry_exit_notify); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + if (notify_status != TX_SUCCESS) + { + status = notify_status; + } +#else + + /* Notification is compiled out, so the registration is expected to be + refused and the callback never runs. */ + if (notify_status != TX_FEATURE_NOT_ENABLED) + { + status = notify_status; + } +#endif + +#ifdef TX_THREAD_SMP_MAX_CORES + + if (status == TX_SUCCESS) + { + status = tx_thread_smp_core_exclude(&victim, 0xE); + } +#endif + + return(status); +} + + +/* The gate between scenarios. A kernel that has already failed an expectation + has, in these scenarios, already left the scheduler inconsistent, and + driving it further would report nothing more while risking a wedge instead + of a verdict. */ + +static UINT ok_so_far(void) +{ + +UINT result; + + + result = TX_FALSE; + + if (expectations_failed == 0) + { + result = TX_TRUE; + } + + return(result); +} + + +static void controller_entry(ULONG thread_input) +{ + +ULONG expected_exits; +ULONG expected_entries; +UINT index; + + + (void) thread_input; + + controller_counter++; + expected_exits = 0; + expected_entries = 0; + + /* Inform user. */ + printf("Running Thread Exit Callback Transition Test............... "); + + /* The scheduler must be self-consistent before anything is measured, so + that a later failure is attributable to this test. */ + expect(scheduler_consistent(), 10); + + /* ------------------------------------------------------------------- */ + /* Scenario A: terminate a ready target that is not the current thread, */ + /* with two peers ready at the same priority. The callback attempts */ + /* the delete, and recreates the control block if it succeeded. */ + /* ------------------------------------------------------------------- */ + + if (ok_so_far() == TX_TRUE) + { + + peers_run = TX_TRUE; + victim_hold = TX_TRUE; + + expect_status(tx_thread_resume(&peer_a), TX_SUCCESS, 11); + expect_status(tx_thread_resume(&peer_b), TX_SUCCESS, 12); + + arm_probe(TX_TRUE, TX_FALSE, TX_FALSE, TX_TRUE); + + expect_status(create_victim(VICTIM_PRIORITY, TX_AUTO_START), TX_SUCCESS, 13); + } + + if (ok_so_far() == TX_TRUE) + { + + /* Let the victim and both peers become ready and start spinning, so + that the victim's unlink is from a multi-member ring. */ + tx_thread_sleep(3); + + expect_status(victim.tx_thread_state, TX_READY, 14); + expect(ready_ring_contains(VICTIM_PRIORITY, &victim), 15); + expect(ready_ring_contains(VICTIM_PRIORITY, &peer_a), 16); + expect(ready_ring_contains(VICTIM_PRIORITY, &peer_b), 17); + } + + if (ok_so_far() == TX_TRUE) + { + + expect_status(tx_thread_terminate(&victim), TX_SUCCESS, 18); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + expect(probe_ran, 19); + + /* The callback runs after the terminal state has been published, and + inside the transition, which is what the flag records. */ + expect_status(probe_state, TX_TERMINATED, 20); + expect_status(probe_suspending, TX_TRUE, 21); + + /* Both the wrapper and the core service must refuse. */ + expect_status(probe_delete_status, TX_DELETE_ERROR, 22); + expect_status(probe_core_delete_status, TX_DELETE_ERROR, 23); + + /* So the recreate never happened and nothing is inconsistent. */ + expect_status(delete_succeeded, TX_FALSE, 24); + expect_status(probe_create_status, PROBE_NOT_ATTEMPTED, 25); + expect_status(probe_consistent, TX_TRUE, 26); + expect_count(replacement_counter, 0, 27); +#endif + + /* After the service returns the termination is complete: the state is + terminal, the marker is clear, the target is on no ready list and in + no execute slot, and the peers are undisturbed. */ + expect_status(victim.tx_thread_state, TX_TERMINATED, 28); + expect_status(victim.tx_thread_suspending, TX_FALSE, 29); + expect(fully_detached(&victim), 30); + expect(ready_ring_contains(VICTIM_PRIORITY, &peer_a), 31); + expect(ready_ring_contains(VICTIM_PRIORITY, &peer_b), 32); + expect(scheduler_consistent(), 33); + } + + if (ok_so_far() == TX_TRUE) + { + + arm_probe(TX_FALSE, TX_FALSE, TX_FALSE, TX_FALSE); + + /* The documented behaviour is available again. */ + expect_status(tx_thread_delete(&victim), TX_SUCCESS, 34); + } + + /* ------------------------------------------------------------------- */ + /* Scenario B: the same termination, but the callback attempts a reset */ + /* and then the resume that a successful reset would have unlocked. */ + /* */ + /* This is the leg where the transition check is the only thing */ + /* standing between the callback and a reset of a thread that is still */ + /* on the ready list. Without it the reset succeeds, the resume */ + /* clears the suspending flag and restores TX_READY, the outer service */ + /* then finds the flag clear and skips the removal, and */ + /* tx_thread_terminate returns TX_SUCCESS for a runnable thread. */ + /* ------------------------------------------------------------------- */ + + if (ok_so_far() == TX_TRUE) + { + + arm_probe(TX_FALSE, TX_TRUE, TX_FALSE, TX_FALSE); + + expect_status(create_victim(VICTIM_PRIORITY, TX_AUTO_START), TX_SUCCESS, 40); + } + + if (ok_so_far() == TX_TRUE) + { + + tx_thread_sleep(3); + + expect_status(victim.tx_thread_state, TX_READY, 41); + expect_status(tx_thread_terminate(&victim), TX_SUCCESS, 42); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + expect(probe_ran, 43); + expect_status(probe_state, TX_TERMINATED, 44); + expect_status(probe_suspending, TX_TRUE, 45); + + /* The discriminating leg. The target is not the current thread and + its published state is terminal, so both of the conditions the + service tested before this fix are satisfied. */ + expect_status(probe_reset_status, TX_NOT_DONE, 46); + expect_status(probe_core_reset_status, TX_NOT_DONE, 47); + + /* With the reset refused, the state is still terminal, so the resume + cannot reach the branch that would void the termination. */ + expect_status(probe_resume_status, TX_RESUME_ERROR, 48); + expect_status(probe_consistent, TX_TRUE, 49); +#endif + + /* And the termination stands. A kernel that let the callback reset + and resume the target arrives here with the victim ready to run. */ + expect_status(victim.tx_thread_state, TX_TERMINATED, 50); + expect_status(victim.tx_thread_suspending, TX_FALSE, 51); + expect(fully_detached(&victim), 52); + expect(scheduler_consistent(), 53); + } + + if (ok_so_far() == TX_TRUE) + { + + arm_probe(TX_FALSE, TX_FALSE, TX_FALSE, TX_FALSE); + + expect_status(tx_thread_reset(&victim), TX_SUCCESS, 54); + expect_status(tx_thread_terminate(&victim), TX_SUCCESS, 55); + expect_status(tx_thread_delete(&victim), TX_SUCCESS, 56); + } + + /* Retire the peers, so that the ring drops to a single member and then to + none, and check consistency across both unlinks. */ + + if (ok_so_far() == TX_TRUE) + { + + peers_run = TX_FALSE; + tx_thread_sleep(3); + + expect_status(peer_a.tx_thread_state, TX_COMPLETED, 57); + expect_status(peer_b.tx_thread_state, TX_COMPLETED, 58); + expect(scheduler_consistent(), 59); + expect_status(tx_thread_delete(&peer_a), TX_SUCCESS, 60); + expect_status(tx_thread_delete(&peer_b), TX_SUCCESS, 61); + } + + /* ------------------------------------------------------------------- */ + /* Scenario C: terminate a target suspended on an object, so that the */ + /* non-ready branch of _tx_thread_terminate runs -- suspension cleanup, */ + /* the terminated extension, the callback, and mutex release, in that */ + /* order. That branch used to clear the marker before the callback */ + /* rather than after the last dereference of the target. */ + /* ------------------------------------------------------------------- */ + + if (ok_so_far() == TX_TRUE) + { + + arm_probe(TX_TRUE, TX_TRUE, TX_FALSE, TX_FALSE); + victim_hold = TX_FALSE; + victim_take_mutex = TX_TRUE; + victim_wait_semaphore = TX_TRUE; + + expect_status(create_victim(VICTIM_PRIORITY, TX_AUTO_START), TX_SUCCESS, 70); + } + + if (ok_so_far() == TX_TRUE) + { + + /* Let the victim take the mutex and suspend on the semaphore. */ + tx_thread_sleep(3); + + expect_status(victim.tx_thread_state, TX_SEMAPHORE_SUSP, 71); + expect_pointer(victim_mutex.tx_mutex_owner, &victim, 72); + } + + if (ok_so_far() == TX_TRUE) + { + + expect_status(tx_thread_terminate(&victim), TX_SUCCESS, 73); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + expect(probe_ran, 74); + expect_status(probe_state, TX_TERMINATED, 75); + + /* The discriminating leg for this branch. The marker used to be + cleared before this point, which left the callback free to delete or + reset a control block that the service still had mutex-release + processing to do against. */ + expect_status(probe_suspending, TX_TRUE, 76); + expect_status(probe_delete_status, TX_DELETE_ERROR, 77); + expect_status(probe_core_delete_status, TX_DELETE_ERROR, 78); + expect_status(probe_reset_status, TX_NOT_DONE, 79); + expect_status(probe_core_reset_status, TX_NOT_DONE, 80); + expect_status(probe_resume_status, TX_RESUME_ERROR, 81); + expect_status(delete_succeeded, TX_FALSE, 82); + expect_status(probe_consistent, TX_TRUE, 83); +#endif + + /* The marker is cleared at the safe point, after the mutex release, + and the mutex the terminated thread owned has been given up. The + value of the flag during the release itself is not observable from + application code; what is observable is that there is exactly one + clear site and that it sits downstream of the release. */ + expect_status(victim.tx_thread_suspending, TX_FALSE, 84); + expect_pointer(victim_mutex.tx_mutex_owner, TX_NULL, 85); + expect_count((unsigned long) victim_semaphore.tx_semaphore_suspended_count, 0, 86); + expect(fully_detached(&victim), 87); + expect(scheduler_consistent(), 88); + } + + if (ok_so_far() == TX_TRUE) + { + + arm_probe(TX_FALSE, TX_FALSE, TX_FALSE, TX_FALSE); + + expect_status(tx_thread_delete(&victim), TX_SUCCESS, 89); + } + + /* ------------------------------------------------------------------- */ + /* Scenario D: natural completion, victim alone at its priority. */ + /* */ + /* The callback here runs on the completing thread itself, so a */ + /* callback-side delete that succeeds destroys the host thread on the */ + /* simulation ports. This scenario is therefore placed after the ones */ + /* that reach an assertion, and the gate above stops the run before it */ + /* if any of them has already failed. */ + /* ------------------------------------------------------------------- */ + + if (ok_so_far() == TX_TRUE) + { + + arm_probe(TX_TRUE, TX_TRUE, TX_TRUE, TX_FALSE); + victim_take_mutex = TX_FALSE; + victim_wait_semaphore = TX_FALSE; + + expect_status(create_victim(VICTIM_PRIORITY, TX_AUTO_START), TX_SUCCESS, 100); + } + + if (ok_so_far() == TX_TRUE) + { + + /* Let the victim run to completion, so that its callback runs inside + the completion transition. */ + tx_thread_sleep(3); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + expect(probe_ran, 101); + expect_status(probe_state, TX_COMPLETED, 102); + expect_status(probe_suspending, TX_TRUE, 103); + expect_status(probe_delete_status, TX_DELETE_ERROR, 104); + expect_status(probe_core_delete_status, TX_DELETE_ERROR, 105); + + /* Reset of the running thread is refused for two independent reasons + here -- it is the current thread, and its transition is in progress + -- so this leg is a guard rather than a discriminator. Scenario B + is where the transition check is the only thing refusing a reset. */ + expect_status(probe_reset_status, TX_NOT_DONE, 106); + expect_status(probe_core_reset_status, TX_NOT_DONE, 107); + + /* A completed thread is neither resumable nor suspendable, and + terminating one is a documented no-op. */ + expect_status(probe_resume_status, TX_RESUME_ERROR, 108); + expect_status(probe_suspend_status, TX_SUSPEND_ERROR, 109); + expect_status(probe_terminate_status, TX_SUCCESS, 110); + expect_status(delete_succeeded, TX_FALSE, 111); + expect_status(probe_consistent, TX_TRUE, 112); +#endif + + /* The transition has finished, so the calls the callback was refused + must succeed. The refusal is transient and nothing has become + permanently undeletable. */ + expect_status(victim.tx_thread_state, TX_COMPLETED, 113); + expect_status(victim.tx_thread_suspending, TX_FALSE, 114); + expect(fully_detached(&victim), 115); + expect(scheduler_consistent(), 116); + expect(((victim_counter > 0) ? TX_TRUE : TX_FALSE), 117); + } + + if (ok_so_far() == TX_TRUE) + { + + arm_probe(TX_FALSE, TX_FALSE, TX_FALSE, TX_FALSE); + + /* Reset, so that the documented reset of a completed thread is covered + on a target whose transition has finished, and so that the + reset/terminate/delete order is exercised on this branch too. */ + expect_status(tx_thread_reset(&victim), TX_SUCCESS, 118); + expect_status(victim.tx_thread_state, TX_SUSPENDED, 119); + expect_status(tx_thread_delete(&victim), TX_DELETE_ERROR, 120); + expect_status(tx_thread_terminate(&victim), TX_SUCCESS, 121); + expect_status(victim.tx_thread_suspending, TX_FALSE, 122); + expect_status(tx_thread_delete(&victim), TX_SUCCESS, 123); + } + + /* A safe post-completion recreate at a different priority, which is the + lifecycle the callback was refused, performed at the point it is + legitimate. It exercises the priority map and the list heads for a + recreate that moves priority as well as for one that does not. */ + + if (ok_so_far() == TX_TRUE) + { + + expect_status(create_victim(RECREATE_PRIORITY, TX_AUTO_START), TX_SUCCESS, 124); + + tx_thread_sleep(3); + + expect_status(victim.tx_thread_state, TX_COMPLETED, 125); + expect(scheduler_consistent(), 126); + expect_status(tx_thread_delete(&victim), TX_SUCCESS, 127); + } + + /* ------------------------------------------------------------------- */ + /* Scenario E: self termination. The callback fires once, in the */ + /* victim's own context, the lifecycle mutation is refused there too, */ + /* and another thread can complete the lifecycle afterwards. */ + /* ------------------------------------------------------------------- */ + + if (ok_so_far() == TX_TRUE) + { + + victim_self_terminate = TX_TRUE; + expected_exits = callback_exit_counter; + + arm_probe(TX_TRUE, TX_TRUE, TX_FALSE, TX_FALSE); + + expect_status(create_victim(VICTIM_PRIORITY, TX_AUTO_START), TX_SUCCESS, 130); + } + + if (ok_so_far() == TX_TRUE) + { + + tx_thread_sleep(3); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Exactly one exit notification, even though the thread terminated + itself from inside its own entry function. */ + expect_count(callback_exit_counter, expected_exits + 1, 131); + expect_status(probe_state, TX_TERMINATED, 132); + expect_status(probe_suspending, TX_TRUE, 133); + expect_status(probe_delete_status, TX_DELETE_ERROR, 134); + expect_status(probe_core_delete_status, TX_DELETE_ERROR, 135); + expect_status(probe_reset_status, TX_NOT_DONE, 136); + expect_status(delete_succeeded, TX_FALSE, 137); + expect_status(probe_consistent, TX_TRUE, 138); +#else + + expect_count(callback_exit_counter, expected_exits, 139); +#endif + + expect_status(victim.tx_thread_state, TX_TERMINATED, 140); + expect_status(victim.tx_thread_suspending, TX_FALSE, 141); + expect(fully_detached(&victim), 142); + } + + if (ok_so_far() == TX_TRUE) + { + + arm_probe(TX_FALSE, TX_FALSE, TX_FALSE, TX_FALSE); + + expect_status(tx_thread_reset(&victim), TX_SUCCESS, 143); + expect_status(tx_thread_terminate(&victim), TX_SUCCESS, 144); + expect_status(tx_thread_delete(&victim), TX_SUCCESS, 145); + expect(scheduler_consistent(), 146); + } + + /* ------------------------------------------------------------------- */ + /* Scenario F: a benign callback is unaffected. The notification */ + /* ordering and counts are what they were. */ + /* ------------------------------------------------------------------- */ + + if (ok_so_far() == TX_TRUE) + { + + victim_self_terminate = TX_FALSE; + expected_exits = callback_exit_counter; + expected_entries = callback_entry_counter; + exit_saw_entry_first = TX_FALSE; + last_notify_type = PROBE_NOT_ATTEMPTED; + + arm_probe(TX_FALSE, TX_FALSE, TX_FALSE, TX_FALSE); + + expect_status(create_victim(VICTIM_PRIORITY, TX_AUTO_START), TX_SUCCESS, 150); + } + + if (ok_so_far() == TX_TRUE) + { + + tx_thread_sleep(3); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* This incarnation ran and completed, so it reported exactly one entry + and one exit, and the entry came first. The transition marker has + changed neither how often notifications are delivered nor in what + order. */ + expect_count(callback_exit_counter, expected_exits + 1, 151); + expect_count(callback_entry_counter, expected_entries + 1, 152); + expect_status(exit_saw_entry_first, TX_TRUE, 153); +#else + + expect_count(callback_exit_counter, expected_exits, 154); + expect_count(callback_entry_counter, expected_entries, 155); +#endif + + expect_status(tx_thread_delete(&victim), TX_SUCCESS, 156); + expect(scheduler_consistent(), 157); + } + + /* ------------------------------------------------------------------- */ + /* Scenario G: state and boundary cases. A thread that never entered a */ + /* terminal state, and one that is already fully detached, behave as */ + /* documented -- the new refusal applies only while the marker is set. */ + /* ------------------------------------------------------------------- */ + + if (ok_so_far() == TX_TRUE) + { + + expect_status(create_victim(VICTIM_PRIORITY, TX_DONT_START), TX_SUCCESS, 170); + + /* Suspended, never run: neither state is terminal, so both services + are refused for the reason they always were, and the marker is not + set on a thread that is not transitioning. */ + expect_status(tx_thread_delete(&victim), TX_DELETE_ERROR, 171); + expect_status(tx_thread_reset(&victim), TX_NOT_DONE, 172); + expect_status(victim.tx_thread_suspending, TX_FALSE, 173); + + /* Terminated from a suspended state: deletable immediately, and + repeatedly resettable and re-terminable in between. */ + expect_status(tx_thread_terminate(&victim), TX_SUCCESS, 174); + expect_status(victim.tx_thread_suspending, TX_FALSE, 175); + expect_status(tx_thread_reset(&victim), TX_SUCCESS, 176); + expect_status(tx_thread_terminate(&victim), TX_SUCCESS, 177); + expect_status(tx_thread_terminate(&victim), TX_SUCCESS, 178); + expect_status(tx_thread_delete(&victim), TX_SUCCESS, 179); + expect(scheduler_consistent(), 180); + } + + if (expectations_failed != 0) + { + + printf("ERROR #%u (%lu of %lu expectations failed:", + first_failure, expectations_failed, expectations_checked); + + for (index = 0; index < failed_tag_count; index++) + { + printf(" %u", failed_tags[index]); + } + + if (expectations_failed > ((unsigned long) failed_tag_count)) + { + printf(" ..."); + } + + printf(")\n"); + fflush(stdout); + test_control_return(1); + } + else + { + printf("SUCCESS!\n"); + test_control_return(0); + } +} + + +static void victim_entry(ULONG thread_input) +{ + + (void) thread_input; + + victim_counter++; + + if (victim_take_mutex == TX_TRUE) + { + tx_mutex_get(&victim_mutex, TX_NO_WAIT); + } + + if (victim_wait_semaphore == TX_TRUE) + { + + /* Suspend on an object, so that a termination takes the non-ready + branch and runs the suspension cleanup routine. */ + tx_semaphore_get(&victim_semaphore, TX_WAIT_FOREVER); + } + + if (victim_self_terminate == TX_TRUE) + { + + /* This does not return: the termination detaches this thread and the + preemption check at the end of the service switches away from it. */ + tx_thread_terminate(tx_thread_identify()); + } + + while (victim_hold == TX_TRUE) + { + + /* Stay ready, so that a terminate issued by another thread finds this + thread on the ready list. */ + tx_thread_relinquish(); + } + + /* Returning enters the completion transition. */ +} + + +static void peer_entry(ULONG thread_input) +{ + + if (thread_input == 1) + { + peer_a_counter++; + } + else + { + peer_b_counter++; + } + + while (peers_run == TX_TRUE) + { + + /* Stay ready at the victim's priority, so that the victim's ready ring + has more than one member. */ + tx_thread_relinquish(); + } +} + + +static void replacement_entry(ULONG thread_input) +{ + + (void) thread_input; + + replacement_counter++; + + /* Only reached on a kernel that let the callback recreate the control + block. Suspend rather than return, so that the run does not depend on a + second completion transition over a control block already known to be + inconsistent. */ + tx_thread_suspend(tx_thread_identify()); +} diff --git a/test/tx/thread_transition/threadx_thread_transition_configuration_test.c b/test/tx/thread_transition/threadx_thread_transition_configuration_test.c new file mode 100644 index 000000000..fe6acb7e5 --- /dev/null +++ b/test/tx/thread_transition/threadx_thread_transition_configuration_test.c @@ -0,0 +1,607 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Test */ +/** */ +/** Thread lifecycle transition configuration coverage */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +/* The two configurations that matter to this change and that neither + regression tree builds are TX_NOT_INTERRUPTABLE and + TX_DISABLE_ERROR_CHECKING. This executable is built once for each + combination of them, against the four sources that change, and drives the + completion and termination transitions directly. + + Why each one needs its own build rather than a case in the in-tree test: + + - TX_NOT_INTERRUPTABLE selects a different transition. There the exit + notification callback runs with interrupts still disabled and the + interruptable suspension path -- which is what sets and clears the + transition marker in the configurations the trees do build -- is not + used at all, so the marker is set and cleared by explicit stores that + exist only in this configuration. A marker left set there would make a + normally completed thread permanently undeletable, which is the failure + mode worth more than a compile. + + - TX_DISABLE_ERROR_CHECKING removes the _txe_ wrappers, so the public + names bind straight to the core services. The refusal has to live in + the core services for exactly that reason, and the way to demonstrate it + is to call the public names in a build that has no wrappers. + + The scheduler is not linked. _tx_thread_system_ni_suspend and + _tx_thread_system_suspend are recorders, which is what makes the marker's + value at the moment of detachment directly observable -- and, in the + TX_NOT_INTERRUPTABLE completion path, the reason the marker has to be + cleared before the call rather than after it: on a real port that call + returns to the scheduler and never comes back. + + Everything here is straight-line: there are no threads, no timers and no + waits, so there is nothing that can hang. */ + +#include +#include + +/* tx_api.h is included without TX_SOURCE_CODE, so that the public service names + are mapped the way an application sees them: to the _txe_ wrappers with error + checking on, and straight to the core services with it off. Letting the header + make that choice is the point -- the refusal has to survive the choice. Only + then is TX_SOURCE_CODE defined, for the internal declarations the recorders + below implement. */ + +#include "tx_api.h" + +/* tx_thread_entry_exit_notify is both a service name and a TX_THREAD field name, + and it is the only name in this file that is both, so the mapping above would + rewrite the field assignment further down into a member that does not exist. + Dropping just that one mapping keeps the mapping that matters -- the one on the + three services this test calls -- while leaving the field reachable. The test + never calls the notify service; it plants the callback in the control block + directly, because the create path that would otherwise do it is not linked. */ + +#undef tx_thread_entry_exit_notify + +#define TX_SOURCE_CODE +#include "tx_thread.h" + + +/* Counters the force-included port shim's macros drive. */ + +unsigned int test_interrupt_disable_depth = 0; +unsigned int test_interrupt_disable_max_depth = 0; +unsigned int test_interrupt_restore_underflows = 0; +unsigned int test_delete_port_completion_count = 0; +unsigned int test_reset_port_completion_count = 0; + + +#define TEST_STACK_BYTES 512 + +static TX_THREAD victim; +static TX_THREAD other; +static UCHAR victim_stack[TEST_STACK_BYTES]; + +/* What the recorders saw. */ + +static unsigned int ni_suspend_calls = 0; +static UINT ni_suspend_suspending = 0xFFFFFFFFU; +static UINT ni_suspend_state = 0xFFFFFFFFU; +static unsigned int ni_suspend_depth = 0xFFFFFFFFU; + +static unsigned int suspend_calls = 0; +static UINT suspend_suspending = 0xFFFFFFFFU; + +static unsigned int stack_build_calls = 0; +static unsigned int preempt_check_calls = 0; +static unsigned int timer_deactivate_calls = 0; + +/* What the exit callback saw. */ + +static unsigned int callback_calls = 0; +static UINT callback_state = 0xFFFFFFFFU; +static UINT callback_suspending = 0xFFFFFFFFU; +static unsigned int callback_depth = 0xFFFFFFFFU; +static UINT callback_delete_status = 0xFFFFFFFFU; +static UINT callback_reset_status = 0xFFFFFFFFU; +static UINT callback_delete_completions = 0xFFFFFFFFU; +static UINT callback_reset_completions = 0xFFFFFFFFU; + +static unsigned int entry_calls = 0; + +static unsigned long expectations_checked = 0; +static unsigned long expectations_failed = 0; + + +static void expect(int condition, const char *what) +{ + + expectations_checked++; + + if (condition == 0) + { + expectations_failed++; + printf(" FAILED: %s\n", what); + } +} + + +static void expect_uint(UINT actual, UINT wanted, const char *what) +{ + + expectations_checked++; + + if (actual != wanted) + { + expectations_failed++; + printf(" FAILED: %s (got %lu, wanted %lu)\n", what, + (unsigned long) actual, (unsigned long) wanted); + } +} + + +/* ------------------------------------------------------------------------ */ +/* Recorders standing in for the scheduler. */ +/* ------------------------------------------------------------------------ */ + +VOID _tx_thread_system_ni_suspend(TX_THREAD *thread_ptr, ULONG wait_option) +{ + + (void) wait_option; + + ni_suspend_calls++; + ni_suspend_suspending = thread_ptr -> tx_thread_suspending; + ni_suspend_state = thread_ptr -> tx_thread_state; + ni_suspend_depth = test_interrupt_disable_depth; +} + + +VOID _tx_thread_system_suspend(TX_THREAD *thread_ptr) +{ + + suspend_calls++; + suspend_suspending = thread_ptr -> tx_thread_suspending; + + /* The interruptable suspension path is where the marker is cleared in the + configurations the regression trees build, so the recorder clears it as + the real one does, on the same condition. */ + if (thread_ptr -> tx_thread_suspending == TX_TRUE) + { + thread_ptr -> tx_thread_suspending = TX_FALSE; + } + + /* It also decrements the preemption disable count, which its callers have + raised on its behalf. The recorder has to do the same, or the balance + this test asserts across the whole transition would be off by one for a + reason that belongs to the recorder rather than to the code under + test. */ + _tx_thread_preempt_disable--; +} + + +VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID)) +{ + + (void) thread_ptr; + (void) function_ptr; + + stack_build_calls++; +} + + +VOID _tx_thread_system_preempt_check(VOID) +{ + preempt_check_calls++; +} + + +/* _tx_thread_terminate deactivates the target's timeout timer, and + _txe_thread_reset refuses a call made from the timer thread. Neither the + timer component nor the timer thread is linked, so both are supplied here: + the deactivation as a recorder, and the timer thread as a control block that + is never the current thread, so the wrapper's check is exercised and takes + the not-the-timer-thread branch. */ + +VOID _tx_timer_system_deactivate(TX_TIMER_INTERNAL *timer_ptr) +{ + + (void) timer_ptr; + + timer_deactivate_calls++; +} + + +TX_THREAD _tx_timer_thread; + + +/* ------------------------------------------------------------------------ */ +/* The thread under test. */ +/* ------------------------------------------------------------------------ */ + +static void reset_records(void) +{ + + ni_suspend_calls = 0; + ni_suspend_suspending = 0xFFFFFFFFU; + ni_suspend_state = 0xFFFFFFFFU; + ni_suspend_depth = 0xFFFFFFFFU; + suspend_calls = 0; + suspend_suspending = 0xFFFFFFFFU; + stack_build_calls = 0; + preempt_check_calls = 0; + timer_deactivate_calls = 0; + callback_calls = 0; + callback_state = 0xFFFFFFFFU; + callback_suspending = 0xFFFFFFFFU; + callback_depth = 0xFFFFFFFFU; + callback_delete_status = 0xFFFFFFFFU; + callback_reset_status = 0xFFFFFFFFU; + callback_delete_completions = 0xFFFFFFFFU; + callback_reset_completions = 0xFFFFFFFFU; + entry_calls = 0; + + test_interrupt_disable_depth = 0; + test_interrupt_disable_max_depth = 0; + test_interrupt_restore_underflows = 0; + test_delete_port_completion_count = 0; + test_reset_port_completion_count = 0; +} + + +static VOID victim_entry(ULONG input) +{ + (void) input; + entry_calls++; +} + + +static VOID exit_notify(TX_THREAD *thread_ptr, UINT type) +{ + + if (type != TX_THREAD_EXIT) + { + return; + } + + callback_calls++; + callback_state = thread_ptr -> tx_thread_state; + callback_suspending = thread_ptr -> tx_thread_suspending; + callback_depth = test_interrupt_disable_depth; + + /* The public names. With error checking on these are the _txe_ wrappers; + with it off they are the core services. Either way the refusal has to + come back. */ + callback_delete_status = tx_thread_delete(thread_ptr); + callback_reset_status = tx_thread_reset(thread_ptr); + + /* A refused delete or reset must not have run the port's completion + processing, which on a real port tears the thread's port resources + down. */ + callback_delete_completions = test_delete_port_completion_count; + callback_reset_completions = test_reset_port_completion_count; +} + + +/* Put the victim's control block into the shape the kernel would have left it + in after tx_thread_create, for the fields the four sources under test read. + tx_thread_create itself is not linked, because the scheduler it resumes into + is not linked either. */ + +static void make_victim(UINT state) +{ + + memset(&victim, 0, sizeof(victim)); + memset(victim_stack, 0xEF, sizeof(victim_stack)); + + victim.tx_thread_id = TX_THREAD_ID; + victim.tx_thread_state = state; + victim.tx_thread_suspending = TX_FALSE; + victim.tx_thread_entry = victim_entry; + victim.tx_thread_entry_parameter = 0; +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* The field itself does not exist when notification is compiled out. */ + victim.tx_thread_entry_exit_notify = exit_notify; +#endif + victim.tx_thread_stack_start = victim_stack; + victim.tx_thread_stack_size = sizeof(victim_stack); + victim.tx_thread_priority = 16; + victim.tx_thread_preempt_threshold = 16; + victim.tx_thread_suspend_cleanup = TX_NULL; + + /* A created list with the victim and one other thread on it, so that + delete takes the link-up-the-neighbours branch rather than the + only-thread branch. */ + memset(&other, 0, sizeof(other)); + other.tx_thread_id = TX_THREAD_ID; + other.tx_thread_state = TX_SUSPENDED; + other.tx_thread_created_next = &victim; + other.tx_thread_created_previous = &victim; + + victim.tx_thread_created_next = &other; + victim.tx_thread_created_previous = &other; + + _tx_thread_created_ptr = &victim; + _tx_thread_created_count = 2; + + _tx_thread_current_ptr = &victim; + _tx_thread_execute_ptr = &victim; + _tx_thread_preempt_disable = 0; + _tx_thread_system_state = 0; +} + + +static void scenario_completion(void) +{ + + printf("Completion transition:\n"); + + reset_records(); + make_victim(TX_SUSPENDED); + + /* _tx_thread_shell_entry picks the thread up from the current pointer, + calls its entry function, and then runs the completion transition. */ + _tx_thread_shell_entry(); + + expect_uint((UINT) entry_calls, 1, "the entry function ran exactly once"); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + expect_uint((UINT) callback_calls, 1, "the exit callback ran exactly once"); + + /* The terminal state is published before the callback. */ + expect_uint(callback_state, TX_COMPLETED, "the callback saw TX_COMPLETED"); + + /* And the transition is marked while the callback runs, in this + configuration as in the interruptable one. */ + expect_uint(callback_suspending, TX_TRUE, "the callback saw the transition marked"); + +#ifdef TX_NOT_INTERRUPTABLE + + /* In this configuration the callback runs inside the interrupt lock. */ + expect(callback_depth > 0, "the callback ran with interrupts disabled"); +#else + expect_uint((UINT) callback_depth, 0, "the callback ran with interrupts enabled"); +#endif + + /* The two refusals, from whichever of the wrapper and the core service + this build binds the public name to. */ + expect_uint(callback_delete_status, TX_DELETE_ERROR, "the callback's delete was refused"); + expect_uint(callback_reset_status, TX_NOT_DONE, "the callback's reset was refused"); + + /* A refused delete or reset ran no port completion processing. */ + expect_uint(callback_delete_completions, 0, "the refused delete ran no port completion"); + expect_uint(callback_reset_completions, 0, "the refused reset ran no port completion"); +#endif + + /* The detachment saw the marker in the state that keeps the thread + deletable afterwards. This is the failure mode the configuration exists + to catch: on a real port the suspension call below returns to the + scheduler and does not come back, so a marker cleared after it rather + than before it would stay set for ever and the completed thread could + never be deleted. */ +#ifdef TX_NOT_INTERRUPTABLE + + expect_uint((UINT) ni_suspend_calls, 1, "the non-interruptable suspension ran once"); + expect_uint(ni_suspend_state, TX_COMPLETED, "it was entered with the terminal state"); + expect_uint(ni_suspend_suspending, TX_FALSE, + "the marker was already cleared when the suspension was entered"); + expect(ni_suspend_depth > 0, "the suspension was entered with interrupts disabled"); + expect_uint((UINT) suspend_calls, 0, "the interruptable suspension was not used"); +#else + + expect_uint((UINT) suspend_calls, 1, "the interruptable suspension ran once"); + expect_uint(suspend_suspending, TX_TRUE, + "the marker was still set when the suspension was entered, for it to clear"); + expect_uint((UINT) ni_suspend_calls, 0, "the non-interruptable suspension was not used"); +#endif + + /* Either way the thread is deletable once the transition has finished. */ + expect_uint(victim.tx_thread_suspending, TX_FALSE, "the marker is clear afterwards"); + expect_uint(tx_thread_delete(&victim), TX_SUCCESS, "the completed thread deletes afterwards"); + expect_uint((UINT) test_delete_port_completion_count, 1, + "the successful delete ran the port completion once"); + + /* And the interrupt lock is balanced across the whole transition. */ + expect_uint((UINT) test_interrupt_disable_depth, 0, "the interrupt lock is balanced"); + expect_uint((UINT) test_interrupt_restore_underflows, 0, "no unmatched interrupt restore"); +} + + +static void scenario_terminate_ready(void) +{ + + printf("Termination of a ready thread:\n"); + + reset_records(); + make_victim(TX_READY); + + /* Terminate a target that is not the current thread, so that the reset the + callback attempts is refused by the transition check alone rather than + by the current-thread rule. */ + _tx_thread_current_ptr = &other; + + expect_uint(tx_thread_terminate(&victim), TX_SUCCESS, "the termination succeeded"); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + expect_uint((UINT) callback_calls, 1, "the exit callback ran exactly once"); + expect_uint(callback_state, TX_TERMINATED, "the callback saw TX_TERMINATED"); + expect_uint(callback_suspending, TX_TRUE, "the callback saw the transition marked"); + expect_uint(callback_delete_status, TX_DELETE_ERROR, "the callback's delete was refused"); + expect_uint(callback_reset_status, TX_NOT_DONE, "the callback's reset was refused"); + expect_uint(callback_reset_completions, 0, "the refused reset ran no port completion"); + expect_uint((UINT) stack_build_calls, 0, "the refused reset rebuilt no stack"); +#endif + +#ifdef TX_NOT_INTERRUPTABLE + + expect_uint((UINT) ni_suspend_calls, 1, "the non-interruptable suspension ran once"); + expect(callback_depth > 0, "the callback ran with interrupts disabled"); +#else + + expect_uint((UINT) suspend_calls, 1, "the interruptable suspension ran once"); +#endif + + /* The marker is cleared in the common tail, after the callback and after + the mutex-release processing. */ + expect_uint(victim.tx_thread_suspending, TX_FALSE, "the marker is clear afterwards"); + expect_uint(victim.tx_thread_state, TX_TERMINATED, "the state is terminal afterwards"); + expect_uint((UINT) _tx_thread_preempt_disable, 0, "the preempt disable count is balanced"); + expect_uint((UINT) test_interrupt_disable_depth, 0, "the interrupt lock is balanced"); + expect_uint((UINT) test_interrupt_restore_underflows, 0, "no unmatched interrupt restore"); + + expect_uint(tx_thread_delete(&victim), TX_SUCCESS, "the terminated thread deletes afterwards"); +} + + +static void scenario_terminate_suspended(void) +{ + +UINT reset_status; + + + printf("Termination of a suspended thread:\n"); + + reset_records(); + make_victim(TX_SUSPENDED); + _tx_thread_current_ptr = &other; + + expect_uint(tx_thread_terminate(&victim), TX_SUCCESS, "the termination succeeded"); + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + expect_uint((UINT) callback_calls, 1, "the exit callback ran exactly once"); + expect_uint(callback_state, TX_TERMINATED, "the callback saw TX_TERMINATED"); + + /* The non-ready branch used to clear the marker before this point. */ + expect_uint(callback_suspending, TX_TRUE, "the callback saw the transition marked"); + expect_uint(callback_delete_status, TX_DELETE_ERROR, "the callback's delete was refused"); + expect_uint(callback_reset_status, TX_NOT_DONE, "the callback's reset was refused"); + expect_uint((UINT) stack_build_calls, 0, "the refused reset rebuilt no stack"); +#endif + + /* This branch never calls a suspension routine: the thread was already off + the ready list. */ + expect_uint((UINT) ni_suspend_calls, 0, "no non-interruptable suspension on this branch"); + expect_uint((UINT) suspend_calls, 0, "no interruptable suspension on this branch"); + + expect_uint(victim.tx_thread_suspending, TX_FALSE, "the marker is clear afterwards"); + expect_uint((UINT) _tx_thread_preempt_disable, 0, "the preempt disable count is balanced"); + expect_uint((UINT) test_interrupt_disable_depth, 0, "the interrupt lock is balanced"); + expect_uint((UINT) test_interrupt_restore_underflows, 0, "no unmatched interrupt restore"); + + /* The documented lifecycle is available afterwards, on this branch too. */ + reset_status = tx_thread_reset(&victim); + expect_uint(reset_status, TX_SUCCESS, "the terminated thread resets afterwards"); + expect_uint(victim.tx_thread_state, TX_SUSPENDED, "the reset left it suspended"); + expect_uint((UINT) stack_build_calls, 1, "the successful reset rebuilt the stack once"); + expect_uint((UINT) test_reset_port_completion_count, 1, + "the successful reset ran the port completion once"); + + expect_uint(tx_thread_delete(&victim), TX_DELETE_ERROR, "a reset thread is not deletable"); + expect_uint(tx_thread_terminate(&victim), TX_SUCCESS, "it terminates again"); + expect_uint(tx_thread_delete(&victim), TX_SUCCESS, "and then deletes"); +} + + +static void scenario_marker_not_set_outside_transition(void) +{ + + printf("Outside a transition:\n"); + + reset_records(); + make_victim(TX_SUSPENDED); + _tx_thread_current_ptr = &other; + + /* Neither state is terminal, so both services refuse for the reason they + always did, and the marker plays no part. */ + expect_uint(victim.tx_thread_suspending, TX_FALSE, "the marker is clear on a live thread"); + expect_uint(tx_thread_delete(&victim), TX_DELETE_ERROR, "delete refuses a suspended thread"); + expect_uint(tx_thread_reset(&victim), TX_NOT_DONE, "reset refuses a suspended thread"); + + /* A terminal state with the marker clear is the ordinary deletable case, + which is what the refusal must not have broken. */ + victim.tx_thread_state = TX_COMPLETED; + victim.tx_thread_suspending = TX_FALSE; + expect_uint(tx_thread_reset(&victim), TX_SUCCESS, "reset accepts a settled completed thread"); + + victim.tx_thread_state = TX_TERMINATED; + expect_uint(tx_thread_delete(&victim), TX_SUCCESS, "delete accepts a settled terminated thread"); + + /* And a terminal state with the marker set is the new refusal, tested + directly rather than through a transition, so that both services are + covered on both terminal states. */ + make_victim(TX_COMPLETED); + victim.tx_thread_suspending = TX_TRUE; + _tx_thread_current_ptr = &other; + expect_uint(tx_thread_delete(&victim), TX_DELETE_ERROR, "delete refuses a marked completed thread"); + expect_uint(tx_thread_reset(&victim), TX_NOT_DONE, "reset refuses a marked completed thread"); + + victim.tx_thread_state = TX_TERMINATED; + expect_uint(tx_thread_delete(&victim), TX_DELETE_ERROR, "delete refuses a marked terminated thread"); + expect_uint(tx_thread_reset(&victim), TX_NOT_DONE, "reset refuses a marked terminated thread"); + + /* Clearing the marker makes both available again, which is the whole + claim about the refusal being transient. */ + victim.tx_thread_suspending = TX_FALSE; + expect_uint(tx_thread_reset(&victim), TX_SUCCESS, "clearing the marker restores reset"); + victim.tx_thread_state = TX_TERMINATED; + expect_uint(tx_thread_delete(&victim), TX_SUCCESS, "clearing the marker restores delete"); +} + + +int main(void) +{ + + printf("Thread lifecycle transition configuration test: "); + +#ifdef TX_NOT_INTERRUPTABLE + printf("TX_NOT_INTERRUPTABLE "); +#else + printf("interruptable "); +#endif +#ifdef TX_DISABLE_ERROR_CHECKING + printf("TX_DISABLE_ERROR_CHECKING "); +#else + printf("error checking "); +#endif +#ifdef TX_DISABLE_NOTIFY_CALLBACKS + printf("TX_DISABLE_NOTIFY_CALLBACKS"); +#else + printf("notify callbacks"); +#endif + printf("\n"); + + scenario_completion(); + scenario_terminate_ready(); + scenario_terminate_suspended(); + scenario_marker_not_set_outside_transition(); + + printf("%lu of %lu expectations passed.\n", + expectations_checked - expectations_failed, expectations_checked); + + if (expectations_failed != 0) + { + printf("FAILED: %lu expectations.\n", expectations_failed); + return(1); + } + + printf("SUCCESS!\n"); + return(0); +} diff --git a/test/tx/thread_transition/threadx_thread_transition_host_test_port.h b/test/tx/thread_transition/threadx_thread_transition_host_test_port.h new file mode 100644 index 000000000..204933e3b --- /dev/null +++ b/test/tx/thread_transition/threadx_thread_transition_host_test_port.h @@ -0,0 +1,120 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Test */ +/** */ +/** Thread lifecycle transition host test port shim */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +/* TX_NOT_INTERRUPTABLE and TX_DISABLE_ERROR_CHECKING are not among the five + build configurations either regression tree compiles, and both trees build + the whole ThreadX library once per configuration, so there is no way to + reach those two from inside them. The completion and termination + transitions have code that only exists under TX_NOT_INTERRUPTABLE -- the + callback there runs with interrupts disabled and the transition marker has + to be set and cleared explicitly rather than by the interruptable + suspension path -- and that code is exactly where a marker cleared at the + wrong point would make a normally completed thread permanently undeletable. + It therefore needs a test rather than a compile. + + This harness compiles the four sources that change, plus the two error + wrappers whose absence a TX_DISABLE_ERROR_CHECKING build is defined by, + directly into a test executable, once per configuration. It is deliberately + not part of the coverage report: the same file compiled under different + feature macros has different line sets, and merging them would confuse the + union rather than add to it. The configurations the trees do build are what + the coverage figure is taken from. + + This header is force-included ahead of each source under test. It brings + the base port's headers in first, so every declaration a source needs is the + port's own, and then replaces the primitives that would otherwise reach the + host's pthread emulation: + + - the interrupt lock becomes a counter, which is also how the test asserts + that the transition really did run with interrupts disabled and left the + nesting balanced, + - the delete and reset port completions become recorders, because on this + port they cancel and join the pthread backing the thread, which is not + something a host test that owns no such thread can be asked to do. */ + +#ifndef THREADX_THREAD_TRANSITION_HOST_TEST_PORT_H +#define THREADX_THREAD_TRANSITION_HOST_TEST_PORT_H + +#define TX_SOURCE_CODE + +#include "tx_api.h" + +#undef TX_INTERRUPT_SAVE_AREA +#undef TX_DISABLE +#undef TX_RESTORE +#undef TX_THREAD_DELETE_PORT_COMPLETION +#undef TX_THREAD_RESET_PORT_COMPLETION + +/* Nesting depth of the stand-in interrupt lock, the deepest it has reached, + and the number of times a restore was issued without a matching disable. + Defined by the test, which is the only translation unit that reads them. */ + +extern unsigned int test_interrupt_disable_depth; +extern unsigned int test_interrupt_disable_max_depth; +extern unsigned int test_interrupt_restore_underflows; + +/* Counts of the two port completions, and the interrupt depth each was + entered at. */ + +extern unsigned int test_delete_port_completion_count; +extern unsigned int test_reset_port_completion_count; + +#define TX_INTERRUPT_SAVE_AREA + +#define TX_DISABLE \ + { \ + test_interrupt_disable_depth++; \ + if (test_interrupt_disable_depth > test_interrupt_disable_max_depth) \ + { \ + test_interrupt_disable_max_depth = test_interrupt_disable_depth; \ + } \ + } + +#define TX_RESTORE \ + { \ + if (test_interrupt_disable_depth == 0U) \ + { \ + test_interrupt_restore_underflows++; \ + } \ + else \ + { \ + test_interrupt_disable_depth--; \ + } \ + } + +#define TX_THREAD_DELETE_PORT_COMPLETION(thread_ptr) \ + { \ + (void) (thread_ptr); \ + test_delete_port_completion_count++; \ + } + +#define TX_THREAD_RESET_PORT_COMPLETION(thread_ptr) \ + { \ + (void) (thread_ptr); \ + test_reset_port_completion_count++; \ + } + +#endif From c0aa4dbe2932bb12bb69545ff5d4945e0b019ffe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Thu, 10 Sep 2026 12:06:54 -0400 Subject: [PATCH 131/181] Initialized the suspend status before the non-interruptable suspend in tx_thread_sleep, so a sleep no longer returns a stale error left over from an earlier timed-out suspension (#725) When TX_NOT_INTERRUPTABLE is defined, _tx_thread_sleep did not set tx_thread_suspend_status to TX_SUCCESS before calling _tx_thread_system_ni_suspend. The interruptable path always did. Nothing else writes that field on behalf of a sleeping thread: _tx_thread_timeout resumes a TX_SLEEP thread directly and there is no suspend cleanup routine for sleep. The value therefore survived from whatever suspension the thread performed last, and tx_thread_sleep returned it. A tx_semaphore_get that timed out with TX_NO_INSTANCE would be followed by a tx_thread_sleep that also returned TX_NO_INSTANCE after sleeping correctly. The same change is applied to the SMP copy, which is identical. Assisted-by: Copilot (Opus 5) --- common/src/tx_thread_sleep.c | 4 ++++ common_smp/src/tx_thread_sleep.c | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/common/src/tx_thread_sleep.c b/common/src/tx_thread_sleep.c index fd986a0b6..fb04f3375 100644 --- a/common/src/tx_thread_sleep.c +++ b/common/src/tx_thread_sleep.c @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -155,6 +156,9 @@ TX_THREAD *thread_ptr; #ifdef TX_NOT_INTERRUPTABLE + /* Initialize the status to successful. */ + thread_ptr -> tx_thread_suspend_status = TX_SUCCESS; + /* Call actual non-interruptable thread suspension routine. */ _tx_thread_system_ni_suspend(thread_ptr, timer_ticks); diff --git a/common_smp/src/tx_thread_sleep.c b/common_smp/src/tx_thread_sleep.c index fd986a0b6..fb04f3375 100644 --- a/common_smp/src/tx_thread_sleep.c +++ b/common_smp/src/tx_thread_sleep.c @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -155,6 +156,9 @@ TX_THREAD *thread_ptr; #ifdef TX_NOT_INTERRUPTABLE + /* Initialize the status to successful. */ + thread_ptr -> tx_thread_suspend_status = TX_SUCCESS; + /* Call actual non-interruptable thread suspension routine. */ _tx_thread_system_ni_suspend(thread_ptr, timer_ticks); From dde43b8ab2e8accfe636842d5216204f70682fc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Fri, 11 Sep 2026 13:27:32 -0400 Subject: [PATCH 132/181] Replaced the stale system stack switch pseudo-code in the ARMv7-A ports with comments that describe what the code actually does (#735) The context save, vectored context save and system return routines in the ARMv7-A ports carried pseudo-code comments claiming that they saved the thread stack pointer and then switched to _tx_thread_system_stack_ptr. Neither of those things happens, and none of these ports references that variable outside an unused IMPORT in their example builds. On ARMv7-A each processor mode has its own banked stack pointer. The IRQ handler branches to _tx_thread_context_save while still in IRQ mode, so the core's banked IRQ stack already serves as the system stack, and the thread stack pointer is stored in the control block by _tx_thread_context_restore, and only when the interrupt results in preemption. The scheduler runs on the banked SVC mode stack that the startup code sets up. There is nothing for a software stack switch to do. The comments were therefore misleading rather than merely redundant, and had led at least one user to try to restore the code they described. They are now replaced by a description of the actual mechanism. The AArch64 SMP ports keep their comments unchanged, because ARMv8-A does not bank a stack pointer per processor mode and those ports do reload _tx_thread_system_stack_ptr[core] explicitly. This is a comment-only change. Every changed line is a comment, and all twenty-five GNU variants still assemble cleanly for their target core. The fourteen files under ports/cortex_a{5,7,8,9,12,15,17} were regenerated from ports_arch/ARMv7-A/threadx/common/src/tx_thread_system_return.S with ports_arch/ARMv7-A/update.sh. The ARMv7-A SMP ports have no generator, so those files were edited directly. Fixes #734 Assisted-by: Copilot (Opus 5) --- ports/cortex_a12/ac6/src/tx_thread_system_return.S | 5 ++++- ports/cortex_a12/gnu/src/tx_thread_system_return.S | 5 ++++- ports/cortex_a15/ac6/src/tx_thread_system_return.S | 5 ++++- ports/cortex_a15/gnu/src/tx_thread_system_return.S | 5 ++++- ports/cortex_a17/ac6/src/tx_thread_system_return.S | 5 ++++- ports/cortex_a17/gnu/src/tx_thread_system_return.S | 5 ++++- ports/cortex_a5/ac6/src/tx_thread_system_return.S | 5 ++++- ports/cortex_a5/gnu/src/tx_thread_system_return.S | 5 ++++- ports/cortex_a7/ac6/src/tx_thread_system_return.S | 5 ++++- ports/cortex_a7/gnu/src/tx_thread_system_return.S | 5 ++++- ports/cortex_a8/ac6/src/tx_thread_system_return.S | 5 ++++- ports/cortex_a8/gnu/src/tx_thread_system_return.S | 5 ++++- ports/cortex_a9/ac6/src/tx_thread_system_return.S | 5 ++++- ports/cortex_a9/gnu/src/tx_thread_system_return.S | 5 ++++- .../threadx/common/src/tx_thread_system_return.S | 5 ++++- .../gnu/module_manager/src/tx_thread_system_return.S | 5 ++++- .../iar/module_manager/src/tx_thread_system_return.s | 6 +++++- .../cortex_a5_smp/ac5/src/tx_thread_context_save.s | 12 +++++++----- .../cortex_a5_smp/ac5/src/tx_thread_system_return.s | 7 +++++-- .../ac5/src/tx_thread_vectored_context_save.s | 12 +++++++----- .../cortex_a5_smp/gnu/src/tx_thread_context_save.S | 12 +++++++----- .../cortex_a5_smp/gnu/src/tx_thread_system_return.S | 7 +++++-- .../gnu/src/tx_thread_vectored_context_save.S | 12 +++++++----- .../cortex_a7_smp/ac5/src/tx_thread_context_save.s | 12 +++++++----- .../cortex_a7_smp/ac5/src/tx_thread_system_return.s | 7 +++++-- .../ac5/src/tx_thread_vectored_context_save.s | 12 +++++++----- .../cortex_a7_smp/gnu/src/tx_thread_context_save.S | 12 +++++++----- .../cortex_a7_smp/gnu/src/tx_thread_system_return.S | 7 +++++-- .../gnu/src/tx_thread_vectored_context_save.S | 12 +++++++----- .../cortex_a9_smp/ac5/src/tx_thread_context_save.s | 12 +++++++----- .../cortex_a9_smp/ac5/src/tx_thread_system_return.s | 7 +++++-- .../ac5/src/tx_thread_vectored_context_save.s | 12 +++++++----- .../cortex_a9_smp/gnu/src/tx_thread_context_save.S | 12 +++++++----- .../cortex_a9_smp/gnu/src/tx_thread_system_return.S | 7 +++++-- .../gnu/src/tx_thread_vectored_context_save.S | 12 +++++++----- .../cortex_r8_smp/ac5/src/tx_thread_context_save.s | 11 ++++++----- .../cortex_r8_smp/ac5/src/tx_thread_system_return.s | 6 ++++-- .../ac5/src/tx_thread_vectored_context_save.s | 11 ++++++----- 38 files changed, 199 insertions(+), 101 deletions(-) diff --git a/ports/cortex_a12/ac6/src/tx_thread_system_return.S b/ports/cortex_a12/ac6/src/tx_thread_system_return.S index 1a17446bc..9aa7e0e50 100644 --- a/ports/cortex_a12/ac6/src/tx_thread_system_return.S +++ b/ports/cortex_a12/ac6/src/tx_thread_system_return.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -121,7 +122,9 @@ _tx_skip_solicited_vfp_save: LDR r2, =_tx_timer_time_slice // Pickup address of time slice LDR r1, [r2] // Pickup current time slice - /* Save current stack and switch to system stack. */ + /* Save the current stack pointer in the thread control block. The + scheduler runs on the banked SVC mode stack that the startup code + set up, so there is no stack switch to perform. */ STR sp, [r0, #8] // Save thread stack pointer diff --git a/ports/cortex_a12/gnu/src/tx_thread_system_return.S b/ports/cortex_a12/gnu/src/tx_thread_system_return.S index 1a17446bc..9aa7e0e50 100644 --- a/ports/cortex_a12/gnu/src/tx_thread_system_return.S +++ b/ports/cortex_a12/gnu/src/tx_thread_system_return.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -121,7 +122,9 @@ _tx_skip_solicited_vfp_save: LDR r2, =_tx_timer_time_slice // Pickup address of time slice LDR r1, [r2] // Pickup current time slice - /* Save current stack and switch to system stack. */ + /* Save the current stack pointer in the thread control block. The + scheduler runs on the banked SVC mode stack that the startup code + set up, so there is no stack switch to perform. */ STR sp, [r0, #8] // Save thread stack pointer diff --git a/ports/cortex_a15/ac6/src/tx_thread_system_return.S b/ports/cortex_a15/ac6/src/tx_thread_system_return.S index 1a17446bc..9aa7e0e50 100644 --- a/ports/cortex_a15/ac6/src/tx_thread_system_return.S +++ b/ports/cortex_a15/ac6/src/tx_thread_system_return.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -121,7 +122,9 @@ _tx_skip_solicited_vfp_save: LDR r2, =_tx_timer_time_slice // Pickup address of time slice LDR r1, [r2] // Pickup current time slice - /* Save current stack and switch to system stack. */ + /* Save the current stack pointer in the thread control block. The + scheduler runs on the banked SVC mode stack that the startup code + set up, so there is no stack switch to perform. */ STR sp, [r0, #8] // Save thread stack pointer diff --git a/ports/cortex_a15/gnu/src/tx_thread_system_return.S b/ports/cortex_a15/gnu/src/tx_thread_system_return.S index 1a17446bc..9aa7e0e50 100644 --- a/ports/cortex_a15/gnu/src/tx_thread_system_return.S +++ b/ports/cortex_a15/gnu/src/tx_thread_system_return.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -121,7 +122,9 @@ _tx_skip_solicited_vfp_save: LDR r2, =_tx_timer_time_slice // Pickup address of time slice LDR r1, [r2] // Pickup current time slice - /* Save current stack and switch to system stack. */ + /* Save the current stack pointer in the thread control block. The + scheduler runs on the banked SVC mode stack that the startup code + set up, so there is no stack switch to perform. */ STR sp, [r0, #8] // Save thread stack pointer diff --git a/ports/cortex_a17/ac6/src/tx_thread_system_return.S b/ports/cortex_a17/ac6/src/tx_thread_system_return.S index 1a17446bc..9aa7e0e50 100644 --- a/ports/cortex_a17/ac6/src/tx_thread_system_return.S +++ b/ports/cortex_a17/ac6/src/tx_thread_system_return.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -121,7 +122,9 @@ _tx_skip_solicited_vfp_save: LDR r2, =_tx_timer_time_slice // Pickup address of time slice LDR r1, [r2] // Pickup current time slice - /* Save current stack and switch to system stack. */ + /* Save the current stack pointer in the thread control block. The + scheduler runs on the banked SVC mode stack that the startup code + set up, so there is no stack switch to perform. */ STR sp, [r0, #8] // Save thread stack pointer diff --git a/ports/cortex_a17/gnu/src/tx_thread_system_return.S b/ports/cortex_a17/gnu/src/tx_thread_system_return.S index 1a17446bc..9aa7e0e50 100644 --- a/ports/cortex_a17/gnu/src/tx_thread_system_return.S +++ b/ports/cortex_a17/gnu/src/tx_thread_system_return.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -121,7 +122,9 @@ _tx_skip_solicited_vfp_save: LDR r2, =_tx_timer_time_slice // Pickup address of time slice LDR r1, [r2] // Pickup current time slice - /* Save current stack and switch to system stack. */ + /* Save the current stack pointer in the thread control block. The + scheduler runs on the banked SVC mode stack that the startup code + set up, so there is no stack switch to perform. */ STR sp, [r0, #8] // Save thread stack pointer diff --git a/ports/cortex_a5/ac6/src/tx_thread_system_return.S b/ports/cortex_a5/ac6/src/tx_thread_system_return.S index 1a17446bc..9aa7e0e50 100644 --- a/ports/cortex_a5/ac6/src/tx_thread_system_return.S +++ b/ports/cortex_a5/ac6/src/tx_thread_system_return.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -121,7 +122,9 @@ _tx_skip_solicited_vfp_save: LDR r2, =_tx_timer_time_slice // Pickup address of time slice LDR r1, [r2] // Pickup current time slice - /* Save current stack and switch to system stack. */ + /* Save the current stack pointer in the thread control block. The + scheduler runs on the banked SVC mode stack that the startup code + set up, so there is no stack switch to perform. */ STR sp, [r0, #8] // Save thread stack pointer diff --git a/ports/cortex_a5/gnu/src/tx_thread_system_return.S b/ports/cortex_a5/gnu/src/tx_thread_system_return.S index 1a17446bc..9aa7e0e50 100644 --- a/ports/cortex_a5/gnu/src/tx_thread_system_return.S +++ b/ports/cortex_a5/gnu/src/tx_thread_system_return.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -121,7 +122,9 @@ _tx_skip_solicited_vfp_save: LDR r2, =_tx_timer_time_slice // Pickup address of time slice LDR r1, [r2] // Pickup current time slice - /* Save current stack and switch to system stack. */ + /* Save the current stack pointer in the thread control block. The + scheduler runs on the banked SVC mode stack that the startup code + set up, so there is no stack switch to perform. */ STR sp, [r0, #8] // Save thread stack pointer diff --git a/ports/cortex_a7/ac6/src/tx_thread_system_return.S b/ports/cortex_a7/ac6/src/tx_thread_system_return.S index 1a17446bc..9aa7e0e50 100644 --- a/ports/cortex_a7/ac6/src/tx_thread_system_return.S +++ b/ports/cortex_a7/ac6/src/tx_thread_system_return.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -121,7 +122,9 @@ _tx_skip_solicited_vfp_save: LDR r2, =_tx_timer_time_slice // Pickup address of time slice LDR r1, [r2] // Pickup current time slice - /* Save current stack and switch to system stack. */ + /* Save the current stack pointer in the thread control block. The + scheduler runs on the banked SVC mode stack that the startup code + set up, so there is no stack switch to perform. */ STR sp, [r0, #8] // Save thread stack pointer diff --git a/ports/cortex_a7/gnu/src/tx_thread_system_return.S b/ports/cortex_a7/gnu/src/tx_thread_system_return.S index 1a17446bc..9aa7e0e50 100644 --- a/ports/cortex_a7/gnu/src/tx_thread_system_return.S +++ b/ports/cortex_a7/gnu/src/tx_thread_system_return.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -121,7 +122,9 @@ _tx_skip_solicited_vfp_save: LDR r2, =_tx_timer_time_slice // Pickup address of time slice LDR r1, [r2] // Pickup current time slice - /* Save current stack and switch to system stack. */ + /* Save the current stack pointer in the thread control block. The + scheduler runs on the banked SVC mode stack that the startup code + set up, so there is no stack switch to perform. */ STR sp, [r0, #8] // Save thread stack pointer diff --git a/ports/cortex_a8/ac6/src/tx_thread_system_return.S b/ports/cortex_a8/ac6/src/tx_thread_system_return.S index 1a17446bc..9aa7e0e50 100644 --- a/ports/cortex_a8/ac6/src/tx_thread_system_return.S +++ b/ports/cortex_a8/ac6/src/tx_thread_system_return.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -121,7 +122,9 @@ _tx_skip_solicited_vfp_save: LDR r2, =_tx_timer_time_slice // Pickup address of time slice LDR r1, [r2] // Pickup current time slice - /* Save current stack and switch to system stack. */ + /* Save the current stack pointer in the thread control block. The + scheduler runs on the banked SVC mode stack that the startup code + set up, so there is no stack switch to perform. */ STR sp, [r0, #8] // Save thread stack pointer diff --git a/ports/cortex_a8/gnu/src/tx_thread_system_return.S b/ports/cortex_a8/gnu/src/tx_thread_system_return.S index 1a17446bc..9aa7e0e50 100644 --- a/ports/cortex_a8/gnu/src/tx_thread_system_return.S +++ b/ports/cortex_a8/gnu/src/tx_thread_system_return.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -121,7 +122,9 @@ _tx_skip_solicited_vfp_save: LDR r2, =_tx_timer_time_slice // Pickup address of time slice LDR r1, [r2] // Pickup current time slice - /* Save current stack and switch to system stack. */ + /* Save the current stack pointer in the thread control block. The + scheduler runs on the banked SVC mode stack that the startup code + set up, so there is no stack switch to perform. */ STR sp, [r0, #8] // Save thread stack pointer diff --git a/ports/cortex_a9/ac6/src/tx_thread_system_return.S b/ports/cortex_a9/ac6/src/tx_thread_system_return.S index 1a17446bc..9aa7e0e50 100644 --- a/ports/cortex_a9/ac6/src/tx_thread_system_return.S +++ b/ports/cortex_a9/ac6/src/tx_thread_system_return.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -121,7 +122,9 @@ _tx_skip_solicited_vfp_save: LDR r2, =_tx_timer_time_slice // Pickup address of time slice LDR r1, [r2] // Pickup current time slice - /* Save current stack and switch to system stack. */ + /* Save the current stack pointer in the thread control block. The + scheduler runs on the banked SVC mode stack that the startup code + set up, so there is no stack switch to perform. */ STR sp, [r0, #8] // Save thread stack pointer diff --git a/ports/cortex_a9/gnu/src/tx_thread_system_return.S b/ports/cortex_a9/gnu/src/tx_thread_system_return.S index 1a17446bc..9aa7e0e50 100644 --- a/ports/cortex_a9/gnu/src/tx_thread_system_return.S +++ b/ports/cortex_a9/gnu/src/tx_thread_system_return.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -121,7 +122,9 @@ _tx_skip_solicited_vfp_save: LDR r2, =_tx_timer_time_slice // Pickup address of time slice LDR r1, [r2] // Pickup current time slice - /* Save current stack and switch to system stack. */ + /* Save the current stack pointer in the thread control block. The + scheduler runs on the banked SVC mode stack that the startup code + set up, so there is no stack switch to perform. */ STR sp, [r0, #8] // Save thread stack pointer diff --git a/ports_arch/ARMv7-A/threadx/common/src/tx_thread_system_return.S b/ports_arch/ARMv7-A/threadx/common/src/tx_thread_system_return.S index 1a17446bc..9aa7e0e50 100644 --- a/ports_arch/ARMv7-A/threadx/common/src/tx_thread_system_return.S +++ b/ports_arch/ARMv7-A/threadx/common/src/tx_thread_system_return.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -121,7 +122,9 @@ _tx_skip_solicited_vfp_save: LDR r2, =_tx_timer_time_slice // Pickup address of time slice LDR r1, [r2] // Pickup current time slice - /* Save current stack and switch to system stack. */ + /* Save the current stack pointer in the thread control block. The + scheduler runs on the banked SVC mode stack that the startup code + set up, so there is no stack switch to perform. */ STR sp, [r0, #8] // Save thread stack pointer diff --git a/ports_module/cortex_a7/gnu/module_manager/src/tx_thread_system_return.S b/ports_module/cortex_a7/gnu/module_manager/src/tx_thread_system_return.S index fd8de2273..fae8a96a2 100644 --- a/ports_module/cortex_a7/gnu/module_manager/src/tx_thread_system_return.S +++ b/ports_module/cortex_a7/gnu/module_manager/src/tx_thread_system_return.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -117,7 +118,9 @@ _tx_skip_solicited_vfp_save: LDR r2, =_tx_timer_time_slice // Pickup address of time slice LDR r1, [r2] // Pickup current time slice - /* Save current stack and switch to system stack. */ + /* Save the current stack pointer in the thread control block. The + scheduler runs on the banked SVC mode stack that the startup code + set up, so there is no stack switch to perform. */ STR sp, [r0, #8] // Save thread stack pointer diff --git a/ports_module/cortex_a7/iar/module_manager/src/tx_thread_system_return.s b/ports_module/cortex_a7/iar/module_manager/src/tx_thread_system_return.s index f22ca01c5..dd041adc0 100644 --- a/ports_module/cortex_a7/iar/module_manager/src/tx_thread_system_return.s +++ b/ports_module/cortex_a7/iar/module_manager/src/tx_thread_system_return.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026-present Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -8,6 +9,7 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ ; +; // Some portions generated by Copilot (Opus 5). ; ;/**************************************************************************/ ;/**************************************************************************/ @@ -113,7 +115,9 @@ _tx_skip_solicited_vfp_save: LDR r2, =_tx_timer_time_slice ; Pickup address of time slice LDR r1, [r2] ; Pickup current time slice -; /* Save current stack and switch to system stack. */ +; /* Save the current stack pointer in the thread control block. The +; scheduler runs on the banked SVC mode stack that the startup code +; set up, so there is no stack switch to perform. */ STR sp, [r0, #8] ; Save thread stack pointer diff --git a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_context_save.s b/ports_smp/cortex_a5_smp/ac5/src/tx_thread_context_save.s index 330478930..e3e0290e6 100644 --- a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_context_save.s +++ b/ports_smp/cortex_a5_smp/ac5/src/tx_thread_context_save.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026-present Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -8,6 +9,7 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ ; +; // Some portions generated by Copilot (Opus 5). ; ;/**************************************************************************/ ;/**************************************************************************/ @@ -145,11 +147,11 @@ __tx_thread_not_nested_save BEQ __tx_thread_idle_system_save ; If so, interrupt occurred in ; scheduling loop - nothing needs saving! ; -; /* Save the current stack pointer in the thread's control block. */ -; _tx_thread_current_ptr[core] -> tx_thread_stack_ptr = sp; -; -; /* Switch to the system stack. */ -; sp = _tx_thread_system_stack_ptr; +; /* This routine runs in IRQ mode on this core's banked IRQ stack, which +; serves as the system stack on this architecture, so there is no stack +; switch to perform here. The thread's stack pointer is saved in its +; control block by _tx_thread_context_restore, and only when the +; interrupt results in preemption. */ ; MOV r10, #0 ; Clear stack limit diff --git a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_system_return.s b/ports_smp/cortex_a5_smp/ac5/src/tx_thread_system_return.s index da21d7c16..cb527029f 100644 --- a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_system_return.s +++ b/ports_smp/cortex_a5_smp/ac5/src/tx_thread_system_return.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026-present Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -8,6 +9,7 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ ; +; // Some portions generated by Copilot (Opus 5). ; ;/**************************************************************************/ ;/**************************************************************************/ @@ -132,9 +134,10 @@ _tx_skip_solicited_vfp_save ADD r2, r2, r12 ; Build index into time-slice array LDR r1, [r2, #0] ; Pickup current time slice ; -; /* Save current stack and switch to system stack. */ +; /* Save the current stack pointer in the thread's control block. The +; scheduler runs on this core's banked SVC mode stack, which the startup +; code set up, so there is no stack switch to perform. */ ; _tx_thread_current_ptr[core] -> tx_thread_stack_ptr = sp; -; sp = _tx_thread_system_stack_ptr[core]; ; STR sp, [r0, #8] ; Save thread stack pointer ; diff --git a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_vectored_context_save.s b/ports_smp/cortex_a5_smp/ac5/src/tx_thread_vectored_context_save.s index 69a226939..586be818f 100644 --- a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_vectored_context_save.s +++ b/ports_smp/cortex_a5_smp/ac5/src/tx_thread_vectored_context_save.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026-present Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -8,6 +9,7 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ ; +; // Some portions generated by Copilot (Opus 5). ; ;/**************************************************************************/ ;/**************************************************************************/ @@ -143,11 +145,11 @@ __tx_thread_not_nested_save ; ; /* Note: Minimal context of interrupted thread is already saved. */ ; -; /* Save the current stack pointer in the thread's control block. */ -; _tx_thread_current_ptr[core] -> tx_thread_stack_ptr = sp; -; -; /* Switch to the system stack. */ -; sp = _tx_thread_system_stack_ptr[core]; +; /* This routine runs in IRQ mode on this core's banked IRQ stack, which +; serves as the system stack on this architecture, so there is no stack +; switch to perform here. The thread's stack pointer is saved in its +; control block by _tx_thread_context_restore, and only when the +; interrupt results in preemption. */ ; MOV r10, #0 ; Clear stack limit diff --git a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_context_save.S b/ports_smp/cortex_a5_smp/gnu/src/tx_thread_context_save.S index 3148c0f5c..0da2af21b 100644 --- a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_context_save.S +++ b/ports_smp/cortex_a5_smp/gnu/src/tx_thread_context_save.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * Copyright (c) 2026-present Eclipse ThreadX contributors @ * @ * This program and the accompanying materials are made available under the @ * terms of the MIT License which is available at @@ -8,6 +9,7 @@ @ * SPDX-License-Identifier: MIT @ **************************************************************************/ @ +@ // Some portions generated by Copilot (Opus 5). @ @/**************************************************************************/ @/**************************************************************************/ @@ -147,11 +149,11 @@ __tx_thread_not_nested_save: BEQ __tx_thread_idle_system_save @ If so, interrupt occurred in @ scheduling loop - nothing needs saving! @ -@ /* Save the current stack pointer in the thread's control block. */ -@ _tx_thread_current_ptr[core] -> tx_thread_stack_ptr = sp; -@ -@ /* Switch to the system stack. */ -@ sp = _tx_thread_system_stack_ptr; +@ /* This routine runs in IRQ mode on this core's banked IRQ stack, which +@ serves as the system stack on this architecture, so there is no stack +@ switch to perform here. The thread's stack pointer is saved in its +@ control block by _tx_thread_context_restore, and only when the +@ interrupt results in preemption. */ @ MOV r10, #0 @ Clear stack limit diff --git a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_system_return.S b/ports_smp/cortex_a5_smp/gnu/src/tx_thread_system_return.S index f49d8324c..33d1760eb 100644 --- a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_system_return.S +++ b/ports_smp/cortex_a5_smp/gnu/src/tx_thread_system_return.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * Copyright (c) 2026-present Eclipse ThreadX contributors @ * @ * This program and the accompanying materials are made available under the @ * terms of the MIT License which is available at @@ -8,6 +9,7 @@ @ * SPDX-License-Identifier: MIT @ **************************************************************************/ @ +@ // Some portions generated by Copilot (Opus 5). @ @/**************************************************************************/ @/**************************************************************************/ @@ -134,9 +136,10 @@ _tx_skip_solicited_vfp_save: ADD r2, r2, r12 @ Build index into time-slice array LDR r1, [r2, #0] @ Pickup current time slice @ -@ /* Save current stack and switch to system stack. */ +@ /* Save the current stack pointer in the thread's control block. The +@ scheduler runs on this core's banked SVC mode stack, which the startup +@ code set up, so there is no stack switch to perform. */ @ _tx_thread_current_ptr[core] -> tx_thread_stack_ptr = sp; -@ sp = _tx_thread_system_stack_ptr[core]; @ STR sp, [r0, #8] @ Save thread stack pointer @ diff --git a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_vectored_context_save.S b/ports_smp/cortex_a5_smp/gnu/src/tx_thread_vectored_context_save.S index aed336ada..8a3eb6685 100644 --- a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_vectored_context_save.S +++ b/ports_smp/cortex_a5_smp/gnu/src/tx_thread_vectored_context_save.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * Copyright (c) 2026-present Eclipse ThreadX contributors @ * @ * This program and the accompanying materials are made available under the @ * terms of the MIT License which is available at @@ -8,6 +9,7 @@ @ * SPDX-License-Identifier: MIT @ **************************************************************************/ @ +@ // Some portions generated by Copilot (Opus 5). @ @/**************************************************************************/ @/**************************************************************************/ @@ -145,11 +147,11 @@ __tx_thread_not_nested_save: @ @ /* Note: Minimal context of interrupted thread is already saved. */ @ -@ /* Save the current stack pointer in the thread's control block. */ -@ _tx_thread_current_ptr[core] -> tx_thread_stack_ptr = sp; -@ -@ /* Switch to the system stack. */ -@ sp = _tx_thread_system_stack_ptr[core]; +@ /* This routine runs in IRQ mode on this core's banked IRQ stack, which +@ serves as the system stack on this architecture, so there is no stack +@ switch to perform here. The thread's stack pointer is saved in its +@ control block by _tx_thread_context_restore, and only when the +@ interrupt results in preemption. */ @ MOV r10, #0 @ Clear stack limit diff --git a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_context_save.s b/ports_smp/cortex_a7_smp/ac5/src/tx_thread_context_save.s index acc2de11c..8c45f4a97 100644 --- a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_context_save.s +++ b/ports_smp/cortex_a7_smp/ac5/src/tx_thread_context_save.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026-present Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -8,6 +9,7 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ ; +; // Some portions generated by Copilot (Opus 5). ; ;/**************************************************************************/ ;/**************************************************************************/ @@ -145,11 +147,11 @@ __tx_thread_not_nested_save BEQ __tx_thread_idle_system_save ; If so, interrupt occurred in ; scheduling loop - nothing needs saving! ; -; /* Save the current stack pointer in the thread's control block. */ -; _tx_thread_current_ptr[core] -> tx_thread_stack_ptr = sp; -; -; /* Switch to the system stack. */ -; sp = _tx_thread_system_stack_ptr; +; /* This routine runs in IRQ mode on this core's banked IRQ stack, which +; serves as the system stack on this architecture, so there is no stack +; switch to perform here. The thread's stack pointer is saved in its +; control block by _tx_thread_context_restore, and only when the +; interrupt results in preemption. */ ; MOV r10, #0 ; Clear stack limit diff --git a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_system_return.s b/ports_smp/cortex_a7_smp/ac5/src/tx_thread_system_return.s index ebd80ae25..75bea71e5 100644 --- a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_system_return.s +++ b/ports_smp/cortex_a7_smp/ac5/src/tx_thread_system_return.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026-present Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -8,6 +9,7 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ ; +; // Some portions generated by Copilot (Opus 5). ; ;/**************************************************************************/ ;/**************************************************************************/ @@ -132,9 +134,10 @@ _tx_skip_solicited_vfp_save ADD r2, r2, r12 ; Build index into time-slice array LDR r1, [r2, #0] ; Pickup current time slice ; -; /* Save current stack and switch to system stack. */ +; /* Save the current stack pointer in the thread's control block. The +; scheduler runs on this core's banked SVC mode stack, which the startup +; code set up, so there is no stack switch to perform. */ ; _tx_thread_current_ptr[core] -> tx_thread_stack_ptr = sp; -; sp = _tx_thread_system_stack_ptr[core]; ; STR sp, [r0, #8] ; Save thread stack pointer ; diff --git a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_vectored_context_save.s b/ports_smp/cortex_a7_smp/ac5/src/tx_thread_vectored_context_save.s index 86145e1e6..a46578ece 100644 --- a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_vectored_context_save.s +++ b/ports_smp/cortex_a7_smp/ac5/src/tx_thread_vectored_context_save.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026-present Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -8,6 +9,7 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ ; +; // Some portions generated by Copilot (Opus 5). ; ;/**************************************************************************/ ;/**************************************************************************/ @@ -143,11 +145,11 @@ __tx_thread_not_nested_save ; ; /* Note: Minimal context of interrupted thread is already saved. */ ; -; /* Save the current stack pointer in the thread's control block. */ -; _tx_thread_current_ptr[core] -> tx_thread_stack_ptr = sp; -; -; /* Switch to the system stack. */ -; sp = _tx_thread_system_stack_ptr[core]; +; /* This routine runs in IRQ mode on this core's banked IRQ stack, which +; serves as the system stack on this architecture, so there is no stack +; switch to perform here. The thread's stack pointer is saved in its +; control block by _tx_thread_context_restore, and only when the +; interrupt results in preemption. */ ; MOV r10, #0 ; Clear stack limit diff --git a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_context_save.S b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_context_save.S index 448b3a5af..6deb2371d 100644 --- a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_context_save.S +++ b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_context_save.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * Copyright (c) 2026-present Eclipse ThreadX contributors @ * @ * This program and the accompanying materials are made available under the @ * terms of the MIT License which is available at @@ -8,6 +9,7 @@ @ * SPDX-License-Identifier: MIT @ **************************************************************************/ @ +@ // Some portions generated by Copilot (Opus 5). @ @/**************************************************************************/ @/**************************************************************************/ @@ -150,11 +152,11 @@ __tx_thread_not_nested_save: BEQ __tx_thread_idle_system_save @ If so, interrupt occurred in @ scheduling loop - nothing needs saving! @ -@ /* Save the current stack pointer in the thread's control block. */ -@ _tx_thread_current_ptr[core] -> tx_thread_stack_ptr = sp; -@ -@ /* Switch to the system stack. */ -@ sp = _tx_thread_system_stack_ptr; +@ /* This routine runs in IRQ mode on this core's banked IRQ stack, which +@ serves as the system stack on this architecture, so there is no stack +@ switch to perform here. The thread's stack pointer is saved in its +@ control block by _tx_thread_context_restore, and only when the +@ interrupt results in preemption. */ @ MOV r10, #0 @ Clear stack limit diff --git a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_system_return.S b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_system_return.S index 98e64ad1c..565390fce 100644 --- a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_system_return.S +++ b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_system_return.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * Copyright (c) 2026-present Eclipse ThreadX contributors @ * @ * This program and the accompanying materials are made available under the @ * terms of the MIT License which is available at @@ -8,6 +9,7 @@ @ * SPDX-License-Identifier: MIT @ **************************************************************************/ @ +@ // Some portions generated by Copilot (Opus 5). @ @/**************************************************************************/ @/**************************************************************************/ @@ -134,9 +136,10 @@ _tx_skip_solicited_vfp_save: ADD r2, r2, r12 @ Build index into time-slice array LDR r1, [r2, #0] @ Pickup current time slice @ -@ /* Save current stack and switch to system stack. */ +@ /* Save the current stack pointer in the thread's control block. The +@ scheduler runs on this core's banked SVC mode stack, which the startup +@ code set up, so there is no stack switch to perform. */ @ _tx_thread_current_ptr[core] -> tx_thread_stack_ptr = sp; -@ sp = _tx_thread_system_stack_ptr[core]; @ STR sp, [r0, #8] @ Save thread stack pointer @ diff --git a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_vectored_context_save.S b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_vectored_context_save.S index 0d8aab556..a656be78b 100644 --- a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_vectored_context_save.S +++ b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_vectored_context_save.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * Copyright (c) 2026-present Eclipse ThreadX contributors @ * @ * This program and the accompanying materials are made available under the @ * terms of the MIT License which is available at @@ -8,6 +9,7 @@ @ * SPDX-License-Identifier: MIT @ **************************************************************************/ @ +@ // Some portions generated by Copilot (Opus 5). @ @/**************************************************************************/ @/**************************************************************************/ @@ -145,11 +147,11 @@ __tx_thread_not_nested_save: @ @ /* Note: Minimal context of interrupted thread is already saved. */ @ -@ /* Save the current stack pointer in the thread's control block. */ -@ _tx_thread_current_ptr[core] -> tx_thread_stack_ptr = sp; -@ -@ /* Switch to the system stack. */ -@ sp = _tx_thread_system_stack_ptr[core]; +@ /* This routine runs in IRQ mode on this core's banked IRQ stack, which +@ serves as the system stack on this architecture, so there is no stack +@ switch to perform here. The thread's stack pointer is saved in its +@ control block by _tx_thread_context_restore, and only when the +@ interrupt results in preemption. */ @ MOV r10, #0 @ Clear stack limit diff --git a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_context_save.s b/ports_smp/cortex_a9_smp/ac5/src/tx_thread_context_save.s index a0e2a5e6c..948748287 100644 --- a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_context_save.s +++ b/ports_smp/cortex_a9_smp/ac5/src/tx_thread_context_save.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026-present Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -8,6 +9,7 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ ; +; // Some portions generated by Copilot (Opus 5). ; ;/**************************************************************************/ ;/**************************************************************************/ @@ -145,11 +147,11 @@ __tx_thread_not_nested_save BEQ __tx_thread_idle_system_save ; If so, interrupt occurred in ; scheduling loop - nothing needs saving! ; -; /* Save the current stack pointer in the thread's control block. */ -; _tx_thread_current_ptr[core] -> tx_thread_stack_ptr = sp; -; -; /* Switch to the system stack. */ -; sp = _tx_thread_system_stack_ptr; +; /* This routine runs in IRQ mode on this core's banked IRQ stack, which +; serves as the system stack on this architecture, so there is no stack +; switch to perform here. The thread's stack pointer is saved in its +; control block by _tx_thread_context_restore, and only when the +; interrupt results in preemption. */ ; MOV r10, #0 ; Clear stack limit diff --git a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_system_return.s b/ports_smp/cortex_a9_smp/ac5/src/tx_thread_system_return.s index f03fc6fe4..4b8b56ce0 100644 --- a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_system_return.s +++ b/ports_smp/cortex_a9_smp/ac5/src/tx_thread_system_return.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026-present Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -8,6 +9,7 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ ; +; // Some portions generated by Copilot (Opus 5). ; ;/**************************************************************************/ ;/**************************************************************************/ @@ -132,9 +134,10 @@ _tx_skip_solicited_vfp_save ADD r2, r2, r12 ; Build index into time-slice array LDR r1, [r2, #0] ; Pickup current time slice ; -; /* Save current stack and switch to system stack. */ +; /* Save the current stack pointer in the thread's control block. The +; scheduler runs on this core's banked SVC mode stack, which the startup +; code set up, so there is no stack switch to perform. */ ; _tx_thread_current_ptr[core] -> tx_thread_stack_ptr = sp; -; sp = _tx_thread_system_stack_ptr[core]; ; STR sp, [r0, #8] ; Save thread stack pointer ; diff --git a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_vectored_context_save.s b/ports_smp/cortex_a9_smp/ac5/src/tx_thread_vectored_context_save.s index 8102e78bf..8bd7dc61d 100644 --- a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_vectored_context_save.s +++ b/ports_smp/cortex_a9_smp/ac5/src/tx_thread_vectored_context_save.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * Copyright (c) 2026-present Eclipse ThreadX contributors ; * ; * This program and the accompanying materials are made available under the ; * terms of the MIT License which is available at @@ -8,6 +9,7 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ ; +; // Some portions generated by Copilot (Opus 5). ; ;/**************************************************************************/ ;/**************************************************************************/ @@ -143,11 +145,11 @@ __tx_thread_not_nested_save ; ; /* Note: Minimal context of interrupted thread is already saved. */ ; -; /* Save the current stack pointer in the thread's control block. */ -; _tx_thread_current_ptr[core] -> tx_thread_stack_ptr = sp; -; -; /* Switch to the system stack. */ -; sp = _tx_thread_system_stack_ptr[core]; +; /* This routine runs in IRQ mode on this core's banked IRQ stack, which +; serves as the system stack on this architecture, so there is no stack +; switch to perform here. The thread's stack pointer is saved in its +; control block by _tx_thread_context_restore, and only when the +; interrupt results in preemption. */ ; MOV r10, #0 ; Clear stack limit diff --git a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_context_save.S b/ports_smp/cortex_a9_smp/gnu/src/tx_thread_context_save.S index ae4065c41..32a78bc8d 100644 --- a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_context_save.S +++ b/ports_smp/cortex_a9_smp/gnu/src/tx_thread_context_save.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * Copyright (c) 2026-present Eclipse ThreadX contributors @ * @ * This program and the accompanying materials are made available under the @ * terms of the MIT License which is available at @@ -8,6 +9,7 @@ @ * SPDX-License-Identifier: MIT @ **************************************************************************/ @ +@ // Some portions generated by Copilot (Opus 5). @ @/**************************************************************************/ @/**************************************************************************/ @@ -147,11 +149,11 @@ __tx_thread_not_nested_save: BEQ __tx_thread_idle_system_save @ If so, interrupt occurred in @ scheduling loop - nothing needs saving! @ -@ /* Save the current stack pointer in the thread's control block. */ -@ _tx_thread_current_ptr[core] -> tx_thread_stack_ptr = sp; -@ -@ /* Switch to the system stack. */ -@ sp = _tx_thread_system_stack_ptr; +@ /* This routine runs in IRQ mode on this core's banked IRQ stack, which +@ serves as the system stack on this architecture, so there is no stack +@ switch to perform here. The thread's stack pointer is saved in its +@ control block by _tx_thread_context_restore, and only when the +@ interrupt results in preemption. */ @ MOV r10, #0 @ Clear stack limit diff --git a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_system_return.S b/ports_smp/cortex_a9_smp/gnu/src/tx_thread_system_return.S index 6feec05b6..7c0ba3d3b 100644 --- a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_system_return.S +++ b/ports_smp/cortex_a9_smp/gnu/src/tx_thread_system_return.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * Copyright (c) 2026-present Eclipse ThreadX contributors @ * @ * This program and the accompanying materials are made available under the @ * terms of the MIT License which is available at @@ -8,6 +9,7 @@ @ * SPDX-License-Identifier: MIT @ **************************************************************************/ @ +@ // Some portions generated by Copilot (Opus 5). @ @/**************************************************************************/ @/**************************************************************************/ @@ -134,9 +136,10 @@ _tx_skip_solicited_vfp_save: ADD r2, r2, r12 @ Build index into time-slice array LDR r1, [r2, #0] @ Pickup current time slice @ -@ /* Save current stack and switch to system stack. */ +@ /* Save the current stack pointer in the thread's control block. The +@ scheduler runs on this core's banked SVC mode stack, which the startup +@ code set up, so there is no stack switch to perform. */ @ _tx_thread_current_ptr[core] -> tx_thread_stack_ptr = sp; -@ sp = _tx_thread_system_stack_ptr[core]; @ STR sp, [r0, #8] @ Save thread stack pointer @ diff --git a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_vectored_context_save.S b/ports_smp/cortex_a9_smp/gnu/src/tx_thread_vectored_context_save.S index 5991c4707..8c85ddbd0 100644 --- a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_vectored_context_save.S +++ b/ports_smp/cortex_a9_smp/gnu/src/tx_thread_vectored_context_save.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * Copyright (c) 2026-present Eclipse ThreadX contributors @ * @ * This program and the accompanying materials are made available under the @ * terms of the MIT License which is available at @@ -8,6 +9,7 @@ @ * SPDX-License-Identifier: MIT @ **************************************************************************/ @ +@ // Some portions generated by Copilot (Opus 5). @ @/**************************************************************************/ @/**************************************************************************/ @@ -145,11 +147,11 @@ __tx_thread_not_nested_save: @ @ /* Note: Minimal context of interrupted thread is already saved. */ @ -@ /* Save the current stack pointer in the thread's control block. */ -@ _tx_thread_current_ptr[core] -> tx_thread_stack_ptr = sp; -@ -@ /* Switch to the system stack. */ -@ sp = _tx_thread_system_stack_ptr[core]; +@ /* This routine runs in IRQ mode on this core's banked IRQ stack, which +@ serves as the system stack on this architecture, so there is no stack +@ switch to perform here. The thread's stack pointer is saved in its +@ control block by _tx_thread_context_restore, and only when the +@ interrupt results in preemption. */ @ MOV r10, #0 @ Clear stack limit diff --git a/ports_smp/cortex_r8_smp/ac5/src/tx_thread_context_save.s b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_context_save.s index 780a6b0ae..f506f4e42 100644 --- a/ports_smp/cortex_r8_smp/ac5/src/tx_thread_context_save.s +++ b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_context_save.s @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -134,11 +135,11 @@ __tx_thread_not_nested_save BEQ __tx_thread_idle_system_save // If so, interrupt occurred in // scheduling loop - nothing needs saving! - /* Save the current stack pointer in the thread's control block. */ - // _tx_thread_current_ptr[core] -> tx_thread_stack_ptr = sp; - - /* Switch to the system stack. */ - // sp = _tx_thread_system_stack_ptr; + /* This routine runs in IRQ mode on this core's banked IRQ stack, which + serves as the system stack on this architecture, so there is no stack + switch to perform here. The thread's stack pointer is saved in its + control block by _tx_thread_context_restore, and only when the + interrupt results in preemption. */ MOV r10, #0 // Clear stack limit diff --git a/ports_smp/cortex_r8_smp/ac5/src/tx_thread_system_return.s b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_system_return.s index 2280a3518..fc1b59ed8 100644 --- a/ports_smp/cortex_r8_smp/ac5/src/tx_thread_system_return.s +++ b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_system_return.s @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -120,9 +121,10 @@ _tx_skip_solicited_vfp_save ADD r2, r2, r12 // Build index into time-slice array LDR r1, [r2, #0] // Pickup current time slice - /* Save current stack and switch to system stack. */ + /* Save the current stack pointer in the thread's control block. The + scheduler runs on this core's banked SVC mode stack, which the startup + code set up, so there is no stack switch to perform. */ // _tx_thread_current_ptr[core] -> tx_thread_stack_ptr = sp; - // sp = _tx_thread_system_stack_ptr[core]; STR sp, [r0, #8] // Save thread stack pointer diff --git a/ports_smp/cortex_r8_smp/ac5/src/tx_thread_vectored_context_save.s b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_vectored_context_save.s index c62297e85..9e82773c0 100644 --- a/ports_smp/cortex_r8_smp/ac5/src/tx_thread_vectored_context_save.s +++ b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_vectored_context_save.s @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -132,11 +133,11 @@ __tx_thread_not_nested_save /* Note: Minimal context of interrupted thread is already saved. */ - /* Save the current stack pointer in the thread's control block. */ - // _tx_thread_current_ptr[core] -> tx_thread_stack_ptr = sp; - - /* Switch to the system stack. */ - // sp = _tx_thread_system_stack_ptr[core]; + /* This routine runs in IRQ mode on this core's banked IRQ stack, which + serves as the system stack on this architecture, so there is no stack + switch to perform here. The thread's stack pointer is saved in its + control block by _tx_thread_context_restore, and only when the + interrupt results in preemption. */ MOV r10, #0 // Clear stack limit From 83a3e62c280b855568ed96ff92a82f1a9092d737 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 14 Sep 2026 16:08:48 -0400 Subject: [PATCH 133/181] Added a Module Manager host test harness and released a module thread's kernel stack only when it has one (#738) * Released a module thread's kernel stack only when it has one, so deleting a thread without a manager-allocated stack no longer asks for that memory back The thread delete dispatcher decided whether to release a kernel stack from the calling module's property flags. A user-mode module can be given the address of a thread that carries no kernel stack the manager allocated, and deleting it passed that thread's null stack pointer to _txm_module_manager_object_deallocate(). The pointer is now tested instead of the module's properties. Both thread create paths clear the whole control block before filling it in, so a thread with no manager-allocated kernel stack holds TX_NULL in the field, which makes the test exact rather than an inference from how the module was loaded. Assisted-by: Claude Code (Opus 5) * Added a Module Manager host test harness and covered the user-mode thread kernel stack lifetime The Module Manager is not in the ThreadX library the test tree links, and its control blocks come from a module port rather than a base port, so nothing in the suite could reach it. The thread_transition directory already describes this technique as the one "the module manager tests in this tree use", but no such tests existed. This adds the directory that comment refers to: a port shim that replaces the three interrupt primitives with host equivalents that count, and a CMake target that compiles the manager sources under test directly against one module port's headers. The dispatch layer is one header of static functions and an unoptimised build emits all of them, so a test that includes it to reach one dispatcher would pull in references to every service the manager can dispatch. The header guards each dispatcher with its own TXM__CALL_NOT_USED macro, so the build reads that list out of the header and defines every guard except the ones the test needs. Reading it rather than writing it down means a service added later is excluded without anyone having to remember. The first test asserts the invariant a user-mode module thread has to hold: one logical thread costs the object pool two allocations, the control block the module asks for and the kernel stack the manager takes on its behalf, and deleting the thread must return the pool's available bytes and the module's allocation-list count to exactly what they were. It asserts an equality rather than a bound, because a bound would pass while one of the two was left behind on every cycle, and then runs enough cycles that a leak of one stack per cycle exhausts the pool several times over. Assisted-by: Claude Code (Opus 5) --- .../inc/txm_module_manager_dispatch.h | 9 +- test/tx/cmake/CMakeLists.txt | 5 + test/tx/cmake/module_manager/CMakeLists.txt | 80 +++ .../threadx_module_manager_host_test_port.h | 80 +++ ..._module_manager_thread_kernel_stack_test.c | 535 ++++++++++++++++++ 5 files changed, 707 insertions(+), 2 deletions(-) create mode 100644 test/tx/cmake/module_manager/CMakeLists.txt create mode 100644 test/tx/module_manager/threadx_module_manager_host_test_port.h create mode 100644 test/tx/module_manager/threadx_module_manager_thread_kernel_stack_test.c diff --git a/common_modules/module_manager/inc/txm_module_manager_dispatch.h b/common_modules/module_manager/inc/txm_module_manager_dispatch.h index 465366068..03ba6ea53 100644 --- a/common_modules/module_manager/inc/txm_module_manager_dispatch.h +++ b/common_modules/module_manager/inc/txm_module_manager_dispatch.h @@ -2078,9 +2078,14 @@ ALIGN_TYPE stack_status; return_value = (ALIGN_TYPE) _txe_thread_delete(thread_ptr); - /* Deallocate the kernel stack for a user-mode thread. */ + /* Deallocate the kernel stack for a user-mode thread. The pointer is tested + rather than the module's properties: both thread create paths clear the whole + control block before filling it in, so a thread that carries no kernel stack + the manager allocated holds TX_NULL here, and a user-mode module can be given + the address of such a thread. */ if ((return_value == TX_SUCCESS) && - (module_instance -> txm_module_instance_property_flags & TXM_MODULE_USER_MODE)) + (module_instance -> txm_module_instance_property_flags & TXM_MODULE_USER_MODE) && + (thread_ptr -> tx_thread_module_kernel_stack_start != TX_NULL)) { stack_status = _txm_module_manager_object_deallocate(thread_ptr -> tx_thread_module_kernel_stack_start); } diff --git a/test/tx/cmake/CMakeLists.txt b/test/tx/cmake/CMakeLists.txt index 235a28d2e..f8e902efa 100644 --- a/test/tx/cmake/CMakeLists.txt +++ b/test/tx/cmake/CMakeLists.txt @@ -70,6 +70,11 @@ add_subdirectory(samples) # there turns a set of clean merges into a set of one-line conflicts. add_subdirectory(thread_transition) +# Host tests for the Module Manager. Listed after thread_transition for the reason +# given above it: additions here are appended rather than inserted, so that branches +# adding a directory of their own merge cleanly. +add_subdirectory(module_manager) + # Coverage # # The gate here used to be the build type alone, and only one of the five diff --git a/test/tx/cmake/module_manager/CMakeLists.txt b/test/tx/cmake/module_manager/CMakeLists.txt new file mode 100644 index 000000000..38808a26e --- /dev/null +++ b/test/tx/cmake/module_manager/CMakeLists.txt @@ -0,0 +1,80 @@ +cmake_minimum_required(VERSION 3.13 FATAL_ERROR) +cmake_policy(SET CMP0057 NEW) + +project(module_manager_test LANGUAGES C) + +set(REPO_ROOT ${CMAKE_CURRENT_LIST_DIR}/../../../..) +set(SOURCE_DIR ${REPO_ROOT}/test/tx/module_manager) + +# The Module Manager is not part of the ThreadX library this test tree builds, and +# its control blocks come from a module port rather than a base port. These tests +# therefore compile the manager sources they exercise directly against one module +# port's headers, and stand stubs behind the kernel services those sources call, so +# that they run on the host like every other test here. It is the same technique the +# thread_transition directory uses, for the same reason: the code under test cannot +# be reached through the library the suite links. +# +# Every module port is an embedded architecture, so the interrupt primitives those +# sources use are inline assembly the host assembler cannot take. The port shim +# header is force-included ahead of every translation unit here and replaces the +# three of them with host equivalents that count. + +set(module_manager_dir ${REPO_ROOT}/common_modules/module_manager) +set(cortex_a7_module_dir ${REPO_ROOT}/ports_module/cortex_a7/gnu) + +add_executable( + threadx_module_manager_thread_kernel_stack_test + ${SOURCE_DIR}/threadx_module_manager_thread_kernel_stack_test.c + ${module_manager_dir}/src/txm_module_manager_util.c + ${module_manager_dir}/src/txm_module_manager_object_allocate.c + ${module_manager_dir}/src/txm_module_manager_object_deallocate.c) + +target_include_directories( + threadx_module_manager_thread_kernel_stack_test + PRIVATE ${SOURCE_DIR} + ${REPO_ROOT}/common/inc + ${REPO_ROOT}/common_modules/inc + ${module_manager_dir}/inc + ${cortex_a7_module_dir}/inc) + +# The dispatch layer is one header of static functions, one per kernel service. A +# test reaches the dispatcher it exercises by including that header, which defines +# every other dispatcher too, and an unoptimised build emits them all -- so their +# references to services this harness stands behind nothing for would reach the +# linker. +# +# The header guards each dispatcher with its own TXM__CALL_NOT_USED macro, +# which is the supported way to trim the dispatch table. Defining every guard except +# the ones a test needs leaves that test's translation unit holding only the +# dispatcher under test. The list is read out of the header rather than written down +# here, so a service added later is excluded without anyone having to remember. +file(STRINGS ${module_manager_dir}/inc/txm_module_manager_dispatch.h + dispatch_guard_lines REGEX "^#ifndef TXM_[A-Z0-9_]+_CALL_NOT_USED") + +set(dispatch_guards "") +foreach(guard_line ${dispatch_guard_lines}) + string(REGEX MATCH "TXM_[A-Z0-9_]+_CALL_NOT_USED" guard "${guard_line}") + list(APPEND dispatch_guards ${guard}) +endforeach() +list(REMOVE_DUPLICATES dispatch_guards) + +# The dispatchers this test calls, which therefore must stay in. +set(kernel_stack_dispatchers TXM_THREAD_DELETE_CALL_NOT_USED) + +set(kernel_stack_guards ${dispatch_guards}) +list(REMOVE_ITEM kernel_stack_guards ${kernel_stack_dispatchers}) + +target_compile_definitions(threadx_module_manager_thread_kernel_stack_test + PRIVATE ${kernel_stack_guards}) + +# The port shim is force-included ahead of every translation unit, the test included, +# because the manager sources and the dispatch header both reach for the port's +# interrupt primitives. +target_compile_options( + threadx_module_manager_thread_kernel_stack_test + PRIVATE -Wall + -Wextra + -include ${SOURCE_DIR}/threadx_module_manager_host_test_port.h) + +add_test(${CMAKE_BUILD_TYPE}::threadx_module_manager_thread_kernel_stack_test + threadx_module_manager_thread_kernel_stack_test) diff --git a/test/tx/module_manager/threadx_module_manager_host_test_port.h b/test/tx/module_manager/threadx_module_manager_host_test_port.h new file mode 100644 index 000000000..36607d206 --- /dev/null +++ b/test/tx/module_manager/threadx_module_manager_host_test_port.h @@ -0,0 +1,80 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Test */ +/** */ +/** Module Manager host test port shim */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +/* The Module Manager is not in the ThreadX library this test tree builds, and its + control blocks come from a module port rather than a base port, so the manager + sources under test are compiled directly against one module port's headers. Every + module port is an embedded architecture, and their interrupt primitives are + inline assembly for that architecture, which the host assembler cannot take. + + This header is force-included ahead of each manager source under test. It brings + the port's headers in first, so every declaration the source needs is the port's + own, and then replaces the three interrupt primitives with host equivalents that + count instead of executing. Counting is not only what makes them portable: a test + can assert that a source under test left the interrupt lock balanced, and that a + section which has to run with interrupts disabled did so. */ + +#ifndef THREADX_MODULE_MANAGER_HOST_TEST_PORT_H +#define THREADX_MODULE_MANAGER_HOST_TEST_PORT_H + +#define TX_SOURCE_CODE + +#include "tx_api.h" + +#undef TX_INTERRUPT_SAVE_AREA +#undef TX_DISABLE +#undef TX_RESTORE + +/* Nesting depth of the stand-in interrupt lock, and the deepest it has ever been. + Defined by the test, which is the only translation unit that reads them. */ +extern unsigned int test_interrupt_disable_depth; +extern unsigned int test_interrupt_disable_max_depth; +extern unsigned int test_interrupt_restore_underflows; + +#define TX_INTERRUPT_SAVE_AREA + +#define TX_DISABLE \ + { \ + test_interrupt_disable_depth++; \ + if (test_interrupt_disable_depth > test_interrupt_disable_max_depth) \ + { \ + test_interrupt_disable_max_depth = test_interrupt_disable_depth; \ + } \ + } + +#define TX_RESTORE \ + { \ + if (test_interrupt_disable_depth == 0U) \ + { \ + test_interrupt_restore_underflows++; \ + } \ + else \ + { \ + test_interrupt_disable_depth--; \ + } \ + } + +#endif diff --git a/test/tx/module_manager/threadx_module_manager_thread_kernel_stack_test.c b/test/tx/module_manager/threadx_module_manager_thread_kernel_stack_test.c new file mode 100644 index 000000000..8d319b554 --- /dev/null +++ b/test/tx/module_manager/threadx_module_manager_thread_kernel_stack_test.c @@ -0,0 +1,535 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Test */ +/** */ +/** Module thread kernel stack lifetime */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +/* One logical thread of a user-mode module costs the object pool two allocations: + the TX_THREAD control block the module asks for, and the privileged kernel stack + the manager takes on the module's behalf and records in that control block. Both + are linked onto the module's allocation list, and only the module's own request + is visible to it. + + What this asserts is an equality rather than a bound: the pool's available bytes + and the module's allocation-list count must come back to exactly what they were + before the thread existed. A bound would pass while one of the two allocations + was left behind on every cycle. */ + +#include + +#include "tx_api.h" +#include "tx_thread.h" +#include "tx_timer.h" +#include "tx_queue.h" +#include "tx_semaphore.h" +#include "tx_mutex.h" +#include "tx_event_flags.h" +#include "tx_block_pool.h" +#include "tx_byte_pool.h" +#include "txm_module.h" +#include "txm_module_manager_util.h" +#include "txm_module_manager_dispatch.h" + + +/* A pool small enough that a leak of one kernel stack per cycle exhausts it well + inside the cycle count below. */ +#define TEST_POOL_BYTES 12280 + +/* How many create and delete cycles to run. Far more than the pool can absorb if + anything is left behind. */ +#define TEST_CYCLES 200 + + +/* The arena the stand-in byte pool hands out of, aligned as the real pool is. */ +static union +{ + ULONG test_pool_alignment; + UCHAR test_pool_bytes[TEST_POOL_BYTES]; +} test_pool_arena; + +/* Bump position, and a free list of blocks given back. A released block is offered + again only for a request of exactly its size, which is all the cycles below need + and keeps the arena from growing when nothing leaks. */ +static ULONG test_pool_offset; + +typedef struct TEST_FREE_BLOCK_STRUCT +{ + UCHAR *test_free_start; + ULONG test_free_size; +} TEST_FREE_BLOCK; + +#define TEST_FREE_BLOCKS 64 + +static TEST_FREE_BLOCK test_free_list[TEST_FREE_BLOCKS]; +static ULONG test_free_count; + +/* Counts of what the manager asked the pool to do. */ +static ULONG test_allocations; +static ULONG test_releases; + +/* Expectation accounting. */ +static ULONG test_checks; +static ULONG test_failures; + +/* Interrupt lock accounting, referenced by the force-included port shim. */ +unsigned int test_interrupt_disable_depth; +unsigned int test_interrupt_disable_max_depth; +unsigned int test_interrupt_restore_underflows; + +/* The manager globals the sources under test refer to. */ +TX_BYTE_POOL _txm_module_manager_object_pool; +UINT _txm_module_manager_object_pool_created; +TX_MUTEX _txm_module_manager_mutex; +TX_THREAD *_tx_thread_current_ptr; + +/* The thread the requests are made on behalf of. */ +static TX_THREAD test_current_thread; + +/* What the stand-in thread delete was told, and what it should report. */ +static TX_THREAD *test_deleted_thread; +static UINT test_delete_status; + + +/* Record the outcome of one expectation. */ +static VOID test_expect(const char *description, ULONG actual, ULONG expected) +{ + + test_checks++; + + if (actual != expected) + { + printf("FAIL: %s (expected %lu, got %lu)\n", description, + (unsigned long) expected, (unsigned long) actual); + test_failures++; + } +} + + +/* Stand in for the byte pool. Requests come only from the manager's allocator, and + the accounting mirrors the real one closely enough for an equality assertion: + available falls by exactly what was handed out and rises by exactly what came + back. */ +UINT _txe_byte_allocate(TX_BYTE_POOL *pool_ptr, VOID **memory_ptr, ULONG memory_size, ULONG wait_option) +{ + +ULONG index; +UCHAR *block_start; + + + (VOID) wait_option; + + if ((pool_ptr != &_txm_module_manager_object_pool) || (memory_ptr == TX_NULL)) + { + return(TX_PTR_ERROR); + } + + block_start = TX_NULL; + + /* Offer a block of exactly this size back before taking new arena. */ + for (index = 0; index < test_free_count; index++) + { + if (test_free_list[index].test_free_size == memory_size) + { + block_start = test_free_list[index].test_free_start; + + test_free_count--; + test_free_list[index] = test_free_list[test_free_count]; + break; + } + } + + if (block_start == TX_NULL) + { + + /* Keep every block aligned the way the real pool does. */ + ULONG rounded_size = (memory_size + (sizeof(ULONG) - 1U)) & (~(sizeof(ULONG) - 1U)); + + if ((test_pool_offset + rounded_size) > ((ULONG) TEST_POOL_BYTES)) + { + return(TX_NO_MEMORY); + } + + block_start = &test_pool_arena.test_pool_bytes[test_pool_offset]; + test_pool_offset = test_pool_offset + rounded_size; + } + + _txm_module_manager_object_pool.tx_byte_pool_available = + _txm_module_manager_object_pool.tx_byte_pool_available - memory_size; + + test_allocations++; + + *memory_ptr = (VOID *) block_start; + + return(TX_SUCCESS); +} + + +/* Stand in for the release side. An address outside the arena is refused, which is + what makes a release of memory the pool never handed out visible as a failure + rather than as silent bookkeeping. */ +UINT _txe_byte_release(VOID *memory_ptr) +{ + +UCHAR *block_start; +ULONG index; + + + block_start = (UCHAR *) memory_ptr; + + if ((block_start < test_pool_arena.test_pool_bytes) || + (block_start >= &test_pool_arena.test_pool_bytes[TEST_POOL_BYTES])) + { + return(TX_PTR_ERROR); + } + + /* The size is the one recorded in the manager's header, which sits at the start + of the block, plus the header itself. */ + { + TXM_MODULE_ALLOCATED_OBJECT *header_ptr; + ULONG block_size; + + header_ptr = (TXM_MODULE_ALLOCATED_OBJECT *) memory_ptr; + block_size = header_ptr -> txm_module_object_size + (ULONG) sizeof(TXM_MODULE_ALLOCATED_OBJECT); + + _txm_module_manager_object_pool.tx_byte_pool_available = + _txm_module_manager_object_pool.tx_byte_pool_available + block_size; + + if (test_free_count < ((ULONG) TEST_FREE_BLOCKS)) + { + index = test_free_count; + test_free_list[index].test_free_start = block_start; + test_free_list[index].test_free_size = block_size; + test_free_count++; + } + } + + test_releases++; + + return(TX_SUCCESS); +} + + +/* Stand in for the module port's data-range check. Nothing here is inside a module's + own data, so every address the manager asks about is outside it. */ +UINT _txm_module_manager_inside_data_check(ULONG obj_ptr) +{ + + (VOID) obj_ptr; + + return(TX_FALSE); +} + + +/* Stand in for the module port's alignment adjustment. It is referenced by a + loading path this test does not drive, and is never reached from here. */ +VOID _txm_module_manager_alignment_adjust(TXM_MODULE_PREAMBLE *module_preamble, ULONG *code_size, + ULONG *code_alignment, ULONG *data_size, ULONG *data_alignment) +{ + + (VOID) module_preamble; + (VOID) code_size; + (VOID) code_alignment; + (VOID) data_size; + (VOID) data_alignment; +} + + +UINT _txe_mutex_get(TX_MUTEX *mutex_ptr, ULONG wait_option) +{ + + (VOID) mutex_ptr; + (VOID) wait_option; + + return(TX_SUCCESS); +} + + +UINT _txe_mutex_put(TX_MUTEX *mutex_ptr) +{ + + (VOID) mutex_ptr; + + return(TX_SUCCESS); +} + + +/* Stand in for the thread delete the dispatcher calls. It records what it was given + and reports what the case under test wants, so that the dispatcher's behaviour + either side of a refusal can be asserted. */ +UINT _txe_thread_delete(TX_THREAD *thread_ptr) +{ + + test_deleted_thread = thread_ptr; + + return(test_delete_status); +} + + +/* Put the pool, the module and the counters back to a known state. */ +static VOID test_reset(TXM_MODULE_INSTANCE *module_ptr, ULONG property_flags) +{ + +ULONG index; + + + for (index = 0; index < ((ULONG) TEST_POOL_BYTES); index++) + { + test_pool_arena.test_pool_bytes[index] = (UCHAR) 0; + } + + test_pool_offset = 0; + test_free_count = 0; + test_allocations = 0; + test_releases = 0; + + test_deleted_thread = TX_NULL; + test_delete_status = TX_SUCCESS; + + _txm_module_manager_object_pool.tx_byte_pool_id = TX_BYTE_POOL_ID; + _txm_module_manager_object_pool.tx_byte_pool_start = test_pool_arena.test_pool_bytes; + _txm_module_manager_object_pool.tx_byte_pool_size = TEST_POOL_BYTES; + _txm_module_manager_object_pool.tx_byte_pool_available = TEST_POOL_BYTES; + _txm_module_manager_object_pool_created = TX_TRUE; + + TX_MEMSET(module_ptr, 0, sizeof(TXM_MODULE_INSTANCE)); + module_ptr -> txm_module_instance_property_flags = property_flags; + + TX_MEMSET(&test_current_thread, 0, sizeof(TX_THREAD)); + test_current_thread.tx_thread_module_instance_ptr = module_ptr; + _tx_thread_current_ptr = &test_current_thread; +} + + +/* Create a module thread the way the manager does: the control block the module + asks for, and then, for a user-mode module, the kernel stack the manager takes on + its behalf and records in the control block. The stack allocation is the one the + module never sees and never asks to have back. */ +static TX_THREAD *test_thread_create(TXM_MODULE_INSTANCE *module_ptr) +{ + +TX_THREAD *thread_ptr; +VOID *stack_ptr; + + + thread_ptr = TX_NULL; + + if (_txm_module_manager_object_allocate((VOID **) &thread_ptr, (ULONG) sizeof(TX_THREAD), + module_ptr) != TX_SUCCESS) + { + return(TX_NULL); + } + + TX_MEMSET(thread_ptr, 0, sizeof(TX_THREAD)); + + thread_ptr -> tx_thread_id = TX_THREAD_ID; + thread_ptr -> tx_thread_module_instance_ptr = module_ptr; + + if ((module_ptr -> txm_module_instance_property_flags & TXM_MODULE_USER_MODE) != 0U) + { + + stack_ptr = TX_NULL; + + if (_txm_module_manager_object_allocate(&stack_ptr, (ULONG) TXM_MODULE_KERNEL_STACK_SIZE, + module_ptr) != TX_SUCCESS) + { + return(TX_NULL); + } + + thread_ptr -> tx_thread_module_kernel_stack_start = stack_ptr; + } + + return(thread_ptr); +} + + +int main(void) +{ + +TXM_MODULE_INSTANCE module_instance; +TX_THREAD *thread_ptr; +ULONG baseline_available; +ULONG baseline_count; +ULONG cycle; +ULONG status; + + + /**********************************************************************/ + /* One user-mode thread, created and deleted. */ + /**********************************************************************/ + + test_reset(&module_instance, (ULONG) (TXM_MODULE_USER_MODE | TXM_MODULE_MEMORY_PROTECTION)); + + baseline_available = _txm_module_manager_object_pool.tx_byte_pool_available; + baseline_count = module_instance.txm_module_instance_object_list_count; + + thread_ptr = test_thread_create(&module_instance); + + test_expect("a user-mode module thread was created", + (ULONG) (thread_ptr != TX_NULL), (ULONG) TX_TRUE); + test_expect("...costing the pool two allocations", test_allocations, ((ULONG) 2)); + test_expect("...both on the module's allocation list", + module_instance.txm_module_instance_object_list_count, (baseline_count + ((ULONG) 2))); + test_expect("...and it holds a kernel stack", + (ULONG) (thread_ptr -> tx_thread_module_kernel_stack_start != TX_NULL), (ULONG) TX_TRUE); + + status = (ULONG) _txm_module_manager_tx_thread_delete_dispatch(&module_instance, + (ALIGN_TYPE) thread_ptr); + + test_expect("deleting it succeeds", status, (ULONG) TX_SUCCESS); + test_expect("...and gives both allocations back", test_releases, ((ULONG) 2)); + test_expect("...leaving the allocation list as it was", + module_instance.txm_module_instance_object_list_count, baseline_count); + test_expect("...and the pool's available bytes exactly as they were", + _txm_module_manager_object_pool.tx_byte_pool_available, baseline_available); + + /**********************************************************************/ + /* Many cycles. A leak of one kernel stack per cycle would exhaust */ + /* this pool long before the count below is reached. */ + /**********************************************************************/ + + test_reset(&module_instance, (ULONG) (TXM_MODULE_USER_MODE | TXM_MODULE_MEMORY_PROTECTION)); + + baseline_available = _txm_module_manager_object_pool.tx_byte_pool_available; + baseline_count = module_instance.txm_module_instance_object_list_count; + + for (cycle = 0; cycle < ((ULONG) TEST_CYCLES); cycle++) + { + + thread_ptr = test_thread_create(&module_instance); + + if (thread_ptr == TX_NULL) + { + printf("FAIL: the pool was exhausted at cycle %lu\n", (unsigned long) cycle); + test_failures++; + test_checks++; + break; + } + + if (_txm_module_manager_tx_thread_delete_dispatch(&module_instance, + (ALIGN_TYPE) thread_ptr) != TX_SUCCESS) + { + printf("FAIL: the delete was refused at cycle %lu\n", (unsigned long) cycle); + test_failures++; + test_checks++; + break; + } + } + + test_expect("every cycle completed", cycle, ((ULONG) TEST_CYCLES)); + test_expect("...with the allocation list back where it started", + module_instance.txm_module_instance_object_list_count, baseline_count); + test_expect("...and the pool's available bytes back where they started", + _txm_module_manager_object_pool.tx_byte_pool_available, baseline_available); + test_expect("...having released exactly what it allocated", test_releases, test_allocations); + + /**********************************************************************/ + /* A thread that carries no kernel stack the manager allocated. */ + /**********************************************************************/ + + test_reset(&module_instance, (ULONG) (TXM_MODULE_USER_MODE | TXM_MODULE_MEMORY_PROTECTION)); + + baseline_available = _txm_module_manager_object_pool.tx_byte_pool_available; + + thread_ptr = TX_NULL; + + status = (ULONG) _txm_module_manager_object_allocate((VOID **) &thread_ptr, + (ULONG) sizeof(TX_THREAD), &module_instance); + + test_expect("a control block with no kernel stack can be allocated", status, (ULONG) TX_SUCCESS); + + TX_MEMSET(thread_ptr, 0, sizeof(TX_THREAD)); + thread_ptr -> tx_thread_id = TX_THREAD_ID; + thread_ptr -> tx_thread_module_instance_ptr = &module_instance; + + test_expect("...and holds no kernel stack", + (ULONG) (thread_ptr -> tx_thread_module_kernel_stack_start == TX_NULL), (ULONG) TX_TRUE); + + test_releases = 0; + + status = (ULONG) _txm_module_manager_tx_thread_delete_dispatch(&module_instance, + (ALIGN_TYPE) thread_ptr); + + test_expect("a user-mode module deleting it succeeds", status, (ULONG) TX_SUCCESS); + test_expect("...giving back the control block and nothing else", test_releases, ((ULONG) 1)); + test_expect("...and the pool's available bytes exactly as they were", + _txm_module_manager_object_pool.tx_byte_pool_available, baseline_available); + + /**********************************************************************/ + /* A module that is not in user mode. */ + /**********************************************************************/ + + test_reset(&module_instance, (ULONG) TXM_MODULE_MEMORY_PROTECTION); + + baseline_available = _txm_module_manager_object_pool.tx_byte_pool_available; + + thread_ptr = test_thread_create(&module_instance); + + test_expect("a thread of a module that is not in user mode was created", + (ULONG) (thread_ptr != TX_NULL), (ULONG) TX_TRUE); + test_expect("...costing the pool one allocation", test_allocations, ((ULONG) 1)); + + status = (ULONG) _txm_module_manager_tx_thread_delete_dispatch(&module_instance, + (ALIGN_TYPE) thread_ptr); + + test_expect("deleting it succeeds", status, (ULONG) TX_SUCCESS); + test_expect("...giving back that one allocation", test_releases, ((ULONG) 1)); + test_expect("...and the pool's available bytes exactly as they were", + _txm_module_manager_object_pool.tx_byte_pool_available, baseline_available); + + /**********************************************************************/ + /* A refused delete releases nothing. */ + /**********************************************************************/ + + test_reset(&module_instance, (ULONG) (TXM_MODULE_USER_MODE | TXM_MODULE_MEMORY_PROTECTION)); + + thread_ptr = test_thread_create(&module_instance); + baseline_count = module_instance.txm_module_instance_object_list_count; + test_delete_status = TX_DELETE_ERROR; + + status = (ULONG) _txm_module_manager_tx_thread_delete_dispatch(&module_instance, + (ALIGN_TYPE) thread_ptr); + + test_expect("a refused delete is reported", status, (ULONG) TX_DELETE_ERROR); + test_expect("...and releases nothing", test_releases, ((ULONG) 0)); + test_expect("...leaving both allocations on the module's list", + module_instance.txm_module_instance_object_list_count, baseline_count); + + /**********************************************************************/ + /* What the whole run has to have held. */ + /**********************************************************************/ + + test_expect("the interrupt lock was left balanced", + (ULONG) test_interrupt_disable_depth, ((ULONG) 0)); + test_expect("...and was never restored more often than it was taken", + (ULONG) test_interrupt_restore_underflows, ((ULONG) 0)); + + if (test_failures == 0U) + { + printf("SUCCESS! %lu expectations\n", (unsigned long) test_checks); + return(0); + } + + printf("ERROR: %lu expectation(s) failed of %lu\n", + (unsigned long) test_failures, (unsigned long) test_checks); + return(1); +} From cd6a2d90347945f2736a6afe25dcf745ffc31a6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 14 Sep 2026 17:09:00 -0400 Subject: [PATCH 134/181] Put the module manager test's thread on the kernel's created list, so the stand-in kernel matches the one the manager reads (#739) The host test built a TX_THREAD, gave it an ID and a module instance, and left it off the kernel's created list. A created thread lives on that list, so the thread the test created was not one the kernel would recognise. The created list head and count are now defined for each object type, the thread the test creates goes onto the thread list the way thread create puts it there, and a successful delete takes it off again the way thread delete does. Only the thread list is populated; the others stay empty because nothing here creates an object of those types. No expectation changed. Assisted-by: Claude Code (Opus 5) --- ..._module_manager_thread_kernel_stack_test.c | 39 +++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/test/tx/module_manager/threadx_module_manager_thread_kernel_stack_test.c b/test/tx/module_manager/threadx_module_manager_thread_kernel_stack_test.c index 8d319b554..e971b1599 100644 --- a/test/tx/module_manager/threadx_module_manager_thread_kernel_stack_test.c +++ b/test/tx/module_manager/threadx_module_manager_thread_kernel_stack_test.c @@ -96,6 +96,27 @@ unsigned int test_interrupt_disable_depth; unsigned int test_interrupt_disable_max_depth; unsigned int test_interrupt_restore_underflows; +/* The kernel's created lists. A created object lives on the list for its type, and + the manager reads those lists, so a test that stands in for the kernel has to + provide them. Only the thread list is populated here, by the thread this test + creates; the rest stay empty because nothing here creates an object of that type. */ +TX_BLOCK_POOL *_tx_block_pool_created_ptr; +ULONG _tx_block_pool_created_count; +TX_BYTE_POOL *_tx_byte_pool_created_ptr; +ULONG _tx_byte_pool_created_count; +TX_EVENT_FLAGS_GROUP *_tx_event_flags_created_ptr; +ULONG _tx_event_flags_created_count; +TX_MUTEX *_tx_mutex_created_ptr; +ULONG _tx_mutex_created_count; +TX_QUEUE *_tx_queue_created_ptr; +ULONG _tx_queue_created_count; +TX_SEMAPHORE *_tx_semaphore_created_ptr; +ULONG _tx_semaphore_created_count; +TX_THREAD *_tx_thread_created_ptr; +ULONG _tx_thread_created_count; +TX_TIMER *_tx_timer_created_ptr; +ULONG _tx_timer_created_count; + /* The manager globals the sources under test refer to. */ TX_BYTE_POOL _txm_module_manager_object_pool; UINT _txm_module_manager_object_pool_created; @@ -281,6 +302,13 @@ UINT _txe_thread_delete(TX_THREAD *thread_ptr) test_deleted_thread = thread_ptr; + /* A successful delete takes the thread off the kernel's created list. */ + if (test_delete_status == TX_SUCCESS) + { + _tx_thread_created_ptr = TX_NULL; + _tx_thread_created_count = (ULONG) 0; + } + return(test_delete_status); } @@ -344,6 +372,13 @@ VOID *stack_ptr; thread_ptr -> tx_thread_id = TX_THREAD_ID; thread_ptr -> tx_thread_module_instance_ptr = module_ptr; + /* Put it on the kernel's created list, which is where a created thread lives. + One thread exists at a time here, so the list is that thread alone. */ + thread_ptr -> tx_thread_created_next = thread_ptr; + thread_ptr -> tx_thread_created_previous = thread_ptr; + _tx_thread_created_ptr = thread_ptr; + _tx_thread_created_count = (ULONG) 1; + if ((module_ptr -> txm_module_instance_property_flags & TXM_MODULE_USER_MODE) != 0U) { @@ -460,6 +495,10 @@ ULONG status; TX_MEMSET(thread_ptr, 0, sizeof(TX_THREAD)); thread_ptr -> tx_thread_id = TX_THREAD_ID; thread_ptr -> tx_thread_module_instance_ptr = &module_instance; + thread_ptr -> tx_thread_created_next = thread_ptr; + thread_ptr -> tx_thread_created_previous = thread_ptr; + _tx_thread_created_ptr = thread_ptr; + _tx_thread_created_count = (ULONG) 1; test_expect("...and holds no kernel stack", (ULONG) (thread_ptr -> tx_thread_module_kernel_stack_start == TX_NULL), (ULONG) TX_TRUE); From 5d235a534c8969cc5ed50bfd492806b5b6993a3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Tue, 15 Sep 2026 16:24:09 -0400 Subject: [PATCH 135/181] Fixed the garbage _tx_initialize_unused_memory in the GNU Cortex-A ports (#726) Fixes #435 `LDR x1, =__top_of_ram` already loads the top of RAM, so the `LDR x1, [x1]` that followed read whatever sat at that address and left `_tx_initialize_unused_memory` holding garbage. Dropped that instruction from the 13 non-SMP GNU Cortex-A ports, the ARMv8-A source they are generated from, and the two Cortex-A35 module examples. The SMP GNU ports already had the correct form, and the Arm Compiler ports are unaffected -- their symbol really does need the dereference. `scripts/check_ports.sh` passes and the `gnu` CI job build-verifies the AArch64 ports. Not run on hardware. Assisted-by: Copilot (Opus 5) --- ports/cortex_a34/gnu/src/tx_initialize_low_level.S | 2 +- ports/cortex_a35/gnu/src/tx_initialize_low_level.S | 2 +- ports/cortex_a53/gnu/src/tx_initialize_low_level.S | 2 +- ports/cortex_a55/gnu/src/tx_initialize_low_level.S | 2 +- ports/cortex_a57/gnu/src/tx_initialize_low_level.S | 2 +- ports/cortex_a65/gnu/src/tx_initialize_low_level.S | 2 +- ports/cortex_a65ae/gnu/src/tx_initialize_low_level.S | 2 +- ports/cortex_a72/gnu/src/tx_initialize_low_level.S | 2 +- ports/cortex_a73/gnu/src/tx_initialize_low_level.S | 2 +- ports/cortex_a75/gnu/src/tx_initialize_low_level.S | 2 +- ports/cortex_a76/gnu/src/tx_initialize_low_level.S | 2 +- ports/cortex_a76ae/gnu/src/tx_initialize_low_level.S | 2 +- ports/cortex_a77/gnu/src/tx_initialize_low_level.S | 2 +- .../ARMv8-A/threadx/ports/gnu/src/tx_initialize_low_level.S | 2 +- .../gnu/example_build/sample_threadx/tx_initialize_low_level.S | 2 +- .../sample_threadx_module_manager/tx_initialize_low_level.S | 2 +- 16 files changed, 16 insertions(+), 16 deletions(-) diff --git a/ports/cortex_a34/gnu/src/tx_initialize_low_level.S b/ports/cortex_a34/gnu/src/tx_initialize_low_level.S index 3025f12bc..07e4ea111 100644 --- a/ports/cortex_a34/gnu/src/tx_initialize_low_level.S +++ b/ports/cortex_a34/gnu/src/tx_initialize_low_level.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -83,7 +84,6 @@ _tx_initialize_low_level: LDR x0, =_tx_initialize_unused_memory // Pickup address of unused memory ptr LDR x1, =__top_of_ram // Pickup unused memory address - LDR x1, [x1] // STR x1, [x0] // Store unused memory address /* Done, return to caller. */ diff --git a/ports/cortex_a35/gnu/src/tx_initialize_low_level.S b/ports/cortex_a35/gnu/src/tx_initialize_low_level.S index 3025f12bc..07e4ea111 100644 --- a/ports/cortex_a35/gnu/src/tx_initialize_low_level.S +++ b/ports/cortex_a35/gnu/src/tx_initialize_low_level.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -83,7 +84,6 @@ _tx_initialize_low_level: LDR x0, =_tx_initialize_unused_memory // Pickup address of unused memory ptr LDR x1, =__top_of_ram // Pickup unused memory address - LDR x1, [x1] // STR x1, [x0] // Store unused memory address /* Done, return to caller. */ diff --git a/ports/cortex_a53/gnu/src/tx_initialize_low_level.S b/ports/cortex_a53/gnu/src/tx_initialize_low_level.S index 3025f12bc..07e4ea111 100644 --- a/ports/cortex_a53/gnu/src/tx_initialize_low_level.S +++ b/ports/cortex_a53/gnu/src/tx_initialize_low_level.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -83,7 +84,6 @@ _tx_initialize_low_level: LDR x0, =_tx_initialize_unused_memory // Pickup address of unused memory ptr LDR x1, =__top_of_ram // Pickup unused memory address - LDR x1, [x1] // STR x1, [x0] // Store unused memory address /* Done, return to caller. */ diff --git a/ports/cortex_a55/gnu/src/tx_initialize_low_level.S b/ports/cortex_a55/gnu/src/tx_initialize_low_level.S index 3025f12bc..07e4ea111 100644 --- a/ports/cortex_a55/gnu/src/tx_initialize_low_level.S +++ b/ports/cortex_a55/gnu/src/tx_initialize_low_level.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -83,7 +84,6 @@ _tx_initialize_low_level: LDR x0, =_tx_initialize_unused_memory // Pickup address of unused memory ptr LDR x1, =__top_of_ram // Pickup unused memory address - LDR x1, [x1] // STR x1, [x0] // Store unused memory address /* Done, return to caller. */ diff --git a/ports/cortex_a57/gnu/src/tx_initialize_low_level.S b/ports/cortex_a57/gnu/src/tx_initialize_low_level.S index 3025f12bc..07e4ea111 100644 --- a/ports/cortex_a57/gnu/src/tx_initialize_low_level.S +++ b/ports/cortex_a57/gnu/src/tx_initialize_low_level.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -83,7 +84,6 @@ _tx_initialize_low_level: LDR x0, =_tx_initialize_unused_memory // Pickup address of unused memory ptr LDR x1, =__top_of_ram // Pickup unused memory address - LDR x1, [x1] // STR x1, [x0] // Store unused memory address /* Done, return to caller. */ diff --git a/ports/cortex_a65/gnu/src/tx_initialize_low_level.S b/ports/cortex_a65/gnu/src/tx_initialize_low_level.S index 3025f12bc..07e4ea111 100644 --- a/ports/cortex_a65/gnu/src/tx_initialize_low_level.S +++ b/ports/cortex_a65/gnu/src/tx_initialize_low_level.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -83,7 +84,6 @@ _tx_initialize_low_level: LDR x0, =_tx_initialize_unused_memory // Pickup address of unused memory ptr LDR x1, =__top_of_ram // Pickup unused memory address - LDR x1, [x1] // STR x1, [x0] // Store unused memory address /* Done, return to caller. */ diff --git a/ports/cortex_a65ae/gnu/src/tx_initialize_low_level.S b/ports/cortex_a65ae/gnu/src/tx_initialize_low_level.S index 3025f12bc..07e4ea111 100644 --- a/ports/cortex_a65ae/gnu/src/tx_initialize_low_level.S +++ b/ports/cortex_a65ae/gnu/src/tx_initialize_low_level.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -83,7 +84,6 @@ _tx_initialize_low_level: LDR x0, =_tx_initialize_unused_memory // Pickup address of unused memory ptr LDR x1, =__top_of_ram // Pickup unused memory address - LDR x1, [x1] // STR x1, [x0] // Store unused memory address /* Done, return to caller. */ diff --git a/ports/cortex_a72/gnu/src/tx_initialize_low_level.S b/ports/cortex_a72/gnu/src/tx_initialize_low_level.S index 3025f12bc..07e4ea111 100644 --- a/ports/cortex_a72/gnu/src/tx_initialize_low_level.S +++ b/ports/cortex_a72/gnu/src/tx_initialize_low_level.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -83,7 +84,6 @@ _tx_initialize_low_level: LDR x0, =_tx_initialize_unused_memory // Pickup address of unused memory ptr LDR x1, =__top_of_ram // Pickup unused memory address - LDR x1, [x1] // STR x1, [x0] // Store unused memory address /* Done, return to caller. */ diff --git a/ports/cortex_a73/gnu/src/tx_initialize_low_level.S b/ports/cortex_a73/gnu/src/tx_initialize_low_level.S index 3025f12bc..07e4ea111 100644 --- a/ports/cortex_a73/gnu/src/tx_initialize_low_level.S +++ b/ports/cortex_a73/gnu/src/tx_initialize_low_level.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -83,7 +84,6 @@ _tx_initialize_low_level: LDR x0, =_tx_initialize_unused_memory // Pickup address of unused memory ptr LDR x1, =__top_of_ram // Pickup unused memory address - LDR x1, [x1] // STR x1, [x0] // Store unused memory address /* Done, return to caller. */ diff --git a/ports/cortex_a75/gnu/src/tx_initialize_low_level.S b/ports/cortex_a75/gnu/src/tx_initialize_low_level.S index 3025f12bc..07e4ea111 100644 --- a/ports/cortex_a75/gnu/src/tx_initialize_low_level.S +++ b/ports/cortex_a75/gnu/src/tx_initialize_low_level.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -83,7 +84,6 @@ _tx_initialize_low_level: LDR x0, =_tx_initialize_unused_memory // Pickup address of unused memory ptr LDR x1, =__top_of_ram // Pickup unused memory address - LDR x1, [x1] // STR x1, [x0] // Store unused memory address /* Done, return to caller. */ diff --git a/ports/cortex_a76/gnu/src/tx_initialize_low_level.S b/ports/cortex_a76/gnu/src/tx_initialize_low_level.S index 3025f12bc..07e4ea111 100644 --- a/ports/cortex_a76/gnu/src/tx_initialize_low_level.S +++ b/ports/cortex_a76/gnu/src/tx_initialize_low_level.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -83,7 +84,6 @@ _tx_initialize_low_level: LDR x0, =_tx_initialize_unused_memory // Pickup address of unused memory ptr LDR x1, =__top_of_ram // Pickup unused memory address - LDR x1, [x1] // STR x1, [x0] // Store unused memory address /* Done, return to caller. */ diff --git a/ports/cortex_a76ae/gnu/src/tx_initialize_low_level.S b/ports/cortex_a76ae/gnu/src/tx_initialize_low_level.S index 3025f12bc..07e4ea111 100644 --- a/ports/cortex_a76ae/gnu/src/tx_initialize_low_level.S +++ b/ports/cortex_a76ae/gnu/src/tx_initialize_low_level.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -83,7 +84,6 @@ _tx_initialize_low_level: LDR x0, =_tx_initialize_unused_memory // Pickup address of unused memory ptr LDR x1, =__top_of_ram // Pickup unused memory address - LDR x1, [x1] // STR x1, [x0] // Store unused memory address /* Done, return to caller. */ diff --git a/ports/cortex_a77/gnu/src/tx_initialize_low_level.S b/ports/cortex_a77/gnu/src/tx_initialize_low_level.S index 3025f12bc..07e4ea111 100644 --- a/ports/cortex_a77/gnu/src/tx_initialize_low_level.S +++ b/ports/cortex_a77/gnu/src/tx_initialize_low_level.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -83,7 +84,6 @@ _tx_initialize_low_level: LDR x0, =_tx_initialize_unused_memory // Pickup address of unused memory ptr LDR x1, =__top_of_ram // Pickup unused memory address - LDR x1, [x1] // STR x1, [x0] // Store unused memory address /* Done, return to caller. */ diff --git a/ports_arch/ARMv8-A/threadx/ports/gnu/src/tx_initialize_low_level.S b/ports_arch/ARMv8-A/threadx/ports/gnu/src/tx_initialize_low_level.S index 3025f12bc..07e4ea111 100644 --- a/ports_arch/ARMv8-A/threadx/ports/gnu/src/tx_initialize_low_level.S +++ b/ports_arch/ARMv8-A/threadx/ports/gnu/src/tx_initialize_low_level.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -83,7 +84,6 @@ _tx_initialize_low_level: LDR x0, =_tx_initialize_unused_memory // Pickup address of unused memory ptr LDR x1, =__top_of_ram // Pickup unused memory address - LDR x1, [x1] // STR x1, [x0] // Store unused memory address /* Done, return to caller. */ diff --git a/ports_module/cortex_a35/gnu/example_build/sample_threadx/tx_initialize_low_level.S b/ports_module/cortex_a35/gnu/example_build/sample_threadx/tx_initialize_low_level.S index 55ec0f9fd..834568ed2 100644 --- a/ports_module/cortex_a35/gnu/example_build/sample_threadx/tx_initialize_low_level.S +++ b/ports_module/cortex_a35/gnu/example_build/sample_threadx/tx_initialize_low_level.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -79,7 +80,6 @@ _tx_initialize_low_level: LDR x0, =_tx_initialize_unused_memory // Pickup address of unused memory ptr LDR x1, =__top_of_ram // Pickup unused memory address - LDR x1, [x1] // STR x1, [x0] // Store unused memory address /* Done, return to caller. */ diff --git a/ports_module/cortex_a35/gnu/example_build/sample_threadx_module_manager/tx_initialize_low_level.S b/ports_module/cortex_a35/gnu/example_build/sample_threadx_module_manager/tx_initialize_low_level.S index 55ec0f9fd..834568ed2 100644 --- a/ports_module/cortex_a35/gnu/example_build/sample_threadx_module_manager/tx_initialize_low_level.S +++ b/ports_module/cortex_a35/gnu/example_build/sample_threadx_module_manager/tx_initialize_low_level.S @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -79,7 +80,6 @@ _tx_initialize_low_level: LDR x0, =_tx_initialize_unused_memory // Pickup address of unused memory ptr LDR x1, =__top_of_ram // Pickup unused memory address - LDR x1, [x1] // STR x1, [x0] // Store unused memory address /* Done, return to caller. */ From 1d4a4aeec84832f74b11c300cd53d980dd5980b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Tue, 15 Sep 2026 16:24:35 -0400 Subject: [PATCH 136/181] Guarded _tx_thread_stack_analyze against inverted stack pointers (#727) Fixes #460 `TX_ULONG_POINTER_DIF` casts the pointer difference to `ULONG`, so when `tx_thread_stack_highest_ptr` sits below `tx_thread_stack_start` the midpoint wraps to a huge value, the probe lands outside the stack, and the search never converges: the caller hangs or faults. `_tx_thread_stack_analyze` now requires the highest pointer to be strictly above the start of the stack, and bounds the final scan by it. #464 covered the `TX_THREAD_STACK_CHECK` path; this covers direct callers too, as @billlamiework suggested on the issue. Inconsistent pointers still mean a real overflow or a corrupted control block, which remains the application's problem. What changes is that ThreadX reports it through the stack error handler instead of hanging. New cases for an inverted and an equal pointer pair crash the suite without the fix and pass with it. Assisted-by: Copilot (Opus 5) --- common/src/tx_thread_stack_analyze.c | 13 ++++++++++--- common_smp/src/tx_thread_stack_analyze.c | 13 ++++++++++--- .../threadx_thread_stack_checking_test.c | 15 +++++++++++++++ .../threadx_thread_stack_checking_test.c | 15 +++++++++++++++ 4 files changed, 50 insertions(+), 6 deletions(-) diff --git a/common/src/tx_thread_stack_analyze.c b/common/src/tx_thread_stack_analyze.c index e3023f13d..37a5ac2d0 100644 --- a/common/src/tx_thread_stack_analyze.c +++ b/common/src/tx_thread_stack_analyze.c @@ -73,6 +73,7 @@ ULONG *stack_ptr; ULONG *stack_lowest; ULONG *stack_highest; ULONG *probe_ptr; +ULONG *stack_limit; ULONG probe_count; UINT fill_present; ULONG size; @@ -99,10 +100,16 @@ ULONG size; /* Pickup the highest stack pointer. */ stack_highest = TX_VOID_TO_ULONG_POINTER_CONVERT(thread_ptr -> tx_thread_stack_highest_ptr); - /* Determine if the pointer is null. */ - if (stack_highest != TX_NULL) + /* Determine if the pointer is null or if the highest stack pointer is not above the + start of the stack. The latter indicates a stack overflow or a corrupted thread + control block, and the unsigned pointer arithmetic in the binary search below would + wrap around and never converge, hanging the caller. */ + if ((stack_highest != TX_NULL) && (stack_highest > stack_lowest)) { + /* Remember the upper bound of the search so the scan below cannot run past it. */ + stack_limit = stack_highest; + /* Restore interrupts. */ TX_RESTORE @@ -173,7 +180,7 @@ ULONG size; } while(size > ((ULONG) 1)); /* Position to first used word - at this point we are within a few words. */ - while (*stack_ptr == TX_STACK_FILL) + while ((stack_ptr < stack_limit) && (*stack_ptr == TX_STACK_FILL)) { /* Position to next word in stack. */ diff --git a/common_smp/src/tx_thread_stack_analyze.c b/common_smp/src/tx_thread_stack_analyze.c index e3023f13d..37a5ac2d0 100644 --- a/common_smp/src/tx_thread_stack_analyze.c +++ b/common_smp/src/tx_thread_stack_analyze.c @@ -73,6 +73,7 @@ ULONG *stack_ptr; ULONG *stack_lowest; ULONG *stack_highest; ULONG *probe_ptr; +ULONG *stack_limit; ULONG probe_count; UINT fill_present; ULONG size; @@ -99,10 +100,16 @@ ULONG size; /* Pickup the highest stack pointer. */ stack_highest = TX_VOID_TO_ULONG_POINTER_CONVERT(thread_ptr -> tx_thread_stack_highest_ptr); - /* Determine if the pointer is null. */ - if (stack_highest != TX_NULL) + /* Determine if the pointer is null or if the highest stack pointer is not above the + start of the stack. The latter indicates a stack overflow or a corrupted thread + control block, and the unsigned pointer arithmetic in the binary search below would + wrap around and never converge, hanging the caller. */ + if ((stack_highest != TX_NULL) && (stack_highest > stack_lowest)) { + /* Remember the upper bound of the search so the scan below cannot run past it. */ + stack_limit = stack_highest; + /* Restore interrupts. */ TX_RESTORE @@ -173,7 +180,7 @@ ULONG size; } while(size > ((ULONG) 1)); /* Position to first used word - at this point we are within a few words. */ - while (*stack_ptr == TX_STACK_FILL) + while ((stack_ptr < stack_limit) && (*stack_ptr == TX_STACK_FILL)) { /* Position to next word in stack. */ diff --git a/test/smp/regression/threadx_thread_stack_checking_test.c b/test/smp/regression/threadx_thread_stack_checking_test.c index 9db10d0aa..d30e624f1 100644 --- a/test/smp/regression/threadx_thread_stack_checking_test.c +++ b/test/smp/regression/threadx_thread_stack_checking_test.c @@ -9,6 +9,8 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ +// Some portions generated by Copilot (Opus 5). + /* This test is for the thread stack checking services. */ #include @@ -200,6 +202,19 @@ TX_THREAD fake_thread; fake_thread.tx_thread_stack_highest_ptr = TX_NULL; _tx_thread_stack_analyze(&fake_thread); + /* Call the stack analyze with a highest stack pointer below the start of the stack, which is + what a stack overflow or a corrupted control block looks like. This used to hang. */ + fake_thread.tx_thread_id = ((ULONG) 0x54485244); + fake_thread.tx_thread_stack_start = (void *) 0x2000; + fake_thread.tx_thread_stack_highest_ptr = (void *) 0x1000; + _tx_thread_stack_analyze(&fake_thread); + + /* Call the stack analyze with a highest stack pointer equal to the start of the stack. */ + fake_thread.tx_thread_id = ((ULONG) 0x54485244); + fake_thread.tx_thread_stack_start = (void *) 0x2000; + fake_thread.tx_thread_stack_highest_ptr = (void *) 0x2000; + _tx_thread_stack_analyze(&fake_thread); + /* Clear the pattern in thread 2's stack. */ TX_MEMSET(thread_2_stack_start, (CHAR) 0x11, TEST_STACK_SIZE_PRINTF); diff --git a/test/tx/regression/threadx_thread_stack_checking_test.c b/test/tx/regression/threadx_thread_stack_checking_test.c index 9db10d0aa..d30e624f1 100644 --- a/test/tx/regression/threadx_thread_stack_checking_test.c +++ b/test/tx/regression/threadx_thread_stack_checking_test.c @@ -9,6 +9,8 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ +// Some portions generated by Copilot (Opus 5). + /* This test is for the thread stack checking services. */ #include @@ -200,6 +202,19 @@ TX_THREAD fake_thread; fake_thread.tx_thread_stack_highest_ptr = TX_NULL; _tx_thread_stack_analyze(&fake_thread); + /* Call the stack analyze with a highest stack pointer below the start of the stack, which is + what a stack overflow or a corrupted control block looks like. This used to hang. */ + fake_thread.tx_thread_id = ((ULONG) 0x54485244); + fake_thread.tx_thread_stack_start = (void *) 0x2000; + fake_thread.tx_thread_stack_highest_ptr = (void *) 0x1000; + _tx_thread_stack_analyze(&fake_thread); + + /* Call the stack analyze with a highest stack pointer equal to the start of the stack. */ + fake_thread.tx_thread_id = ((ULONG) 0x54485244); + fake_thread.tx_thread_stack_start = (void *) 0x2000; + fake_thread.tx_thread_stack_highest_ptr = (void *) 0x2000; + _tx_thread_stack_analyze(&fake_thread); + /* Clear the pattern in thread 2's stack. */ TX_MEMSET(thread_2_stack_start, (CHAR) 0x11, TEST_STACK_SIZE_PRINTF); From d15f28ab9f7dbc38a4f96ae376a426c3bd38e4b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Tue, 15 Sep 2026 16:24:40 -0400 Subject: [PATCH 137/181] Masked the SMP remap core maps to silence a false -O2 array bounds error (#728) Fixes #469 `_tx_thread_smp_remap_solution_find` indexes `_tx_thread_smp_schedule_list` with the lowest set bit of the core maps it is given. Every caller already masks those maps with `TX_THREAD_SMP_CORE_MASK`, but the compiler cannot see it, so when the function is inlined into `_tx_thread_system_suspend` at `-O2` GCC assumes a bit number as high as 31 and reports an out-of-bounds subscript. `-Werror` turns that into a build failure. Masked the three incoming maps at the top of the function, in both the inline version in `common_smp/inc/tx_thread.h` and the twin in `tx_thread_smp_utilities.c`. The masks are semantic no-ops, so scheduling is unchanged, but the range is now visible to the optimizer. The first core queue entry is also initialized, because the narrowed range lets GCC consider an empty queue and warn about that instead. Reproduced on the Cortex-A9 SMP port with arm-none-eabi-gcc 13.2.1, and clean afterwards across -O2, -O3 and -Os and 2, 4 and 8 core configurations. SMP suite 116/116. Assisted-by: Copilot (Opus 5) --- common_smp/inc/tx_thread.h | 9 +++++++++ common_smp/src/tx_thread_smp_utilities.c | 9 +++++++++ 2 files changed, 18 insertions(+) diff --git a/common_smp/inc/tx_thread.h b/common_smp/inc/tx_thread.h index b92ce50e6..64998a694 100644 --- a/common_smp/inc/tx_thread.h +++ b/common_smp/inc/tx_thread.h @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -1171,6 +1172,11 @@ TX_THREAD *last_thread; TX_THREAD *thread_remap_list[TX_THREAD_SMP_MAX_CORES]; + /* Limit the supplied core maps to the cores that are actually present. */ + available_cores = available_cores & ((ULONG) TX_THREAD_SMP_CORE_MASK); + thread_possible_cores = thread_possible_cores & ((ULONG) TX_THREAD_SMP_CORE_MASK); + test_possible_cores = test_possible_cores & ((ULONG) TX_THREAD_SMP_CORE_MASK); + /* Clear the last thread cores in the search. */ last_thread_cores = ((ULONG) 0); @@ -1181,6 +1187,9 @@ TX_THREAD *thread_remap_list[TX_THREAD_SMP_MAX_CORES]; queue_first = ((UINT) 0); queue_last = ((UINT) 0); + /* Initialize the first core queue entry. */ + core_queue[0] = ((UINT) 0); + /* Build a list of possible cores for this thread to execute on, starting with the previously mapped core. */ core = schedule_thread -> tx_thread_smp_core_mapped; diff --git a/common_smp/src/tx_thread_smp_utilities.c b/common_smp/src/tx_thread_smp_utilities.c index 833a9aab4..cb31e33a9 100644 --- a/common_smp/src/tx_thread_smp_utilities.c +++ b/common_smp/src/tx_thread_smp_utilities.c @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ /**************************************************************************/ @@ -654,6 +655,11 @@ TX_THREAD *last_thread; TX_THREAD *thread_remap_list[TX_THREAD_SMP_MAX_CORES]; + /* Limit the supplied core maps to the cores that are actually present. */ + available_cores = available_cores & ((ULONG) TX_THREAD_SMP_CORE_MASK); + thread_possible_cores = thread_possible_cores & ((ULONG) TX_THREAD_SMP_CORE_MASK); + test_possible_cores = test_possible_cores & ((ULONG) TX_THREAD_SMP_CORE_MASK); + /* Clear the last thread cores in the search. */ last_thread_cores = ((ULONG) 0); @@ -664,6 +670,9 @@ TX_THREAD *thread_remap_list[TX_THREAD_SMP_MAX_CORES]; queue_first = ((UINT) 0); queue_last = ((UINT) 0); + /* Initialize the first core queue entry. */ + core_queue[0] = ((UINT) 0); + /* Build a list of possible cores for this thread to execute on, starting with the previously mapped core. */ core = schedule_thread -> tx_thread_smp_core_mapped; From 9b2979e6b010edb27c741c3e58e9de5faa911528 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Tue, 15 Sep 2026 16:24:45 -0400 Subject: [PATCH 138/181] Replaced the GNU-only dsb/isb 0xF operands with the UAL sy form (#729) Fixes #551 `_tx_thread_system_return_inline()` in the Cortex-M `tx_port.h` headers spells its barriers `dsb 0xF` and `isb 0xF`. A bare hexadecimal operand is a GNU assembler extension, and IAR rejects it with `operand syntax error`, so the header cannot be included at all. The block is guarded for GCC, armclang and IAR together, so every IAR user of an affected port hits it -- four independent reports on Cortex-M33 and M7 with EWARM 9.50 and 9.70. Both operands become `sy`, the Arm UAL name for exactly what `0xF` encodes. The generated instruction is unchanged. Applied to the two `ports_arch` masters and all 32 copies under `ports`, covering M0, M23, M3, M33, M4, M52, M55, M7 and M85 across ac5, ac6, gnu, iar and keil, plus the `scripts/check_ports.sh` probes that matched the old spelling. `check_ports.sh` passes, the copy scripts still reproduce every generated port byte for byte, and `arm-none-eabi-gcc -O2` compiles a caller for every patched header, emitting `dsb sy` and `isb sy`. Three headers that need toolchain intrinsics GCC does not ship fail identically on `dev`. Assisted-by: Copilot (Opus 5) --- ports/cortex_m0/ac6/inc/tx_port.h | 6 ++++-- ports/cortex_m0/gnu/inc/tx_port.h | 5 +++-- ports/cortex_m0/iar/inc/tx_port.h | 6 ++++-- ports/cortex_m23/ac6/inc/tx_port.h | 3 ++- ports/cortex_m23/gnu/inc/tx_port.h | 5 +++-- ports/cortex_m23/iar/inc/tx_port.h | 4 +++- ports/cortex_m3/ac5/inc/tx_port.h | 5 +++-- ports/cortex_m3/ac6/inc/tx_port.h | 5 +++-- ports/cortex_m3/gnu/inc/tx_port.h | 5 +++-- ports/cortex_m3/iar/inc/tx_port.h | 5 +++-- ports/cortex_m3/keil/inc/tx_port.h | 5 +++-- ports/cortex_m33/ac6/inc/tx_port.h | 5 +++-- ports/cortex_m33/gnu/inc/tx_port.h | 5 +++-- ports/cortex_m33/iar/inc/tx_port.h | 5 +++-- ports/cortex_m4/ac5/inc/tx_port.h | 5 +++-- ports/cortex_m4/ac6/inc/tx_port.h | 5 +++-- ports/cortex_m4/gnu/inc/tx_port.h | 5 +++-- ports/cortex_m4/iar/inc/tx_port.h | 5 +++-- ports/cortex_m4/keil/inc/tx_port.h | 5 +++-- ports/cortex_m52/ac6/inc/tx_port.h | 5 +++-- ports/cortex_m52/gnu/inc/tx_port.h | 5 +++-- ports/cortex_m52/iar/inc/tx_port.h | 5 +++-- ports/cortex_m55/ac6/inc/tx_port.h | 5 +++-- ports/cortex_m55/gnu/inc/tx_port.h | 5 +++-- ports/cortex_m55/iar/inc/tx_port.h | 5 +++-- ports/cortex_m7/ac5/inc/tx_port.h | 5 +++-- ports/cortex_m7/ac6/inc/tx_port.h | 5 +++-- ports/cortex_m7/gnu/inc/tx_port.h | 5 +++-- ports/cortex_m7/iar/inc/tx_port.h | 5 +++-- ports/cortex_m85/ac6/inc/tx_port.h | 5 +++-- ports/cortex_m85/gnu/inc/tx_port.h | 5 +++-- ports/cortex_m85/iar/inc/tx_port.h | 5 +++-- ports_arch/ARMv7-M/threadx/inc/tx_port.h | 5 +++-- ports_arch/ARMv8-M/threadx/inc/tx_port.h | 5 +++-- scripts/check_ports.sh | 2 +- 35 files changed, 104 insertions(+), 67 deletions(-) diff --git a/ports/cortex_m0/ac6/inc/tx_port.h b/ports/cortex_m0/ac6/inc/tx_port.h index 214ca8e86..d6e036270 100644 --- a/ports/cortex_m0/ac6/inc/tx_port.h +++ b/ports/cortex_m0/ac6/inc/tx_port.h @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -322,13 +324,13 @@ unsigned int interrupt_save; /* Set PendSV to invoke ThreadX scheduler. */ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); - __asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory"); + __asm__ volatile ("dsb sy \n isb sy " : : : "memory"); if (__get_ipsr_value() == 0) { interrupt_save = __get_primask_value(); __enable_interrupts(); __restore_interrupts(interrupt_save); - __asm__ volatile ("isb 0xF " : : : "memory"); + __asm__ volatile ("isb sy " : : : "memory"); } } diff --git a/ports/cortex_m0/gnu/inc/tx_port.h b/ports/cortex_m0/gnu/inc/tx_port.h index 4e5270de8..51f67b654 100644 --- a/ports/cortex_m0/gnu/inc/tx_port.h +++ b/ports/cortex_m0/gnu/inc/tx_port.h @@ -10,6 +10,7 @@ **************************************************************************/ // Some portions generated by Gemini (Gemini 2.0 Flash). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -324,13 +325,13 @@ unsigned int interrupt_save; /* Set PendSV to invoke ThreadX scheduler. */ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); - __asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory"); + __asm__ volatile ("dsb sy \n isb sy " : : : "memory"); if (__get_ipsr_value() == 0) { interrupt_save = __get_primask_value(); __enable_interrupts(); __restore_interrupts(interrupt_save); - __asm__ volatile ("isb 0xF " : : : "memory"); + __asm__ volatile ("isb sy " : : : "memory"); } } diff --git a/ports/cortex_m0/iar/inc/tx_port.h b/ports/cortex_m0/iar/inc/tx_port.h index 035009e7f..cabb0402f 100644 --- a/ports/cortex_m0/iar/inc/tx_port.h +++ b/ports/cortex_m0/iar/inc/tx_port.h @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -313,13 +315,13 @@ __istate_t interrupt_save; /* Set PendSV to invoke ThreadX scheduler. */ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); - __asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory"); + __asm__ volatile ("dsb sy \n isb sy " : : : "memory"); if (__get_IPSR() == 0) { interrupt_save = __get_interrupt_state(); __enable_interrupt(); __set_interrupt_state(interrupt_save); - __asm__ volatile ("isb 0xF " : : : "memory"); + __asm__ volatile ("isb sy " : : : "memory"); } } diff --git a/ports/cortex_m23/ac6/inc/tx_port.h b/ports/cortex_m23/ac6/inc/tx_port.h index 97cc1feeb..dcd0f3542 100644 --- a/ports/cortex_m23/ac6/inc/tx_port.h +++ b/ports/cortex_m23/ac6/inc/tx_port.h @@ -10,6 +10,7 @@ **************************************************************************/ // Some portions generated by Gemini (Gemini 2.0 Flash). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -378,7 +379,7 @@ unsigned int was_masked; /* Set PendSV to invoke ThreadX scheduler. */ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); - __asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory"); + __asm__ volatile ("dsb sy \n isb sy " : : : "memory"); if (_get_ipsr() == 0) { was_masked = __disable_irq(); diff --git a/ports/cortex_m23/gnu/inc/tx_port.h b/ports/cortex_m23/gnu/inc/tx_port.h index dac6fbb80..a8ec7db2b 100644 --- a/ports/cortex_m23/gnu/inc/tx_port.h +++ b/ports/cortex_m23/gnu/inc/tx_port.h @@ -10,6 +10,7 @@ **************************************************************************/ // Some portions generated by Gemini (Gemini 2.0 Flash). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -391,13 +392,13 @@ unsigned int interrupt_save; /* Set PendSV to invoke ThreadX scheduler. */ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); - __asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory"); + __asm__ volatile ("dsb sy \n isb sy " : : : "memory"); if (_get_ipsr() == 0) { interrupt_save = __get_primask_value(); __enable_interrupts(); __restore_interrupts(interrupt_save); - __asm__ volatile ("isb 0xF " : : : "memory"); + __asm__ volatile ("isb sy " : : : "memory"); } } diff --git a/ports/cortex_m23/iar/inc/tx_port.h b/ports/cortex_m23/iar/inc/tx_port.h index 38649ac3b..50887409e 100644 --- a/ports/cortex_m23/iar/inc/tx_port.h +++ b/ports/cortex_m23/iar/inc/tx_port.h @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -399,7 +401,7 @@ __istate_t interrupt_save; /* Set PendSV to invoke ThreadX scheduler. */ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); - __asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory"); + __asm__ volatile ("dsb sy \n isb sy " : : : "memory"); if (__get_IPSR() == 0) { interrupt_save = __get_interrupt_state(); diff --git a/ports/cortex_m3/ac5/inc/tx_port.h b/ports/cortex_m3/ac5/inc/tx_port.h index 62cae66d0..21f2543aa 100644 --- a/ports/cortex_m3/ac5/inc/tx_port.h +++ b/ports/cortex_m3/ac5/inc/tx_port.h @@ -12,6 +12,7 @@ // Some portions generated by Gemini (Gemini 2.0 Flash). // Some portions generated by Copilot (Claude Sonnet 4.6). // Some portions generated by Claude Code (Opus 5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -583,7 +584,7 @@ unsigned int interrupt_save; /* Set PendSV to invoke ThreadX scheduler. */ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); - __asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory"); + __asm__ volatile ("dsb sy \n isb sy " : : : "memory"); if (__get_ipsr_value() == 0) { interrupt_save = __get_interrupt_posture(); @@ -593,7 +594,7 @@ unsigned int interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); - __asm__ volatile ("isb 0xF " : : : "memory"); + __asm__ volatile ("isb sy " : : : "memory"); } } diff --git a/ports/cortex_m3/ac6/inc/tx_port.h b/ports/cortex_m3/ac6/inc/tx_port.h index 7265724ef..29e23a471 100644 --- a/ports/cortex_m3/ac6/inc/tx_port.h +++ b/ports/cortex_m3/ac6/inc/tx_port.h @@ -12,6 +12,7 @@ // Some portions generated by Gemini (Gemini 2.0 Flash). // Some portions generated by Copilot (Claude Sonnet 4.6). // Some portions generated by Claude Code (Opus 5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -583,7 +584,7 @@ unsigned int interrupt_save; /* Set PendSV to invoke ThreadX scheduler. */ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); - __asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory"); + __asm__ volatile ("dsb sy \n isb sy " : : : "memory"); if (__get_ipsr_value() == 0) { interrupt_save = __get_interrupt_posture(); @@ -593,7 +594,7 @@ unsigned int interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); - __asm__ volatile ("isb 0xF " : : : "memory"); + __asm__ volatile ("isb sy " : : : "memory"); } } diff --git a/ports/cortex_m3/gnu/inc/tx_port.h b/ports/cortex_m3/gnu/inc/tx_port.h index d5299cb38..1db71238a 100644 --- a/ports/cortex_m3/gnu/inc/tx_port.h +++ b/ports/cortex_m3/gnu/inc/tx_port.h @@ -12,6 +12,7 @@ // Some portions generated by Gemini (Gemini 2.0 Flash). // Some portions generated by Copilot (Claude Sonnet 4.6). // Some portions generated by Claude Code (Opus 5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -583,7 +584,7 @@ unsigned int interrupt_save; /* Set PendSV to invoke ThreadX scheduler. */ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); - __asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory"); + __asm__ volatile ("dsb sy \n isb sy " : : : "memory"); if (__get_ipsr_value() == 0) { interrupt_save = __get_interrupt_posture(); @@ -593,7 +594,7 @@ unsigned int interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); - __asm__ volatile ("isb 0xF " : : : "memory"); + __asm__ volatile ("isb sy " : : : "memory"); } } diff --git a/ports/cortex_m3/iar/inc/tx_port.h b/ports/cortex_m3/iar/inc/tx_port.h index 5b05c277a..f14b730a1 100644 --- a/ports/cortex_m3/iar/inc/tx_port.h +++ b/ports/cortex_m3/iar/inc/tx_port.h @@ -12,6 +12,7 @@ // Some portions generated by Gemini (Gemini 2.0 Flash). // Some portions generated by Copilot (Claude Sonnet 4.6). // Some portions generated by Claude Code (Opus 5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -583,7 +584,7 @@ unsigned int interrupt_save; /* Set PendSV to invoke ThreadX scheduler. */ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); - __asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory"); + __asm__ volatile ("dsb sy \n isb sy " : : : "memory"); if (__get_ipsr_value() == 0) { interrupt_save = __get_interrupt_posture(); @@ -593,7 +594,7 @@ unsigned int interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); - __asm__ volatile ("isb 0xF " : : : "memory"); + __asm__ volatile ("isb sy " : : : "memory"); } } diff --git a/ports/cortex_m3/keil/inc/tx_port.h b/ports/cortex_m3/keil/inc/tx_port.h index 0fc2ea65a..13745458d 100644 --- a/ports/cortex_m3/keil/inc/tx_port.h +++ b/ports/cortex_m3/keil/inc/tx_port.h @@ -12,6 +12,7 @@ // Some portions generated by Gemini (Gemini 2.0 Flash). // Some portions generated by Copilot (Claude Sonnet 4.6). // Some portions generated by Claude Code (Opus 5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -583,7 +584,7 @@ unsigned int interrupt_save; /* Set PendSV to invoke ThreadX scheduler. */ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); - __asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory"); + __asm__ volatile ("dsb sy \n isb sy " : : : "memory"); if (__get_ipsr_value() == 0) { interrupt_save = __get_interrupt_posture(); @@ -593,7 +594,7 @@ unsigned int interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); - __asm__ volatile ("isb 0xF " : : : "memory"); + __asm__ volatile ("isb sy " : : : "memory"); } } diff --git a/ports/cortex_m33/ac6/inc/tx_port.h b/ports/cortex_m33/ac6/inc/tx_port.h index 86411a859..98f953e4b 100644 --- a/ports/cortex_m33/ac6/inc/tx_port.h +++ b/ports/cortex_m33/ac6/inc/tx_port.h @@ -11,6 +11,7 @@ // Some portions generated by Gemini (Gemini 2.0 Flash). // Some portions generated by Claude Code (Opus 5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -583,7 +584,7 @@ UINT interrupt_save; /* Set PendSV to invoke ThreadX scheduler. */ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); - __asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory"); + __asm__ volatile ("dsb sy \n isb sy " : : : "memory"); if (_tx_ipsr_get() == 0) { interrupt_save = __get_interrupt_posture(); @@ -593,7 +594,7 @@ UINT interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); - __asm__ volatile ("isb 0xF " : : : "memory"); + __asm__ volatile ("isb sy " : : : "memory"); } } diff --git a/ports/cortex_m33/gnu/inc/tx_port.h b/ports/cortex_m33/gnu/inc/tx_port.h index dc67c0015..828058ea9 100644 --- a/ports/cortex_m33/gnu/inc/tx_port.h +++ b/ports/cortex_m33/gnu/inc/tx_port.h @@ -11,6 +11,7 @@ // Some portions generated by Gemini (Gemini 2.0 Flash). // Some portions generated by Claude Code (Opus 5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -583,7 +584,7 @@ UINT interrupt_save; /* Set PendSV to invoke ThreadX scheduler. */ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); - __asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory"); + __asm__ volatile ("dsb sy \n isb sy " : : : "memory"); if (_tx_ipsr_get() == 0) { interrupt_save = __get_interrupt_posture(); @@ -593,7 +594,7 @@ UINT interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); - __asm__ volatile ("isb 0xF " : : : "memory"); + __asm__ volatile ("isb sy " : : : "memory"); } } diff --git a/ports/cortex_m33/iar/inc/tx_port.h b/ports/cortex_m33/iar/inc/tx_port.h index 6527b34a1..1203e4019 100644 --- a/ports/cortex_m33/iar/inc/tx_port.h +++ b/ports/cortex_m33/iar/inc/tx_port.h @@ -11,6 +11,7 @@ // Some portions generated by Gemini (Gemini 2.0 Flash). // Some portions generated by Claude Code (Opus 5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -583,7 +584,7 @@ UINT interrupt_save; /* Set PendSV to invoke ThreadX scheduler. */ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); - __asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory"); + __asm__ volatile ("dsb sy \n isb sy " : : : "memory"); if (_tx_ipsr_get() == 0) { interrupt_save = __get_interrupt_posture(); @@ -593,7 +594,7 @@ UINT interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); - __asm__ volatile ("isb 0xF " : : : "memory"); + __asm__ volatile ("isb sy " : : : "memory"); } } diff --git a/ports/cortex_m4/ac5/inc/tx_port.h b/ports/cortex_m4/ac5/inc/tx_port.h index ea89ed1aa..2b6361d4f 100644 --- a/ports/cortex_m4/ac5/inc/tx_port.h +++ b/ports/cortex_m4/ac5/inc/tx_port.h @@ -12,6 +12,7 @@ // Some portions generated by Gemini (Gemini 2.0 Flash). // Some portions generated by Copilot (Claude Sonnet 4.6). // Some portions generated by Claude Code (Opus 5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -583,7 +584,7 @@ unsigned int interrupt_save; /* Set PendSV to invoke ThreadX scheduler. */ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); - __asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory"); + __asm__ volatile ("dsb sy \n isb sy " : : : "memory"); if (__get_ipsr_value() == 0) { interrupt_save = __get_interrupt_posture(); @@ -593,7 +594,7 @@ unsigned int interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); - __asm__ volatile ("isb 0xF " : : : "memory"); + __asm__ volatile ("isb sy " : : : "memory"); } } diff --git a/ports/cortex_m4/ac6/inc/tx_port.h b/ports/cortex_m4/ac6/inc/tx_port.h index 3946fec21..1db55ef54 100644 --- a/ports/cortex_m4/ac6/inc/tx_port.h +++ b/ports/cortex_m4/ac6/inc/tx_port.h @@ -12,6 +12,7 @@ // Some portions generated by Gemini (Gemini 2.0 Flash). // Some portions generated by Copilot (Claude Sonnet 4.6). // Some portions generated by Claude Code (Opus 5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -583,7 +584,7 @@ unsigned int interrupt_save; /* Set PendSV to invoke ThreadX scheduler. */ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); - __asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory"); + __asm__ volatile ("dsb sy \n isb sy " : : : "memory"); if (__get_ipsr_value() == 0) { interrupt_save = __get_interrupt_posture(); @@ -593,7 +594,7 @@ unsigned int interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); - __asm__ volatile ("isb 0xF " : : : "memory"); + __asm__ volatile ("isb sy " : : : "memory"); } } diff --git a/ports/cortex_m4/gnu/inc/tx_port.h b/ports/cortex_m4/gnu/inc/tx_port.h index 98d81669f..fe240f62b 100644 --- a/ports/cortex_m4/gnu/inc/tx_port.h +++ b/ports/cortex_m4/gnu/inc/tx_port.h @@ -12,6 +12,7 @@ // Some portions generated by Gemini (Gemini 2.0 Flash). // Some portions generated by Copilot (Claude Sonnet 4.6). // Some portions generated by Claude Code (Opus 5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -583,7 +584,7 @@ unsigned int interrupt_save; /* Set PendSV to invoke ThreadX scheduler. */ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); - __asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory"); + __asm__ volatile ("dsb sy \n isb sy " : : : "memory"); if (__get_ipsr_value() == 0) { interrupt_save = __get_interrupt_posture(); @@ -593,7 +594,7 @@ unsigned int interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); - __asm__ volatile ("isb 0xF " : : : "memory"); + __asm__ volatile ("isb sy " : : : "memory"); } } diff --git a/ports/cortex_m4/iar/inc/tx_port.h b/ports/cortex_m4/iar/inc/tx_port.h index 8acba9076..1ca170081 100644 --- a/ports/cortex_m4/iar/inc/tx_port.h +++ b/ports/cortex_m4/iar/inc/tx_port.h @@ -12,6 +12,7 @@ // Some portions generated by Gemini (Gemini 2.0 Flash). // Some portions generated by Copilot (Claude Sonnet 4.6). // Some portions generated by Claude Code (Opus 5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -583,7 +584,7 @@ unsigned int interrupt_save; /* Set PendSV to invoke ThreadX scheduler. */ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); - __asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory"); + __asm__ volatile ("dsb sy \n isb sy " : : : "memory"); if (__get_ipsr_value() == 0) { interrupt_save = __get_interrupt_posture(); @@ -593,7 +594,7 @@ unsigned int interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); - __asm__ volatile ("isb 0xF " : : : "memory"); + __asm__ volatile ("isb sy " : : : "memory"); } } diff --git a/ports/cortex_m4/keil/inc/tx_port.h b/ports/cortex_m4/keil/inc/tx_port.h index 415d5f507..f54822ff0 100644 --- a/ports/cortex_m4/keil/inc/tx_port.h +++ b/ports/cortex_m4/keil/inc/tx_port.h @@ -12,6 +12,7 @@ // Some portions generated by Gemini (Gemini 2.0 Flash). // Some portions generated by Copilot (Claude Sonnet 4.6). // Some portions generated by Claude Code (Opus 5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -583,7 +584,7 @@ unsigned int interrupt_save; /* Set PendSV to invoke ThreadX scheduler. */ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); - __asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory"); + __asm__ volatile ("dsb sy \n isb sy " : : : "memory"); if (__get_ipsr_value() == 0) { interrupt_save = __get_interrupt_posture(); @@ -593,7 +594,7 @@ unsigned int interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); - __asm__ volatile ("isb 0xF " : : : "memory"); + __asm__ volatile ("isb sy " : : : "memory"); } } diff --git a/ports/cortex_m52/ac6/inc/tx_port.h b/ports/cortex_m52/ac6/inc/tx_port.h index 18f28f0d9..db3284347 100644 --- a/ports/cortex_m52/ac6/inc/tx_port.h +++ b/ports/cortex_m52/ac6/inc/tx_port.h @@ -11,6 +11,7 @@ // Some portions generated by Gemini (Gemini 2.0 Flash). // Some portions generated by Claude Code (Opus 5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -583,7 +584,7 @@ UINT interrupt_save; /* Set PendSV to invoke ThreadX scheduler. */ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); - __asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory"); + __asm__ volatile ("dsb sy \n isb sy " : : : "memory"); if (_tx_ipsr_get() == 0) { interrupt_save = __get_interrupt_posture(); @@ -593,7 +594,7 @@ UINT interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); - __asm__ volatile ("isb 0xF " : : : "memory"); + __asm__ volatile ("isb sy " : : : "memory"); } } diff --git a/ports/cortex_m52/gnu/inc/tx_port.h b/ports/cortex_m52/gnu/inc/tx_port.h index bdba07b2d..ca101c68d 100644 --- a/ports/cortex_m52/gnu/inc/tx_port.h +++ b/ports/cortex_m52/gnu/inc/tx_port.h @@ -11,6 +11,7 @@ // Some portions generated by Gemini (Gemini 2.0 Flash). // Some portions generated by Claude Code (Opus 5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -583,7 +584,7 @@ UINT interrupt_save; /* Set PendSV to invoke ThreadX scheduler. */ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); - __asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory"); + __asm__ volatile ("dsb sy \n isb sy " : : : "memory"); if (_tx_ipsr_get() == 0) { interrupt_save = __get_interrupt_posture(); @@ -593,7 +594,7 @@ UINT interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); - __asm__ volatile ("isb 0xF " : : : "memory"); + __asm__ volatile ("isb sy " : : : "memory"); } } diff --git a/ports/cortex_m52/iar/inc/tx_port.h b/ports/cortex_m52/iar/inc/tx_port.h index 6a3b23a6e..493b54c16 100644 --- a/ports/cortex_m52/iar/inc/tx_port.h +++ b/ports/cortex_m52/iar/inc/tx_port.h @@ -11,6 +11,7 @@ // Some portions generated by Gemini (Gemini 2.0 Flash). // Some portions generated by Claude Code (Opus 5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -583,7 +584,7 @@ UINT interrupt_save; /* Set PendSV to invoke ThreadX scheduler. */ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); - __asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory"); + __asm__ volatile ("dsb sy \n isb sy " : : : "memory"); if (_tx_ipsr_get() == 0) { interrupt_save = __get_interrupt_posture(); @@ -593,7 +594,7 @@ UINT interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); - __asm__ volatile ("isb 0xF " : : : "memory"); + __asm__ volatile ("isb sy " : : : "memory"); } } diff --git a/ports/cortex_m55/ac6/inc/tx_port.h b/ports/cortex_m55/ac6/inc/tx_port.h index f3cbba3a1..63a49e126 100644 --- a/ports/cortex_m55/ac6/inc/tx_port.h +++ b/ports/cortex_m55/ac6/inc/tx_port.h @@ -11,6 +11,7 @@ // Some portions generated by Gemini (Gemini 2.0 Flash). // Some portions generated by Claude Code (Opus 5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -583,7 +584,7 @@ UINT interrupt_save; /* Set PendSV to invoke ThreadX scheduler. */ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); - __asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory"); + __asm__ volatile ("dsb sy \n isb sy " : : : "memory"); if (_tx_ipsr_get() == 0) { interrupt_save = __get_interrupt_posture(); @@ -593,7 +594,7 @@ UINT interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); - __asm__ volatile ("isb 0xF " : : : "memory"); + __asm__ volatile ("isb sy " : : : "memory"); } } diff --git a/ports/cortex_m55/gnu/inc/tx_port.h b/ports/cortex_m55/gnu/inc/tx_port.h index 3f91c12d4..eb7176f57 100644 --- a/ports/cortex_m55/gnu/inc/tx_port.h +++ b/ports/cortex_m55/gnu/inc/tx_port.h @@ -11,6 +11,7 @@ // Some portions generated by Gemini (Gemini 2.0 Flash). // Some portions generated by Claude Code (Opus 5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -583,7 +584,7 @@ UINT interrupt_save; /* Set PendSV to invoke ThreadX scheduler. */ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); - __asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory"); + __asm__ volatile ("dsb sy \n isb sy " : : : "memory"); if (_tx_ipsr_get() == 0) { interrupt_save = __get_interrupt_posture(); @@ -593,7 +594,7 @@ UINT interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); - __asm__ volatile ("isb 0xF " : : : "memory"); + __asm__ volatile ("isb sy " : : : "memory"); } } diff --git a/ports/cortex_m55/iar/inc/tx_port.h b/ports/cortex_m55/iar/inc/tx_port.h index 3ff916b30..8f7105065 100644 --- a/ports/cortex_m55/iar/inc/tx_port.h +++ b/ports/cortex_m55/iar/inc/tx_port.h @@ -11,6 +11,7 @@ // Some portions generated by Gemini (Gemini 2.0 Flash). // Some portions generated by Claude Code (Opus 5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -583,7 +584,7 @@ UINT interrupt_save; /* Set PendSV to invoke ThreadX scheduler. */ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); - __asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory"); + __asm__ volatile ("dsb sy \n isb sy " : : : "memory"); if (_tx_ipsr_get() == 0) { interrupt_save = __get_interrupt_posture(); @@ -593,7 +594,7 @@ UINT interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); - __asm__ volatile ("isb 0xF " : : : "memory"); + __asm__ volatile ("isb sy " : : : "memory"); } } diff --git a/ports/cortex_m7/ac5/inc/tx_port.h b/ports/cortex_m7/ac5/inc/tx_port.h index 8f84e7fe7..320f23d8f 100644 --- a/ports/cortex_m7/ac5/inc/tx_port.h +++ b/ports/cortex_m7/ac5/inc/tx_port.h @@ -12,6 +12,7 @@ // Some portions generated by Gemini (Gemini 2.0 Flash). // Some portions generated by Copilot (Claude Sonnet 4.6). // Some portions generated by Claude Code (Opus 5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -583,7 +584,7 @@ unsigned int interrupt_save; /* Set PendSV to invoke ThreadX scheduler. */ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); - __asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory"); + __asm__ volatile ("dsb sy \n isb sy " : : : "memory"); if (__get_ipsr_value() == 0) { interrupt_save = __get_interrupt_posture(); @@ -593,7 +594,7 @@ unsigned int interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); - __asm__ volatile ("isb 0xF " : : : "memory"); + __asm__ volatile ("isb sy " : : : "memory"); } } diff --git a/ports/cortex_m7/ac6/inc/tx_port.h b/ports/cortex_m7/ac6/inc/tx_port.h index bf2276eb0..8a4981deb 100644 --- a/ports/cortex_m7/ac6/inc/tx_port.h +++ b/ports/cortex_m7/ac6/inc/tx_port.h @@ -12,6 +12,7 @@ // Some portions generated by Gemini (Gemini 2.0 Flash). // Some portions generated by Copilot (Claude Sonnet 4.6). // Some portions generated by Claude Code (Opus 5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -583,7 +584,7 @@ unsigned int interrupt_save; /* Set PendSV to invoke ThreadX scheduler. */ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); - __asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory"); + __asm__ volatile ("dsb sy \n isb sy " : : : "memory"); if (__get_ipsr_value() == 0) { interrupt_save = __get_interrupt_posture(); @@ -593,7 +594,7 @@ unsigned int interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); - __asm__ volatile ("isb 0xF " : : : "memory"); + __asm__ volatile ("isb sy " : : : "memory"); } } diff --git a/ports/cortex_m7/gnu/inc/tx_port.h b/ports/cortex_m7/gnu/inc/tx_port.h index b01873cf1..c47b27fd0 100644 --- a/ports/cortex_m7/gnu/inc/tx_port.h +++ b/ports/cortex_m7/gnu/inc/tx_port.h @@ -12,6 +12,7 @@ // Some portions generated by Gemini (Gemini 2.0 Flash). // Some portions generated by Copilot (Claude Sonnet 4.6). // Some portions generated by Claude Code (Opus 5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -583,7 +584,7 @@ unsigned int interrupt_save; /* Set PendSV to invoke ThreadX scheduler. */ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); - __asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory"); + __asm__ volatile ("dsb sy \n isb sy " : : : "memory"); if (__get_ipsr_value() == 0) { interrupt_save = __get_interrupt_posture(); @@ -593,7 +594,7 @@ unsigned int interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); - __asm__ volatile ("isb 0xF " : : : "memory"); + __asm__ volatile ("isb sy " : : : "memory"); } } diff --git a/ports/cortex_m7/iar/inc/tx_port.h b/ports/cortex_m7/iar/inc/tx_port.h index a9ebe3c88..bd0c8507f 100644 --- a/ports/cortex_m7/iar/inc/tx_port.h +++ b/ports/cortex_m7/iar/inc/tx_port.h @@ -12,6 +12,7 @@ // Some portions generated by Gemini (Gemini 2.0 Flash). // Some portions generated by Copilot (Claude Sonnet 4.6). // Some portions generated by Claude Code (Opus 5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -583,7 +584,7 @@ unsigned int interrupt_save; /* Set PendSV to invoke ThreadX scheduler. */ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); - __asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory"); + __asm__ volatile ("dsb sy \n isb sy " : : : "memory"); if (__get_ipsr_value() == 0) { interrupt_save = __get_interrupt_posture(); @@ -593,7 +594,7 @@ unsigned int interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); - __asm__ volatile ("isb 0xF " : : : "memory"); + __asm__ volatile ("isb sy " : : : "memory"); } } diff --git a/ports/cortex_m85/ac6/inc/tx_port.h b/ports/cortex_m85/ac6/inc/tx_port.h index 38def972b..bc9dff5d5 100644 --- a/ports/cortex_m85/ac6/inc/tx_port.h +++ b/ports/cortex_m85/ac6/inc/tx_port.h @@ -11,6 +11,7 @@ // Some portions generated by Gemini (Gemini 2.0 Flash). // Some portions generated by Claude Code (Opus 5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -583,7 +584,7 @@ UINT interrupt_save; /* Set PendSV to invoke ThreadX scheduler. */ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); - __asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory"); + __asm__ volatile ("dsb sy \n isb sy " : : : "memory"); if (_tx_ipsr_get() == 0) { interrupt_save = __get_interrupt_posture(); @@ -593,7 +594,7 @@ UINT interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); - __asm__ volatile ("isb 0xF " : : : "memory"); + __asm__ volatile ("isb sy " : : : "memory"); } } diff --git a/ports/cortex_m85/gnu/inc/tx_port.h b/ports/cortex_m85/gnu/inc/tx_port.h index 1f1702dfa..9a02f9405 100644 --- a/ports/cortex_m85/gnu/inc/tx_port.h +++ b/ports/cortex_m85/gnu/inc/tx_port.h @@ -11,6 +11,7 @@ // Some portions generated by Gemini (Gemini 2.0 Flash). // Some portions generated by Claude Code (Opus 5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -583,7 +584,7 @@ UINT interrupt_save; /* Set PendSV to invoke ThreadX scheduler. */ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); - __asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory"); + __asm__ volatile ("dsb sy \n isb sy " : : : "memory"); if (_tx_ipsr_get() == 0) { interrupt_save = __get_interrupt_posture(); @@ -593,7 +594,7 @@ UINT interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); - __asm__ volatile ("isb 0xF " : : : "memory"); + __asm__ volatile ("isb sy " : : : "memory"); } } diff --git a/ports/cortex_m85/iar/inc/tx_port.h b/ports/cortex_m85/iar/inc/tx_port.h index 26ab0c756..1f8741cdc 100644 --- a/ports/cortex_m85/iar/inc/tx_port.h +++ b/ports/cortex_m85/iar/inc/tx_port.h @@ -11,6 +11,7 @@ // Some portions generated by Gemini (Gemini 2.0 Flash). // Some portions generated by Claude Code (Opus 5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -583,7 +584,7 @@ UINT interrupt_save; /* Set PendSV to invoke ThreadX scheduler. */ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); - __asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory"); + __asm__ volatile ("dsb sy \n isb sy " : : : "memory"); if (_tx_ipsr_get() == 0) { interrupt_save = __get_interrupt_posture(); @@ -593,7 +594,7 @@ UINT interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); - __asm__ volatile ("isb 0xF " : : : "memory"); + __asm__ volatile ("isb sy " : : : "memory"); } } diff --git a/ports_arch/ARMv7-M/threadx/inc/tx_port.h b/ports_arch/ARMv7-M/threadx/inc/tx_port.h index b988675f1..1b1471397 100644 --- a/ports_arch/ARMv7-M/threadx/inc/tx_port.h +++ b/ports_arch/ARMv7-M/threadx/inc/tx_port.h @@ -12,6 +12,7 @@ // Some portions generated by Gemini (Gemini 2.0 Flash). // Some portions generated by Copilot (Claude Sonnet 4.6). // Some portions generated by Claude Code (Opus 5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -583,7 +584,7 @@ unsigned int interrupt_save; /* Set PendSV to invoke ThreadX scheduler. */ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); - __asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory"); + __asm__ volatile ("dsb sy \n isb sy " : : : "memory"); if (__get_ipsr_value() == 0) { interrupt_save = __get_interrupt_posture(); @@ -593,7 +594,7 @@ unsigned int interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); - __asm__ volatile ("isb 0xF " : : : "memory"); + __asm__ volatile ("isb sy " : : : "memory"); } } diff --git a/ports_arch/ARMv8-M/threadx/inc/tx_port.h b/ports_arch/ARMv8-M/threadx/inc/tx_port.h index 1f088d412..cabf1c203 100644 --- a/ports_arch/ARMv8-M/threadx/inc/tx_port.h +++ b/ports_arch/ARMv8-M/threadx/inc/tx_port.h @@ -11,6 +11,7 @@ // Some portions generated by Gemini (Gemini 2.0 Flash). // Some portions generated by Claude Code (Opus 5). +// Some portions generated by Copilot (Opus 5). /**************************************************************************/ @@ -583,7 +584,7 @@ UINT interrupt_save; /* Set PendSV to invoke ThreadX scheduler. */ *((volatile ULONG *) 0xE000ED04) = ((ULONG) 0x10000000); - __asm__ volatile ("dsb 0xF \n isb 0xF " : : : "memory"); + __asm__ volatile ("dsb sy \n isb sy " : : : "memory"); if (_tx_ipsr_get() == 0) { interrupt_save = __get_interrupt_posture(); @@ -593,7 +594,7 @@ UINT interrupt_save; __enable_interrupts(); #endif __restore_interrupt(interrupt_save); - __asm__ volatile ("isb 0xF " : : : "memory"); + __asm__ volatile ("isb sy " : : : "memory"); } } diff --git a/scripts/check_ports.sh b/scripts/check_ports.sh index 1ba13ca03..19b350cae 100755 --- a/scripts/check_ports.sh +++ b/scripts/check_ports.sh @@ -261,7 +261,7 @@ say "== Families with no copy script (report only) ==" if [ "$quiet" -eq 0 ]; then for family in ports/cortex_m0 ports/cortex_m0+ ports/cortex_m23; do [ -d "$family" ] || continue - for probe in "dsb 0xF" "isb 0xF"; do + for probe in "dsb sy" "isb sy"; do have=""; missing="" for header in "$family"/*/inc/tx_port.h; do [ -f "$header" ] || continue From 3e5a16c95bff3086cc28fecec292894a4f94a34d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Tue, 15 Sep 2026 16:24:50 -0400 Subject: [PATCH 139/181] Allowed tx_timer_change to be called from tx_application_define (#730) Fixes #224 `_txe_timer_change` returned `TX_CALLER_ERROR` for any call at or above `TX_INITIALIZE_IN_PROGRESS`, making `tx_timer_change` the only timer service that could not be called from `tx_application_define` -- while still being allowed from an ISR. The check has no technical basis: `_tx_timer_change` only writes the expiration fields of a timer that is not on an active list, with interrupts disabled. Removed it from both the `common` and `common_smp` copies of `txe_timer_change.c`, with the now-unused includes and the `TX_CALLER_ERROR` line in the header comment. Relaxing an error check is backward compatible. `testcontrol.c` in both suites now calls `tx_timer_change` at initialization, so the timer simple test covers it: `ERROR #30` on `dev`, green with the fix. 116/116 SMP, 103/103 non-SMP. Assisted-by: Copilot (Opus 5) --- common/src/txe_timer_change.c | 12 ++---------- common_smp/src/txe_timer_change.c | 12 ++---------- test/smp/regression/testcontrol.c | 7 +++++++ test/tx/regression/testcontrol.c | 7 +++++++ 4 files changed, 18 insertions(+), 20 deletions(-) diff --git a/common/src/txe_timer_change.c b/common/src/txe_timer_change.c index ef503ffa8..91b104d08 100644 --- a/common/src/txe_timer_change.c +++ b/common/src/txe_timer_change.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -26,8 +28,6 @@ /* Include necessary system files. */ #include "tx_api.h" -#include "tx_initialize.h" -#include "tx_thread.h" #include "tx_timer.h" @@ -56,7 +56,6 @@ /* */ /* TX_TIMER_ERROR Invalid application timer pointer */ /* TX_TICK_ERROR Invalid initial tick value of 0 */ -/* TX_CALLER_ERROR Invalid caller of this function */ /* status Actual completion status */ /* */ /* CALLS */ @@ -98,13 +97,6 @@ UINT status; status = TX_TICK_ERROR; } - /* Check for invalid caller of this function. */ - else if (TX_THREAD_GET_SYSTEM_STATE() >= TX_INITIALIZE_IN_PROGRESS) - { - - /* Invalid caller of this function, return appropriate error code. */ - status = TX_CALLER_ERROR; - } else { diff --git a/common_smp/src/txe_timer_change.c b/common_smp/src/txe_timer_change.c index ef503ffa8..91b104d08 100644 --- a/common_smp/src/txe_timer_change.c +++ b/common_smp/src/txe_timer_change.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -26,8 +28,6 @@ /* Include necessary system files. */ #include "tx_api.h" -#include "tx_initialize.h" -#include "tx_thread.h" #include "tx_timer.h" @@ -56,7 +56,6 @@ /* */ /* TX_TIMER_ERROR Invalid application timer pointer */ /* TX_TICK_ERROR Invalid initial tick value of 0 */ -/* TX_CALLER_ERROR Invalid caller of this function */ /* status Actual completion status */ /* */ /* CALLS */ @@ -98,13 +97,6 @@ UINT status; status = TX_TICK_ERROR; } - /* Check for invalid caller of this function. */ - else if (TX_THREAD_GET_SYSTEM_STATE() >= TX_INITIALIZE_IN_PROGRESS) - { - - /* Invalid caller of this function, return appropriate error code. */ - status = TX_CALLER_ERROR; - } else { diff --git a/test/smp/regression/testcontrol.c b/test/smp/regression/testcontrol.c index 59d8e69a7..632ae9214 100644 --- a/test/smp/regression/testcontrol.c +++ b/test/smp/regression/testcontrol.c @@ -11,6 +11,7 @@ /* This is the test control routine of the ThreadX kernel. All tests are dispatched from this routine. */ // Some portions generated by Codex (gpt 5.5). +// Some portions generated by Copilot (Opus 5). #define TX_THREAD_SMP_SOURCE_CODE @@ -65,6 +66,7 @@ TX_BLOCK_POOL init_block_pool; ULONG init_block_pool_area[50]; TX_EVENT_FLAGS_GROUP init_event_flags; TX_TIMER init_timer; +TX_TIMER init_timer_change; TX_THREAD init_test_thread; TX_THREAD second_test_thread; #ifndef TX_TIMER_PROCESS_IN_ISR @@ -692,6 +694,11 @@ TX_THREAD *thread_ptr; test_timer_create_init = tx_timer_create(&init_timer, "init timer", init_timer_entry, 0x5678, 100, 200, TX_AUTO_ACTIVATE); + /* Test timer change from initialization. */ + test_timer_create_init += tx_timer_create(&init_timer_change, "init timer change", init_timer_entry, 0x5678, + 100, 200, TX_NO_ACTIVATE); + test_timer_create_init += tx_timer_change(&init_timer_change, 50, 100); + /* Test calling tx_thread_relinquish to see if the error checking throws it out. */ tx_thread_relinquish(); #endif diff --git a/test/tx/regression/testcontrol.c b/test/tx/regression/testcontrol.c index 00e31d9b0..6b60d79ea 100644 --- a/test/tx/regression/testcontrol.c +++ b/test/tx/regression/testcontrol.c @@ -11,6 +11,7 @@ /* This is the test control routine of the ThreadX kernel. All tests are dispatched from this routine. */ // Some portions generated by Codex (gpt 5.4). +// Some portions generated by Copilot (Opus 5). #include "tx_api.h" #include @@ -69,6 +70,7 @@ TX_BLOCK_POOL init_block_pool; ULONG init_block_pool_area[50]; TX_EVENT_FLAGS_GROUP init_event_flags; TX_TIMER init_timer; +TX_TIMER init_timer_change; TX_THREAD init_test_thread; TX_THREAD second_test_thread; #ifndef TX_TIMER_PROCESS_IN_ISR @@ -567,6 +569,11 @@ TX_THREAD *thread_ptr; test_timer_create_init = tx_timer_create(&init_timer, "init timer", init_timer_entry, 0x5678, 100, 200, TX_AUTO_ACTIVATE); + /* Test timer change from initialization. */ + test_timer_create_init += tx_timer_create(&init_timer_change, "init timer change", init_timer_entry, 0x5678, + 100, 200, TX_NO_ACTIVATE); + test_timer_create_init += tx_timer_change(&init_timer_change, 50, 100); + /* Test calling tx_thread_relinquish to see if the error checking throws it out. */ tx_thread_relinquish(); #endif From 201cc046092a8751cdf88cc8614b7cf4a7595838 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Tue, 15 Sep 2026 16:24:54 -0400 Subject: [PATCH 140/181] Applied R_ARM_RELATIVE relocations at GNU ThreadX module startup (#731) Fixes #230 `gcc_setup.s` rebases the GOT and copies initialized data into the module data area, but never applies the relocations the linker records for words inside that data. A global initialized with a link-time constant -- `char *pBuffer = buffer;`, a function pointer, a struct member holding a string literal's address -- kept its link address and pointed outside the loaded module. `gcc_setup.s` now walks `.rel.dyn` after the data copy and adjusts every `R_ARM_RELATIVE` entry targeting the module data area, reusing the GOT loop's base arithmetic and skip rules, and reloading the flash base first because `crt0_memory_copy` clobbers `r3`. The table is only emitted with `-pie`, so the example build scripts now pass `-pie --no-dynamic-linker` and the example linker scripts discard `.dynamic`, which `-pie` would otherwise place at address zero and inflate the image to nearly 200 KB. Without `-pie` the table is empty and the loop is a no-op. Covers Cortex-M3, M4, M7, M33 and M0+. Cortex-M23 ships no module linker or build script and AArch64 uses a different relocation format; both left for a follow-up. Verified on `qemu-system-arm` with a module linked at one address and loaded at another: char, function, string and struct-member pointers all resolve to the loaded addresses, and the same module built without `-pie` still runs. Assisted-by: Copilot (Opus 5) --- .../sample_threadx_module/gcc_setup.s | 42 +++++++++++++++++++ .../sample_threadx_module.ld | 8 ++++ .../build_threadx_module_sample.bat | 2 +- .../cortex_m3/gnu/example_build/gcc_setup.s | 42 +++++++++++++++++++ .../example_build/sample_threadx_module.ld | 8 ++++ .../cortex_m33/gnu/example_build/gcc_setup.s | 42 +++++++++++++++++++ .../build_threadx_module_sample.bat | 2 +- .../cortex_m4/gnu/example_build/gcc_setup.s | 42 +++++++++++++++++++ .../example_build/sample_threadx_module.ld | 8 ++++ .../build_threadx_module_sample.bat | 2 +- .../cortex_m7/gnu/example_build/gcc_setup.s | 42 +++++++++++++++++++ .../example_build/sample_threadx_module.ld | 8 ++++ 12 files changed, 245 insertions(+), 3 deletions(-) diff --git a/ports_module/cortex_m0+/gnu/example_build/sample_threadx_module/gcc_setup.s b/ports_module/cortex_m0+/gnu/example_build/sample_threadx_module/gcc_setup.s index 013e5825e..999b99eea 100644 --- a/ports_module/cortex_m0+/gnu/example_build/sample_threadx_module/gcc_setup.s +++ b/ports_module/cortex_m0+/gnu/example_build/sample_threadx_module/gcc_setup.s @@ -1,4 +1,6 @@ +// Some portions generated by Copilot (Opus 5). + .text .align 4 .syntax unified @@ -73,6 +75,46 @@ got_setup_done: movs r2, #0 bl crt0_memory_set + /* Apply the R_ARM_RELATIVE relocations that target the module data area. */ + + ldr r3, =__FLASH_segment_start__ // crt0_memory_copy used r3 as a scratch register + ldr r0, =__reldyn_load_start__ + subs r0,r0,r3 + add r0,r0,r5 + ldr r1, =__reldyn_end__ + subs r1,r1,r3 + add r1,r1,r5 + +new_reldyn_setup: + cmp r0, r1 // See if there are more relocation entries + beq reldyn_setup_done // No, done with the relocations + ldr r6, [r0] // Pickup the r_offset field + ldr r7, [r0, #4] // Pickup the r_info field + adds r0, r0, #8 // Move to the next entry + uxtb r7, r7 // The relocation type is in the low byte + cmp r7, #23 // Is it R_ARM_RELATIVE? + bne new_reldyn_setup // No, only R_ARM_RELATIVE is supported + cmp r6, r4 // Does it target the code or the data area? + blt new_reldyn_setup // The code area is shared and read-only, skip it + subs r6, r6, r4 // Compute offset of data area + add r6, r6, r9 // Build the address of the word to relocate + ldr r7, [r6] // Pickup the link time address stored there + cmp r7, #0 // Is it 0? + beq new_reldyn_setup // Yes, just skip the adjustment + cmp r7, r4 // Is it in the code or data area? + blt reldyn_flash_area // If less than, it is a code address + subs r7, r7, r4 // Compute offset of data area + add r7, r7, r9 // Build address based on the loaded data address + b reldyn_built // Finished building address +reldyn_flash_area: + subs r7, r7, r3 // Compute offset of code area + add r7, r7, r5 // Build address based on the loaded code address +reldyn_built: + str r7, [r6] // Store the relocated address back + b new_reldyn_setup // Continue at the top of the loop +reldyn_setup_done: + + /* Setup heap - not recommended for Threadx but here for compatibility reasons */ diff --git a/ports_module/cortex_m0+/gnu/example_build/sample_threadx_module/sample_threadx_module.ld b/ports_module/cortex_m0+/gnu/example_build/sample_threadx_module/sample_threadx_module.ld index 963205251..afc903aa7 100644 --- a/ports_module/cortex_m0+/gnu/example_build/sample_threadx_module/sample_threadx_module.ld +++ b/ports_module/cortex_m0+/gnu/example_build/sample_threadx_module/sample_threadx_module.ld @@ -211,5 +211,13 @@ SECTIONS __data_size__ = __heap_end__ - __RAM_segment_start__; + /* The dynamic linking metadata is not used by the module manager. Discarding + it keeps it out of the binary image produced from this ELF file. */ + + /DISCARD/ : + { + *(.dynamic) + } + } diff --git a/ports_module/cortex_m3/gnu/example_build/build_threadx_module_sample.bat b/ports_module/cortex_m3/gnu/example_build/build_threadx_module_sample.bat index a25f370b9..db4672d45 100644 --- a/ports_module/cortex_m3/gnu/example_build/build_threadx_module_sample.bat +++ b/ports_module/cortex_m3/gnu/example_build/build_threadx_module_sample.bat @@ -1,5 +1,5 @@ arm-none-eabi-gcc -c -g -mcpu=cortex-m3 -fpie -fno-plt -mno-pic-data-is-text-relative -msingle-pic-base txm_module_preamble.s arm-none-eabi-gcc -c -g -mcpu=cortex-m3 -fpie -fno-plt -mno-pic-data-is-text-relative -msingle-pic-base gcc_setup.S arm-none-eabi-gcc -c -g -mcpu=cortex-m3 -fpie -fno-plt -mno-pic-data-is-text-relative -msingle-pic-base -I..\inc -I..\..\..\..\common\inc -I..\..\..\..\common_modules\inc sample_threadx_module.c -arm-none-eabi-ld -A cortex-m3 -T sample_threadx_module.ld txm_module_preamble.o gcc_setup.o sample_threadx_module.o -e _txm_module_thread_shell_entry txm.a -o sample_threadx_module.axf -M > sample_threadx_module.map +arm-none-eabi-ld -A cortex-m3 -T sample_threadx_module.ld -pie --no-dynamic-linker txm_module_preamble.o gcc_setup.o sample_threadx_module.o -e _txm_module_thread_shell_entry txm.a -o sample_threadx_module.axf -M > sample_threadx_module.map diff --git a/ports_module/cortex_m3/gnu/example_build/gcc_setup.s b/ports_module/cortex_m3/gnu/example_build/gcc_setup.s index 4a729ffe8..1126df2d1 100644 --- a/ports_module/cortex_m3/gnu/example_build/gcc_setup.s +++ b/ports_module/cortex_m3/gnu/example_build/gcc_setup.s @@ -1,4 +1,6 @@ +// Some portions generated by Copilot (Opus 5). + .text .align 4 .syntax unified @@ -71,6 +73,46 @@ got_setup_done: mov r2, #0 bl crt0_memory_set + /* Apply the R_ARM_RELATIVE relocations that target the module data area. */ + + ldr r3, =__FLASH_segment_start__ // crt0_memory_copy used r3 as a scratch register + ldr r0, =__reldyn_load_start__ + sub r0,r0,r3 + add r0,r0,r5 + ldr r1, =__reldyn_end__ + sub r1,r1,r3 + add r1,r1,r5 + +new_reldyn_setup: + cmp r0, r1 // See if there are more relocation entries + beq reldyn_setup_done // No, done with the relocations + ldr r6, [r0] // Pickup the r_offset field + ldr r7, [r0, #4] // Pickup the r_info field + add r0, r0, #8 // Move to the next entry + uxtb r7, r7 // The relocation type is in the low byte + cmp r7, #23 // Is it R_ARM_RELATIVE? + bne new_reldyn_setup // No, only R_ARM_RELATIVE is supported + cmp r6, r4 // Does it target the code or the data area? + blt new_reldyn_setup // The code area is shared and read-only, skip it + sub r6, r6, r4 // Compute offset of data area + add r6, r6, r9 // Build the address of the word to relocate + ldr r7, [r6] // Pickup the link time address stored there + cmp r7, #0 // Is it 0? + beq new_reldyn_setup // Yes, just skip the adjustment + cmp r7, r4 // Is it in the code or data area? + blt reldyn_flash_area // If less than, it is a code address + sub r7, r7, r4 // Compute offset of data area + add r7, r7, r9 // Build address based on the loaded data address + b reldyn_built // Finished building address +reldyn_flash_area: + sub r7, r7, r3 // Compute offset of code area + add r7, r7, r5 // Build address based on the loaded code address +reldyn_built: + str r7, [r6] // Store the relocated address back + b new_reldyn_setup // Continue at the top of the loop +reldyn_setup_done: + + /* Setup heap - not recommended for Threadx but here for compatibility reasons */ diff --git a/ports_module/cortex_m3/gnu/example_build/sample_threadx_module.ld b/ports_module/cortex_m3/gnu/example_build/sample_threadx_module.ld index 5fa4c6803..f77beddae 100644 --- a/ports_module/cortex_m3/gnu/example_build/sample_threadx_module.ld +++ b/ports_module/cortex_m3/gnu/example_build/sample_threadx_module.ld @@ -206,5 +206,13 @@ SECTIONS __data_size__ = __heap_end__ - __RAM_segment_start__; + /* The dynamic linking metadata is not used by the module manager. Discarding + it keeps it out of the binary image produced from this ELF file. */ + + /DISCARD/ : + { + *(.dynamic) + } + } diff --git a/ports_module/cortex_m33/gnu/example_build/gcc_setup.s b/ports_module/cortex_m33/gnu/example_build/gcc_setup.s index 4a729ffe8..1126df2d1 100644 --- a/ports_module/cortex_m33/gnu/example_build/gcc_setup.s +++ b/ports_module/cortex_m33/gnu/example_build/gcc_setup.s @@ -1,4 +1,6 @@ +// Some portions generated by Copilot (Opus 5). + .text .align 4 .syntax unified @@ -71,6 +73,46 @@ got_setup_done: mov r2, #0 bl crt0_memory_set + /* Apply the R_ARM_RELATIVE relocations that target the module data area. */ + + ldr r3, =__FLASH_segment_start__ // crt0_memory_copy used r3 as a scratch register + ldr r0, =__reldyn_load_start__ + sub r0,r0,r3 + add r0,r0,r5 + ldr r1, =__reldyn_end__ + sub r1,r1,r3 + add r1,r1,r5 + +new_reldyn_setup: + cmp r0, r1 // See if there are more relocation entries + beq reldyn_setup_done // No, done with the relocations + ldr r6, [r0] // Pickup the r_offset field + ldr r7, [r0, #4] // Pickup the r_info field + add r0, r0, #8 // Move to the next entry + uxtb r7, r7 // The relocation type is in the low byte + cmp r7, #23 // Is it R_ARM_RELATIVE? + bne new_reldyn_setup // No, only R_ARM_RELATIVE is supported + cmp r6, r4 // Does it target the code or the data area? + blt new_reldyn_setup // The code area is shared and read-only, skip it + sub r6, r6, r4 // Compute offset of data area + add r6, r6, r9 // Build the address of the word to relocate + ldr r7, [r6] // Pickup the link time address stored there + cmp r7, #0 // Is it 0? + beq new_reldyn_setup // Yes, just skip the adjustment + cmp r7, r4 // Is it in the code or data area? + blt reldyn_flash_area // If less than, it is a code address + sub r7, r7, r4 // Compute offset of data area + add r7, r7, r9 // Build address based on the loaded data address + b reldyn_built // Finished building address +reldyn_flash_area: + sub r7, r7, r3 // Compute offset of code area + add r7, r7, r5 // Build address based on the loaded code address +reldyn_built: + str r7, [r6] // Store the relocated address back + b new_reldyn_setup // Continue at the top of the loop +reldyn_setup_done: + + /* Setup heap - not recommended for Threadx but here for compatibility reasons */ diff --git a/ports_module/cortex_m4/gnu/example_build/build_threadx_module_sample.bat b/ports_module/cortex_m4/gnu/example_build/build_threadx_module_sample.bat index f146d7432..ec102df73 100644 --- a/ports_module/cortex_m4/gnu/example_build/build_threadx_module_sample.bat +++ b/ports_module/cortex_m4/gnu/example_build/build_threadx_module_sample.bat @@ -1,5 +1,5 @@ arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -fpie -fno-plt -mno-pic-data-is-text-relative -msingle-pic-base txm_module_preamble.s arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -fpie -fno-plt -mno-pic-data-is-text-relative -msingle-pic-base gcc_setup.S arm-none-eabi-gcc -c -g -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=vfpv4 -fpie -fno-plt -mno-pic-data-is-text-relative -msingle-pic-base -I..\inc -I..\..\..\..\common\inc -I..\..\..\..\common_modules\inc sample_threadx_module.c -arm-none-eabi-ld -A cortex-m4 -T sample_threadx_module.ld txm_module_preamble.o gcc_setup.o sample_threadx_module.o -e _txm_module_thread_shell_entry txm.a -o sample_threadx_module.axf -M > sample_threadx_module.map +arm-none-eabi-ld -A cortex-m4 -T sample_threadx_module.ld -pie --no-dynamic-linker txm_module_preamble.o gcc_setup.o sample_threadx_module.o -e _txm_module_thread_shell_entry txm.a -o sample_threadx_module.axf -M > sample_threadx_module.map diff --git a/ports_module/cortex_m4/gnu/example_build/gcc_setup.s b/ports_module/cortex_m4/gnu/example_build/gcc_setup.s index 4a729ffe8..1126df2d1 100644 --- a/ports_module/cortex_m4/gnu/example_build/gcc_setup.s +++ b/ports_module/cortex_m4/gnu/example_build/gcc_setup.s @@ -1,4 +1,6 @@ +// Some portions generated by Copilot (Opus 5). + .text .align 4 .syntax unified @@ -71,6 +73,46 @@ got_setup_done: mov r2, #0 bl crt0_memory_set + /* Apply the R_ARM_RELATIVE relocations that target the module data area. */ + + ldr r3, =__FLASH_segment_start__ // crt0_memory_copy used r3 as a scratch register + ldr r0, =__reldyn_load_start__ + sub r0,r0,r3 + add r0,r0,r5 + ldr r1, =__reldyn_end__ + sub r1,r1,r3 + add r1,r1,r5 + +new_reldyn_setup: + cmp r0, r1 // See if there are more relocation entries + beq reldyn_setup_done // No, done with the relocations + ldr r6, [r0] // Pickup the r_offset field + ldr r7, [r0, #4] // Pickup the r_info field + add r0, r0, #8 // Move to the next entry + uxtb r7, r7 // The relocation type is in the low byte + cmp r7, #23 // Is it R_ARM_RELATIVE? + bne new_reldyn_setup // No, only R_ARM_RELATIVE is supported + cmp r6, r4 // Does it target the code or the data area? + blt new_reldyn_setup // The code area is shared and read-only, skip it + sub r6, r6, r4 // Compute offset of data area + add r6, r6, r9 // Build the address of the word to relocate + ldr r7, [r6] // Pickup the link time address stored there + cmp r7, #0 // Is it 0? + beq new_reldyn_setup // Yes, just skip the adjustment + cmp r7, r4 // Is it in the code or data area? + blt reldyn_flash_area // If less than, it is a code address + sub r7, r7, r4 // Compute offset of data area + add r7, r7, r9 // Build address based on the loaded data address + b reldyn_built // Finished building address +reldyn_flash_area: + sub r7, r7, r3 // Compute offset of code area + add r7, r7, r5 // Build address based on the loaded code address +reldyn_built: + str r7, [r6] // Store the relocated address back + b new_reldyn_setup // Continue at the top of the loop +reldyn_setup_done: + + /* Setup heap - not recommended for Threadx but here for compatibility reasons */ diff --git a/ports_module/cortex_m4/gnu/example_build/sample_threadx_module.ld b/ports_module/cortex_m4/gnu/example_build/sample_threadx_module.ld index 5fa4c6803..f77beddae 100644 --- a/ports_module/cortex_m4/gnu/example_build/sample_threadx_module.ld +++ b/ports_module/cortex_m4/gnu/example_build/sample_threadx_module.ld @@ -206,5 +206,13 @@ SECTIONS __data_size__ = __heap_end__ - __RAM_segment_start__; + /* The dynamic linking metadata is not used by the module manager. Discarding + it keeps it out of the binary image produced from this ELF file. */ + + /DISCARD/ : + { + *(.dynamic) + } + } diff --git a/ports_module/cortex_m7/gnu/example_build/build_threadx_module_sample.bat b/ports_module/cortex_m7/gnu/example_build/build_threadx_module_sample.bat index c4ae437e4..bb55bb6f9 100644 --- a/ports_module/cortex_m7/gnu/example_build/build_threadx_module_sample.bat +++ b/ports_module/cortex_m7/gnu/example_build/build_threadx_module_sample.bat @@ -1,5 +1,5 @@ arm-none-eabi-gcc -c -g -mcpu=cortex-m7 -mfloat-abi=hard -mfpu=fpv5-d16 -fpie -fno-plt -mno-pic-data-is-text-relative -msingle-pic-base txm_module_preamble.s arm-none-eabi-gcc -c -g -mcpu=cortex-m7 -mfloat-abi=hard -mfpu=fpv5-d16 -fpie -fno-plt -mno-pic-data-is-text-relative -msingle-pic-base gcc_setup.S arm-none-eabi-gcc -c -g -mcpu=cortex-m7 -mfloat-abi=hard -mfpu=fpv5-d16 -fpie -fno-plt -mno-pic-data-is-text-relative -msingle-pic-base -I..\inc -I..\..\..\..\common\inc -I..\..\..\..\common_modules\inc sample_threadx_module.c -arm-none-eabi-ld -A cortex-m7 -T sample_threadx_module.ld txm_module_preamble.o gcc_setup.o sample_threadx_module.o -e _txm_module_thread_shell_entry txm.a -o sample_threadx_module.axf -M > sample_threadx_module.map +arm-none-eabi-ld -A cortex-m7 -T sample_threadx_module.ld -pie --no-dynamic-linker txm_module_preamble.o gcc_setup.o sample_threadx_module.o -e _txm_module_thread_shell_entry txm.a -o sample_threadx_module.axf -M > sample_threadx_module.map diff --git a/ports_module/cortex_m7/gnu/example_build/gcc_setup.s b/ports_module/cortex_m7/gnu/example_build/gcc_setup.s index 4a729ffe8..1126df2d1 100644 --- a/ports_module/cortex_m7/gnu/example_build/gcc_setup.s +++ b/ports_module/cortex_m7/gnu/example_build/gcc_setup.s @@ -1,4 +1,6 @@ +// Some portions generated by Copilot (Opus 5). + .text .align 4 .syntax unified @@ -71,6 +73,46 @@ got_setup_done: mov r2, #0 bl crt0_memory_set + /* Apply the R_ARM_RELATIVE relocations that target the module data area. */ + + ldr r3, =__FLASH_segment_start__ // crt0_memory_copy used r3 as a scratch register + ldr r0, =__reldyn_load_start__ + sub r0,r0,r3 + add r0,r0,r5 + ldr r1, =__reldyn_end__ + sub r1,r1,r3 + add r1,r1,r5 + +new_reldyn_setup: + cmp r0, r1 // See if there are more relocation entries + beq reldyn_setup_done // No, done with the relocations + ldr r6, [r0] // Pickup the r_offset field + ldr r7, [r0, #4] // Pickup the r_info field + add r0, r0, #8 // Move to the next entry + uxtb r7, r7 // The relocation type is in the low byte + cmp r7, #23 // Is it R_ARM_RELATIVE? + bne new_reldyn_setup // No, only R_ARM_RELATIVE is supported + cmp r6, r4 // Does it target the code or the data area? + blt new_reldyn_setup // The code area is shared and read-only, skip it + sub r6, r6, r4 // Compute offset of data area + add r6, r6, r9 // Build the address of the word to relocate + ldr r7, [r6] // Pickup the link time address stored there + cmp r7, #0 // Is it 0? + beq new_reldyn_setup // Yes, just skip the adjustment + cmp r7, r4 // Is it in the code or data area? + blt reldyn_flash_area // If less than, it is a code address + sub r7, r7, r4 // Compute offset of data area + add r7, r7, r9 // Build address based on the loaded data address + b reldyn_built // Finished building address +reldyn_flash_area: + sub r7, r7, r3 // Compute offset of code area + add r7, r7, r5 // Build address based on the loaded code address +reldyn_built: + str r7, [r6] // Store the relocated address back + b new_reldyn_setup // Continue at the top of the loop +reldyn_setup_done: + + /* Setup heap - not recommended for Threadx but here for compatibility reasons */ diff --git a/ports_module/cortex_m7/gnu/example_build/sample_threadx_module.ld b/ports_module/cortex_m7/gnu/example_build/sample_threadx_module.ld index 5fa4c6803..f77beddae 100644 --- a/ports_module/cortex_m7/gnu/example_build/sample_threadx_module.ld +++ b/ports_module/cortex_m7/gnu/example_build/sample_threadx_module.ld @@ -206,5 +206,13 @@ SECTIONS __data_size__ = __heap_end__ - __RAM_segment_start__; + /* The dynamic linking metadata is not used by the module manager. Discarding + it keeps it out of the binary image produced from this ELF file. */ + + /DISCARD/ : + { + *(.dynamic) + } + } From 30b3d22adceb10221de7ac3b4c4fd7ebcd3117e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Tue, 15 Sep 2026 16:24:58 -0400 Subject: [PATCH 141/181] Restored the random stack fill value cleared during thread creation (#732) Fixes #723 With `TX_ENABLE_STACK_CHECKING` and `TX_ENABLE_RANDOM_NUMBER_STACK_FILLING` both enabled, `_tx_thread_create` picked a random byte, stored it in `tx_thread_stack_fill_value`, filled the stack with it -- and then cleared the whole control block with `TX_MEMSET`. The stack held the pattern while the control block claimed zero, so `TX_THREAD_STACK_CHECK` and `_tx_thread_stack_analyze` compared against the wrong value for the entire life of the thread. The value is now computed into a local and written back after the clear. The clear stays where it is, because the module manager's error checking walks the created list before the control block may be touched. Fixed in `common/src/tx_thread_create.c`, `common_smp/src/tx_thread_create.c` and `txm_module_manager_thread_create.c`, where it additionally left a user-mode module thread's kernel stack filled with zeros. `threadx_thread_stack_fill_value_test` creates sixteen unstarted threads and checks each control block against the pattern in its stack, tolerating a random zero byte without letting that hide the defect. Added to both suites: `ERROR #3` on `dev` in `stack_checking_rand_fill_build`, green with the fix. Five tx configurations at 104 tests, five SMP at 117, and all three sources clean under `-Wall -Wextra` across every combination of the four stack-filling switches. Assisted-by: Copilot (Opus 5) --- common/src/tx_thread_create.c | 28 ++- .../src/txm_module_manager_thread_create.c | 26 ++- common_smp/src/tx_thread_create.c | 28 ++- test/smp/cmake/regression/CMakeLists.txt | 1 + test/smp/regression/testcontrol.c | 2 + .../threadx_thread_stack_fill_value_test.c | 190 ++++++++++++++++++ test/tx/cmake/regression/CMakeLists.txt | 1 + test/tx/regression/testcontrol.c | 2 + .../threadx_thread_stack_fill_value_test.c | 190 ++++++++++++++++++ 9 files changed, 453 insertions(+), 15 deletions(-) create mode 100644 test/smp/regression/threadx_thread_stack_fill_value_test.c create mode 100644 test/tx/regression/threadx_thread_stack_fill_value_test.c diff --git a/common/src/tx_thread_create.c b/common/src/tx_thread_create.c index 026b0ada5..37b4d3e2d 100644 --- a/common/src/tx_thread_create.c +++ b/common/src/tx_thread_create.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -93,18 +95,26 @@ UCHAR *temp_ptr; ALIGN_TYPE new_stack_start; ALIGN_TYPE updated_stack_start; #endif +#if defined(TX_ENABLE_RANDOM_NUMBER_STACK_FILLING) && defined(TX_ENABLE_STACK_CHECKING) && !defined(TX_DISABLE_STACK_FILLING) +ULONG stack_fill_value; +#endif #ifndef TX_DISABLE_STACK_FILLING #if defined(TX_ENABLE_RANDOM_NUMBER_STACK_FILLING) && defined(TX_ENABLE_STACK_CHECKING) /* Initialize the stack fill value to a 8-bit random value. */ - thread_ptr -> tx_thread_stack_fill_value = ((ULONG) TX_RAND()) & 0xFFUL; + stack_fill_value = ((ULONG) TX_RAND()) & 0xFFUL; /* Duplicate the random value in each of the 4 bytes of the stack fill value. */ - thread_ptr -> tx_thread_stack_fill_value = thread_ptr -> tx_thread_stack_fill_value | - (thread_ptr -> tx_thread_stack_fill_value << 8) | - (thread_ptr -> tx_thread_stack_fill_value << 16) | - (thread_ptr -> tx_thread_stack_fill_value << 24); + stack_fill_value = stack_fill_value | + (stack_fill_value << 8) | + (stack_fill_value << 16) | + (stack_fill_value << 24); + + /* Store the fill value in the control block so that the stack fill below picks it up + through the TX_STACK_FILL macro. The control block is cleared further down in this + function, so the value is stored again once that has been done. */ + thread_ptr -> tx_thread_stack_fill_value = stack_fill_value; #endif /* Set the thread stack to a pattern prior to creating the initial @@ -150,6 +160,14 @@ ALIGN_TYPE updated_stack_start; /* Initialize thread control block to all zeros. */ TX_MEMSET(thread_ptr, 0, (sizeof(TX_THREAD))); +#if defined(TX_ENABLE_RANDOM_NUMBER_STACK_FILLING) && defined(TX_ENABLE_STACK_CHECKING) && !defined(TX_DISABLE_STACK_FILLING) + + /* Clearing the control block reset the stack fill value, so store the value that was + actually used to fill the stack again. Otherwise the stack checking and stack analyze + routines would look for a pattern that is not the one present in the stack. */ + thread_ptr -> tx_thread_stack_fill_value = stack_fill_value; +#endif + /* Place the supplied parameters into the thread's control block. */ thread_ptr -> tx_thread_name = name_ptr; thread_ptr -> tx_thread_entry = entry_function; diff --git a/common_modules/module_manager/src/txm_module_manager_thread_create.c b/common_modules/module_manager/src/txm_module_manager_thread_create.c index a178cc35a..fdb0e768a 100644 --- a/common_modules/module_manager/src/txm_module_manager_thread_create.c +++ b/common_modules/module_manager/src/txm_module_manager_thread_create.c @@ -106,6 +106,9 @@ UCHAR *temp_ptr; ALIGN_TYPE new_stack_start; ALIGN_TYPE updated_stack_start; #endif +#if defined(TX_ENABLE_RANDOM_NUMBER_STACK_FILLING) && defined(TX_ENABLE_STACK_CHECKING) && !defined(TX_DISABLE_STACK_FILLING) +ULONG stack_fill_value; +#endif TXM_MODULE_THREAD_ENTRY_INFO *thread_entry_info; VOID *stack_end; ULONG i; @@ -263,13 +266,18 @@ ULONG i; #if defined(TX_ENABLE_RANDOM_NUMBER_STACK_FILLING) && defined(TX_ENABLE_STACK_CHECKING) /* Initialize the stack fill value to a 8-bit random value. */ - thread_ptr -> tx_thread_stack_fill_value = ((ULONG) TX_RAND()) & 0xFFUL; + stack_fill_value = ((ULONG) TX_RAND()) & 0xFFUL; /* Duplicate the random value in each of the 4 bytes of the stack fill value. */ - thread_ptr -> tx_thread_stack_fill_value = thread_ptr -> tx_thread_stack_fill_value | - (thread_ptr -> tx_thread_stack_fill_value << 8) | - (thread_ptr -> tx_thread_stack_fill_value << 16) | - (thread_ptr -> tx_thread_stack_fill_value << 24); + stack_fill_value = stack_fill_value | + (stack_fill_value << 8) | + (stack_fill_value << 16) | + (stack_fill_value << 24); + + /* Store the fill value in the control block so that the stack fill below picks it up + through the TX_STACK_FILL macro. The control block is cleared further down in this + function, so the value is stored again once that has been done. */ + thread_ptr -> tx_thread_stack_fill_value = stack_fill_value; #endif /* Set the thread stack to a pattern prior to creating the initial @@ -311,6 +319,14 @@ ULONG i; /* Initialize thread control block to all zeros. */ TX_MEMSET(thread_ptr, 0, sizeof(TX_THREAD)); +#if defined(TX_ENABLE_RANDOM_NUMBER_STACK_FILLING) && defined(TX_ENABLE_STACK_CHECKING) && !defined(TX_DISABLE_STACK_FILLING) + + /* Clearing the control block reset the stack fill value, so store the value that was + actually used to fill the stack again. Otherwise the stack checking and stack analyze + routines would look for a pattern that is not the one present in the stack. */ + thread_ptr -> tx_thread_stack_fill_value = stack_fill_value; +#endif + /* Note that TX_ENABLE_STACK_CHECKING is not supported for module threads. A user mode module thread owns two stacks and the scheduler swaps tx_thread_stack_start, tx_thread_stack_end and tx_thread_stack_size over to the kernel stack whenever the diff --git a/common_smp/src/tx_thread_create.c b/common_smp/src/tx_thread_create.c index 28a1dae1b..05019ab8b 100644 --- a/common_smp/src/tx_thread_create.c +++ b/common_smp/src/tx_thread_create.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Copilot (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -93,19 +95,27 @@ UCHAR *temp_ptr; ALIGN_TYPE new_stack_start; ALIGN_TYPE updated_stack_start; #endif +#if defined(TX_ENABLE_RANDOM_NUMBER_STACK_FILLING) && defined(TX_ENABLE_STACK_CHECKING) && !defined(TX_DISABLE_STACK_FILLING) +ULONG stack_fill_value; +#endif #ifndef TX_DISABLE_STACK_FILLING #if defined(TX_ENABLE_RANDOM_NUMBER_STACK_FILLING) && defined(TX_ENABLE_STACK_CHECKING) /* Initialize the stack fill value to a 8-bit random value. */ - thread_ptr -> tx_thread_stack_fill_value = ((ULONG) TX_RAND()) & 0xFFUL; + stack_fill_value = ((ULONG) TX_RAND()) & 0xFFUL; /* Duplicate the random value in each of the 4 bytes of the stack fill value. */ - thread_ptr -> tx_thread_stack_fill_value = thread_ptr -> tx_thread_stack_fill_value | - (thread_ptr -> tx_thread_stack_fill_value << 8) | - (thread_ptr -> tx_thread_stack_fill_value << 16) | - (thread_ptr -> tx_thread_stack_fill_value << 24); + stack_fill_value = stack_fill_value | + (stack_fill_value << 8) | + (stack_fill_value << 16) | + (stack_fill_value << 24); + + /* Store the fill value in the control block so that the stack fill below picks it up + through the TX_STACK_FILL macro. The control block is cleared further down in this + function, so the value is stored again once that has been done. */ + thread_ptr -> tx_thread_stack_fill_value = stack_fill_value; #endif /* Set the thread stack to a pattern prior to creating the initial @@ -143,6 +153,14 @@ ALIGN_TYPE updated_stack_start; /* Initialize thread control block to all zeros. */ TX_MEMSET(thread_ptr, 0, sizeof(TX_THREAD)); +#if defined(TX_ENABLE_RANDOM_NUMBER_STACK_FILLING) && defined(TX_ENABLE_STACK_CHECKING) && !defined(TX_DISABLE_STACK_FILLING) + + /* Clearing the control block reset the stack fill value, so store the value that was + actually used to fill the stack again. Otherwise the stack checking and stack analyze + routines would look for a pattern that is not the one present in the stack. */ + thread_ptr -> tx_thread_stack_fill_value = stack_fill_value; +#endif + /* Place the supplied parameters into the thread's control block. */ thread_ptr -> tx_thread_name = name_ptr; thread_ptr -> tx_thread_entry = entry_function; diff --git a/test/smp/cmake/regression/CMakeLists.txt b/test/smp/cmake/regression/CMakeLists.txt index dd1d48a30..771fb44dd 100644 --- a/test/smp/cmake/regression/CMakeLists.txt +++ b/test/smp/cmake/regression/CMakeLists.txt @@ -114,6 +114,7 @@ set(regression_test_cases ${SOURCE_DIR}/threadx_thread_sleep_for_100ticks_test.c ${SOURCE_DIR}/threadx_thread_sleep_terminate_test.c ${SOURCE_DIR}/threadx_thread_stack_checking_test.c + ${SOURCE_DIR}/threadx_thread_stack_fill_value_test.c ${SOURCE_DIR}/threadx_thread_terminate_delete_test.c ${SOURCE_DIR}/threadx_thread_exit_callback_transition_test.c ${SOURCE_DIR}/threadx_smp_thread_exit_callback_remote_test.c diff --git a/test/smp/regression/testcontrol.c b/test/smp/regression/testcontrol.c index 632ae9214..816d15080 100644 --- a/test/smp/regression/testcontrol.c +++ b/test/smp/regression/testcontrol.c @@ -255,6 +255,7 @@ void threadx_thread_create_preemption_threshold_application_define(void *); void threadx_thread_information_application_define(void *); void threadx_thread_reset_application_define(void *); void threadx_thread_stack_checking_application_define(void *); +void threadx_thread_stack_fill_value_application_define(void *); void threadx_time_get_set_application_define(void *); @@ -403,6 +404,7 @@ TEST_ENTRY test_control_tests[] = threadx_thread_information_application_define, threadx_thread_reset_application_define, threadx_thread_stack_checking_application_define, + threadx_thread_stack_fill_value_application_define, threadx_time_get_set_application_define, diff --git a/test/smp/regression/threadx_thread_stack_fill_value_test.c b/test/smp/regression/threadx_thread_stack_fill_value_test.c new file mode 100644 index 000000000..896c0c7f7 --- /dev/null +++ b/test/smp/regression/threadx_thread_stack_fill_value_test.c @@ -0,0 +1,190 @@ +/***************************************************************************/ +/* 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 */ +/***************************************************************************/ + +// Some portions generated by Copilot (Opus 5). + +/* This test checks that the stack fill value recorded in a thread control block is the + value that was actually written into that thread's stack. The two used to disagree + when TX_ENABLE_RANDOM_NUMBER_STACK_FILLING was enabled, because the control block was + cleared after the random value had been chosen and the stack had been filled with it, + which left the stack checking and stack analyze routines looking for a pattern that is + not the one present in the stack. */ + +#include +#include "tx_api.h" + + +/* Number of probe threads created. A random fill value can legitimately come out as zero, + which hides the defect for that one thread, so several threads are created and at least + one of them is required to have produced a non-zero pattern. */ + +#define TEST_PROBE_THREADS 16 + + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +static TX_THREAD probe_thread; +static ULONG probe_stack[TX_MINIMUM_STACK / sizeof(ULONG)]; + + +/* Define task prototypes. */ + +static void thread_0_entry(ULONG task_input); + + +/* Prototype for test control return. */ + +void test_control_return(UINT status); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_thread_stack_fill_value_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, TX_NO_TIME_SLICE, TX_AUTO_START); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Stack Fill Value Test................................ ERROR #1\n"); + test_control_return(1); + } +} + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; +UINT i; +ULONG stack_pattern; +UINT non_zero_seen = TX_FALSE; + + + /* Increment thread 0 counter. */ + thread_0_counter++; + + /* Inform user of success getting to this test. */ + printf("Running Thread Stack Fill Value Test................................ "); + + for (i = 0; i < TEST_PROBE_THREADS; i++) + { + + /* Create a thread that is never started, so that its stack still holds nothing but + the fill pattern and the initial stack frame built at the top of the stack. */ + status = tx_thread_create(&probe_thread, "probe thread", thread_0_entry, 0, + probe_stack, sizeof(probe_stack), + 17, 17, TX_NO_TIME_SLICE, TX_DONT_START); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("ERROR #2\n"); + test_control_return(1); + } + + /* Pick up the pattern the create service wrote into the unused part of the stack. */ + stack_pattern = *(((ULONG *) probe_thread.tx_thread_stack_start) + 4); + +#ifndef TX_DISABLE_STACK_FILLING +#if defined(TX_ENABLE_RANDOM_NUMBER_STACK_FILLING) && defined(TX_ENABLE_STACK_CHECKING) + + /* The control block must hold the value that was written into the stack. */ + if (probe_thread.tx_thread_stack_fill_value != stack_pattern) + { + + printf("ERROR #3\n"); + test_control_return(1); + } + + /* The random value is duplicated into all four bytes of the fill value. */ + if ((stack_pattern & 0xFFUL) != + ((stack_pattern >> 24) & 0xFFUL)) + { + + printf("ERROR #4\n"); + test_control_return(1); + } + + if (stack_pattern != ((ULONG) 0)) + { + + non_zero_seen = TX_TRUE; + } +#else + + /* Without random filling, the pattern is the fixed one. */ + if (stack_pattern != ((ULONG) 0xEFEFEFEFUL)) + { + + printf("ERROR #5\n"); + test_control_return(1); + } + + non_zero_seen = TX_TRUE; +#endif +#else + + /* Stack filling is disabled, so there is nothing to compare. */ + non_zero_seen = TX_TRUE; +#endif + + /* Terminate and delete the probe thread so that the next pass starts from a clean + slate. A thread created with TX_DONT_START is suspended rather than completed, + so it must be terminated before it can be deleted. */ + status = tx_thread_terminate(&probe_thread); + + if (status == TX_SUCCESS) + { + + status = tx_thread_delete(&probe_thread); + } + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("ERROR #6\n"); + test_control_return(1); + } + } + + /* A run in which every fill value came out as zero would prove nothing. */ + if (non_zero_seen != TX_TRUE) + { + + printf("ERROR #7\n"); + test_control_return(1); + } + + /* Success! */ + printf("SUCCESS!\n"); + test_control_return(0); +} diff --git a/test/tx/cmake/regression/CMakeLists.txt b/test/tx/cmake/regression/CMakeLists.txt index 1479a93e0..6b94a8576 100644 --- a/test/tx/cmake/regression/CMakeLists.txt +++ b/test/tx/cmake/regression/CMakeLists.txt @@ -97,6 +97,7 @@ set(regression_test_cases ${SOURCE_DIR}/threadx_thread_sleep_for_100ticks_test.c ${SOURCE_DIR}/threadx_thread_sleep_terminate_test.c ${SOURCE_DIR}/threadx_thread_stack_checking_test.c + ${SOURCE_DIR}/threadx_thread_stack_fill_value_test.c ${SOURCE_DIR}/threadx_thread_terminate_delete_test.c ${SOURCE_DIR}/threadx_thread_exit_callback_transition_test.c ${SOURCE_DIR}/threadx_thread_time_slice_change_test.c diff --git a/test/tx/regression/testcontrol.c b/test/tx/regression/testcontrol.c index 6b60d79ea..4e03dd55e 100644 --- a/test/tx/regression/testcontrol.c +++ b/test/tx/regression/testcontrol.c @@ -232,6 +232,7 @@ void threadx_thread_create_preemption_threshold_application_define(void *); void threadx_thread_information_application_define(void *); void threadx_thread_reset_application_define(void *); void threadx_thread_stack_checking_application_define(void *); +void threadx_thread_stack_fill_value_application_define(void *); void threadx_time_get_set_application_define(void *); @@ -352,6 +353,7 @@ TEST_ENTRY test_control_tests[] = threadx_thread_information_application_define, threadx_thread_reset_application_define, threadx_thread_stack_checking_application_define, + threadx_thread_stack_fill_value_application_define, threadx_time_get_set_application_define, diff --git a/test/tx/regression/threadx_thread_stack_fill_value_test.c b/test/tx/regression/threadx_thread_stack_fill_value_test.c new file mode 100644 index 000000000..896c0c7f7 --- /dev/null +++ b/test/tx/regression/threadx_thread_stack_fill_value_test.c @@ -0,0 +1,190 @@ +/***************************************************************************/ +/* 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 */ +/***************************************************************************/ + +// Some portions generated by Copilot (Opus 5). + +/* This test checks that the stack fill value recorded in a thread control block is the + value that was actually written into that thread's stack. The two used to disagree + when TX_ENABLE_RANDOM_NUMBER_STACK_FILLING was enabled, because the control block was + cleared after the random value had been chosen and the stack had been filled with it, + which left the stack checking and stack analyze routines looking for a pattern that is + not the one present in the stack. */ + +#include +#include "tx_api.h" + + +/* Number of probe threads created. A random fill value can legitimately come out as zero, + which hides the defect for that one thread, so several threads are created and at least + one of them is required to have produced a non-zero pattern. */ + +#define TEST_PROBE_THREADS 16 + + +static unsigned long thread_0_counter = 0; +static TX_THREAD thread_0; + +static TX_THREAD probe_thread; +static ULONG probe_stack[TX_MINIMUM_STACK / sizeof(ULONG)]; + + +/* Define task prototypes. */ + +static void thread_0_entry(ULONG task_input); + + +/* Prototype for test control return. */ + +void test_control_return(UINT status); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_thread_stack_fill_value_application_define(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; + + pointer = (CHAR *) first_unused_memory; + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + status = tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0, + pointer, TEST_STACK_SIZE_PRINTF, + 16, 16, TX_NO_TIME_SLICE, TX_AUTO_START); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("Running Thread Stack Fill Value Test................................ ERROR #1\n"); + test_control_return(1); + } +} + + +/* Define the test threads. */ + +static void thread_0_entry(ULONG thread_input) +{ + +UINT status; +UINT i; +ULONG stack_pattern; +UINT non_zero_seen = TX_FALSE; + + + /* Increment thread 0 counter. */ + thread_0_counter++; + + /* Inform user of success getting to this test. */ + printf("Running Thread Stack Fill Value Test................................ "); + + for (i = 0; i < TEST_PROBE_THREADS; i++) + { + + /* Create a thread that is never started, so that its stack still holds nothing but + the fill pattern and the initial stack frame built at the top of the stack. */ + status = tx_thread_create(&probe_thread, "probe thread", thread_0_entry, 0, + probe_stack, sizeof(probe_stack), + 17, 17, TX_NO_TIME_SLICE, TX_DONT_START); + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("ERROR #2\n"); + test_control_return(1); + } + + /* Pick up the pattern the create service wrote into the unused part of the stack. */ + stack_pattern = *(((ULONG *) probe_thread.tx_thread_stack_start) + 4); + +#ifndef TX_DISABLE_STACK_FILLING +#if defined(TX_ENABLE_RANDOM_NUMBER_STACK_FILLING) && defined(TX_ENABLE_STACK_CHECKING) + + /* The control block must hold the value that was written into the stack. */ + if (probe_thread.tx_thread_stack_fill_value != stack_pattern) + { + + printf("ERROR #3\n"); + test_control_return(1); + } + + /* The random value is duplicated into all four bytes of the fill value. */ + if ((stack_pattern & 0xFFUL) != + ((stack_pattern >> 24) & 0xFFUL)) + { + + printf("ERROR #4\n"); + test_control_return(1); + } + + if (stack_pattern != ((ULONG) 0)) + { + + non_zero_seen = TX_TRUE; + } +#else + + /* Without random filling, the pattern is the fixed one. */ + if (stack_pattern != ((ULONG) 0xEFEFEFEFUL)) + { + + printf("ERROR #5\n"); + test_control_return(1); + } + + non_zero_seen = TX_TRUE; +#endif +#else + + /* Stack filling is disabled, so there is nothing to compare. */ + non_zero_seen = TX_TRUE; +#endif + + /* Terminate and delete the probe thread so that the next pass starts from a clean + slate. A thread created with TX_DONT_START is suspended rather than completed, + so it must be terminated before it can be deleted. */ + status = tx_thread_terminate(&probe_thread); + + if (status == TX_SUCCESS) + { + + status = tx_thread_delete(&probe_thread); + } + + /* Check for status. */ + if (status != TX_SUCCESS) + { + + printf("ERROR #6\n"); + test_control_return(1); + } + } + + /* A run in which every fill value came out as zero would prove nothing. */ + if (non_zero_seen != TX_TRUE) + { + + printf("ERROR #7\n"); + test_control_return(1); + } + + /* Success! */ + printf("SUCCESS!\n"); + test_control_return(0); +} From f5e59a1dd3cd2bdbc6214d408253a089af75a967 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Tue, 15 Sep 2026 16:47:08 -0400 Subject: [PATCH 142/181] Completed Windows simulator support and regression coverage (#736) Completed and stabilized the Win32 and Win64 MSVC simulator ports. - Replaced high-latency host synchronization with bounded scheduler handoffs and critical sections. - Added a high-resolution timer, tick batching, idle fast-forward, shutdown coordination and Win64 extension-pointer support. - Brought the Windows regression tooling and the new thread-transition tests up on CMake, Ninja and the Visual Studio Build Tools. - Extended the SMP teardown diagnostics and corrected 64-bit trace-test handling. This supersedes the historical `win64`, `win32-perf`, `windows-sim-ports` and `windows-sim-ports-completion` branches; no unmerged change from them is missing here. The original Win64 port landed in #529. 1,610 of 1,610 tests pass, across five configurations each: Win32 515, Win64 515, Win64 SMP 580. No external dependency was added, and the existing MSVC warnings in the trace configuration are unchanged. Hardware validation does not apply to host simulator ports. Assisted-by: Codex (gpt-5.6-sol) --- ports/win32/vs_2019/inc/tx_port.h | 44 +++- .../vs_2019/src/tx_initialize_low_level.c | 245 +++++++++++++++++- .../vs_2019/src/tx_thread_context_restore.c | 55 +++- .../vs_2019/src/tx_thread_context_save.c | 19 +- .../vs_2019/src/tx_thread_interrupt_control.c | 15 +- ports/win32/vs_2019/src/tx_thread_schedule.c | 139 ++++++---- .../win32/vs_2019/src/tx_thread_stack_build.c | 78 +++++- .../vs_2019/src/tx_thread_system_return.c | 27 +- ports/win64/vs_2022/inc/tx_port.h | 21 +- .../vs_2022/src/tx_initialize_low_level.c | 67 ++++- .../vs_2022/src/tx_thread_context_restore.c | 14 +- .../vs_2022/src/tx_thread_interrupt_control.c | 15 +- ports/win64/vs_2022/src/tx_thread_schedule.c | 84 +++--- .../win64/vs_2022/src/tx_thread_stack_build.c | 9 +- .../vs_2022/src/tx_thread_system_return.c | 10 +- test/smp/regression/testcontrol.c | 102 +++++++- .../tx/cmake/thread_transition/CMakeLists.txt | 36 ++- .../threadx_thread_basic_execution_test.c | 4 +- .../threadx_trace_entry_update_test.c | 23 +- 19 files changed, 796 insertions(+), 211 deletions(-) diff --git a/ports/win32/vs_2019/inc/tx_port.h b/ports/win32/vs_2019/inc/tx_port.h index 655a2f697..4d3e3b509 100644 --- a/ports/win32/vs_2019/inc/tx_port.h +++ b/ports/win32/vs_2019/inc/tx_port.h @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (gpt-5.6-sol). + /**************************************************************************/ /**************************************************************************/ @@ -63,6 +65,7 @@ /* Define compiler library include files. */ +#include #include #include @@ -303,9 +306,10 @@ void _tx_initialize_start_interrupts(void); #define TX_THREAD_EXTENSION_0 HANDLE tx_thread_win32_thread_handle; \ DWORD tx_thread_win32_thread_id; \ HANDLE tx_thread_win32_thread_run_semaphore; \ + HANDLE tx_thread_win32_thread_start_semaphore; \ UINT tx_thread_win32_suspension_type; \ UINT tx_thread_win32_int_disabled_flag; -#define TX_THREAD_EXTENSION_1 +#define TX_THREAD_EXTENSION_1 VOID *tx_thread_extension_ptr; #define TX_THREAD_EXTENSION_2 #define TX_THREAD_EXTENSION_3 @@ -361,13 +365,27 @@ void _tx_initialize_start_interrupts(void); #define TX_TIMER_DELETE_EXTENSION(timer_ptr) +/* Store the owning object pointer in the internal timer so timeout handlers can + recover it via a pointer field rather than the ULONG timeout parameter. This + matches the Win64 port and satisfies NetXDuo/USBX default extension macros + that reference tx_timer_internal_extension_ptr / tx_thread_extension_ptr. */ + +#define TX_TIMER_INTERNAL_EXTENSION VOID *tx_timer_internal_extension_ptr; + +#define TX_THREAD_CREATE_TIMEOUT_SETUP(t) (t) -> tx_thread_timer.tx_timer_internal_timeout_function = &(_tx_thread_timeout); \ + (t) -> tx_thread_timer.tx_timer_internal_timeout_param = 0; \ + (t) -> tx_thread_timer.tx_timer_internal_extension_ptr = (VOID *) (t); + +#define TX_THREAD_TIMEOUT_POINTER_SETUP(t) (t) = (TX_THREAD *) _tx_timer_expired_timer_ptr -> tx_timer_internal_extension_ptr; + + struct TX_THREAD_STRUCT; /* Define the Win32 critical section data structure. */ typedef struct TX_WIN32_CRITICAL_SECTION_STRUCT { - HANDLE tx_win32_critical_section_mutex_handle; + CRITICAL_SECTION tx_win32_critical_section_lock; DWORD tx_win32_critical_section_owner; ULONG tx_win32_critical_section_nested_count; } TX_WIN32_CRITICAL_SECTION; @@ -475,24 +493,40 @@ extern CHAR _tx_version_id[]; extern TX_WIN32_CRITICAL_SECTION _tx_win32_critical_section; extern HANDLE _tx_win32_scheduler_semaphore; +extern HANDLE _tx_win32_scheduler_wake_event; extern DWORD _tx_win32_scheduler_id; extern ULONG _tx_win32_global_int_disabled_flag; extern LARGE_INTEGER _tx_win32_time_stamp; extern ULONG _tx_win32_system_error; extern HANDLE _tx_win32_timer_handle; +extern HANDLE _tx_win32_timer_thread_handle; +extern HANDLE _tx_win32_isr_semaphore; extern UINT _tx_win32_timer_id; -extern LARGE_INTEGER _tx_win32_time_stamp; +extern UINT _tx_win32_timer_waiting; +#ifdef TX_WIN32_NO_IDLE_ENABLE +extern HANDLE _tx_win32_timer_kick_event; +#endif + +VOID _tx_win32_scheduler_wake(VOID); + +#ifndef TX_WIN32_USE_HIGH_RESOLUTION_TIMER +#define TX_WIN32_USE_HIGH_RESOLUTION_TIMER 1 +#endif + +#ifndef TX_WIN32_HANDOFF_SPIN_COUNT +#define TX_WIN32_HANDOFF_SPIN_COUNT 64 +#endif #ifndef TX_WIN32_MEMORY_SIZE -#define TX_WIN32_MEMORY_SIZE 64000 +#define TX_WIN32_MEMORY_SIZE 256000 #endif #ifndef TX_TIMER_PERIODIC #ifdef TX_WIN32_SLOW_TIMER #define TX_TIMER_PERIODIC TX_WIN32_SLOW_TIMER #else -#define TX_TIMER_PERIODIC 10 +#define TX_TIMER_PERIODIC 1 #endif #endif diff --git a/ports/win32/vs_2019/src/tx_initialize_low_level.c b/ports/win32/vs_2019/src/tx_initialize_low_level.c index c362b3e73..e531b1ca9 100644 --- a/ports/win32/vs_2019/src/tx_initialize_low_level.c +++ b/ports/win32/vs_2019/src/tx_initialize_low_level.c @@ -1,6 +1,6 @@ /*************************************************************************** * Copyright (c) 2024 Microsoft Corporation - * Copyright (c) 2026-present Eclipse ThreadX contributors + * 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 @@ -10,6 +10,7 @@ **************************************************************************/ // Some portions generated by Codex (gpt 5.4). +// Some portions generated by Codex (gpt-5.6-sol). /**************************************************************************/ /**************************************************************************/ @@ -37,19 +38,40 @@ TX_WIN32_CRITICAL_SECTION _tx_win32_critical_section; HANDLE _tx_win32_scheduler_semaphore; +HANDLE _tx_win32_scheduler_wake_event; DWORD _tx_win32_scheduler_id; ULONG _tx_win32_global_int_disabled_flag; LARGE_INTEGER _tx_win32_time_stamp; ULONG _tx_win32_system_error; +HANDLE _tx_win32_timer_handle; +HANDLE _tx_win32_timer_thread_handle; +HANDLE _tx_win32_isr_semaphore; +UINT _tx_win32_timer_waiting; extern TX_THREAD *_tx_thread_current_ptr; +#ifdef TX_WIN32_NO_IDLE_ENABLE +/* Auto-reset event used by the scheduler to kick the timer thread so that the + simulated clock advances immediately when no thread is ready to run, instead + of waiting for the wall-clock periodic timer. This makes the simulation + CPU-bound rather than wall-clock-bound during idle periods, mirroring the + Linux port's TX_LINUX_NO_IDLE_ENABLE behavior. */ +HANDLE _tx_win32_timer_kick_event; +#endif + +/* Flag set by the atexit handler to stop the timer thread before CRT cleanup + suspends any application threads. Declared volatile so both the main thread + (which sets it) and the timer thread (which reads it) see the change. */ +volatile LONG _tx_win32_exiting = 0; + /* Define simulated timer interrupt. This is done inside a thread, which is how other interrupts may be defined as well. See code below for an example. */ UINT _tx_win32_timer_id; -VOID CALLBACK _tx_win32_timer_interrupt(UINT wTimerID, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2); +VOID CALLBACK _tx_win32_timer_interrupt(UINT wTimerID, UINT msg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2); +static VOID _tx_win32_timer_start(VOID); +static DWORD WINAPI _tx_win32_timer_thread_entry(LPVOID thread_input); #ifdef TX_WIN32_DEBUG_ENABLE @@ -151,6 +173,10 @@ void _tx_timer_interrupt(void); VOID _tx_initialize_low_level(VOID); VOID _tx_thread_context_save(VOID); VOID _tx_thread_context_restore(VOID); +VOID _tx_win32_scheduler_wake(VOID); + +/* Forward declaration of the process-exit cleanup function. */ +static void _tx_win32_exit_cleanup(void); /* Define other external variable references. */ @@ -186,7 +212,7 @@ extern VOID *_tx_initialize_unused_memory; /* */ /* CALLS */ /* */ -/* CreateMutex Win32 create mutex */ +/* InitializeCriticalSection Win32 initialize lock */ /* CreateThread Win32 create thread */ /* CreateSemaphore Win32 create semaphore */ /* GetCurrentThreadId Win32 get current thread ID */ @@ -226,22 +252,80 @@ VOID _tx_initialize_low_level(VOID) /* Pickup the unique Id of the current thread, which will also be the Id of the scheduler. */ _tx_win32_scheduler_id = GetCurrentThreadId(); - /* Create the system critical section mutex. This is used by the system to block all other access, + /* Initialize the system critical section. This is used by the system to block all other access, analogous to an interrupt lockout on an embedded target. */ - _tx_win32_critical_section.tx_win32_critical_section_mutex_handle = CreateMutex(NULL, FALSE, NULL); + InitializeCriticalSection(&_tx_win32_critical_section.tx_win32_critical_section_lock); _tx_win32_critical_section.tx_win32_critical_section_nested_count = 0; _tx_win32_critical_section.tx_win32_critical_section_owner = 0; /* Create the semaphore that regulates when the scheduler executes. */ _tx_win32_scheduler_semaphore = CreateSemaphore(NULL, 0, 1, NULL); + _tx_win32_isr_semaphore = CreateSemaphore(NULL, 0, 1, NULL); + + /* Create the event that wakes the scheduler whenever the ready state changes. */ + _tx_win32_scheduler_wake_event = CreateEvent(NULL, FALSE, FALSE, NULL); + if (_tx_win32_scheduler_wake_event == NULL) + { + printf("ThreadX Win32 error creating scheduler wake event!\n"); + while(1) + { + } + } + +#ifdef TX_WIN32_NO_IDLE_ENABLE + + /* Create the auto-reset event used to kick the timer thread when the + scheduler detects an idle system (see _tx_thread_schedule). */ + _tx_win32_timer_kick_event = CreateEvent(NULL, FALSE, FALSE, NULL); + if (_tx_win32_timer_kick_event == NULL) + { + printf("ThreadX Win32 error creating timer kick event!\n"); + while(1) + { + } + } +#endif /* Initialize the global interrupt disabled flag. */ _tx_win32_global_int_disabled_flag = TX_FALSE; + _tx_win32_timer_waiting = TX_FALSE; /* Done, return to caller. */ } +/* Called by the C runtime during exit() before any CRT cleanup. Sets the + exiting flag so the timer thread and context-save code stop touching + application OS threads (which may hold the CRT heap lock), then forcibly + terminates the timer thread so it cannot fire again during cleanup. */ + +static void _tx_win32_exit_cleanup(void) +{ + + /* Signal all timer-path code to stop. */ + _InterlockedExchange(&_tx_win32_exiting, 1); + + /* Unblock the timer thread if it is waiting on the waitable timer. */ + if (_tx_win32_timer_handle != NULL) + { + CancelWaitableTimer(_tx_win32_timer_handle); + } + + /* Wait up to 50 ms for the timer thread to exit on its own. */ + if (_tx_win32_timer_thread_handle != NULL) + { + if (WaitForSingleObject(_tx_win32_timer_thread_handle, 50) != WAIT_OBJECT_0) + { + + /* Force-terminate if it has not stopped in time. */ + TerminateThread(_tx_win32_timer_thread_handle, 0); + } + _tx_win32_timer_thread_handle = NULL; + } +} + + + /* This routine is called after initialization is complete in order to start all interrupt threads. Interrupt threads in addition to the timer may be added to this routine as well. */ @@ -263,22 +347,161 @@ void _tx_initialize_start_interrupts(void) wTimerRes = min(max(tc.wPeriodMin, TX_TIMER_PERIODIC), tc.wPeriodMax); - /* Start a specified timer event. The timer runs in its own thread. - It calls the specified callback function when the event is activated. */ - _tx_win32_timer_id = timeSetEvent(TX_TIMER_PERIODIC, wTimerRes, _tx_win32_timer_interrupt, 0, TIME_PERIODIC); + /* Request the best available timer resolution for the simulation. */ + if (timeBeginPeriod(wTimerRes) != TIMERR_NOERROR) + { + printf("ThreadX Win32 error configuring timer resolution!\n"); + while (1) + { + } + } + + /* Create the periodic waitable timer used to drive simulated interrupts. */ +#if (TX_WIN32_USE_HIGH_RESOLUTION_TIMER != 0) + _tx_win32_timer_handle = CreateWaitableTimerEx(NULL, NULL, CREATE_WAITABLE_TIMER_HIGH_RESOLUTION, TIMER_ALL_ACCESS); + if (_tx_win32_timer_handle == NULL) +#endif + { + _tx_win32_timer_handle = CreateWaitableTimer(NULL, FALSE, NULL); + } + + if (_tx_win32_timer_handle == NULL) + { + printf("ThreadX Win32 error creating timer handle!\n"); + while (1) + { + } + } + + /* Create the timer thread so interrupts are serialized through one execution context. */ + _tx_win32_timer_thread_handle = CreateThread(NULL, 0, _tx_win32_timer_thread_entry, NULL, 0, NULL); + if (_tx_win32_timer_thread_handle == NULL) + { + printf("ThreadX Win32 error creating timer thread!\n"); + while (1) + { + } + } + + SetThreadPriority(_tx_win32_timer_thread_handle, THREAD_PRIORITY_HIGHEST); + + _tx_win32_timer_id = 1; + + /* Register exit cleanup so the timer thread is stopped before CRT cleanup + runs. Without this, exit() can deadlock: the CRT holds the heap lock + while the timer fires and suspends the exiting thread via SuspendThread, + causing any subsequent malloc to block forever. */ + atexit(_tx_win32_exit_cleanup); + + /* Start the first simulated tick. */ + _tx_win32_timer_start(); } /* Define the ThreadX system timer interrupt. Other interrupts may be simulated in a similar way. */ -VOID CALLBACK _tx_win32_timer_interrupt(UINT wTimerID, UINT msg, DWORD dwUser, DWORD dw1, DWORD dw2) +VOID CALLBACK _tx_win32_timer_interrupt(UINT wTimerID, UINT msg, DWORD_PTR dwUser, DWORD_PTR dw1, DWORD_PTR dw2) { + TX_PARAMETER_NOT_USED(wTimerID); + TX_PARAMETER_NOT_USED(msg); + TX_PARAMETER_NOT_USED(dwUser); + TX_PARAMETER_NOT_USED(dw1); + TX_PARAMETER_NOT_USED(dw2); + + /* Skip the interrupt entirely if exit() has been called. The CRT heap + lock may be held by the exiting thread; calling SuspendThread() on it + at this point causes a permanent deadlock. */ + if (_tx_win32_exiting) + return; + /* Call ThreadX context save for interrupt preparation. */ _tx_thread_context_save(); - /* Call the ThreadX system timer interrupt processing. */ - _tx_timer_interrupt(); + /* Fire TX_WIN32_TICKS_PER_INTERRUPT ticks inside a single interrupt + context. The SuspendThread/ResumeThread overhead is amortized across + all N ticks, and all timer-based delays shrink by factor N. The + relative ordering of thread wakeups is preserved because each call to + _tx_timer_interrupt() advances the tick counter by exactly one step and + processes the timers that expire at that step. */ +#ifndef TX_WIN32_TICKS_PER_INTERRUPT +#define TX_WIN32_TICKS_PER_INTERRUPT 5 +#endif + { + UINT _tick_i; + for (_tick_i = 0; _tick_i < TX_WIN32_TICKS_PER_INTERRUPT; _tick_i++) + _tx_timer_interrupt(); + } /* Call ThreadX context restore for interrupt completion. */ _tx_thread_context_restore(); + + /* Wake the scheduler so it can promptly observe timer-driven work. */ + _tx_win32_scheduler_wake(); +} + + +static DWORD WINAPI _tx_win32_timer_thread_entry(LPVOID thread_input) +{ + TX_PARAMETER_NOT_USED(thread_input); + + /* Drive periodic simulated interrupts from a single thread. + Exit the loop when _tx_win32_exiting is set by the atexit handler. */ + while (!_tx_win32_exiting) + { +#ifdef TX_WIN32_NO_IDLE_ENABLE + + /* Wake either on the periodic wall-clock timer or on a scheduler kick + (issued when the system is idle). Firing on the kick advances the + simulated clock immediately, without waiting for the wall clock. */ + HANDLE _wait_handles[2]; + + _wait_handles[0] = _tx_win32_timer_handle; + _wait_handles[1] = _tx_win32_timer_kick_event; + if (WaitForMultipleObjects(2, _wait_handles, FALSE, INFINITE) == WAIT_FAILED) + break; +#else + if (WaitForSingleObject(_tx_win32_timer_handle, INFINITE) != WAIT_OBJECT_0) + break; +#endif + if (_tx_win32_exiting) + break; + _tx_win32_timer_interrupt(0, 0, 0, 0, 0); + if (_tx_win32_exiting) + break; + _tx_win32_timer_start(); + } + return 0; +} + + +VOID _tx_win32_scheduler_wake(VOID) +{ + + /* Wake the scheduler if it is waiting for a state change. */ + if (_tx_win32_scheduler_wake_event != NULL) + { + SetEvent(_tx_win32_scheduler_wake_event); + } +} + + +static VOID _tx_win32_timer_start(VOID) +{ + +LARGE_INTEGER due_time; + + + /* Rearm the host timer relative to "now" to avoid burst catch-up ticks. */ + due_time.QuadPart = -(((LONGLONG) TX_TIMER_PERIODIC) * 10000LL); +#if (TX_WIN32_USE_HIGH_RESOLUTION_TIMER != 0) + if (SetWaitableTimerEx(_tx_win32_timer_handle, &due_time, 0, NULL, NULL, NULL, 0) == 0) +#else + if (SetWaitableTimer(_tx_win32_timer_handle, &due_time, 0, NULL, NULL, FALSE) == 0) +#endif + { + printf("ThreadX Win32 error starting timer!\n"); + while (1) + { + } + } } diff --git a/ports/win32/vs_2019/src/tx_thread_context_restore.c b/ports/win32/vs_2019/src/tx_thread_context_restore.c index 36fa1e4b0..ae559bed8 100644 --- a/ports/win32/vs_2019/src/tx_thread_context_restore.c +++ b/ports/win32/vs_2019/src/tx_thread_context_restore.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (gpt-5.6-sol). + /**************************************************************************/ /**************************************************************************/ @@ -70,6 +72,7 @@ /**************************************************************************/ VOID _tx_thread_context_restore(VOID) { +TX_THREAD *execute_thread; /* Enter critical section to ensure other threads are not playing with the core ThreadX data structures. */ @@ -81,6 +84,9 @@ VOID _tx_thread_context_restore(VOID) /* Decrement the nested interrupt count. */ _tx_thread_system_state--; + /* Pickup the execute thread pointer. */ + execute_thread = _tx_thread_execute_ptr; + /* Determine if this is the first nested interrupt and if a ThreadX application thread was running at the time. */ if ((!_tx_thread_system_state) && (_tx_thread_current_ptr)) @@ -109,8 +115,32 @@ VOID _tx_thread_context_restore(VOID) /* Clear the current thread pointer. */ _tx_thread_current_ptr = TX_NULL; + /* Block the timer ISR until the resumed thread has observed the wakeup. */ + _tx_win32_timer_waiting = TX_TRUE; + /* Wakeup the system thread by setting the system semaphore. */ ReleaseSemaphore(_tx_win32_scheduler_semaphore, 1, NULL); + _tx_win32_scheduler_wake(); + + /* If the timer made a solicited wakeup ready, let that thread run before + the host timer ISR continues. */ + if ((execute_thread != TX_NULL) && + (execute_thread -> tx_thread_win32_suspension_type == 0)) + { + + /* Spin-poll for the scheduler to complete the solicited wakeup + before the timer ISR proceeds. */ + _tx_win32_critical_section_release_all(&_tx_win32_critical_section); + while (WaitForSingleObject(_tx_win32_isr_semaphore, 0) != WAIT_OBJECT_0) + SwitchToThread(); + _tx_win32_critical_section_obtain(&_tx_win32_critical_section); + while (WaitForSingleObject(_tx_win32_isr_semaphore, 0) == WAIT_OBJECT_0) + { + } + } + + /* The timer ISR no longer needs to hold off future ticks. */ + _tx_win32_timer_waiting = TX_FALSE; } else { @@ -119,8 +149,31 @@ VOID _tx_thread_context_restore(VOID) ResumeThread(_tx_thread_current_ptr -> tx_thread_win32_thread_handle); } } + else if ((!_tx_thread_system_state) && (execute_thread != TX_NULL)) + { + + /* The timer made a thread ready while the scheduler was idle. Keep the + timer ISR blocked until the solicited wakeup has started running. */ + _tx_win32_timer_waiting = TX_TRUE; + _tx_win32_scheduler_wake(); + + if (execute_thread -> tx_thread_win32_suspension_type == 0) + { + + /* Spin-poll for the scheduler to hand off to the next thread and + acknowledge via the ISR semaphore. Keeps timer-path latency low. */ + _tx_win32_critical_section_release_all(&_tx_win32_critical_section); + while (WaitForSingleObject(_tx_win32_isr_semaphore, 0) != WAIT_OBJECT_0) + SwitchToThread(); + _tx_win32_critical_section_obtain(&_tx_win32_critical_section); + while (WaitForSingleObject(_tx_win32_isr_semaphore, 0) == WAIT_OBJECT_0) + { + } + } + + _tx_win32_timer_waiting = TX_FALSE; + } /* Leave Win32 critical section. */ _tx_win32_critical_section_release_all(&_tx_win32_critical_section); } - diff --git a/ports/win32/vs_2019/src/tx_thread_context_save.c b/ports/win32/vs_2019/src/tx_thread_context_save.c index 2f4afb403..4574b8277 100644 --- a/ports/win32/vs_2019/src/tx_thread_context_save.c +++ b/ports/win32/vs_2019/src/tx_thread_context_save.c @@ -1,6 +1,6 @@ /*************************************************************************** * Copyright (c) 2024 Microsoft Corporation - * Copyright (c) 2026-present Eclipse ThreadX contributors + * 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 @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (gpt-5.6-sol). + /**************************************************************************/ /**************************************************************************/ @@ -30,6 +32,11 @@ #include "tx_thread.h" #include "tx_timer.h" +/* Set to non-zero by the atexit handler in tx_initialize_low_level.c when the + process is calling exit(). Prevents SuspendThread() from being called on + a thread that may be holding the CRT heap lock. */ +extern volatile LONG _tx_win32_exiting; + /**************************************************************************/ /* */ @@ -86,6 +93,15 @@ TX_THREAD *thread_ptr; if ((thread_ptr) && (_tx_thread_system_state == 0)) { + /* Skip if the process is calling exit(). Suspending a thread that + holds the CRT heap lock causes a permanent deadlock because any + subsequent malloc in another thread will block forever. */ + if (_tx_win32_exiting) + { + _tx_win32_critical_section_release(&_tx_win32_critical_section); + return; + } + /* Yes, this is the first interrupt and an application thread is running... suspend it! */ @@ -104,4 +120,3 @@ TX_THREAD *thread_ptr; /* Exit Win32 critical section. */ _tx_win32_critical_section_release(&_tx_win32_critical_section); } - diff --git a/ports/win32/vs_2019/src/tx_thread_interrupt_control.c b/ports/win32/vs_2019/src/tx_thread_interrupt_control.c index 019aabefd..ca73b7fba 100644 --- a/ports/win32/vs_2019/src/tx_thread_interrupt_control.c +++ b/ports/win32/vs_2019/src/tx_thread_interrupt_control.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (gpt-5.6-sol). + /**************************************************************************/ /**************************************************************************/ @@ -93,8 +95,6 @@ UINT _tx_thread_interrupt_control(UINT new_posture) { UINT old_posture; -HANDLE threadhandle; -int threadpriority; DWORD threadid; TX_THREAD *thread_ptr; @@ -119,22 +119,16 @@ TX_THREAD *thread_ptr; /* Determine if the thread was terminated. */ - /* Pickup the handle of the current thread. */ - threadhandle = GetCurrentThread(); - /* Pickup the current thread pointer. */ thread_ptr = _tx_thread_current_ptr; - /* Pickup the priority of the current thread. */ - threadpriority = GetThreadPriority(threadhandle); - /* Pickup the ID of the current thread. */ threadid = GetCurrentThreadId(); /* Determine if this is a thread (THREAD_PRIORITY_LOWEST) and it does not match the current thread pointer. */ - if ((threadpriority == THREAD_PRIORITY_LOWEST) && - ((!thread_ptr) || (thread_ptr -> tx_thread_win32_thread_id != threadid))) + if (((!thread_ptr) || (thread_ptr -> tx_thread_win32_thread_id != threadid)) && + (GetThreadPriority(GetCurrentThread()) == THREAD_PRIORITY_LOWEST)) { /* This indicates the Win32 thread was actually terminated by ThreadX is only @@ -204,4 +198,3 @@ TX_THREAD *thread_ptr; /* Return the previous interrupt disable posture. */ return(old_posture); } - diff --git a/ports/win32/vs_2019/src/tx_thread_schedule.c b/ports/win32/vs_2019/src/tx_thread_schedule.c index d67efee85..1fa11c596 100644 --- a/ports/win32/vs_2019/src/tx_thread_schedule.c +++ b/ports/win32/vs_2019/src/tx_thread_schedule.c @@ -1,6 +1,6 @@ /*************************************************************************** * Copyright (c) 2024 Microsoft Corporation - * Copyright (c) 2026-present Eclipse ThreadX contributors + * 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 @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (gpt-5.6-sol). + /**************************************************************************/ /**************************************************************************/ @@ -31,6 +33,9 @@ #include "tx_timer.h" +static VOID _tx_win32_semaphore_reset(HANDLE semaphore_handle); + + /**************************************************************************/ /* */ /* FUNCTION RELEASE */ @@ -59,7 +64,6 @@ /* */ /* ReleaseSemaphore Win32 release semaphore */ /* ResumeThread Win32 resume thread */ -/* Sleep Win32 thread sleep */ /* WaitForSingleObject Win32 wait on a semaphore */ /* _tx_win32_critical_section_obtain Obtain critical section */ /* _tx_win32_critical_section_release Release critical section */ @@ -71,6 +75,8 @@ /**************************************************************************/ VOID _tx_thread_schedule(VOID) { +DWORD wait_status; + /* Loop forever. */ @@ -102,8 +108,27 @@ VOID _tx_thread_schedule(VOID) /* Leave the critical section. */ _tx_win32_critical_section_release(&_tx_win32_critical_section); - /* Now sleep so we don't block forever. */ - Sleep(2); +#ifdef TX_WIN32_NO_IDLE_ENABLE + + /* No thread is ready to run: advance the simulated clock now + instead of waiting for the wall-clock periodic timer. Kick + the timer thread so it fires the next tick(s) immediately, + then wait for it to signal progress via the wake event. A + short bounded timeout guards against a missed wake. This + makes idle periods CPU-bound rather than wall-clock-bound, + mirroring the Linux port's TX_LINUX_NO_IDLE_ENABLE path. */ + SetEvent(_tx_win32_timer_kick_event); + WaitForSingleObject(_tx_win32_scheduler_wake_event, 2); +#else + + /* Yield to other threads (timer, application threads) instead of + blocking indefinitely. This spin-poll eliminates the ~0.5 ms + kernel-wake latency of WaitForSingleObject(INFINITE) and reduces + context-switch overhead by >10x at the cost of higher CPU usage + during test runs. Drain any pending wake event to keep it clean. */ + WaitForSingleObject(_tx_win32_scheduler_wake_event, 0); + SwitchToThread(); +#endif } } @@ -136,8 +161,38 @@ VOID _tx_thread_schedule(VOID) /* Debug entry. */ _tx_win32_debug_entry_insert("SCHEDULE-release_sem", __FILE__, __LINE__); + /* Clear any stale wakeup acknowledgements before this solicited resume. */ + _tx_win32_semaphore_reset(_tx_thread_current_ptr -> tx_thread_win32_thread_start_semaphore); + _tx_win32_semaphore_reset(_tx_thread_current_ptr -> tx_thread_win32_thread_run_semaphore); + /* Let the thread run again by releasing its run semaphore. */ - ReleaseSemaphore(_tx_thread_current_ptr -> tx_thread_win32_thread_run_semaphore, 1, NULL); + if (ReleaseSemaphore(_tx_thread_current_ptr -> tx_thread_win32_thread_run_semaphore, 1, NULL) == 0) + { + + /* Increment the system error counter. */ + _tx_win32_system_error++; + } + + /* Let the solicited wakeup reach ThreadX before the timer ISR advances again. */ + if (_tx_win32_timer_waiting) + { + + /* Wait for the thread to acknowledge the wakeup and then release the ISR. */ + wait_status = WaitForSingleObject(_tx_thread_current_ptr -> tx_thread_win32_thread_start_semaphore, INFINITE); + if (ReleaseSemaphore(_tx_win32_isr_semaphore, 1, NULL) == 0) + { + + /* Increment the system error counter. */ + _tx_win32_system_error++; + } + + if (wait_status != WAIT_OBJECT_0) + { + + /* Increment the system error counter. */ + _tx_win32_system_error++; + } + } } /* Debug entry. */ @@ -146,20 +201,29 @@ VOID _tx_thread_schedule(VOID) /* Exit Win32 critical section. */ _tx_win32_critical_section_release(&_tx_win32_critical_section); - /* Now suspend the main thread so the application thread can run. */ - WaitForSingleObject(_tx_win32_scheduler_semaphore, INFINITE); + /* Spin-poll for the application thread to return control. Using + SwitchToThread() between polls yields the CPU without blocking, + matching the low-latency approach used in the idle loop above. */ + while (WaitForSingleObject(_tx_win32_scheduler_semaphore, 0) != WAIT_OBJECT_0) + SwitchToThread(); } } -/* Define the ThreadX Win32 critical section get, release, and release all functions. */ - -void _tx_win32_critical_section_obtain(TX_WIN32_CRITICAL_SECTION *critical_section) +static VOID _tx_win32_semaphore_reset(HANDLE semaphore_handle) { -TX_THREAD *thread_ptr; + /* Drain any stale semaphore count from a previous host-side wakeup. */ + while (WaitForSingleObject(semaphore_handle, 0) == WAIT_OBJECT_0) + { + } +} +/* Define the ThreadX Win32 critical section get, release, and release all functions. */ + +void _tx_win32_critical_section_obtain(TX_WIN32_CRITICAL_SECTION *critical_section) +{ /* Is the protection owned? */ if (critical_section -> tx_win32_critical_section_owner == GetCurrentThreadId()) { @@ -170,15 +234,10 @@ TX_THREAD *thread_ptr; else { - /* Pickup the current thread pointer. */ - thread_ptr = _tx_thread_current_ptr; - /* Get the Win32 critical section. */ - while (WaitForSingleObject(critical_section -> tx_win32_critical_section_mutex_handle, 3) != WAIT_OBJECT_0) - { - } + EnterCriticalSection(&critical_section -> tx_win32_critical_section_lock); - /* At this point we have the mutex. */ + /* At this point we have the critical section. */ /* Increment the nesting counter. */ critical_section -> tx_win32_critical_section_nested_count = 1; @@ -193,7 +252,7 @@ void _tx_win32_critical_section_release(TX_WIN32_CRITICAL_SECTION *critical_s { - /* Ensure the caller is the mutex owner. */ + /* Ensure the caller is the critical section owner. */ if (critical_section -> tx_win32_critical_section_owner == GetCurrentThreadId()) { @@ -211,25 +270,9 @@ void _tx_win32_critical_section_release(TX_WIN32_CRITICAL_SECTION *critical_s /* Yes, it is being released clear the owner. */ critical_section -> tx_win32_critical_section_owner = 0; - /* Finally, release the mutex. */ - if (ReleaseMutex(critical_section -> tx_win32_critical_section_mutex_handle) != TX_TRUE) - { - - /* Increment the system error counter. */ - _tx_win32_system_error++; - } - - /* Just in case, make sure there the mutex is not owned. */ - while (ReleaseMutex(critical_section -> tx_win32_critical_section_mutex_handle) == TX_TRUE) - { - - /* Increment the system error counter. */ - _tx_win32_system_error++; - } - - /* Sleep for 0, just to relinquish to other ready threads. */ - Sleep(0); - } + /* Finally, release the critical section. */ + LeaveCriticalSection(&critical_section -> tx_win32_critical_section_lock); + } } } else @@ -244,7 +287,7 @@ void _tx_win32_critical_section_release(TX_WIN32_CRITICAL_SECTION *critical_s void _tx_win32_critical_section_release_all(TX_WIN32_CRITICAL_SECTION *critical_section) { - /* Ensure the caller is the mutex owner. */ + /* Ensure the caller is the critical section owner. */ if (critical_section -> tx_win32_critical_section_owner == GetCurrentThreadId()) { @@ -258,21 +301,8 @@ void _tx_win32_critical_section_release_all(TX_WIN32_CRITICAL_SECTION *cri /* Yes, it is being release clear the owner. */ critical_section -> tx_win32_critical_section_owner = 0; - /* Finally, release the mutex. */ - if (ReleaseMutex(critical_section -> tx_win32_critical_section_mutex_handle) != TX_TRUE) - { - - /* Increment the system error counter. */ - _tx_win32_system_error++; - } - - /* Just in case, make sure there the mutex is not owned. */ - while (ReleaseMutex(critical_section -> tx_win32_critical_section_mutex_handle) == TX_TRUE) - { - - /* Increment the system error counter. */ - _tx_win32_system_error++; - } + /* Finally, release the critical section. */ + LeaveCriticalSection(&critical_section -> tx_win32_critical_section_lock); } } else @@ -282,4 +312,3 @@ void _tx_win32_critical_section_release_all(TX_WIN32_CRITICAL_SECTION *cri _tx_win32_system_error++; } } - diff --git a/ports/win32/vs_2019/src/tx_thread_stack_build.c b/ports/win32/vs_2019/src/tx_thread_stack_build.c index ccbabefd1..f473ec953 100644 --- a/ports/win32/vs_2019/src/tx_thread_stack_build.c +++ b/ports/win32/vs_2019/src/tx_thread_stack_build.c @@ -9,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (gpt-5.6-sol). // Some portions generated by Copilot (Opus 5). @@ -114,6 +115,20 @@ ALIGN_TYPE fake_stack_ptr; } } + /* Create the scheduler acknowledgement semaphore for this thread. */ + thread_ptr -> tx_thread_win32_thread_start_semaphore = CreateSemaphore(NULL, 0, 1, NULL); + + /* Determine if the start semaphore was created successfully. */ + if (!thread_ptr -> tx_thread_win32_thread_start_semaphore) + { + + /* Display an error message. */ + printf("ThreadX Win32 error creating thread start semaphore!\n"); + while(1) + { + } + } + /* Setup the thread suspension type to solicited thread suspension. Pseudo interrupt handlers will suspend with this field set to 1. */ thread_ptr -> tx_thread_win32_suspension_type = 0; @@ -136,24 +151,77 @@ ALIGN_TYPE fake_stack_ptr; /* Make the thread initially ready so it will run to the initial wait on its run semaphore. */ ResumeThread(thread_ptr -> tx_thread_win32_thread_handle); + + /* Wait until the host thread is parked at the controlled handoff point + before ThreadX can schedule it. */ + if (WaitForSingleObject(thread_ptr -> tx_thread_win32_thread_start_semaphore, INFINITE) != WAIT_OBJECT_0) + { + + /* Display an error message. */ + printf("ThreadX Win32 error synchronizing thread startup!\n"); + while(1) + { + } + } } DWORD WINAPI _tx_win32_thread_entry(LPVOID ptr) { -TX_THREAD *thread_ptr; +TX_THREAD *thread_ptr; +TX_THREAD *current_thread_ptr; +HANDLE threadhandle; +int threadpriority; +DWORD threadid; +ULONG handoff_spin_count; /* Pickup the current thread pointer. */ thread_ptr = (TX_THREAD *) ptr; - /* Now suspend the thread initially. If the thread has already - been scheduled, this will return immediately. */ - WaitForSingleObject(thread_ptr -> tx_thread_win32_thread_run_semaphore, INFINITE); + /* Tell the creator that this host thread has reached the controlled + handoff point and is ready to be scheduled. */ + ReleaseSemaphore(thread_ptr -> tx_thread_win32_thread_start_semaphore, 1, NULL); + + /* Spin briefly for the scheduler to release this thread to run, then + block so dormant threads do not consume host CPU indefinitely. */ + handoff_spin_count = TX_WIN32_HANDOFF_SPIN_COUNT; + while (WaitForSingleObject(thread_ptr -> tx_thread_win32_thread_run_semaphore, 0) != WAIT_OBJECT_0) + { + if (handoff_spin_count != 0) + { + handoff_spin_count--; + SwitchToThread(); + } + else + { + WaitForSingleObject(thread_ptr -> tx_thread_win32_thread_run_semaphore, INFINITE); + break; + } + } + + /* Acknowledge that the host thread is now able to execute ThreadX code. */ + ReleaseSemaphore(thread_ptr -> tx_thread_win32_thread_start_semaphore, 1, NULL); + + /* A deleted host thread can be released only to let it exit. In notify-enabled + builds, the first TX_DISABLE in _tx_thread_shell_entry catches this path. + When callbacks are disabled, perform the same check before the shell calls + the stale ThreadX entry function. */ + _tx_win32_critical_section_obtain(&_tx_win32_critical_section); + threadhandle = GetCurrentThread(); + threadpriority = GetThreadPriority(threadhandle); + threadid = GetCurrentThreadId(); + current_thread_ptr = _tx_thread_current_ptr; + if ((threadpriority == THREAD_PRIORITY_LOWEST) && + ((current_thread_ptr == TX_NULL) || (current_thread_ptr -> tx_thread_win32_thread_id != threadid))) + { + _tx_win32_critical_section_release_all(&_tx_win32_critical_section); + ExitThread(0); + } + _tx_win32_critical_section_release(&_tx_win32_critical_section); /* Call ThreadX thread entry point. */ _tx_thread_shell_entry(); return EXIT_SUCCESS; } - diff --git a/ports/win32/vs_2019/src/tx_thread_system_return.c b/ports/win32/vs_2019/src/tx_thread_system_return.c index 601761357..52f65b4f8 100644 --- a/ports/win32/vs_2019/src/tx_thread_system_return.c +++ b/ports/win32/vs_2019/src/tx_thread_system_return.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Codex (gpt-5.6-sol). + /**************************************************************************/ /**************************************************************************/ @@ -83,6 +85,7 @@ UINT temp_thread_state; HANDLE threadhandle; int threadpriority; DWORD threadid; +ULONG handoff_spin_count; /* Enter Win32 critical section. */ @@ -149,6 +152,7 @@ DWORD threadid; on. Note that the main scheduling algorithm will take care of setting the current thread pointer to NULL. */ ReleaseSemaphore(_tx_win32_scheduler_semaphore, 1, NULL); + _tx_win32_scheduler_wake(); /* Leave Win32 critical section. */ _tx_win32_critical_section_release_all(&_tx_win32_critical_section); @@ -161,9 +165,25 @@ DWORD threadid; ExitThread(0); } - /* Wait on the run semaphore for this thread. This won't get set again - until the thread is scheduled. */ - WaitForSingleObject(temp_run_semaphore, INFINITE); + /* Spin briefly for the scheduler to grant this thread a new time-slice, + then block so suspended threads do not consume host CPU indefinitely. */ + handoff_spin_count = TX_WIN32_HANDOFF_SPIN_COUNT; + while (WaitForSingleObject(temp_run_semaphore, 0) != WAIT_OBJECT_0) + { + if (handoff_spin_count != 0) + { + handoff_spin_count--; + SwitchToThread(); + } + else + { + WaitForSingleObject(temp_run_semaphore, INFINITE); + break; + } + } + + /* Acknowledge that the thread is once again executing ThreadX code. */ + ReleaseSemaphore(temp_thread_ptr -> tx_thread_win32_thread_start_semaphore, 1, NULL); /* Enter Win32 critical section. */ _tx_win32_critical_section_obtain(&_tx_win32_critical_section); @@ -203,4 +223,3 @@ DWORD threadid; _tx_win32_critical_section_release(&_tx_win32_critical_section); } } - diff --git a/ports/win64/vs_2022/inc/tx_port.h b/ports/win64/vs_2022/inc/tx_port.h index eeabf651c..2b486ed95 100644 --- a/ports/win64/vs_2022/inc/tx_port.h +++ b/ports/win64/vs_2022/inc/tx_port.h @@ -13,6 +13,8 @@ * SPDX-License-Identifier: MIT and CC0-1.0 **************************************************************************/ +// Some portions generated by Codex (gpt-5.6-sol). + /**************************************************************************/ /**************************************************************************/ @@ -167,6 +169,7 @@ extern TEST_FLAG test_forced_mutex_timeout; back changes structures the application also sees. This port and the win32 one were the only two that did. */ + /* Define ThreadX basic types for this port. */ #define VOID void @@ -331,7 +334,7 @@ void _tx_initialize_start_interrupts(void); HANDLE tx_thread_win32_thread_start_semaphore; \ UINT tx_thread_win32_suspension_type; \ UINT tx_thread_win32_int_disabled_flag; -#define TX_THREAD_EXTENSION_1 +#define TX_THREAD_EXTENSION_1 VOID *tx_thread_extension_ptr; #define TX_THREAD_EXTENSION_2 #define TX_THREAD_EXTENSION_3 @@ -404,7 +407,7 @@ struct TX_THREAD_STRUCT; typedef struct TX_WIN32_CRITICAL_SECTION_STRUCT { - HANDLE tx_win32_critical_section_mutex_handle; + CRITICAL_SECTION tx_win32_critical_section_lock; DWORD tx_win32_critical_section_owner; ULONG tx_win32_critical_section_nested_count; } TX_WIN32_CRITICAL_SECTION; @@ -565,21 +568,29 @@ extern HANDLE _tx_win32_timer_handle; extern HANDLE _tx_win32_timer_thread_handle; extern HANDLE _tx_win32_isr_semaphore; extern UINT _tx_win32_timer_waiting; +#ifdef TX_WIN32_NO_IDLE_ENABLE +extern HANDLE _tx_win32_timer_kick_event; +#endif extern UINT _tx_win32_timer_id; extern LARGE_INTEGER _tx_win32_time_stamp; #ifndef TX_WIN32_MEMORY_SIZE -#define TX_WIN32_MEMORY_SIZE 64000 +#define TX_WIN32_MEMORY_SIZE 256000 #endif VOID _tx_win32_scheduler_wake(VOID); +/* This simulation port is not for production use. Run at 1 ms per tick + (10x faster than wall clock at the default 100 ticks/second) so that + regression tests with protocol timeouts complete in a fraction of real + time without changing any tick-count-based test logic. The slower + TX_WIN32_SLOW_TIMER escape hatch is preserved for debugging. */ #ifndef TX_TIMER_PERIODIC #ifdef TX_WIN32_SLOW_TIMER #define TX_TIMER_PERIODIC TX_WIN32_SLOW_TIMER #else -#define TX_TIMER_PERIODIC 10 +#define TX_TIMER_PERIODIC 1 #endif #endif @@ -596,5 +607,3 @@ VOID _tx_win32_scheduler_wake(VOID); - - diff --git a/ports/win64/vs_2022/src/tx_initialize_low_level.c b/ports/win64/vs_2022/src/tx_initialize_low_level.c index b7e965758..b41477d75 100644 --- a/ports/win64/vs_2022/src/tx_initialize_low_level.c +++ b/ports/win64/vs_2022/src/tx_initialize_low_level.c @@ -14,6 +14,7 @@ **************************************************************************/ // Some portions generated by Codex (gpt 5.4). +// Some portions generated by Codex (gpt-5.6-sol). /**************************************************************************/ /**************************************************************************/ /** */ @@ -51,6 +52,15 @@ HANDLE _tx_win32_isr_semaphore; UINT _tx_win32_timer_waiting; extern TX_THREAD *_tx_thread_current_ptr; +#ifdef TX_WIN32_NO_IDLE_ENABLE +/* Auto-reset event used by the scheduler to kick the timer thread so that the + simulated clock advances immediately when no thread is ready to run, instead + of waiting for the wall-clock periodic timer. This makes the simulation + CPU-bound rather than wall-clock-bound during idle periods, mirroring the + Linux port's TX_LINUX_NO_IDLE_ENABLE behavior. */ +HANDLE _tx_win32_timer_kick_event; +#endif + /* Define simulated timer interrupt. This is done inside a thread, which is how other interrupts may be defined as well. See code below for an @@ -197,7 +207,7 @@ extern VOID *_tx_initialize_unused_memory; /* */ /* CALLS */ /* */ -/* CreateMutex Win32 create mutex */ +/* InitializeCriticalSection Win32 initialize lock */ /* CreateThread Win32 create thread */ /* CreateSemaphore Win32 create semaphore */ /* GetCurrentThreadId Win32 get current thread ID */ @@ -237,18 +247,11 @@ VOID _tx_initialize_low_level(VOID) /* Pickup the unique Id of the current thread, which will also be the Id of the scheduler. */ _tx_win32_scheduler_id = GetCurrentThreadId(); - /* Create the system critical section mutex. This is used by the system to block all other access, + /* Initialize the system critical section. This is used by the system to block all other access, analogous to an interrupt lockout on an embedded target. */ - _tx_win32_critical_section.tx_win32_critical_section_mutex_handle = CreateMutex(NULL, FALSE, NULL); + InitializeCriticalSection(&_tx_win32_critical_section.tx_win32_critical_section_lock); _tx_win32_critical_section.tx_win32_critical_section_nested_count = 0; _tx_win32_critical_section.tx_win32_critical_section_owner = 0; - if (_tx_win32_critical_section.tx_win32_critical_section_mutex_handle == NULL) - { - printf("ThreadX Win64 error creating critical section mutex!\n"); - while(1) - { - } - } /* Create the semaphore that regulates when the scheduler executes. */ _tx_win32_scheduler_semaphore = CreateSemaphore(NULL, 0, 1, NULL); @@ -271,6 +274,20 @@ VOID _tx_initialize_low_level(VOID) } } +#ifdef TX_WIN32_NO_IDLE_ENABLE + + /* Create the auto-reset event used to kick the timer thread when the + scheduler detects an idle system (see _tx_thread_schedule). */ + _tx_win32_timer_kick_event = CreateEvent(NULL, FALSE, FALSE, NULL); + if (_tx_win32_timer_kick_event == NULL) + { + printf("ThreadX Win64 error creating timer kick event!\n"); + while(1) + { + } + } +#endif + /* Initialize the global interrupt disabled flag. */ _tx_win32_global_int_disabled_flag = TX_FALSE; _tx_win32_timer_waiting = TX_FALSE; @@ -358,8 +375,20 @@ VOID CALLBACK _tx_win32_timer_interrupt(UINT wTimerID, UINT msg, DWORD_PTR dwUse /* Call ThreadX context save for interrupt preparation. */ _tx_thread_context_save(); - /* Call the ThreadX system timer interrupt processing. */ - _tx_timer_interrupt(); + /* Fire TX_WIN32_TICKS_PER_INTERRUPT ticks inside a single interrupt + context. The SuspendThread/ResumeThread overhead is amortized across + all N ticks, and all timer-based delays shrink by factor N. The + relative ordering of thread wakeups is preserved because each call to + _tx_timer_interrupt() advances the tick counter by exactly one step and + processes the timers that expire at that step. */ +#ifndef TX_WIN32_TICKS_PER_INTERRUPT +#define TX_WIN32_TICKS_PER_INTERRUPT 5 +#endif + { + UINT _tick_i; + for (_tick_i = 0; _tick_i < TX_WIN32_TICKS_PER_INTERRUPT; _tick_i++) + _tx_timer_interrupt(); + } /* Call ThreadX context restore for interrupt completion. */ _tx_thread_context_restore(); @@ -376,13 +405,26 @@ static DWORD WINAPI _tx_win32_timer_thread_entry(LPVOID thread_input) /* Drive periodic simulated interrupts from a single thread. */ while (1) { +#ifdef TX_WIN32_NO_IDLE_ENABLE + + /* Wake either on the periodic wall-clock timer or on a scheduler kick + (issued when the system is idle). Firing on the kick advances the + simulated clock immediately, without waiting for the wall clock. */ + HANDLE _wait_handles[2]; + + _wait_handles[0] = _tx_win32_timer_handle; + _wait_handles[1] = _tx_win32_timer_kick_event; + WaitForMultipleObjects(2, _wait_handles, FALSE, INFINITE); +#else WaitForSingleObject(_tx_win32_timer_handle, INFINITE); +#endif _tx_win32_timer_interrupt(0, 0, 0, 0, 0); _tx_win32_timer_start(); } } + VOID _tx_win32_scheduler_wake(VOID) { @@ -414,4 +456,3 @@ LARGE_INTEGER due_time; } } } - diff --git a/ports/win64/vs_2022/src/tx_thread_context_restore.c b/ports/win64/vs_2022/src/tx_thread_context_restore.c index 9786e7cbe..f860d61f0 100644 --- a/ports/win64/vs_2022/src/tx_thread_context_restore.c +++ b/ports/win64/vs_2022/src/tx_thread_context_restore.c @@ -14,6 +14,7 @@ **************************************************************************/ // Some portions generated by Codex (gpt 5.4). +// Some portions generated by Codex (gpt-5.6-sol). /**************************************************************************/ /**************************************************************************/ @@ -131,9 +132,11 @@ TX_THREAD *execute_thread; (execute_thread -> tx_thread_win32_suspension_type == 0)) { - /* Release the critical section while the scheduler runs. */ + /* Spin-poll for the scheduler to complete the solicited wakeup + before the timer ISR proceeds. */ _tx_win32_critical_section_release_all(&_tx_win32_critical_section); - WaitForSingleObject(_tx_win32_isr_semaphore, INFINITE); + while (WaitForSingleObject(_tx_win32_isr_semaphore, 0) != WAIT_OBJECT_0) + SwitchToThread(); _tx_win32_critical_section_obtain(&_tx_win32_critical_section); while (WaitForSingleObject(_tx_win32_isr_semaphore, 0) == WAIT_OBJECT_0) { @@ -161,9 +164,11 @@ TX_THREAD *execute_thread; if (execute_thread -> tx_thread_win32_suspension_type == 0) { - /* Release the critical section while the scheduler runs. */ + /* Spin-poll for the scheduler to hand off to the next thread and + acknowledge via the ISR semaphore. Keeps timer-path latency low. */ _tx_win32_critical_section_release_all(&_tx_win32_critical_section); - WaitForSingleObject(_tx_win32_isr_semaphore, INFINITE); + while (WaitForSingleObject(_tx_win32_isr_semaphore, 0) != WAIT_OBJECT_0) + SwitchToThread(); _tx_win32_critical_section_obtain(&_tx_win32_critical_section); while (WaitForSingleObject(_tx_win32_isr_semaphore, 0) == WAIT_OBJECT_0) { @@ -177,4 +182,3 @@ TX_THREAD *execute_thread; _tx_win32_critical_section_release_all(&_tx_win32_critical_section); } - diff --git a/ports/win64/vs_2022/src/tx_thread_interrupt_control.c b/ports/win64/vs_2022/src/tx_thread_interrupt_control.c index ab50a3c9e..b38a0749b 100644 --- a/ports/win64/vs_2022/src/tx_thread_interrupt_control.c +++ b/ports/win64/vs_2022/src/tx_thread_interrupt_control.c @@ -13,6 +13,8 @@ * SPDX-License-Identifier: MIT and CC0-1.0 **************************************************************************/ +// Some portions generated by Codex (gpt-5.6-sol). + /**************************************************************************/ /**************************************************************************/ /** */ @@ -96,8 +98,6 @@ UINT _tx_thread_interrupt_control(UINT new_posture) { UINT old_posture; -HANDLE threadhandle; -int threadpriority; DWORD threadid; TX_THREAD *thread_ptr; @@ -122,22 +122,16 @@ TX_THREAD *thread_ptr; /* Determine if the thread was terminated. */ - /* Pickup the handle of the current thread. */ - threadhandle = GetCurrentThread(); - /* Pickup the current thread pointer. */ thread_ptr = _tx_thread_current_ptr; - /* Pickup the priority of the current thread. */ - threadpriority = GetThreadPriority(threadhandle); - /* Pickup the ID of the current thread. */ threadid = GetCurrentThreadId(); /* Determine if this is a thread (THREAD_PRIORITY_LOWEST) and it does not match the current thread pointer. */ - if ((threadpriority == THREAD_PRIORITY_LOWEST) && - ((!thread_ptr) || (thread_ptr -> tx_thread_win32_thread_id != threadid))) + if (((!thread_ptr) || (thread_ptr -> tx_thread_win32_thread_id != threadid)) && + (GetThreadPriority(GetCurrentThread()) == THREAD_PRIORITY_LOWEST)) { /* This indicates the Win32 thread was actually terminated by ThreadX is only @@ -208,4 +202,3 @@ TX_THREAD *thread_ptr; return(old_posture); } - diff --git a/ports/win64/vs_2022/src/tx_thread_schedule.c b/ports/win64/vs_2022/src/tx_thread_schedule.c index d08305ee8..f6bef9495 100644 --- a/ports/win64/vs_2022/src/tx_thread_schedule.c +++ b/ports/win64/vs_2022/src/tx_thread_schedule.c @@ -14,6 +14,7 @@ **************************************************************************/ // Some portions generated by Codex (gpt 5.4). +// Some portions generated by Codex (gpt-5.6-sol). /**************************************************************************/ /**************************************************************************/ @@ -111,8 +112,27 @@ DWORD wait_status; /* Leave the critical section. */ _tx_win32_critical_section_release(&_tx_win32_critical_section); - /* Wait for the next scheduling state change. */ - WaitForSingleObject(_tx_win32_scheduler_wake_event, INFINITE); +#ifdef TX_WIN32_NO_IDLE_ENABLE + + /* No thread is ready to run: advance the simulated clock now + instead of waiting for the wall-clock periodic timer. Kick + the timer thread so it fires the next tick(s) immediately, + then wait for it to signal progress via the wake event. A + short bounded timeout guards against a missed wake. This + makes idle periods CPU-bound rather than wall-clock-bound, + mirroring the Linux port's TX_LINUX_NO_IDLE_ENABLE path. */ + SetEvent(_tx_win32_timer_kick_event); + WaitForSingleObject(_tx_win32_scheduler_wake_event, 2); +#else + + /* Yield to other threads (timer, application threads) instead of + blocking indefinitely. This spin-poll eliminates the ~0.5 ms + kernel-wake latency of WaitForSingleObject(INFINITE) and reduces + context-switch overhead by >10x at the cost of higher CPU usage + during test runs. Drain any pending wake event to keep it clean. */ + WaitForSingleObject(_tx_win32_scheduler_wake_event, 0); + SwitchToThread(); +#endif } } @@ -185,12 +205,16 @@ DWORD wait_status; /* Exit Win32 critical section. */ _tx_win32_critical_section_release(&_tx_win32_critical_section); - /* Now suspend the main thread so the application thread can run. */ - WaitForSingleObject(_tx_win32_scheduler_semaphore, INFINITE); + /* Spin-poll for the application thread to return control. Using + SwitchToThread() between polls yields the CPU without blocking, + matching the low-latency approach used in the idle loop above. */ + while (WaitForSingleObject(_tx_win32_scheduler_semaphore, 0) != WAIT_OBJECT_0) + SwitchToThread(); } } + static VOID _tx_win32_semaphore_reset(HANDLE semaphore_handle) { @@ -216,17 +240,9 @@ void _tx_win32_critical_section_obtain(TX_WIN32_CRITICAL_SECTION *critical_se { /* Get the Win32 critical section. */ - if (WaitForSingleObject(critical_section -> tx_win32_critical_section_mutex_handle, INFINITE) != WAIT_OBJECT_0) - { - - /* Increment the system error counter and stop when the mutex cannot be acquired. */ - _tx_win32_system_error++; - while(1) - { - } - } + EnterCriticalSection(&critical_section -> tx_win32_critical_section_lock); - /* At this point we have the mutex. */ + /* At this point we have the critical section. */ /* Increment the nesting counter. */ critical_section -> tx_win32_critical_section_nested_count = 1; @@ -241,7 +257,7 @@ void _tx_win32_critical_section_release(TX_WIN32_CRITICAL_SECTION *critical_s { - /* Ensure the caller is the mutex owner. */ + /* Ensure the caller is the critical section owner. */ if (critical_section -> tx_win32_critical_section_owner == GetCurrentThreadId()) { @@ -259,21 +275,8 @@ void _tx_win32_critical_section_release(TX_WIN32_CRITICAL_SECTION *critical_s /* Yes, it is being released clear the owner. */ critical_section -> tx_win32_critical_section_owner = 0; - /* Finally, release the mutex. */ - if (ReleaseMutex(critical_section -> tx_win32_critical_section_mutex_handle) != TX_TRUE) - { - - /* Increment the system error counter. */ - _tx_win32_system_error++; - } - - /* Just in case, make sure there the mutex is not owned. */ - while (ReleaseMutex(critical_section -> tx_win32_critical_section_mutex_handle) == TX_TRUE) - { - - /* Increment the system error counter. */ - _tx_win32_system_error++; - } + /* Finally, release the critical section. */ + LeaveCriticalSection(&critical_section -> tx_win32_critical_section_lock); } } } @@ -289,7 +292,7 @@ void _tx_win32_critical_section_release(TX_WIN32_CRITICAL_SECTION *critical_s void _tx_win32_critical_section_release_all(TX_WIN32_CRITICAL_SECTION *critical_section) { - /* Ensure the caller is the mutex owner. */ + /* Ensure the caller is the critical section owner. */ if (critical_section -> tx_win32_critical_section_owner == GetCurrentThreadId()) { @@ -303,21 +306,8 @@ void _tx_win32_critical_section_release_all(TX_WIN32_CRITICAL_SECTION *cri /* Yes, it is being release clear the owner. */ critical_section -> tx_win32_critical_section_owner = 0; - /* Finally, release the mutex. */ - if (ReleaseMutex(critical_section -> tx_win32_critical_section_mutex_handle) != TX_TRUE) - { - - /* Increment the system error counter. */ - _tx_win32_system_error++; - } - - /* Just in case, make sure there the mutex is not owned. */ - while (ReleaseMutex(critical_section -> tx_win32_critical_section_mutex_handle) == TX_TRUE) - { - - /* Increment the system error counter. */ - _tx_win32_system_error++; - } + /* Finally, release the critical section. */ + LeaveCriticalSection(&critical_section -> tx_win32_critical_section_lock); } } else @@ -327,5 +317,3 @@ void _tx_win32_critical_section_release_all(TX_WIN32_CRITICAL_SECTION *cri _tx_win32_system_error++; } } - - diff --git a/ports/win64/vs_2022/src/tx_thread_stack_build.c b/ports/win64/vs_2022/src/tx_thread_stack_build.c index d48a8f061..4f6be75cf 100644 --- a/ports/win64/vs_2022/src/tx_thread_stack_build.c +++ b/ports/win64/vs_2022/src/tx_thread_stack_build.c @@ -16,6 +16,7 @@ // Some portions generated by Copilot (Opus 5). // Some portions generated by Codex (gpt 5.4). +// Some portions generated by Codex (gpt-5.6-sol). /**************************************************************************/ /**************************************************************************/ @@ -186,9 +187,10 @@ DWORD threadid; handoff point and is ready to be scheduled. */ ReleaseSemaphore(thread_ptr -> tx_thread_win32_thread_start_semaphore, 1, NULL); - /* Now suspend the thread initially. If the thread has already - been scheduled, this will return immediately. */ - WaitForSingleObject(thread_ptr -> tx_thread_win32_thread_run_semaphore, INFINITE); + /* Spin-poll for the scheduler to release this thread to run. + Matches the spin-poll pattern used in _tx_thread_system_return. */ + while (WaitForSingleObject(thread_ptr -> tx_thread_win32_thread_run_semaphore, 0) != WAIT_OBJECT_0) + SwitchToThread(); /* Acknowledge that the host thread is now able to execute ThreadX code. */ ReleaseSemaphore(thread_ptr -> tx_thread_win32_thread_start_semaphore, 1, NULL); @@ -216,4 +218,3 @@ DWORD threadid; return EXIT_SUCCESS; } - diff --git a/ports/win64/vs_2022/src/tx_thread_system_return.c b/ports/win64/vs_2022/src/tx_thread_system_return.c index 7a8fc89c0..9b1fa210a 100644 --- a/ports/win64/vs_2022/src/tx_thread_system_return.c +++ b/ports/win64/vs_2022/src/tx_thread_system_return.c @@ -14,6 +14,7 @@ **************************************************************************/ // Some portions generated by Codex (gpt 5.4). +// Some portions generated by Codex (gpt-5.6-sol). /**************************************************************************/ /**************************************************************************/ @@ -167,9 +168,11 @@ DWORD threadid; ExitThread(0); } - /* Wait on the run semaphore for this thread. This won't get set again - until the thread is scheduled. */ - WaitForSingleObject(temp_run_semaphore, INFINITE); + /* Spin-poll for the scheduler to grant this thread a new time-slice. + SwitchToThread() between polls keeps the CPU available to the scheduler + and timer without paying the full kernel-wake cost of INFINITE. */ + while (WaitForSingleObject(temp_run_semaphore, 0) != WAIT_OBJECT_0) + SwitchToThread(); /* Acknowledge that the thread is once again executing ThreadX code. */ ReleaseSemaphore(temp_thread_ptr -> tx_thread_win32_thread_start_semaphore, 1, NULL); @@ -213,4 +216,3 @@ DWORD threadid; } } - diff --git a/test/smp/regression/testcontrol.c b/test/smp/regression/testcontrol.c index 816d15080..caf06e0d7 100644 --- a/test/smp/regression/testcontrol.c +++ b/test/smp/regression/testcontrol.c @@ -12,6 +12,7 @@ /* This is the test control routine of the ThreadX kernel. All tests are dispatched from this routine. */ // Some portions generated by Codex (gpt 5.5). // Some portions generated by Copilot (Opus 5). +// Some portions generated by Codex (gpt-5.6-sol). #define TX_THREAD_SMP_SOURCE_CODE @@ -28,11 +29,17 @@ #include "tx_event_flags.h" #include #include +#ifdef _WIN32 +#include +#include +#include +#else #include #include #include #include #include +#endif #define TEST_STACK_SIZE 6144 @@ -1377,9 +1384,10 @@ TX_THREAD *thread_ptr; that takes milliseconds, so bounding it cannot turn a slow pass into a failure. - The report is written with write() rather than printf() deliberately. A - wedged thread may hold the stdio lock, and a watchdog that blocked on that - lock would reproduce the silent timeout it exists to replace. + The report is written directly to the standard-error descriptor rather + than with printf() deliberately. A wedged thread may hold the stdio lock, + and a watchdog that blocked on that lock would reproduce the silent timeout + it exists to replace. TX_TEST_TEARDOWN_TIMEOUT overrides the bound, in seconds; zero disables the watchdog. TX_TEST_TEARDOWN_TRACE echoes every stage as it is reached and @@ -1395,6 +1403,26 @@ static volatile UINT test_teardown_armed = TX_FALSE; static UINT test_teardown_timeout = TEST_TEARDOWN_TIMEOUT_DEFAULT; static UINT test_teardown_trace = TX_FALSE; +#ifdef _WIN32 +#define TEST_TEARDOWN_DEFERRED_PREEMPT(thread_ptr) ((thread_ptr) -> tx_thread_win32_deferred_preempt) +#define TEST_TEARDOWN_SUSPENSION_TYPE(thread_ptr) ((thread_ptr) -> tx_thread_win32_suspension_type) +#else +#define TEST_TEARDOWN_DEFERRED_PREEMPT(thread_ptr) ((thread_ptr) -> tx_thread_linux_deferred_preempt) +#define TEST_TEARDOWN_SUSPENSION_TYPE(thread_ptr) ((thread_ptr) -> tx_thread_linux_suspension_type) +#endif + + +/* Write diagnostics directly to standard error without taking the stdio lock. */ +static void test_teardown_write(const char *buffer, size_t length) +{ + +#ifdef _WIN32 + (void) _write(2, buffer, (unsigned int) length); +#else + (void) write(2, buffer, length); +#endif +} + /* Record how far teardown has progressed, and echo it when tracing is on. */ static void test_teardown_stage(const char *stage) @@ -1404,9 +1432,9 @@ static void test_teardown_stage(const char *stage) if (test_teardown_trace != TX_FALSE) { - (void) write(2, "[teardown] ", 11); - (void) write(2, stage, strlen(stage)); - (void) write(2, "\n", 1); + test_teardown_write("[teardown] ", 11u); + test_teardown_write(stage, strlen(stage)); + test_teardown_write("\n", 1u); } } @@ -1445,7 +1473,7 @@ TX_THREAD *thread_ptr; (UINT) _tx_thread_preempt_disable, (ULONG) _tx_thread_created_count); if (length > 0) - (void) write(2, buffer, (size_t) length); + test_teardown_write(buffer, (size_t) length); for (core = 0; core < ((UINT) TX_THREAD_SMP_MAX_CORES); core++) { @@ -1457,7 +1485,7 @@ TX_THREAD *thread_ptr; test_teardown_thread_name(_tx_thread_current_ptr[core]), test_teardown_thread_name(_tx_thread_execute_ptr[core])); if (length > 0) - (void) write(2, buffer, (size_t) length); + test_teardown_write(buffer, (size_t) length); } /* Walk the created list, stopping at the head, and after a fixed number of @@ -1476,10 +1504,10 @@ TX_THREAD *thread_ptr; thread_ptr -> tx_thread_inherit_priority, thread_ptr -> tx_thread_smp_core_mapped, (ULONG) thread_ptr -> tx_thread_smp_core_control, - thread_ptr -> tx_thread_linux_deferred_preempt, - thread_ptr -> tx_thread_linux_suspension_type); + TEST_TEARDOWN_DEFERRED_PREEMPT(thread_ptr), + TEST_TEARDOWN_SUSPENSION_TYPE(thread_ptr)); if (length > 0) - (void) write(2, buffer, (size_t) length); + test_teardown_write(buffer, (size_t) length); thread_ptr = thread_ptr -> tx_thread_created_next; if (thread_ptr == _tx_thread_created_ptr) @@ -1498,6 +1526,41 @@ static void test_teardown_abort(const char *reason) /* Watch an armed teardown, and only an armed one. */ +#ifdef _WIN32 +static unsigned __stdcall test_teardown_watchdog(void *input) +{ + +ULONG waited_ms; +ULONG limit_ms; + + + (void) input; + limit_ms = ((ULONG) test_teardown_timeout) * ((ULONG) 1000); + waited_ms = ((ULONG) 0); + + while (1) + { + + Sleep((DWORD) TEST_TEARDOWN_POLL_MS); + + /* Nothing to watch while teardown is stood down. */ + if (test_teardown_armed == TX_FALSE) + { + waited_ms = ((ULONG) 0); + } + else + { + waited_ms = waited_ms + ((ULONG) TEST_TEARDOWN_POLL_MS); + if (waited_ms >= limit_ms) + { + test_teardown_abort("teardown did not complete"); + } + } + } + + return 0u; +} +#else static void *test_teardown_watchdog(void *input) { @@ -1542,6 +1605,7 @@ ULONG limit_ms; return input; } +#endif /* Start the watchdog, stood down. Called before any test runs, so that no @@ -1549,7 +1613,11 @@ ULONG limit_ms; static void test_teardown_watchdog_start(void) { +#ifdef _WIN32 +uintptr_t watchdog_id; +#else pthread_t watchdog_id; +#endif char *value; @@ -1563,15 +1631,27 @@ char *value; /* Tracing wants the stages in the log next to the output around them, which block buffering would otherwise discard on a kill. */ test_teardown_trace = TX_TRUE; +#ifdef _WIN32 + setvbuf(stdout, TX_NULL, _IONBF, 0u); +#else setvbuf(stdout, TX_NULL, _IOLBF, 0); +#endif } /* A timeout of zero turns the watchdog off. */ if (test_teardown_timeout == ((UINT) 0)) return; +#ifdef _WIN32 + watchdog_id = _beginthreadex(TX_NULL, 0u, test_teardown_watchdog, TX_NULL, 0u, TX_NULL); + if (watchdog_id != ((uintptr_t) 0)) + { + (void) CloseHandle((HANDLE) watchdog_id); + } +#else if (pthread_create(&watchdog_id, TX_NULL, test_teardown_watchdog, TX_NULL) == 0) pthread_detach(watchdog_id); +#endif } diff --git a/test/tx/cmake/thread_transition/CMakeLists.txt b/test/tx/cmake/thread_transition/CMakeLists.txt index f414ed675..a56592382 100644 --- a/test/tx/cmake/thread_transition/CMakeLists.txt +++ b/test/tx/cmake/thread_transition/CMakeLists.txt @@ -1,3 +1,5 @@ +# Some portions generated by Codex (gpt-5.6-sol). + cmake_minimum_required(VERSION 3.13 FATAL_ERROR) cmake_policy(SET CMP0057 NEW) @@ -56,11 +58,22 @@ set(transition_sources # opposite, because calling the public names and letting tx_api.h decide what they # bind to is exactly what the TX_DISABLE_ERROR_CHECKING configuration is here to # demonstrate. +if(MSVC) + set(transition_kernel_compile_options + "/FI${SOURCE_DIR}/threadx_thread_transition_host_test_port.h") + set(transition_undefine_options /UTX_ENABLE_EVENT_TRACE + /UTX_ENABLE_EVENT_LOG) +else() + set(transition_kernel_compile_options + "-include;${SOURCE_DIR}/threadx_thread_transition_host_test_port.h") + set(transition_undefine_options -UTX_ENABLE_EVENT_TRACE + -UTX_ENABLE_EVENT_LOG) +endif() + set_source_files_properties( ${transition_kernel_sources} DIRECTORY ${CMAKE_CURRENT_LIST_DIR} - PROPERTIES COMPILE_OPTIONS - "-include;${SOURCE_DIR}/threadx_thread_transition_host_test_port.h") + PROPERTIES COMPILE_OPTIONS "${transition_kernel_compile_options}") # Each entry is a test-name suffix, a colon, and the feature macros that define the # configuration, separated by "|". A semicolon cannot be used as that separator: it @@ -80,16 +93,20 @@ foreach(configuration ${transition_configurations}) string(REPLACE "|" ";" configuration_macros ${configuration_macro_text}) set(test_name threadx_thread_transition_${configuration_name}_test) + # Keep the internal target name short. CMake includes it in every object path, + # and the descriptive test name can otherwise reach the legacy MSVC MAX_PATH + # boundary in a normally nested Windows worktree. + set(test_target tx_tt_${configuration_name}) - add_executable(${test_name} ${transition_sources}) + add_executable(${test_target} ${transition_sources}) target_include_directories( - ${test_name} + ${test_target} PRIVATE ${SOURCE_DIR} ${REPO_ROOT}/common/inc ${REPO_ROOT}/ports/${THREADX_ARCH}/${THREADX_TOOLCHAIN}/inc) - target_compile_definitions(${test_name} PRIVATE ${configuration_macros}) + target_compile_definitions(${test_target} PRIVATE ${configuration_macros}) # This directory is configured once per build configuration of the tree, so # these executables inherit whichever feature macros that configuration sets -- @@ -103,13 +120,12 @@ foreach(configuration ${transition_configurations}) # lost by turning tracing off here. Event logging is turned off for the same # reason; no configuration of the tree enables it. # - # The -U flags have to reach the test source as well as the kernel sources, + # The undefine options have to reach the test source as well as the kernel sources, # because TX_ENABLE_EVENT_TRACE is visible to tx_api.h and the two must agree on # what the headers declare. Target compile options land after the directory's - # -D flags on the command line, which is what makes the -U effective. - target_compile_options(${test_name} PRIVATE -UTX_ENABLE_EVENT_TRACE - -UTX_ENABLE_EVENT_LOG) + # definition flags on the command line, which is what makes them effective. + target_compile_options(${test_target} PRIVATE ${transition_undefine_options}) - add_test(${CMAKE_BUILD_TYPE}::${test_name} ${test_name}) + add_test(${CMAKE_BUILD_TYPE}::${test_name} ${test_target}) endforeach() diff --git a/test/tx/regression/threadx_thread_basic_execution_test.c b/test/tx/regression/threadx_thread_basic_execution_test.c index c51a677c3..8372fcd9d 100644 --- a/test/tx/regression/threadx_thread_basic_execution_test.c +++ b/test/tx/regression/threadx_thread_basic_execution_test.c @@ -1,4 +1,6 @@ /***************************************************************************/ + +/* Some portions generated by Codex (gpt-5.6-sol). */ /* Copyright (c) 2024 Microsoft Corporation */ /* Copyright (c) 2026 Eclipse ThreadX contributors */ /* */ @@ -401,7 +403,7 @@ VOID (*temp_mutex_release)(TX_THREAD *thread_ptr); test_thread.tx_thread_timer.tx_timer_internal_list_head = TX_NULL; test_thread.tx_thread_suspending = TX_TRUE; test_thread.tx_thread_delayed_suspend = TX_TRUE; -#if defined(_WIN64) || defined(TX_TIMER_EXTENSION_PTR_DEFINED) +#if defined(_WIN32) || defined(TX_TIMER_EXTENSION_PTR_DEFINED) { TX_TIMER_INTERNAL timeout_timer; TX_TIMER_INTERNAL *saved_expired_timer_ptr; diff --git a/test/tx/regression/threadx_trace_entry_update_test.c b/test/tx/regression/threadx_trace_entry_update_test.c index d827497af..6c6d96143 100644 --- a/test/tx/regression/threadx_trace_entry_update_test.c +++ b/test/tx/regression/threadx_trace_entry_update_test.c @@ -12,6 +12,7 @@ * * SPDX-License-Identifier: MIT and CC0-1.0 **************************************************************************/ +// Some portions generated by Codex (gpt-5.6-sol). /* This test drives the trace entry update paths -- the blocks guarded by TX_ENABLE_EVENT_TRACE that go back and patch a trace entry after the call @@ -73,7 +74,7 @@ static TX_SEMAPHORE semaphore_0; static UCHAR trace_buffer[16384]; -/* Four blocks of 20 bytes: 100 / (20 + sizeof(void *)) on a 32-bit build. */ +/* Enough storage for several 20-byte blocks on both 32-bit and 64-bit builds. */ static UCHAR block_pool_area[100]; static UCHAR byte_pool_area[512]; @@ -213,14 +214,22 @@ void *byte_ptr; UINT i; - /* Empty the block pool. The first of these takes the immediate-success path - through tx_block_allocate, which carries the first update block. */ + /* Empty the block pool. The first allocation takes the immediate-success + path through tx_block_allocate, which carries the first update block. + The exact capacity is port-dependent because each block has a pointer- + sized header, so allocate until the pool reports that it is empty. */ held_block = TX_NULL; - for (i = 0; i < 4; i++) + for (i = 0; i < 6u; i++) { status = tx_block_allocate(&block_pool_0, &block_ptr, TX_NO_WAIT); + if (status == TX_NO_MEMORY) + { + + break; + } + if (status != TX_SUCCESS) { @@ -236,6 +245,12 @@ UINT i; } } + if ((status != TX_NO_MEMORY) || (held_block == TX_NULL)) + { + + error++; + } + /* The pool is empty now, so this suspends. It completes in thread 1's context when the block comes back, which is the second update block in tx_block_allocate -- and the suspend and resume it goes through carry the From 9e4c57138dfa004cd512b60259c1c5047a8b3dd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Tue, 15 Sep 2026 17:17:26 -0400 Subject: [PATCH 143/181] Normalized the AI disclosure comment to one fixed line per file (#740) The per-edit disclosure named the product and model, so every agent and every model version appended another line. 74 files carried two to four of them, and the same five products had accumulated 13 spellings -- Copilot against GitHub Copilot, Claude Sonnet 4.6 against claude-sonnet-4.6, four spellings of Codex. Twenty assembly lines carried a doubled comment marker, `; //` or `@ //`. Every file now carries exactly one line, fixed text naming no product: Portions of this file were generated with AI assistance. It is written with the comment character that file already uses, so the `;` and `@` assembly files keep theirs and the doubled markers are gone. Precise attribution stays on the commit, where the Assisted-by trailer is per-change, dated and attached to the diff it describes. A header line cannot hold that record honestly, because the code it names gets rewritten and the line stays. A file-level flag answers whether; the history answers who. Comment-only. 455 files, 455 insertions and 574 deletions: every removed line was a disclosure line, every added line is the fixed text, and no file is left with zero or with more than one. `scripts/check_ports.sh` passes, including the reproducibility check that would catch a ports_arch master and its generated copies drifting apart. Recompiled against dev, every file that builds without a vendor toolchain gives a byte-identical object: 19 of 19 C files under common, 100 of 100 GNU assembly files, and all 16 assemblable files whose comment marker changed. The 10 remaining marker changes are ac5 and IAR sources where `;` already started the comment and only the redundant `//` was removed. Assisted-by: Claude Code (Opus 5) --- common/src/tx_thread_create.c | 2 +- common/src/tx_thread_delete.c | 2 +- common/src/tx_thread_reset.c | 2 +- common/src/tx_thread_shell_entry.c | 2 +- common/src/tx_thread_sleep.c | 2 +- common/src/tx_thread_stack_analyze.c | 2 +- common/src/tx_thread_terminate.c | 2 +- common/src/txe_timer_change.c | 2 +- common_modules/inc/txm_module.h | 2 +- .../module_manager/inc/txm_module_manager_dispatch.h | 3 +-- .../module_manager/src/txm_module_manager_absolute_load.c | 2 +- .../src/txm_module_manager_absolute_load_extended.c | 2 +- .../module_manager/src/txm_module_manager_thread_create.c | 2 +- .../module_manager/utilities/module_binary_to_c_array.c | 2 +- common_modules/module_manager/utilities/module_to_binary.c | 2 +- common_modules/module_manager/utilities/module_to_c_array.c | 2 +- common_smp/inc/tx_thread.h | 2 +- common_smp/src/tx_thread_create.c | 2 +- common_smp/src/tx_thread_delete.c | 2 +- common_smp/src/tx_thread_reset.c | 2 +- common_smp/src/tx_thread_shell_entry.c | 2 +- common_smp/src/tx_thread_sleep.c | 2 +- common_smp/src/tx_thread_smp_utilities.c | 2 +- common_smp/src/tx_thread_stack_analyze.c | 2 +- common_smp/src/tx_thread_terminate.c | 2 +- common_smp/src/txe_timer_change.c | 2 +- ports/arc_em/metaware/src/tx_thread_context_save.s | 2 +- ports/arc_hs/metaware/src/tx_thread_context_save.s | 2 +- ports/arm11/iar/src/tx_iar.c | 2 +- ports/arm9/iar/src/tx_iar.c | 2 +- ports/cortex_a12/ac6/src/tx_thread_system_return.S | 2 +- ports/cortex_a12/gnu/src/tx_thread_system_return.S | 2 +- ports/cortex_a15/ac6/src/tx_thread_system_return.S | 2 +- ports/cortex_a15/gnu/src/tx_thread_system_return.S | 2 +- ports/cortex_a15/iar/src/tx_iar.c | 2 +- ports/cortex_a17/ac6/src/tx_thread_system_return.S | 2 +- ports/cortex_a17/gnu/src/tx_thread_system_return.S | 2 +- ports/cortex_a34/gnu/src/tx_initialize_low_level.S | 2 +- ports/cortex_a35/gnu/src/tx_initialize_low_level.S | 2 +- ports/cortex_a5/ac6/src/tx_thread_system_return.S | 2 +- ports/cortex_a5/gnu/src/tx_thread_system_return.S | 2 +- ports/cortex_a5/iar/src/tx_iar.c | 2 +- ports/cortex_a53/gnu/src/tx_initialize_low_level.S | 2 +- ports/cortex_a55/gnu/src/tx_initialize_low_level.S | 2 +- ports/cortex_a57/gnu/src/tx_initialize_low_level.S | 2 +- ports/cortex_a65/gnu/src/tx_initialize_low_level.S | 2 +- ports/cortex_a65ae/gnu/src/tx_initialize_low_level.S | 2 +- ports/cortex_a7/ac6/src/tx_thread_system_return.S | 2 +- ports/cortex_a7/gnu/src/tx_thread_system_return.S | 2 +- ports/cortex_a7/iar/src/tx_iar.c | 2 +- ports/cortex_a72/gnu/src/tx_initialize_low_level.S | 2 +- ports/cortex_a73/gnu/src/tx_initialize_low_level.S | 2 +- ports/cortex_a75/gnu/src/tx_initialize_low_level.S | 2 +- ports/cortex_a76/gnu/src/tx_initialize_low_level.S | 2 +- ports/cortex_a76ae/gnu/src/tx_initialize_low_level.S | 2 +- ports/cortex_a77/gnu/src/tx_initialize_low_level.S | 2 +- ports/cortex_a8/ac6/src/tx_thread_system_return.S | 2 +- ports/cortex_a8/gnu/src/tx_thread_system_return.S | 2 +- ports/cortex_a8/iar/src/tx_iar.c | 2 +- ports/cortex_a9/ac6/src/tx_thread_system_return.S | 2 +- ports/cortex_a9/gnu/src/tx_thread_system_return.S | 2 +- ports/cortex_a9/iar/src/tx_iar.c | 2 +- ports/cortex_m0/ac5/example_build/tx_initialize_low_level.s | 2 +- .../example_build/sample_threadx/tx_initialize_low_level.S | 3 +-- ports/cortex_m0/ac6/inc/tx_port.h | 2 +- ports/cortex_m0/gnu/example_build/tx_initialize_low_level.S | 2 +- ports/cortex_m0/gnu/inc/tx_port.h | 3 +-- ports/cortex_m0/gnu/src/tx_thread_system_return.S | 2 +- ports/cortex_m0/iar/example_build/tx_initialize_low_level.s | 2 +- ports/cortex_m0/iar/inc/tx_port.h | 2 +- ports/cortex_m0/iar/src/tx_iar.c | 2 +- ports/cortex_m0/iar/src/tx_thread_system_return.s | 2 +- ports/cortex_m0/keil/example_build/tx_initialize_low_level.s | 2 +- ports/cortex_m23/ac6/example_build/tx_initialize_low_level.S | 2 +- ports/cortex_m23/ac6/inc/tx_port.h | 3 +-- ports/cortex_m23/ac6/src/tx_thread_system_return.S | 2 +- ports/cortex_m23/gnu/inc/tx_port.h | 3 +-- ports/cortex_m23/gnu/src/tx_initialize_low_level.S | 2 +- ports/cortex_m23/gnu/src/tx_thread_system_return.S | 2 +- ports/cortex_m23/iar/inc/tx_port.h | 2 +- ports/cortex_m23/iar/src/tx_iar.c | 2 +- ports/cortex_m23/iar/src/tx_initialize_low_level.s | 2 +- ports/cortex_m23/iar/src/tx_thread_system_return.s | 2 +- ports/cortex_m3/ac5/example_build/tx_initialize_low_level.s | 2 +- ports/cortex_m3/ac5/inc/tx_port.h | 5 +---- ports/cortex_m3/ac5/src/tx_thread_schedule.s | 2 +- .../example_build/sample_threadx/tx_initialize_low_level.S | 2 +- ports/cortex_m3/ac6/inc/tx_port.h | 5 +---- ports/cortex_m3/ac6/src/tx_thread_schedule.S | 3 +-- ports/cortex_m3/ac6/src/tx_thread_system_return.S | 2 +- ports/cortex_m3/gnu/example_build/tx_initialize_low_level.S | 2 +- ports/cortex_m3/gnu/inc/tx_port.h | 5 +---- ports/cortex_m3/gnu/src/tx_thread_schedule.S | 3 +-- ports/cortex_m3/gnu/src/tx_thread_system_return.S | 2 +- ports/cortex_m3/iar/example_build/tx_initialize_low_level.s | 2 +- ports/cortex_m3/iar/inc/tx_port.h | 5 +---- ports/cortex_m3/iar/src/tx_iar.c | 2 +- ports/cortex_m3/iar/src/tx_thread_schedule.s | 2 +- ports/cortex_m3/iar/src/tx_thread_system_return.s | 2 +- ports/cortex_m3/keil/example_build/tx_initialize_low_level.s | 2 +- ports/cortex_m3/keil/inc/tx_port.h | 5 +---- ports/cortex_m33/ac6/example_build/tx_initialize_low_level.S | 2 +- ports/cortex_m33/ac6/inc/tx_port.h | 4 +--- ports/cortex_m33/ac6/src/tx_initialize_low_level.S | 2 +- ports/cortex_m33/ac6/src/tx_thread_schedule.S | 3 +-- ports/cortex_m33/ac6/src/tx_thread_system_return.S | 2 +- ports/cortex_m33/gnu/example_build/tx_initialize_low_level.S | 2 +- ports/cortex_m33/gnu/inc/tx_port.h | 4 +--- ports/cortex_m33/gnu/src/tx_thread_schedule.S | 3 +-- ports/cortex_m33/gnu/src/tx_thread_system_return.S | 2 +- ports/cortex_m33/iar/inc/tx_port.h | 4 +--- ports/cortex_m33/iar/src/tx_iar.c | 2 +- ports/cortex_m33/iar/src/tx_initialize_low_level.s | 2 +- ports/cortex_m33/iar/src/tx_thread_schedule.s | 2 +- ports/cortex_m33/iar/src/tx_thread_system_return.s | 2 +- ports/cortex_m4/ac5/example_build/tx_initialize_low_level.s | 2 +- ports/cortex_m4/ac5/inc/tx_port.h | 5 +---- ports/cortex_m4/ac5/src/tx_thread_schedule.s | 2 +- .../example_build/sample_threadx/tx_initialize_low_level.S | 2 +- ports/cortex_m4/ac6/inc/tx_port.h | 5 +---- ports/cortex_m4/ac6/src/tx_thread_schedule.S | 3 +-- ports/cortex_m4/ac6/src/tx_thread_system_return.S | 2 +- ports/cortex_m4/gnu/example_build/tx_initialize_low_level.S | 2 +- ports/cortex_m4/gnu/inc/tx_port.h | 5 +---- ports/cortex_m4/gnu/src/tx_thread_schedule.S | 3 +-- ports/cortex_m4/gnu/src/tx_thread_system_return.S | 2 +- ports/cortex_m4/iar/example_build/tx_initialize_low_level.s | 2 +- ports/cortex_m4/iar/inc/tx_port.h | 5 +---- ports/cortex_m4/iar/src/tx_iar.c | 2 +- ports/cortex_m4/iar/src/tx_thread_schedule.s | 2 +- ports/cortex_m4/iar/src/tx_thread_system_return.s | 2 +- ports/cortex_m4/keil/example_build/tx_initialize_low_level.s | 2 +- ports/cortex_m4/keil/inc/tx_port.h | 5 +---- ports/cortex_m52/ac6/inc/tx_port.h | 4 +--- ports/cortex_m52/ac6/src/tx_initialize_low_level.S | 2 +- ports/cortex_m52/ac6/src/tx_thread_schedule.S | 3 +-- ports/cortex_m52/ac6/src/tx_thread_system_return.S | 2 +- ports/cortex_m52/gnu/inc/tx_port.h | 4 +--- ports/cortex_m52/gnu/src/tx_thread_schedule.S | 3 +-- ports/cortex_m52/gnu/src/tx_thread_system_return.S | 2 +- ports/cortex_m52/iar/inc/tx_port.h | 4 +--- ports/cortex_m52/iar/src/tx_iar.c | 2 +- ports/cortex_m52/iar/src/tx_initialize_low_level.s | 2 +- ports/cortex_m52/iar/src/tx_thread_schedule.s | 2 +- ports/cortex_m52/iar/src/tx_thread_system_return.s | 2 +- ports/cortex_m55/ac6/example_build/tx_initialize_low_level.S | 2 +- ports/cortex_m55/ac6/inc/tx_port.h | 4 +--- ports/cortex_m55/ac6/src/tx_initialize_low_level.S | 2 +- ports/cortex_m55/ac6/src/tx_thread_schedule.S | 3 +-- ports/cortex_m55/ac6/src/tx_thread_system_return.S | 2 +- ports/cortex_m55/gnu/example_build/tx_initialize_low_level.S | 2 +- ports/cortex_m55/gnu/inc/tx_port.h | 4 +--- ports/cortex_m55/gnu/src/tx_thread_schedule.S | 3 +-- ports/cortex_m55/gnu/src/tx_thread_system_return.S | 2 +- ports/cortex_m55/iar/inc/tx_port.h | 4 +--- ports/cortex_m55/iar/src/tx_iar.c | 2 +- ports/cortex_m55/iar/src/tx_initialize_low_level.s | 2 +- ports/cortex_m55/iar/src/tx_thread_schedule.s | 2 +- ports/cortex_m55/iar/src/tx_thread_system_return.s | 2 +- ports/cortex_m7/ac5/example_build/tx_initialize_low_level.s | 2 +- ports/cortex_m7/ac5/inc/tx_port.h | 5 +---- ports/cortex_m7/ac5/src/tx_thread_schedule.s | 2 +- .../example_build/sample_threadx/tx_initialize_low_level.S | 2 +- ports/cortex_m7/ac6/inc/tx_port.h | 5 +---- ports/cortex_m7/ac6/src/tx_thread_schedule.S | 3 +-- ports/cortex_m7/ac6/src/tx_thread_system_return.S | 2 +- ports/cortex_m7/gnu/example_build/tx_initialize_low_level.S | 2 +- ports/cortex_m7/gnu/inc/tx_port.h | 5 +---- ports/cortex_m7/gnu/src/tx_thread_schedule.S | 3 +-- ports/cortex_m7/gnu/src/tx_thread_system_return.S | 2 +- ports/cortex_m7/iar/example_build/tx_initialize_low_level.s | 2 +- ports/cortex_m7/iar/inc/tx_port.h | 5 +---- ports/cortex_m7/iar/src/tx_iar.c | 2 +- ports/cortex_m7/iar/src/tx_thread_schedule.s | 2 +- ports/cortex_m7/iar/src/tx_thread_system_return.s | 2 +- ports/cortex_m85/ac6/inc/tx_port.h | 4 +--- ports/cortex_m85/ac6/src/tx_initialize_low_level.S | 2 +- ports/cortex_m85/ac6/src/tx_thread_schedule.S | 3 +-- ports/cortex_m85/ac6/src/tx_thread_system_return.S | 2 +- ports/cortex_m85/gnu/example_build/tx_initialize_low_level.S | 2 +- ports/cortex_m85/gnu/inc/tx_port.h | 4 +--- ports/cortex_m85/gnu/src/tx_thread_schedule.S | 3 +-- ports/cortex_m85/gnu/src/tx_thread_system_return.S | 2 +- ports/cortex_m85/iar/inc/tx_port.h | 4 +--- ports/cortex_m85/iar/src/tx_iar.c | 2 +- ports/cortex_m85/iar/src/tx_initialize_low_level.s | 2 +- ports/cortex_m85/iar/src/tx_thread_schedule.s | 2 +- ports/cortex_m85/iar/src/tx_thread_system_return.s | 2 +- ports/cortex_r4/ac6/src/tx_thread_stack_build.S | 2 +- ports/cortex_r4/gnu/inc/tx_port.h | 2 +- ports/cortex_r4/iar/src/tx_iar.c | 2 +- ports/cortex_r5/ac5/inc/tx_port.h | 2 +- ports/cortex_r5/ac6/inc/tx_port.h | 2 +- ports/cortex_r5/gnu/inc/tx_port.h | 2 +- ports/cortex_r5/iar/src/tx_iar.c | 2 +- .../gnu/example_build/fvp_baser_aemv8r/demo_threadx.c | 2 +- ports/cortex_r52/gnu/example_build/s32z280_evb/entry.S | 2 +- ports/cortex_r52/gnu/inc/tx_port.h | 2 +- ports/cortex_r52/gnu/src/tx_thread_context_restore.S | 2 +- ports/cortex_r52/gnu/src/tx_thread_context_save.S | 2 +- ports/cortex_r52/gnu/src/tx_thread_fiq_context_restore.S | 2 +- ports/cortex_r52/gnu/src/tx_thread_fiq_context_save.S | 2 +- ports/cortex_r52/gnu/src/tx_thread_fiq_nesting_end.S | 2 +- ports/cortex_r52/gnu/src/tx_thread_fiq_nesting_start.S | 2 +- ports/cortex_r52/gnu/src/tx_thread_interrupt_control.S | 2 +- ports/cortex_r52/gnu/src/tx_thread_interrupt_disable.S | 2 +- ports/cortex_r52/gnu/src/tx_thread_interrupt_restore.S | 2 +- ports/cortex_r52/gnu/src/tx_thread_irq_nesting_end.S | 2 +- ports/cortex_r52/gnu/src/tx_thread_irq_nesting_start.S | 2 +- ports/cortex_r52/gnu/src/tx_thread_schedule.S | 2 +- ports/cortex_r52/gnu/src/tx_thread_stack_build.S | 2 +- ports/cortex_r52/gnu/src/tx_thread_system_return.S | 2 +- ports/cortex_r52/gnu/src/tx_thread_vectored_context_save.S | 2 +- ports/cortex_r52/gnu/src/tx_timer_interrupt.S | 2 +- ports/linux/gnu/src/tx_thread_stack_build.c | 2 +- ports/risc-v32/gnu/src/tx_thread_context_save.S | 2 +- ports/risc-v32/iar/src/tx_thread_context_save.s | 2 +- ports/risc-v64/gnu/inc/tx_port.h | 2 +- ports/risc-v64/gnu/src/tx_thread_context_save.S | 2 +- ports/win32/vs_2019/inc/tx_port.h | 2 +- ports/win32/vs_2019/src/tx_initialize_low_level.c | 3 +-- ports/win32/vs_2019/src/tx_thread_context_restore.c | 2 +- ports/win32/vs_2019/src/tx_thread_context_save.c | 2 +- ports/win32/vs_2019/src/tx_thread_interrupt_control.c | 2 +- ports/win32/vs_2019/src/tx_thread_schedule.c | 2 +- ports/win32/vs_2019/src/tx_thread_stack_build.c | 3 +-- ports/win32/vs_2019/src/tx_thread_system_return.c | 2 +- ports/win64/vs_2022/inc/tx_port.h | 2 +- ports/win64/vs_2022/src/tx_initialize_low_level.c | 3 +-- ports/win64/vs_2022/src/tx_thread_context_restore.c | 3 +-- ports/win64/vs_2022/src/tx_thread_interrupt_control.c | 2 +- ports/win64/vs_2022/src/tx_thread_schedule.c | 3 +-- ports/win64/vs_2022/src/tx_thread_stack_build.c | 4 +--- ports/win64/vs_2022/src/tx_thread_system_return.c | 3 +-- .../ARMv7-A/threadx/common/src/tx_thread_system_return.S | 2 +- .../threadx/ac5/example_build/tx_initialize_low_level.s | 2 +- ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_schedule.s | 2 +- .../example_build/sample_threadx/tx_initialize_low_level.S | 2 +- ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_schedule.S | 3 +-- ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_system_return.S | 2 +- .../threadx/gnu/example_build/tx_initialize_low_level.S | 2 +- ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_schedule.S | 3 +-- ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_system_return.S | 2 +- .../threadx/iar/example_build/tx_initialize_low_level.s | 2 +- ports_arch/ARMv7-M/threadx/iar/src/tx_iar.c | 2 +- ports_arch/ARMv7-M/threadx/iar/src/tx_thread_schedule.s | 2 +- ports_arch/ARMv7-M/threadx/iar/src/tx_thread_system_return.s | 2 +- ports_arch/ARMv7-M/threadx/inc/tx_port.h | 5 +---- .../ac5/module_manager/src/tx_thread_schedule.s | 2 +- .../ac6/module_manager/src/tx_thread_schedule.S | 3 +-- .../gnu/module_manager/src/tx_thread_schedule.S | 3 +-- .../ARMv7-M/threadx_modules/iar/module_manager/src/tx_iar.c | 2 +- .../iar/module_manager/src/tx_thread_schedule.s | 2 +- .../ARMv8-A/threadx/ports/gnu/src/tx_initialize_low_level.S | 2 +- .../ARMv8-A/threadx_smp/common/src/tx_thread_smp_time_get.S | 2 +- ports_arch/ARMv8-M/threadx/ac6/src/tx_initialize_low_level.S | 2 +- ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_schedule.S | 3 +-- ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_system_return.S | 2 +- ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_schedule.S | 3 +-- ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_system_return.S | 2 +- ports_arch/ARMv8-M/threadx/iar/src/tx_iar.c | 2 +- ports_arch/ARMv8-M/threadx/iar/src/tx_initialize_low_level.s | 2 +- ports_arch/ARMv8-M/threadx/iar/src/tx_thread_schedule.s | 2 +- ports_arch/ARMv8-M/threadx/iar/src/tx_thread_system_return.s | 2 +- ports_arch/ARMv8-M/threadx/inc/tx_port.h | 4 +--- .../sample_threadx_module_manager.c | 2 +- .../example_build/sample_threadx/tx_initialize_low_level.S | 2 +- .../sample_threadx_module_manager.c | 2 +- .../sample_threadx_module_manager/tx_initialize_low_level.S | 2 +- .../sample_threadx_module_manager.c | 2 +- .../sample_threadx_module_manager.c | 2 +- .../gnu/module_manager/src/tx_thread_system_return.S | 2 +- ports_module/cortex_a7/iar/module_manager/src/tx_iar.c | 2 +- .../iar/module_manager/src/tx_thread_system_return.s | 2 +- .../example_build/sample_threadx/tx_initialize_low_level.S | 2 +- .../sample_threadx_module_manager/tx_initialize_low_level.S | 2 +- .../example_build/sample_threadx/tx_initialize_low_level.S | 2 +- .../gnu/example_build/sample_threadx_module/gcc_setup.s | 2 +- .../sample_threadx_module_manager/tx_initialize_low_level.S | 2 +- .../cortex_m0+/iar/example_build/tx_initialize_low_level.s | 2 +- ports_module/cortex_m0+/iar/module_manager/src/tx_iar.c | 2 +- .../cortex_m23/ac6/example_build/tx_initialize_low_level.S | 2 +- .../gnu/module_manager/src/tx_initialize_low_level.S | 3 +-- .../gnu/module_manager/src/tx_thread_context_restore.S | 2 +- .../gnu/module_manager/src/tx_thread_context_save.S | 2 +- .../module_manager/src/tx_thread_secure_stack_initialize.S | 2 +- .../cortex_m23/iar/example_build/tx_initialize_low_level.s | 2 +- .../cortex_m3/ac5/example_build/tx_initialize_low_level.S | 2 +- .../cortex_m3/ac5/module_manager/src/tx_thread_schedule.s | 2 +- .../example_build/sample_threadx/tx_initialize_low_level.S | 2 +- .../sample_threadx_module_manager/tx_initialize_low_level.S | 2 +- .../cortex_m3/ac6/module_manager/src/tx_thread_schedule.S | 3 +-- .../ac6/module_manager/src/tx_thread_system_return.S | 2 +- ports_module/cortex_m3/gnu/example_build/gcc_setup.s | 2 +- .../cortex_m3/gnu/example_build/tx_initialize_low_level.S | 2 +- .../cortex_m3/gnu/module_manager/src/tx_thread_schedule.S | 3 +-- .../gnu/module_manager/src/tx_thread_system_return.S | 2 +- .../cortex_m3/iar/example_build/tx_initialize_low_level.s | 2 +- ports_module/cortex_m3/iar/module_manager/src/tx_iar.c | 2 +- .../cortex_m3/iar/module_manager/src/tx_thread_schedule.s | 2 +- .../iar/module_manager/src/tx_thread_system_return.s | 2 +- .../cortex_m33/ac6/example_build/tx_initialize_low_level.S | 2 +- .../cortex_m33/ac6/module_manager/src/tx_thread_schedule.S | 3 +-- ports_module/cortex_m33/gnu/example_build/gcc_setup.s | 2 +- .../gnu/module_manager/src/tx_initialize_low_level.S | 2 +- .../cortex_m33/gnu/module_manager/src/tx_thread_schedule.S | 3 +-- .../cortex_m33/iar/example_build/tx_initialize_low_level.s | 2 +- .../cortex_m33/iar/module_manager/src/tx_thread_schedule.s | 2 +- .../cortex_m4/ac5/example_build/tx_initialize_low_level.S | 2 +- .../cortex_m4/ac5/module_manager/src/tx_thread_schedule.s | 2 +- .../example_build/sample_threadx/tx_initialize_low_level.S | 2 +- .../sample_threadx_module_manager/tx_initialize_low_level.S | 2 +- .../cortex_m4/ac6/module_manager/src/tx_thread_schedule.S | 3 +-- .../ac6/module_manager/src/tx_thread_system_return.S | 2 +- ports_module/cortex_m4/gnu/example_build/gcc_setup.s | 2 +- .../cortex_m4/gnu/example_build/tx_initialize_low_level.S | 2 +- .../cortex_m4/gnu/module_manager/src/tx_thread_schedule.S | 3 +-- .../gnu/module_manager/src/tx_thread_system_return.S | 2 +- .../cortex_m4/iar/example_build/tx_initialize_low_level.s | 2 +- ports_module/cortex_m4/iar/module_manager/src/tx_iar.c | 2 +- .../cortex_m4/iar/module_manager/src/tx_thread_schedule.s | 2 +- .../iar/module_manager/src/tx_thread_system_return.s | 2 +- .../cortex_m7/ac5/example_build/tx_initialize_low_level.S | 2 +- .../cortex_m7/ac5/module_manager/src/tx_thread_schedule.s | 2 +- .../example_build/sample_threadx/tx_initialize_low_level.S | 2 +- .../sample_threadx_module_manager/tx_initialize_low_level.S | 2 +- .../cortex_m7/ac6/module_manager/src/tx_thread_schedule.S | 3 +-- .../ac6/module_manager/src/tx_thread_system_return.S | 2 +- ports_module/cortex_m7/gnu/example_build/gcc_setup.s | 2 +- .../cortex_m7/gnu/example_build/tx_initialize_low_level.S | 2 +- .../cortex_m7/gnu/module_manager/src/tx_thread_schedule.S | 3 +-- .../gnu/module_manager/src/tx_thread_system_return.S | 2 +- .../cortex_m7/iar/example_build/tx_initialize_low_level.s | 2 +- ports_module/cortex_m7/iar/module_manager/src/tx_iar.c | 2 +- .../cortex_m7/iar/module_manager/src/tx_thread_schedule.s | 2 +- .../iar/module_manager/src/tx_thread_system_return.s | 2 +- .../cortex_r4/ac6/module_manager/src/tx_thread_stack_build.S | 2 +- ports_module/cortex_r4/iar/module_manager/src/tx_iar.c | 2 +- ports_smp/arc_hs_smp/metaware/src/tx_thread_context_save.s | 2 +- ports_smp/cortex_a34_smp/ac6/src/tx_thread_smp_time_get.S | 2 +- ports_smp/cortex_a34_smp/gnu/src/tx_thread_smp_time_get.S | 2 +- ports_smp/cortex_a35_smp/ac6/src/tx_thread_smp_time_get.S | 2 +- ports_smp/cortex_a35_smp/gnu/src/tx_thread_smp_time_get.S | 2 +- ports_smp/cortex_a53_smp/ac6/src/tx_thread_smp_time_get.S | 2 +- ports_smp/cortex_a53_smp/gnu/src/tx_thread_smp_time_get.S | 2 +- ports_smp/cortex_a55_smp/ac6/src/tx_thread_smp_time_get.S | 2 +- ports_smp/cortex_a55_smp/gnu/src/tx_thread_smp_time_get.S | 2 +- ports_smp/cortex_a57_smp/ac6/src/tx_thread_smp_time_get.S | 2 +- ports_smp/cortex_a57_smp/gnu/src/tx_thread_smp_time_get.S | 2 +- ports_smp/cortex_a5_smp/ac5/src/tx_thread_context_restore.s | 2 +- ports_smp/cortex_a5_smp/ac5/src/tx_thread_context_save.s | 2 +- ports_smp/cortex_a5_smp/ac5/src/tx_thread_schedule.s | 2 +- ports_smp/cortex_a5_smp/ac5/src/tx_thread_smp_protect.s | 2 +- ports_smp/cortex_a5_smp/ac5/src/tx_thread_smp_time_get.s | 2 +- ports_smp/cortex_a5_smp/ac5/src/tx_thread_smp_unprotect.s | 2 +- ports_smp/cortex_a5_smp/ac5/src/tx_thread_system_return.s | 2 +- .../cortex_a5_smp/ac5/src/tx_thread_vectored_context_save.s | 2 +- ports_smp/cortex_a5_smp/gnu/src/tx_thread_context_restore.S | 2 +- ports_smp/cortex_a5_smp/gnu/src/tx_thread_context_save.S | 2 +- ports_smp/cortex_a5_smp/gnu/src/tx_thread_schedule.S | 2 +- ports_smp/cortex_a5_smp/gnu/src/tx_thread_smp_protect.S | 2 +- ports_smp/cortex_a5_smp/gnu/src/tx_thread_smp_time_get.S | 2 +- ports_smp/cortex_a5_smp/gnu/src/tx_thread_smp_unprotect.S | 2 +- ports_smp/cortex_a5_smp/gnu/src/tx_thread_system_return.S | 2 +- .../cortex_a5_smp/gnu/src/tx_thread_vectored_context_save.S | 2 +- ports_smp/cortex_a5x_smp/ac6/src/tx_thread_smp_time_get.S | 2 +- ports_smp/cortex_a5x_smp/gnu/src/tx_thread_smp_time_get.S | 2 +- ports_smp/cortex_a5x_smp/iar/src/tx_thread_smp_time_get.S | 2 +- ports_smp/cortex_a65_smp/ac6/src/tx_thread_smp_time_get.S | 2 +- ports_smp/cortex_a65_smp/gnu/src/tx_thread_smp_time_get.S | 2 +- ports_smp/cortex_a65ae_smp/ac6/src/tx_thread_smp_time_get.S | 2 +- ports_smp/cortex_a65ae_smp/gnu/src/tx_thread_smp_time_get.S | 2 +- ports_smp/cortex_a72_smp/ac6/src/tx_thread_smp_time_get.S | 2 +- ports_smp/cortex_a72_smp/gnu/src/tx_thread_smp_time_get.S | 2 +- ports_smp/cortex_a73_smp/ac6/src/tx_thread_smp_time_get.S | 2 +- ports_smp/cortex_a73_smp/gnu/src/tx_thread_smp_time_get.S | 2 +- ports_smp/cortex_a75_smp/ac6/src/tx_thread_smp_time_get.S | 2 +- ports_smp/cortex_a75_smp/gnu/src/tx_thread_smp_time_get.S | 2 +- ports_smp/cortex_a76_smp/ac6/src/tx_thread_smp_time_get.S | 2 +- ports_smp/cortex_a76_smp/gnu/src/tx_thread_smp_time_get.S | 2 +- ports_smp/cortex_a76ae_smp/ac6/src/tx_thread_smp_time_get.S | 2 +- ports_smp/cortex_a76ae_smp/gnu/src/tx_thread_smp_time_get.S | 2 +- ports_smp/cortex_a77_smp/ac6/src/tx_thread_smp_time_get.S | 2 +- ports_smp/cortex_a77_smp/gnu/src/tx_thread_smp_time_get.S | 2 +- ports_smp/cortex_a78_smp/ac6/src/tx_thread_smp_time_get.S | 2 +- ports_smp/cortex_a78_smp/gnu/src/tx_thread_smp_time_get.S | 2 +- ports_smp/cortex_a7_smp/ac5/src/tx_thread_context_restore.s | 2 +- ports_smp/cortex_a7_smp/ac5/src/tx_thread_context_save.s | 2 +- ports_smp/cortex_a7_smp/ac5/src/tx_thread_schedule.s | 2 +- ports_smp/cortex_a7_smp/ac5/src/tx_thread_smp_protect.s | 2 +- ports_smp/cortex_a7_smp/ac5/src/tx_thread_smp_time_get.s | 2 +- ports_smp/cortex_a7_smp/ac5/src/tx_thread_smp_unprotect.s | 2 +- ports_smp/cortex_a7_smp/ac5/src/tx_thread_system_return.s | 2 +- .../cortex_a7_smp/ac5/src/tx_thread_vectored_context_save.s | 2 +- ports_smp/cortex_a7_smp/gnu/src/tx_thread_context_restore.S | 2 +- ports_smp/cortex_a7_smp/gnu/src/tx_thread_context_save.S | 2 +- ports_smp/cortex_a7_smp/gnu/src/tx_thread_schedule.S | 2 +- ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_protect.S | 2 +- ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_time_get.S | 2 +- ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_unprotect.S | 2 +- ports_smp/cortex_a7_smp/gnu/src/tx_thread_system_return.S | 2 +- .../cortex_a7_smp/gnu/src/tx_thread_vectored_context_save.S | 2 +- ports_smp/cortex_a9_smp/ac5/src/tx_thread_context_restore.s | 2 +- ports_smp/cortex_a9_smp/ac5/src/tx_thread_context_save.s | 2 +- ports_smp/cortex_a9_smp/ac5/src/tx_thread_schedule.s | 2 +- ports_smp/cortex_a9_smp/ac5/src/tx_thread_smp_protect.s | 2 +- ports_smp/cortex_a9_smp/ac5/src/tx_thread_smp_time_get.s | 2 +- ports_smp/cortex_a9_smp/ac5/src/tx_thread_smp_unprotect.s | 2 +- ports_smp/cortex_a9_smp/ac5/src/tx_thread_system_return.s | 2 +- .../cortex_a9_smp/ac5/src/tx_thread_vectored_context_save.s | 2 +- ports_smp/cortex_a9_smp/gnu/src/tx_thread_context_restore.S | 2 +- ports_smp/cortex_a9_smp/gnu/src/tx_thread_context_save.S | 2 +- ports_smp/cortex_a9_smp/gnu/src/tx_thread_schedule.S | 2 +- ports_smp/cortex_a9_smp/gnu/src/tx_thread_smp_protect.S | 2 +- ports_smp/cortex_a9_smp/gnu/src/tx_thread_smp_time_get.S | 2 +- ports_smp/cortex_a9_smp/gnu/src/tx_thread_smp_unprotect.S | 2 +- ports_smp/cortex_a9_smp/gnu/src/tx_thread_system_return.S | 2 +- .../cortex_a9_smp/gnu/src/tx_thread_vectored_context_save.S | 2 +- ports_smp/cortex_r8_smp/ac5/src/tx_thread_context_save.s | 2 +- ports_smp/cortex_r8_smp/ac5/src/tx_thread_smp_time_get.s | 2 +- ports_smp/cortex_r8_smp/ac5/src/tx_thread_system_return.s | 2 +- .../cortex_r8_smp/ac5/src/tx_thread_vectored_context_save.s | 2 +- ports_smp/linux/gnu/src/tx_thread_stack_build.c | 2 +- ports_smp/win64/vs_2022/src/tx_initialize_low_level.c | 3 +-- ports_smp/win64/vs_2022/src/tx_thread_context_restore.c | 3 +-- ports_smp/win64/vs_2022/src/tx_thread_context_save.c | 3 +-- ports_smp/win64/vs_2022/src/tx_thread_schedule.c | 2 +- ports_smp/win64/vs_2022/src/tx_thread_smp_core_preempt.c | 2 +- .../win64/vs_2022/src/tx_thread_smp_current_state_get.c | 2 +- .../win64/vs_2022/src/tx_thread_smp_current_thread_get.c | 2 +- ports_smp/win64/vs_2022/src/tx_thread_smp_protect.c | 2 +- ports_smp/win64/vs_2022/src/tx_thread_smp_unprotect.c | 2 +- ports_smp/win64/vs_2022/src/tx_thread_stack_build.c | 2 +- ports_smp/win64/vs_2022/src/tx_thread_system_return.c | 2 +- test/smp/regression/testcontrol.c | 4 +--- .../threadx_block_memory_suspension_timeout_test.c | 2 +- .../regression/threadx_byte_memory_suspension_timeout_test.c | 2 +- .../threadx_smp_random_resume_suspend_exclusion_pt_test.c | 2 +- test/smp/regression/threadx_smp_time_slice_test.c | 2 +- test/smp/regression/threadx_thread_multiple_sleep_test.c | 2 +- test/smp/regression/threadx_thread_stack_checking_test.c | 2 +- test/smp/regression/threadx_thread_stack_fill_value_test.c | 2 +- test/tx/cmake/riscv/bsp/tx_initialize_low_level.S | 2 +- test/tx/regression/testcontrol.c | 3 +-- test/tx/regression/threadx_initialize_kernel_setup_test.c | 2 +- test/tx/regression/threadx_thread_basic_execution_test.c | 2 +- test/tx/regression/threadx_thread_stack_checking_test.c | 2 +- test/tx/regression/threadx_thread_stack_fill_value_test.c | 2 +- test/tx/regression/threadx_trace_entry_update_test.c | 2 +- .../execution_profile_kit/smp_version/tx_execution_profile.c | 2 +- utility/rtos_compatibility_layers/FreeRTOS/tx_freertos.c | 2 +- utility/rtos_compatibility_layers/posix/px_cond_broadcast.c | 2 +- utility/rtos_compatibility_layers/posix/px_cond_destroy.c | 2 +- utility/rtos_compatibility_layers/posix/px_cond_init.c | 2 +- utility/rtos_compatibility_layers/posix/px_cond_signal.c | 2 +- 455 files changed, 455 insertions(+), 574 deletions(-) diff --git a/common/src/tx_thread_create.c b/common/src/tx_thread_create.c index 37b4d3e2d..7c9d054c3 100644 --- a/common/src/tx_thread_create.c +++ b/common/src/tx_thread_create.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/common/src/tx_thread_delete.c b/common/src/tx_thread_delete.c index e73fdd319..5bbb12c36 100644 --- a/common/src/tx_thread_delete.c +++ b/common/src/tx_thread_delete.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Claude Code (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/common/src/tx_thread_reset.c b/common/src/tx_thread_reset.c index e87de26be..8e59f1e7e 100644 --- a/common/src/tx_thread_reset.c +++ b/common/src/tx_thread_reset.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Claude Code (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/common/src/tx_thread_shell_entry.c b/common/src/tx_thread_shell_entry.c index c079f18e1..2a16a00b6 100644 --- a/common/src/tx_thread_shell_entry.c +++ b/common/src/tx_thread_shell_entry.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Claude Code (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/common/src/tx_thread_sleep.c b/common/src/tx_thread_sleep.c index fb04f3375..9e3a0afdf 100644 --- a/common/src/tx_thread_sleep.c +++ b/common/src/tx_thread_sleep.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/common/src/tx_thread_stack_analyze.c b/common/src/tx_thread_stack_analyze.c index 37a5ac2d0..ecd7ee13b 100644 --- a/common/src/tx_thread_stack_analyze.c +++ b/common/src/tx_thread_stack_analyze.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/common/src/tx_thread_terminate.c b/common/src/tx_thread_terminate.c index 05ec91a1f..c87efaa0d 100644 --- a/common/src/tx_thread_terminate.c +++ b/common/src/tx_thread_terminate.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Claude Code (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/common/src/txe_timer_change.c b/common/src/txe_timer_change.c index 91b104d08..7f6d6a36b 100644 --- a/common/src/txe_timer_change.c +++ b/common/src/txe_timer_change.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/common_modules/inc/txm_module.h b/common_modules/inc/txm_module.h index 889f43ed0..4e84dcbb0 100644 --- a/common_modules/inc/txm_module.h +++ b/common_modules/inc/txm_module.h @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/common_modules/module_manager/inc/txm_module_manager_dispatch.h b/common_modules/module_manager/inc/txm_module_manager_dispatch.h index 03ba6ea53..3763d35db 100644 --- a/common_modules/module_manager/inc/txm_module_manager_dispatch.h +++ b/common_modules/module_manager/inc/txm_module_manager_dispatch.h @@ -8,8 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/common_modules/module_manager/src/txm_module_manager_absolute_load.c b/common_modules/module_manager/src/txm_module_manager_absolute_load.c index caa94719d..3fc060001 100644 --- a/common_modules/module_manager/src/txm_module_manager_absolute_load.c +++ b/common_modules/module_manager/src/txm_module_manager_absolute_load.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/common_modules/module_manager/src/txm_module_manager_absolute_load_extended.c b/common_modules/module_manager/src/txm_module_manager_absolute_load_extended.c index 77b356789..874cd1d65 100644 --- a/common_modules/module_manager/src/txm_module_manager_absolute_load_extended.c +++ b/common_modules/module_manager/src/txm_module_manager_absolute_load_extended.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/common_modules/module_manager/src/txm_module_manager_thread_create.c b/common_modules/module_manager/src/txm_module_manager_thread_create.c index fdb0e768a..1f9bbc470 100644 --- a/common_modules/module_manager/src/txm_module_manager_thread_create.c +++ b/common_modules/module_manager/src/txm_module_manager_thread_create.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/common_modules/module_manager/utilities/module_binary_to_c_array.c b/common_modules/module_manager/utilities/module_binary_to_c_array.c index 38b38c327..e418fbc13 100644 --- a/common_modules/module_manager/utilities/module_binary_to_c_array.c +++ b/common_modules/module_manager/utilities/module_binary_to_c_array.c @@ -9,7 +9,7 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ -// Some portions generated by Claude Code (Opus 5) +// Portions of this file were generated with AI assistance. #include #include diff --git a/common_modules/module_manager/utilities/module_to_binary.c b/common_modules/module_manager/utilities/module_to_binary.c index b691d9e40..0b159cd78 100644 --- a/common_modules/module_manager/utilities/module_to_binary.c +++ b/common_modules/module_manager/utilities/module_to_binary.c @@ -9,7 +9,7 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ -// Some portions generated by Claude Code (Opus 5) +// Portions of this file were generated with AI assistance. #include #include diff --git a/common_modules/module_manager/utilities/module_to_c_array.c b/common_modules/module_manager/utilities/module_to_c_array.c index 554d13ba8..72e87de0d 100644 --- a/common_modules/module_manager/utilities/module_to_c_array.c +++ b/common_modules/module_manager/utilities/module_to_c_array.c @@ -9,7 +9,7 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ -// Some portions generated by Claude Code (Opus 5) +// Portions of this file were generated with AI assistance. #include #include diff --git a/common_smp/inc/tx_thread.h b/common_smp/inc/tx_thread.h index 64998a694..1ffe88287 100644 --- a/common_smp/inc/tx_thread.h +++ b/common_smp/inc/tx_thread.h @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/common_smp/src/tx_thread_create.c b/common_smp/src/tx_thread_create.c index 05019ab8b..d7c8f507f 100644 --- a/common_smp/src/tx_thread_create.c +++ b/common_smp/src/tx_thread_create.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/common_smp/src/tx_thread_delete.c b/common_smp/src/tx_thread_delete.c index e73fdd319..5bbb12c36 100644 --- a/common_smp/src/tx_thread_delete.c +++ b/common_smp/src/tx_thread_delete.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Claude Code (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/common_smp/src/tx_thread_reset.c b/common_smp/src/tx_thread_reset.c index e87de26be..8e59f1e7e 100644 --- a/common_smp/src/tx_thread_reset.c +++ b/common_smp/src/tx_thread_reset.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Claude Code (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/common_smp/src/tx_thread_shell_entry.c b/common_smp/src/tx_thread_shell_entry.c index c079f18e1..2a16a00b6 100644 --- a/common_smp/src/tx_thread_shell_entry.c +++ b/common_smp/src/tx_thread_shell_entry.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Claude Code (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/common_smp/src/tx_thread_sleep.c b/common_smp/src/tx_thread_sleep.c index fb04f3375..9e3a0afdf 100644 --- a/common_smp/src/tx_thread_sleep.c +++ b/common_smp/src/tx_thread_sleep.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/common_smp/src/tx_thread_smp_utilities.c b/common_smp/src/tx_thread_smp_utilities.c index cb31e33a9..0569a8192 100644 --- a/common_smp/src/tx_thread_smp_utilities.c +++ b/common_smp/src/tx_thread_smp_utilities.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/common_smp/src/tx_thread_stack_analyze.c b/common_smp/src/tx_thread_stack_analyze.c index 37a5ac2d0..ecd7ee13b 100644 --- a/common_smp/src/tx_thread_stack_analyze.c +++ b/common_smp/src/tx_thread_stack_analyze.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/common_smp/src/tx_thread_terminate.c b/common_smp/src/tx_thread_terminate.c index 05ec91a1f..c87efaa0d 100644 --- a/common_smp/src/tx_thread_terminate.c +++ b/common_smp/src/tx_thread_terminate.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Claude Code (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/common_smp/src/txe_timer_change.c b/common_smp/src/txe_timer_change.c index 91b104d08..7f6d6a36b 100644 --- a/common_smp/src/txe_timer_change.c +++ b/common_smp/src/txe_timer_change.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/arc_em/metaware/src/tx_thread_context_save.s b/ports/arc_em/metaware/src/tx_thread_context_save.s index 93b57d231..e8a4bf518 100644 --- a/ports/arc_em/metaware/src/tx_thread_context_save.s +++ b/ports/arc_em/metaware/src/tx_thread_context_save.s @@ -9,7 +9,7 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ -; Some portions generated by Copilot (Opus 5). +; Portions of this file were generated with AI assistance. ;/**************************************************************************/ ;/**************************************************************************/ diff --git a/ports/arc_hs/metaware/src/tx_thread_context_save.s b/ports/arc_hs/metaware/src/tx_thread_context_save.s index 0c4330106..17cff059f 100644 --- a/ports/arc_hs/metaware/src/tx_thread_context_save.s +++ b/ports/arc_hs/metaware/src/tx_thread_context_save.s @@ -9,7 +9,7 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ -; Some portions generated by Copilot (Opus 5). +; Portions of this file were generated with AI assistance. ;/**************************************************************************/ ;/**************************************************************************/ diff --git a/ports/arm11/iar/src/tx_iar.c b/ports/arm11/iar/src/tx_iar.c index ddfdaf3dd..ab6c209cc 100644 --- a/ports/arm11/iar/src/tx_iar.c +++ b/ports/arm11/iar/src/tx_iar.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/arm9/iar/src/tx_iar.c b/ports/arm9/iar/src/tx_iar.c index ddfdaf3dd..ab6c209cc 100644 --- a/ports/arm9/iar/src/tx_iar.c +++ b/ports/arm9/iar/src/tx_iar.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/cortex_a12/ac6/src/tx_thread_system_return.S b/ports/cortex_a12/ac6/src/tx_thread_system_return.S index 9aa7e0e50..7671bba27 100644 --- a/ports/cortex_a12/ac6/src/tx_thread_system_return.S +++ b/ports/cortex_a12/ac6/src/tx_thread_system_return.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/cortex_a12/gnu/src/tx_thread_system_return.S b/ports/cortex_a12/gnu/src/tx_thread_system_return.S index 9aa7e0e50..7671bba27 100644 --- a/ports/cortex_a12/gnu/src/tx_thread_system_return.S +++ b/ports/cortex_a12/gnu/src/tx_thread_system_return.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/cortex_a15/ac6/src/tx_thread_system_return.S b/ports/cortex_a15/ac6/src/tx_thread_system_return.S index 9aa7e0e50..7671bba27 100644 --- a/ports/cortex_a15/ac6/src/tx_thread_system_return.S +++ b/ports/cortex_a15/ac6/src/tx_thread_system_return.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/cortex_a15/gnu/src/tx_thread_system_return.S b/ports/cortex_a15/gnu/src/tx_thread_system_return.S index 9aa7e0e50..7671bba27 100644 --- a/ports/cortex_a15/gnu/src/tx_thread_system_return.S +++ b/ports/cortex_a15/gnu/src/tx_thread_system_return.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/cortex_a15/iar/src/tx_iar.c b/ports/cortex_a15/iar/src/tx_iar.c index ddfdaf3dd..ab6c209cc 100644 --- a/ports/cortex_a15/iar/src/tx_iar.c +++ b/ports/cortex_a15/iar/src/tx_iar.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/cortex_a17/ac6/src/tx_thread_system_return.S b/ports/cortex_a17/ac6/src/tx_thread_system_return.S index 9aa7e0e50..7671bba27 100644 --- a/ports/cortex_a17/ac6/src/tx_thread_system_return.S +++ b/ports/cortex_a17/ac6/src/tx_thread_system_return.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/cortex_a17/gnu/src/tx_thread_system_return.S b/ports/cortex_a17/gnu/src/tx_thread_system_return.S index 9aa7e0e50..7671bba27 100644 --- a/ports/cortex_a17/gnu/src/tx_thread_system_return.S +++ b/ports/cortex_a17/gnu/src/tx_thread_system_return.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/cortex_a34/gnu/src/tx_initialize_low_level.S b/ports/cortex_a34/gnu/src/tx_initialize_low_level.S index 07e4ea111..f86568c5d 100644 --- a/ports/cortex_a34/gnu/src/tx_initialize_low_level.S +++ b/ports/cortex_a34/gnu/src/tx_initialize_low_level.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/cortex_a35/gnu/src/tx_initialize_low_level.S b/ports/cortex_a35/gnu/src/tx_initialize_low_level.S index 07e4ea111..f86568c5d 100644 --- a/ports/cortex_a35/gnu/src/tx_initialize_low_level.S +++ b/ports/cortex_a35/gnu/src/tx_initialize_low_level.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/cortex_a5/ac6/src/tx_thread_system_return.S b/ports/cortex_a5/ac6/src/tx_thread_system_return.S index 9aa7e0e50..7671bba27 100644 --- a/ports/cortex_a5/ac6/src/tx_thread_system_return.S +++ b/ports/cortex_a5/ac6/src/tx_thread_system_return.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/cortex_a5/gnu/src/tx_thread_system_return.S b/ports/cortex_a5/gnu/src/tx_thread_system_return.S index 9aa7e0e50..7671bba27 100644 --- a/ports/cortex_a5/gnu/src/tx_thread_system_return.S +++ b/ports/cortex_a5/gnu/src/tx_thread_system_return.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/cortex_a5/iar/src/tx_iar.c b/ports/cortex_a5/iar/src/tx_iar.c index ddfdaf3dd..ab6c209cc 100644 --- a/ports/cortex_a5/iar/src/tx_iar.c +++ b/ports/cortex_a5/iar/src/tx_iar.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/cortex_a53/gnu/src/tx_initialize_low_level.S b/ports/cortex_a53/gnu/src/tx_initialize_low_level.S index 07e4ea111..f86568c5d 100644 --- a/ports/cortex_a53/gnu/src/tx_initialize_low_level.S +++ b/ports/cortex_a53/gnu/src/tx_initialize_low_level.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/cortex_a55/gnu/src/tx_initialize_low_level.S b/ports/cortex_a55/gnu/src/tx_initialize_low_level.S index 07e4ea111..f86568c5d 100644 --- a/ports/cortex_a55/gnu/src/tx_initialize_low_level.S +++ b/ports/cortex_a55/gnu/src/tx_initialize_low_level.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/cortex_a57/gnu/src/tx_initialize_low_level.S b/ports/cortex_a57/gnu/src/tx_initialize_low_level.S index 07e4ea111..f86568c5d 100644 --- a/ports/cortex_a57/gnu/src/tx_initialize_low_level.S +++ b/ports/cortex_a57/gnu/src/tx_initialize_low_level.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/cortex_a65/gnu/src/tx_initialize_low_level.S b/ports/cortex_a65/gnu/src/tx_initialize_low_level.S index 07e4ea111..f86568c5d 100644 --- a/ports/cortex_a65/gnu/src/tx_initialize_low_level.S +++ b/ports/cortex_a65/gnu/src/tx_initialize_low_level.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/cortex_a65ae/gnu/src/tx_initialize_low_level.S b/ports/cortex_a65ae/gnu/src/tx_initialize_low_level.S index 07e4ea111..f86568c5d 100644 --- a/ports/cortex_a65ae/gnu/src/tx_initialize_low_level.S +++ b/ports/cortex_a65ae/gnu/src/tx_initialize_low_level.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/cortex_a7/ac6/src/tx_thread_system_return.S b/ports/cortex_a7/ac6/src/tx_thread_system_return.S index 9aa7e0e50..7671bba27 100644 --- a/ports/cortex_a7/ac6/src/tx_thread_system_return.S +++ b/ports/cortex_a7/ac6/src/tx_thread_system_return.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/cortex_a7/gnu/src/tx_thread_system_return.S b/ports/cortex_a7/gnu/src/tx_thread_system_return.S index 9aa7e0e50..7671bba27 100644 --- a/ports/cortex_a7/gnu/src/tx_thread_system_return.S +++ b/ports/cortex_a7/gnu/src/tx_thread_system_return.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/cortex_a7/iar/src/tx_iar.c b/ports/cortex_a7/iar/src/tx_iar.c index ddfdaf3dd..ab6c209cc 100644 --- a/ports/cortex_a7/iar/src/tx_iar.c +++ b/ports/cortex_a7/iar/src/tx_iar.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/cortex_a72/gnu/src/tx_initialize_low_level.S b/ports/cortex_a72/gnu/src/tx_initialize_low_level.S index 07e4ea111..f86568c5d 100644 --- a/ports/cortex_a72/gnu/src/tx_initialize_low_level.S +++ b/ports/cortex_a72/gnu/src/tx_initialize_low_level.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/cortex_a73/gnu/src/tx_initialize_low_level.S b/ports/cortex_a73/gnu/src/tx_initialize_low_level.S index 07e4ea111..f86568c5d 100644 --- a/ports/cortex_a73/gnu/src/tx_initialize_low_level.S +++ b/ports/cortex_a73/gnu/src/tx_initialize_low_level.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/cortex_a75/gnu/src/tx_initialize_low_level.S b/ports/cortex_a75/gnu/src/tx_initialize_low_level.S index 07e4ea111..f86568c5d 100644 --- a/ports/cortex_a75/gnu/src/tx_initialize_low_level.S +++ b/ports/cortex_a75/gnu/src/tx_initialize_low_level.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/cortex_a76/gnu/src/tx_initialize_low_level.S b/ports/cortex_a76/gnu/src/tx_initialize_low_level.S index 07e4ea111..f86568c5d 100644 --- a/ports/cortex_a76/gnu/src/tx_initialize_low_level.S +++ b/ports/cortex_a76/gnu/src/tx_initialize_low_level.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/cortex_a76ae/gnu/src/tx_initialize_low_level.S b/ports/cortex_a76ae/gnu/src/tx_initialize_low_level.S index 07e4ea111..f86568c5d 100644 --- a/ports/cortex_a76ae/gnu/src/tx_initialize_low_level.S +++ b/ports/cortex_a76ae/gnu/src/tx_initialize_low_level.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/cortex_a77/gnu/src/tx_initialize_low_level.S b/ports/cortex_a77/gnu/src/tx_initialize_low_level.S index 07e4ea111..f86568c5d 100644 --- a/ports/cortex_a77/gnu/src/tx_initialize_low_level.S +++ b/ports/cortex_a77/gnu/src/tx_initialize_low_level.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/cortex_a8/ac6/src/tx_thread_system_return.S b/ports/cortex_a8/ac6/src/tx_thread_system_return.S index 9aa7e0e50..7671bba27 100644 --- a/ports/cortex_a8/ac6/src/tx_thread_system_return.S +++ b/ports/cortex_a8/ac6/src/tx_thread_system_return.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/cortex_a8/gnu/src/tx_thread_system_return.S b/ports/cortex_a8/gnu/src/tx_thread_system_return.S index 9aa7e0e50..7671bba27 100644 --- a/ports/cortex_a8/gnu/src/tx_thread_system_return.S +++ b/ports/cortex_a8/gnu/src/tx_thread_system_return.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/cortex_a8/iar/src/tx_iar.c b/ports/cortex_a8/iar/src/tx_iar.c index ddfdaf3dd..ab6c209cc 100644 --- a/ports/cortex_a8/iar/src/tx_iar.c +++ b/ports/cortex_a8/iar/src/tx_iar.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/cortex_a9/ac6/src/tx_thread_system_return.S b/ports/cortex_a9/ac6/src/tx_thread_system_return.S index 9aa7e0e50..7671bba27 100644 --- a/ports/cortex_a9/ac6/src/tx_thread_system_return.S +++ b/ports/cortex_a9/ac6/src/tx_thread_system_return.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/cortex_a9/gnu/src/tx_thread_system_return.S b/ports/cortex_a9/gnu/src/tx_thread_system_return.S index 9aa7e0e50..7671bba27 100644 --- a/ports/cortex_a9/gnu/src/tx_thread_system_return.S +++ b/ports/cortex_a9/gnu/src/tx_thread_system_return.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/cortex_a9/iar/src/tx_iar.c b/ports/cortex_a9/iar/src/tx_iar.c index ddfdaf3dd..ab6c209cc 100644 --- a/ports/cortex_a9/iar/src/tx_iar.c +++ b/ports/cortex_a9/iar/src/tx_iar.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/cortex_m0/ac5/example_build/tx_initialize_low_level.s b/ports/cortex_m0/ac5/example_build/tx_initialize_low_level.s index 0c2206ad8..8f2cbaf1b 100644 --- a/ports/cortex_m0/ac5/example_build/tx_initialize_low_level.s +++ b/ports/cortex_m0/ac5/example_build/tx_initialize_low_level.s @@ -8,7 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ -; Some portions generated by Copilot (Opus 5). +; Portions of this file were generated with AI assistance. ; ; ;/**************************************************************************/ diff --git a/ports/cortex_m0/ac6/example_build/sample_threadx/tx_initialize_low_level.S b/ports/cortex_m0/ac6/example_build/sample_threadx/tx_initialize_low_level.S index c3a7a2fe9..a3da17f70 100644 --- a/ports/cortex_m0/ac6/example_build/sample_threadx/tx_initialize_low_level.S +++ b/ports/cortex_m0/ac6/example_build/sample_threadx/tx_initialize_low_level.S @@ -8,8 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ -// Some portions generated by Copilot (Opus 5). -@ // Some portions generated by GitHub Copilot (Claude Sonnet 4.6). +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ diff --git a/ports/cortex_m0/ac6/inc/tx_port.h b/ports/cortex_m0/ac6/inc/tx_port.h index d6e036270..8b33dfec2 100644 --- a/ports/cortex_m0/ac6/inc/tx_port.h +++ b/ports/cortex_m0/ac6/inc/tx_port.h @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m0/gnu/example_build/tx_initialize_low_level.S b/ports/cortex_m0/gnu/example_build/tx_initialize_low_level.S index 0bf70f4a0..3c6307098 100644 --- a/ports/cortex_m0/gnu/example_build/tx_initialize_low_level.S +++ b/ports/cortex_m0/gnu/example_build/tx_initialize_low_level.S @@ -8,7 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ diff --git a/ports/cortex_m0/gnu/inc/tx_port.h b/ports/cortex_m0/gnu/inc/tx_port.h index 51f67b654..215293155 100644 --- a/ports/cortex_m0/gnu/inc/tx_port.h +++ b/ports/cortex_m0/gnu/inc/tx_port.h @@ -9,8 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m0/gnu/src/tx_thread_system_return.S b/ports/cortex_m0/gnu/src/tx_thread_system_return.S index f6135bf70..b03e03ba8 100644 --- a/ports/cortex_m0/gnu/src/tx_thread_system_return.S +++ b/ports/cortex_m0/gnu/src/tx_thread_system_return.S @@ -8,7 +8,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). +@ Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m0/iar/example_build/tx_initialize_low_level.s b/ports/cortex_m0/iar/example_build/tx_initialize_low_level.s index aa5bec7ba..9f83fa063 100644 --- a/ports/cortex_m0/iar/example_build/tx_initialize_low_level.s +++ b/ports/cortex_m0/iar/example_build/tx_initialize_low_level.s @@ -8,7 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ -; Some portions generated by Copilot (Opus 5). +; Portions of this file were generated with AI assistance. ; ; ;/**************************************************************************/ diff --git a/ports/cortex_m0/iar/inc/tx_port.h b/ports/cortex_m0/iar/inc/tx_port.h index cabb0402f..195261c16 100644 --- a/ports/cortex_m0/iar/inc/tx_port.h +++ b/ports/cortex_m0/iar/inc/tx_port.h @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m0/iar/src/tx_iar.c b/ports/cortex_m0/iar/src/tx_iar.c index ddfdaf3dd..ab6c209cc 100644 --- a/ports/cortex_m0/iar/src/tx_iar.c +++ b/ports/cortex_m0/iar/src/tx_iar.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/cortex_m0/iar/src/tx_thread_system_return.s b/ports/cortex_m0/iar/src/tx_thread_system_return.s index ab92a8c7d..929b3a009 100644 --- a/ports/cortex_m0/iar/src/tx_thread_system_return.s +++ b/ports/cortex_m0/iar/src/tx_thread_system_return.s @@ -9,7 +9,7 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ -; Some portions generated by Gemini (Gemini 2.0 Flash). +; Portions of this file were generated with AI assistance. ; ; ;/**************************************************************************/ diff --git a/ports/cortex_m0/keil/example_build/tx_initialize_low_level.s b/ports/cortex_m0/keil/example_build/tx_initialize_low_level.s index 0c2206ad8..8f2cbaf1b 100644 --- a/ports/cortex_m0/keil/example_build/tx_initialize_low_level.s +++ b/ports/cortex_m0/keil/example_build/tx_initialize_low_level.s @@ -8,7 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ -; Some portions generated by Copilot (Opus 5). +; Portions of this file were generated with AI assistance. ; ; ;/**************************************************************************/ diff --git a/ports/cortex_m23/ac6/example_build/tx_initialize_low_level.S b/ports/cortex_m23/ac6/example_build/tx_initialize_low_level.S index bbb2b2491..52fd67e28 100644 --- a/ports/cortex_m23/ac6/example_build/tx_initialize_low_level.S +++ b/ports/cortex_m23/ac6/example_build/tx_initialize_low_level.S @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m23/ac6/inc/tx_port.h b/ports/cortex_m23/ac6/inc/tx_port.h index dcd0f3542..25cfae013 100644 --- a/ports/cortex_m23/ac6/inc/tx_port.h +++ b/ports/cortex_m23/ac6/inc/tx_port.h @@ -9,8 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m23/ac6/src/tx_thread_system_return.S b/ports/cortex_m23/ac6/src/tx_thread_system_return.S index c0bfe023d..3cf7d6eef 100644 --- a/ports/cortex_m23/ac6/src/tx_thread_system_return.S +++ b/ports/cortex_m23/ac6/src/tx_thread_system_return.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m23/gnu/inc/tx_port.h b/ports/cortex_m23/gnu/inc/tx_port.h index a8ec7db2b..f1ca30e3c 100644 --- a/ports/cortex_m23/gnu/inc/tx_port.h +++ b/ports/cortex_m23/gnu/inc/tx_port.h @@ -9,8 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m23/gnu/src/tx_initialize_low_level.S b/ports/cortex_m23/gnu/src/tx_initialize_low_level.S index 602d30b7f..9efac65fe 100644 --- a/ports/cortex_m23/gnu/src/tx_initialize_low_level.S +++ b/ports/cortex_m23/gnu/src/tx_initialize_low_level.S @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m23/gnu/src/tx_thread_system_return.S b/ports/cortex_m23/gnu/src/tx_thread_system_return.S index ca5408d74..a486d8b1e 100644 --- a/ports/cortex_m23/gnu/src/tx_thread_system_return.S +++ b/ports/cortex_m23/gnu/src/tx_thread_system_return.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m23/iar/inc/tx_port.h b/ports/cortex_m23/iar/inc/tx_port.h index 50887409e..e1da96da7 100644 --- a/ports/cortex_m23/iar/inc/tx_port.h +++ b/ports/cortex_m23/iar/inc/tx_port.h @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m23/iar/src/tx_iar.c b/ports/cortex_m23/iar/src/tx_iar.c index ddfdaf3dd..ab6c209cc 100644 --- a/ports/cortex_m23/iar/src/tx_iar.c +++ b/ports/cortex_m23/iar/src/tx_iar.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/cortex_m23/iar/src/tx_initialize_low_level.s b/ports/cortex_m23/iar/src/tx_initialize_low_level.s index 14b78e58a..00e53af4d 100644 --- a/ports/cortex_m23/iar/src/tx_initialize_low_level.s +++ b/ports/cortex_m23/iar/src/tx_initialize_low_level.s @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m23/iar/src/tx_thread_system_return.s b/ports/cortex_m23/iar/src/tx_thread_system_return.s index da4b6d045..165f71bff 100644 --- a/ports/cortex_m23/iar/src/tx_thread_system_return.s +++ b/ports/cortex_m23/iar/src/tx_thread_system_return.s @@ -9,7 +9,7 @@ ;* SPDX-License-Identifier: MIT ;************************************************************************** -; Some portions generated by Gemini (Gemini 2.0 Flash). +; Portions of this file were generated with AI assistance. ;************************************************************************** diff --git a/ports/cortex_m3/ac5/example_build/tx_initialize_low_level.s b/ports/cortex_m3/ac5/example_build/tx_initialize_low_level.s index b8da8e000..5fb83ef7a 100644 --- a/ports/cortex_m3/ac5/example_build/tx_initialize_low_level.s +++ b/ports/cortex_m3/ac5/example_build/tx_initialize_low_level.s @@ -8,7 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ -; Some portions generated by Copilot (Opus 5). +; Portions of this file were generated with AI assistance. ; ; ;/**************************************************************************/ diff --git a/ports/cortex_m3/ac5/inc/tx_port.h b/ports/cortex_m3/ac5/inc/tx_port.h index 21f2543aa..947910f90 100644 --- a/ports/cortex_m3/ac5/inc/tx_port.h +++ b/ports/cortex_m3/ac5/inc/tx_port.h @@ -9,10 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). -// Some portions generated by Copilot (Claude Sonnet 4.6). -// Some portions generated by Claude Code (Opus 5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m3/ac5/src/tx_thread_schedule.s b/ports/cortex_m3/ac5/src/tx_thread_schedule.s index d7ad0b72d..5602f9913 100644 --- a/ports/cortex_m3/ac5/src/tx_thread_schedule.s +++ b/ports/cortex_m3/ac5/src/tx_thread_schedule.s @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m3/ac6/example_build/sample_threadx/tx_initialize_low_level.S b/ports/cortex_m3/ac6/example_build/sample_threadx/tx_initialize_low_level.S index 54a671128..05285bce0 100644 --- a/ports/cortex_m3/ac6/example_build/sample_threadx/tx_initialize_low_level.S +++ b/ports/cortex_m3/ac6/example_build/sample_threadx/tx_initialize_low_level.S @@ -8,7 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ diff --git a/ports/cortex_m3/ac6/inc/tx_port.h b/ports/cortex_m3/ac6/inc/tx_port.h index 29e23a471..e05de4d97 100644 --- a/ports/cortex_m3/ac6/inc/tx_port.h +++ b/ports/cortex_m3/ac6/inc/tx_port.h @@ -9,10 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). -// Some portions generated by Copilot (Claude Sonnet 4.6). -// Some portions generated by Claude Code (Opus 5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m3/ac6/src/tx_thread_schedule.S b/ports/cortex_m3/ac6/src/tx_thread_schedule.S index f585c6f48..9493d2405 100644 --- a/ports/cortex_m3/ac6/src/tx_thread_schedule.S +++ b/ports/cortex_m3/ac6/src/tx_thread_schedule.S @@ -8,8 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m3/ac6/src/tx_thread_system_return.S b/ports/cortex_m3/ac6/src/tx_thread_system_return.S index 6d0e26afa..7b0c1df8c 100644 --- a/ports/cortex_m3/ac6/src/tx_thread_system_return.S +++ b/ports/cortex_m3/ac6/src/tx_thread_system_return.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m3/gnu/example_build/tx_initialize_low_level.S b/ports/cortex_m3/gnu/example_build/tx_initialize_low_level.S index d5bc168f6..1783459e6 100644 --- a/ports/cortex_m3/gnu/example_build/tx_initialize_low_level.S +++ b/ports/cortex_m3/gnu/example_build/tx_initialize_low_level.S @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/cortex_m3/gnu/inc/tx_port.h b/ports/cortex_m3/gnu/inc/tx_port.h index 1db71238a..5748f69c8 100644 --- a/ports/cortex_m3/gnu/inc/tx_port.h +++ b/ports/cortex_m3/gnu/inc/tx_port.h @@ -9,10 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). -// Some portions generated by Copilot (Claude Sonnet 4.6). -// Some portions generated by Claude Code (Opus 5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m3/gnu/src/tx_thread_schedule.S b/ports/cortex_m3/gnu/src/tx_thread_schedule.S index 724a0ed97..41798a897 100644 --- a/ports/cortex_m3/gnu/src/tx_thread_schedule.S +++ b/ports/cortex_m3/gnu/src/tx_thread_schedule.S @@ -8,8 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m3/gnu/src/tx_thread_system_return.S b/ports/cortex_m3/gnu/src/tx_thread_system_return.S index 92ad3f628..8d57c2e60 100644 --- a/ports/cortex_m3/gnu/src/tx_thread_system_return.S +++ b/ports/cortex_m3/gnu/src/tx_thread_system_return.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m3/iar/example_build/tx_initialize_low_level.s b/ports/cortex_m3/iar/example_build/tx_initialize_low_level.s index 2c985dbb1..c0279a2a4 100644 --- a/ports/cortex_m3/iar/example_build/tx_initialize_low_level.s +++ b/ports/cortex_m3/iar/example_build/tx_initialize_low_level.s @@ -8,7 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ -; Some portions generated by Copilot (Opus 5). +; Portions of this file were generated with AI assistance. ; ; ;/**************************************************************************/ diff --git a/ports/cortex_m3/iar/inc/tx_port.h b/ports/cortex_m3/iar/inc/tx_port.h index f14b730a1..b8d81f202 100644 --- a/ports/cortex_m3/iar/inc/tx_port.h +++ b/ports/cortex_m3/iar/inc/tx_port.h @@ -9,10 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). -// Some portions generated by Copilot (Claude Sonnet 4.6). -// Some portions generated by Claude Code (Opus 5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m3/iar/src/tx_iar.c b/ports/cortex_m3/iar/src/tx_iar.c index ddfdaf3dd..ab6c209cc 100644 --- a/ports/cortex_m3/iar/src/tx_iar.c +++ b/ports/cortex_m3/iar/src/tx_iar.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/cortex_m3/iar/src/tx_thread_schedule.s b/ports/cortex_m3/iar/src/tx_thread_schedule.s index 8ed1b469c..0ae6454cb 100644 --- a/ports/cortex_m3/iar/src/tx_thread_schedule.s +++ b/ports/cortex_m3/iar/src/tx_thread_schedule.s @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m3/iar/src/tx_thread_system_return.s b/ports/cortex_m3/iar/src/tx_thread_system_return.s index 7bc5f2ebc..5ff03c35c 100644 --- a/ports/cortex_m3/iar/src/tx_thread_system_return.s +++ b/ports/cortex_m3/iar/src/tx_thread_system_return.s @@ -9,7 +9,7 @@ ;* SPDX-License-Identifier: MIT ;************************************************************************** -; Some portions generated by Gemini (Gemini 2.0 Flash). +; Portions of this file were generated with AI assistance. ;************************************************************************** diff --git a/ports/cortex_m3/keil/example_build/tx_initialize_low_level.s b/ports/cortex_m3/keil/example_build/tx_initialize_low_level.s index 62ea64d02..1ce8867d3 100644 --- a/ports/cortex_m3/keil/example_build/tx_initialize_low_level.s +++ b/ports/cortex_m3/keil/example_build/tx_initialize_low_level.s @@ -8,7 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ -; Some portions generated by Copilot (Opus 5). +; Portions of this file were generated with AI assistance. ; ; ;/**************************************************************************/ diff --git a/ports/cortex_m3/keil/inc/tx_port.h b/ports/cortex_m3/keil/inc/tx_port.h index 13745458d..f66b80fe9 100644 --- a/ports/cortex_m3/keil/inc/tx_port.h +++ b/ports/cortex_m3/keil/inc/tx_port.h @@ -9,10 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). -// Some portions generated by Copilot (Claude Sonnet 4.6). -// Some portions generated by Claude Code (Opus 5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m33/ac6/example_build/tx_initialize_low_level.S b/ports/cortex_m33/ac6/example_build/tx_initialize_low_level.S index f9bd71c62..d26df1352 100644 --- a/ports/cortex_m33/ac6/example_build/tx_initialize_low_level.S +++ b/ports/cortex_m33/ac6/example_build/tx_initialize_low_level.S @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m33/ac6/inc/tx_port.h b/ports/cortex_m33/ac6/inc/tx_port.h index 98f953e4b..a52374927 100644 --- a/ports/cortex_m33/ac6/inc/tx_port.h +++ b/ports/cortex_m33/ac6/inc/tx_port.h @@ -9,9 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). -// Some portions generated by Claude Code (Opus 5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m33/ac6/src/tx_initialize_low_level.S b/ports/cortex_m33/ac6/src/tx_initialize_low_level.S index d38ae7156..19478f005 100644 --- a/ports/cortex_m33/ac6/src/tx_initialize_low_level.S +++ b/ports/cortex_m33/ac6/src/tx_initialize_low_level.S @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m33/ac6/src/tx_thread_schedule.S b/ports/cortex_m33/ac6/src/tx_thread_schedule.S index c0794e2a4..61373edc1 100644 --- a/ports/cortex_m33/ac6/src/tx_thread_schedule.S +++ b/ports/cortex_m33/ac6/src/tx_thread_schedule.S @@ -8,8 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m33/ac6/src/tx_thread_system_return.S b/ports/cortex_m33/ac6/src/tx_thread_system_return.S index cd183702f..6580739ed 100644 --- a/ports/cortex_m33/ac6/src/tx_thread_system_return.S +++ b/ports/cortex_m33/ac6/src/tx_thread_system_return.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m33/gnu/example_build/tx_initialize_low_level.S b/ports/cortex_m33/gnu/example_build/tx_initialize_low_level.S index fe965cd69..4528c4206 100644 --- a/ports/cortex_m33/gnu/example_build/tx_initialize_low_level.S +++ b/ports/cortex_m33/gnu/example_build/tx_initialize_low_level.S @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m33/gnu/inc/tx_port.h b/ports/cortex_m33/gnu/inc/tx_port.h index 828058ea9..605d85a97 100644 --- a/ports/cortex_m33/gnu/inc/tx_port.h +++ b/ports/cortex_m33/gnu/inc/tx_port.h @@ -9,9 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). -// Some portions generated by Claude Code (Opus 5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m33/gnu/src/tx_thread_schedule.S b/ports/cortex_m33/gnu/src/tx_thread_schedule.S index 63c97eb14..e66e5c90f 100644 --- a/ports/cortex_m33/gnu/src/tx_thread_schedule.S +++ b/ports/cortex_m33/gnu/src/tx_thread_schedule.S @@ -8,8 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m33/gnu/src/tx_thread_system_return.S b/ports/cortex_m33/gnu/src/tx_thread_system_return.S index 156093933..85ab2b040 100644 --- a/ports/cortex_m33/gnu/src/tx_thread_system_return.S +++ b/ports/cortex_m33/gnu/src/tx_thread_system_return.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m33/iar/inc/tx_port.h b/ports/cortex_m33/iar/inc/tx_port.h index 1203e4019..96341bac5 100644 --- a/ports/cortex_m33/iar/inc/tx_port.h +++ b/ports/cortex_m33/iar/inc/tx_port.h @@ -9,9 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). -// Some portions generated by Claude Code (Opus 5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m33/iar/src/tx_iar.c b/ports/cortex_m33/iar/src/tx_iar.c index ddfdaf3dd..ab6c209cc 100644 --- a/ports/cortex_m33/iar/src/tx_iar.c +++ b/ports/cortex_m33/iar/src/tx_iar.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/cortex_m33/iar/src/tx_initialize_low_level.s b/ports/cortex_m33/iar/src/tx_initialize_low_level.s index 0bcff9134..8e2cd1707 100644 --- a/ports/cortex_m33/iar/src/tx_initialize_low_level.s +++ b/ports/cortex_m33/iar/src/tx_initialize_low_level.s @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m33/iar/src/tx_thread_schedule.s b/ports/cortex_m33/iar/src/tx_thread_schedule.s index 0018babb4..f1e05ba0f 100644 --- a/ports/cortex_m33/iar/src/tx_thread_schedule.s +++ b/ports/cortex_m33/iar/src/tx_thread_schedule.s @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m33/iar/src/tx_thread_system_return.s b/ports/cortex_m33/iar/src/tx_thread_system_return.s index 89f086fc5..242dd4e7e 100644 --- a/ports/cortex_m33/iar/src/tx_thread_system_return.s +++ b/ports/cortex_m33/iar/src/tx_thread_system_return.s @@ -9,7 +9,7 @@ ;* SPDX-License-Identifier: MIT ;************************************************************************** -; Some portions generated by Gemini (Gemini 2.0 Flash). +; Portions of this file were generated with AI assistance. ;************************************************************************** diff --git a/ports/cortex_m4/ac5/example_build/tx_initialize_low_level.s b/ports/cortex_m4/ac5/example_build/tx_initialize_low_level.s index 706914071..0a37fe626 100644 --- a/ports/cortex_m4/ac5/example_build/tx_initialize_low_level.s +++ b/ports/cortex_m4/ac5/example_build/tx_initialize_low_level.s @@ -1,5 +1,5 @@ ;/**************************************************************************/ -; Some portions generated by Copilot (Opus 5). +; Portions of this file were generated with AI assistance. ;/* */ ;/* Copyright (c) 2024 Microsoft Corporation. */ ;/* */ diff --git a/ports/cortex_m4/ac5/inc/tx_port.h b/ports/cortex_m4/ac5/inc/tx_port.h index 2b6361d4f..b8d903bcf 100644 --- a/ports/cortex_m4/ac5/inc/tx_port.h +++ b/ports/cortex_m4/ac5/inc/tx_port.h @@ -9,10 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). -// Some portions generated by Copilot (Claude Sonnet 4.6). -// Some portions generated by Claude Code (Opus 5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m4/ac5/src/tx_thread_schedule.s b/ports/cortex_m4/ac5/src/tx_thread_schedule.s index 7aa6a366f..3effe03d9 100644 --- a/ports/cortex_m4/ac5/src/tx_thread_schedule.s +++ b/ports/cortex_m4/ac5/src/tx_thread_schedule.s @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m4/ac6/example_build/sample_threadx/tx_initialize_low_level.S b/ports/cortex_m4/ac6/example_build/sample_threadx/tx_initialize_low_level.S index a049386b1..28b9feedb 100644 --- a/ports/cortex_m4/ac6/example_build/sample_threadx/tx_initialize_low_level.S +++ b/ports/cortex_m4/ac6/example_build/sample_threadx/tx_initialize_low_level.S @@ -8,7 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ diff --git a/ports/cortex_m4/ac6/inc/tx_port.h b/ports/cortex_m4/ac6/inc/tx_port.h index 1db55ef54..6c3ef0767 100644 --- a/ports/cortex_m4/ac6/inc/tx_port.h +++ b/ports/cortex_m4/ac6/inc/tx_port.h @@ -9,10 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). -// Some portions generated by Copilot (Claude Sonnet 4.6). -// Some portions generated by Claude Code (Opus 5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m4/ac6/src/tx_thread_schedule.S b/ports/cortex_m4/ac6/src/tx_thread_schedule.S index 227e76f50..6e6426714 100644 --- a/ports/cortex_m4/ac6/src/tx_thread_schedule.S +++ b/ports/cortex_m4/ac6/src/tx_thread_schedule.S @@ -8,8 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m4/ac6/src/tx_thread_system_return.S b/ports/cortex_m4/ac6/src/tx_thread_system_return.S index 59a7210d5..e88861efc 100644 --- a/ports/cortex_m4/ac6/src/tx_thread_system_return.S +++ b/ports/cortex_m4/ac6/src/tx_thread_system_return.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m4/gnu/example_build/tx_initialize_low_level.S b/ports/cortex_m4/gnu/example_build/tx_initialize_low_level.S index e714dee70..fdb71b7a5 100644 --- a/ports/cortex_m4/gnu/example_build/tx_initialize_low_level.S +++ b/ports/cortex_m4/gnu/example_build/tx_initialize_low_level.S @@ -8,7 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ diff --git a/ports/cortex_m4/gnu/inc/tx_port.h b/ports/cortex_m4/gnu/inc/tx_port.h index fe240f62b..8cf28e949 100644 --- a/ports/cortex_m4/gnu/inc/tx_port.h +++ b/ports/cortex_m4/gnu/inc/tx_port.h @@ -9,10 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). -// Some portions generated by Copilot (Claude Sonnet 4.6). -// Some portions generated by Claude Code (Opus 5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m4/gnu/src/tx_thread_schedule.S b/ports/cortex_m4/gnu/src/tx_thread_schedule.S index 8e9f0664f..60287145e 100644 --- a/ports/cortex_m4/gnu/src/tx_thread_schedule.S +++ b/ports/cortex_m4/gnu/src/tx_thread_schedule.S @@ -8,8 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m4/gnu/src/tx_thread_system_return.S b/ports/cortex_m4/gnu/src/tx_thread_system_return.S index 4709af37f..093493187 100644 --- a/ports/cortex_m4/gnu/src/tx_thread_system_return.S +++ b/ports/cortex_m4/gnu/src/tx_thread_system_return.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m4/iar/example_build/tx_initialize_low_level.s b/ports/cortex_m4/iar/example_build/tx_initialize_low_level.s index 044339c05..798fe53b1 100644 --- a/ports/cortex_m4/iar/example_build/tx_initialize_low_level.s +++ b/ports/cortex_m4/iar/example_build/tx_initialize_low_level.s @@ -8,7 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ -; Some portions generated by Copilot (Opus 5). +; Portions of this file were generated with AI assistance. ; ; ;/**************************************************************************/ diff --git a/ports/cortex_m4/iar/inc/tx_port.h b/ports/cortex_m4/iar/inc/tx_port.h index 1ca170081..cd180f948 100644 --- a/ports/cortex_m4/iar/inc/tx_port.h +++ b/ports/cortex_m4/iar/inc/tx_port.h @@ -9,10 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). -// Some portions generated by Copilot (Claude Sonnet 4.6). -// Some portions generated by Claude Code (Opus 5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m4/iar/src/tx_iar.c b/ports/cortex_m4/iar/src/tx_iar.c index ddfdaf3dd..ab6c209cc 100644 --- a/ports/cortex_m4/iar/src/tx_iar.c +++ b/ports/cortex_m4/iar/src/tx_iar.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/cortex_m4/iar/src/tx_thread_schedule.s b/ports/cortex_m4/iar/src/tx_thread_schedule.s index e4ea3bfc9..c7d6beab6 100644 --- a/ports/cortex_m4/iar/src/tx_thread_schedule.s +++ b/ports/cortex_m4/iar/src/tx_thread_schedule.s @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m4/iar/src/tx_thread_system_return.s b/ports/cortex_m4/iar/src/tx_thread_system_return.s index b466bacaa..dd2b38a6e 100644 --- a/ports/cortex_m4/iar/src/tx_thread_system_return.s +++ b/ports/cortex_m4/iar/src/tx_thread_system_return.s @@ -9,7 +9,7 @@ ;* SPDX-License-Identifier: MIT ;************************************************************************** -; Some portions generated by Gemini (Gemini 2.0 Flash). +; Portions of this file were generated with AI assistance. ;************************************************************************** diff --git a/ports/cortex_m4/keil/example_build/tx_initialize_low_level.s b/ports/cortex_m4/keil/example_build/tx_initialize_low_level.s index 015d2c73e..f574cf65f 100644 --- a/ports/cortex_m4/keil/example_build/tx_initialize_low_level.s +++ b/ports/cortex_m4/keil/example_build/tx_initialize_low_level.s @@ -8,7 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ -; Some portions generated by Copilot (Opus 5). +; Portions of this file were generated with AI assistance. ; ; ;/**************************************************************************/ diff --git a/ports/cortex_m4/keil/inc/tx_port.h b/ports/cortex_m4/keil/inc/tx_port.h index f54822ff0..2e7416849 100644 --- a/ports/cortex_m4/keil/inc/tx_port.h +++ b/ports/cortex_m4/keil/inc/tx_port.h @@ -9,10 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). -// Some portions generated by Copilot (Claude Sonnet 4.6). -// Some portions generated by Claude Code (Opus 5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m52/ac6/inc/tx_port.h b/ports/cortex_m52/ac6/inc/tx_port.h index db3284347..ae528beeb 100644 --- a/ports/cortex_m52/ac6/inc/tx_port.h +++ b/ports/cortex_m52/ac6/inc/tx_port.h @@ -9,9 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). -// Some portions generated by Claude Code (Opus 5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m52/ac6/src/tx_initialize_low_level.S b/ports/cortex_m52/ac6/src/tx_initialize_low_level.S index d7921ee30..ceb0e39b9 100644 --- a/ports/cortex_m52/ac6/src/tx_initialize_low_level.S +++ b/ports/cortex_m52/ac6/src/tx_initialize_low_level.S @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m52/ac6/src/tx_thread_schedule.S b/ports/cortex_m52/ac6/src/tx_thread_schedule.S index 2458a417e..d16623ad5 100644 --- a/ports/cortex_m52/ac6/src/tx_thread_schedule.S +++ b/ports/cortex_m52/ac6/src/tx_thread_schedule.S @@ -8,8 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m52/ac6/src/tx_thread_system_return.S b/ports/cortex_m52/ac6/src/tx_thread_system_return.S index abc809648..2670cd579 100644 --- a/ports/cortex_m52/ac6/src/tx_thread_system_return.S +++ b/ports/cortex_m52/ac6/src/tx_thread_system_return.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m52/gnu/inc/tx_port.h b/ports/cortex_m52/gnu/inc/tx_port.h index ca101c68d..7ebc7bdcf 100644 --- a/ports/cortex_m52/gnu/inc/tx_port.h +++ b/ports/cortex_m52/gnu/inc/tx_port.h @@ -9,9 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). -// Some portions generated by Claude Code (Opus 5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m52/gnu/src/tx_thread_schedule.S b/ports/cortex_m52/gnu/src/tx_thread_schedule.S index bc830c302..88ad944ae 100644 --- a/ports/cortex_m52/gnu/src/tx_thread_schedule.S +++ b/ports/cortex_m52/gnu/src/tx_thread_schedule.S @@ -8,8 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m52/gnu/src/tx_thread_system_return.S b/ports/cortex_m52/gnu/src/tx_thread_system_return.S index 3051f9409..da5b7af8b 100644 --- a/ports/cortex_m52/gnu/src/tx_thread_system_return.S +++ b/ports/cortex_m52/gnu/src/tx_thread_system_return.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m52/iar/inc/tx_port.h b/ports/cortex_m52/iar/inc/tx_port.h index 493b54c16..fc3d1b253 100644 --- a/ports/cortex_m52/iar/inc/tx_port.h +++ b/ports/cortex_m52/iar/inc/tx_port.h @@ -9,9 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). -// Some portions generated by Claude Code (Opus 5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m52/iar/src/tx_iar.c b/ports/cortex_m52/iar/src/tx_iar.c index ddfdaf3dd..ab6c209cc 100644 --- a/ports/cortex_m52/iar/src/tx_iar.c +++ b/ports/cortex_m52/iar/src/tx_iar.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/cortex_m52/iar/src/tx_initialize_low_level.s b/ports/cortex_m52/iar/src/tx_initialize_low_level.s index 12ea8649a..23d420a1e 100644 --- a/ports/cortex_m52/iar/src/tx_initialize_low_level.s +++ b/ports/cortex_m52/iar/src/tx_initialize_low_level.s @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m52/iar/src/tx_thread_schedule.s b/ports/cortex_m52/iar/src/tx_thread_schedule.s index a89ca7784..d746cb417 100644 --- a/ports/cortex_m52/iar/src/tx_thread_schedule.s +++ b/ports/cortex_m52/iar/src/tx_thread_schedule.s @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m52/iar/src/tx_thread_system_return.s b/ports/cortex_m52/iar/src/tx_thread_system_return.s index cc5be4596..5768dcbc3 100644 --- a/ports/cortex_m52/iar/src/tx_thread_system_return.s +++ b/ports/cortex_m52/iar/src/tx_thread_system_return.s @@ -9,7 +9,7 @@ ;* SPDX-License-Identifier: MIT ;************************************************************************** -; Some portions generated by Gemini (Gemini 2.0 Flash). +; Portions of this file were generated with AI assistance. ;************************************************************************** diff --git a/ports/cortex_m55/ac6/example_build/tx_initialize_low_level.S b/ports/cortex_m55/ac6/example_build/tx_initialize_low_level.S index b6ea3dcf9..2a95616a5 100644 --- a/ports/cortex_m55/ac6/example_build/tx_initialize_low_level.S +++ b/ports/cortex_m55/ac6/example_build/tx_initialize_low_level.S @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m55/ac6/inc/tx_port.h b/ports/cortex_m55/ac6/inc/tx_port.h index 63a49e126..4d4760637 100644 --- a/ports/cortex_m55/ac6/inc/tx_port.h +++ b/ports/cortex_m55/ac6/inc/tx_port.h @@ -9,9 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). -// Some portions generated by Claude Code (Opus 5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m55/ac6/src/tx_initialize_low_level.S b/ports/cortex_m55/ac6/src/tx_initialize_low_level.S index 8e80b625f..0876c0199 100644 --- a/ports/cortex_m55/ac6/src/tx_initialize_low_level.S +++ b/ports/cortex_m55/ac6/src/tx_initialize_low_level.S @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m55/ac6/src/tx_thread_schedule.S b/ports/cortex_m55/ac6/src/tx_thread_schedule.S index 08a48000b..df84045bd 100644 --- a/ports/cortex_m55/ac6/src/tx_thread_schedule.S +++ b/ports/cortex_m55/ac6/src/tx_thread_schedule.S @@ -8,8 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m55/ac6/src/tx_thread_system_return.S b/ports/cortex_m55/ac6/src/tx_thread_system_return.S index a72a9a418..f3510d746 100644 --- a/ports/cortex_m55/ac6/src/tx_thread_system_return.S +++ b/ports/cortex_m55/ac6/src/tx_thread_system_return.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m55/gnu/example_build/tx_initialize_low_level.S b/ports/cortex_m55/gnu/example_build/tx_initialize_low_level.S index c87d00a32..de010de87 100644 --- a/ports/cortex_m55/gnu/example_build/tx_initialize_low_level.S +++ b/ports/cortex_m55/gnu/example_build/tx_initialize_low_level.S @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m55/gnu/inc/tx_port.h b/ports/cortex_m55/gnu/inc/tx_port.h index eb7176f57..2bd806425 100644 --- a/ports/cortex_m55/gnu/inc/tx_port.h +++ b/ports/cortex_m55/gnu/inc/tx_port.h @@ -9,9 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). -// Some portions generated by Claude Code (Opus 5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m55/gnu/src/tx_thread_schedule.S b/ports/cortex_m55/gnu/src/tx_thread_schedule.S index 7d331dc83..4064a5d6c 100644 --- a/ports/cortex_m55/gnu/src/tx_thread_schedule.S +++ b/ports/cortex_m55/gnu/src/tx_thread_schedule.S @@ -8,8 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m55/gnu/src/tx_thread_system_return.S b/ports/cortex_m55/gnu/src/tx_thread_system_return.S index f13f832a6..3ecbb18ec 100644 --- a/ports/cortex_m55/gnu/src/tx_thread_system_return.S +++ b/ports/cortex_m55/gnu/src/tx_thread_system_return.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m55/iar/inc/tx_port.h b/ports/cortex_m55/iar/inc/tx_port.h index 8f7105065..d908ac7fa 100644 --- a/ports/cortex_m55/iar/inc/tx_port.h +++ b/ports/cortex_m55/iar/inc/tx_port.h @@ -9,9 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). -// Some portions generated by Claude Code (Opus 5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m55/iar/src/tx_iar.c b/ports/cortex_m55/iar/src/tx_iar.c index ddfdaf3dd..ab6c209cc 100644 --- a/ports/cortex_m55/iar/src/tx_iar.c +++ b/ports/cortex_m55/iar/src/tx_iar.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/cortex_m55/iar/src/tx_initialize_low_level.s b/ports/cortex_m55/iar/src/tx_initialize_low_level.s index be4e8ae25..379a4e91d 100644 --- a/ports/cortex_m55/iar/src/tx_initialize_low_level.s +++ b/ports/cortex_m55/iar/src/tx_initialize_low_level.s @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m55/iar/src/tx_thread_schedule.s b/ports/cortex_m55/iar/src/tx_thread_schedule.s index 7edba8302..843cb6751 100644 --- a/ports/cortex_m55/iar/src/tx_thread_schedule.s +++ b/ports/cortex_m55/iar/src/tx_thread_schedule.s @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m55/iar/src/tx_thread_system_return.s b/ports/cortex_m55/iar/src/tx_thread_system_return.s index cb311a479..4d41e09ab 100644 --- a/ports/cortex_m55/iar/src/tx_thread_system_return.s +++ b/ports/cortex_m55/iar/src/tx_thread_system_return.s @@ -9,7 +9,7 @@ ;* SPDX-License-Identifier: MIT ;************************************************************************** -; Some portions generated by Gemini (Gemini 2.0 Flash). +; Portions of this file were generated with AI assistance. ;************************************************************************** diff --git a/ports/cortex_m7/ac5/example_build/tx_initialize_low_level.s b/ports/cortex_m7/ac5/example_build/tx_initialize_low_level.s index 94e13b01f..f943c5727 100644 --- a/ports/cortex_m7/ac5/example_build/tx_initialize_low_level.s +++ b/ports/cortex_m7/ac5/example_build/tx_initialize_low_level.s @@ -8,7 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ -; Some portions generated by Copilot (Opus 5). +; Portions of this file were generated with AI assistance. ; ; ;/**************************************************************************/ diff --git a/ports/cortex_m7/ac5/inc/tx_port.h b/ports/cortex_m7/ac5/inc/tx_port.h index 320f23d8f..a753eb3f0 100644 --- a/ports/cortex_m7/ac5/inc/tx_port.h +++ b/ports/cortex_m7/ac5/inc/tx_port.h @@ -9,10 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). -// Some portions generated by Copilot (Claude Sonnet 4.6). -// Some portions generated by Claude Code (Opus 5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m7/ac5/src/tx_thread_schedule.s b/ports/cortex_m7/ac5/src/tx_thread_schedule.s index ed1c93922..7929cd0c1 100644 --- a/ports/cortex_m7/ac5/src/tx_thread_schedule.s +++ b/ports/cortex_m7/ac5/src/tx_thread_schedule.s @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m7/ac6/example_build/sample_threadx/tx_initialize_low_level.S b/ports/cortex_m7/ac6/example_build/sample_threadx/tx_initialize_low_level.S index 4095c8516..b97690c22 100644 --- a/ports/cortex_m7/ac6/example_build/sample_threadx/tx_initialize_low_level.S +++ b/ports/cortex_m7/ac6/example_build/sample_threadx/tx_initialize_low_level.S @@ -8,7 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ diff --git a/ports/cortex_m7/ac6/inc/tx_port.h b/ports/cortex_m7/ac6/inc/tx_port.h index 8a4981deb..6b08b6117 100644 --- a/ports/cortex_m7/ac6/inc/tx_port.h +++ b/ports/cortex_m7/ac6/inc/tx_port.h @@ -9,10 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). -// Some portions generated by Copilot (Claude Sonnet 4.6). -// Some portions generated by Claude Code (Opus 5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m7/ac6/src/tx_thread_schedule.S b/ports/cortex_m7/ac6/src/tx_thread_schedule.S index 26355e374..8c8bdb44f 100644 --- a/ports/cortex_m7/ac6/src/tx_thread_schedule.S +++ b/ports/cortex_m7/ac6/src/tx_thread_schedule.S @@ -8,8 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m7/ac6/src/tx_thread_system_return.S b/ports/cortex_m7/ac6/src/tx_thread_system_return.S index d0243dea6..4071b1a1e 100644 --- a/ports/cortex_m7/ac6/src/tx_thread_system_return.S +++ b/ports/cortex_m7/ac6/src/tx_thread_system_return.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m7/gnu/example_build/tx_initialize_low_level.S b/ports/cortex_m7/gnu/example_build/tx_initialize_low_level.S index 478d8f156..af109e911 100644 --- a/ports/cortex_m7/gnu/example_build/tx_initialize_low_level.S +++ b/ports/cortex_m7/gnu/example_build/tx_initialize_low_level.S @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/cortex_m7/gnu/inc/tx_port.h b/ports/cortex_m7/gnu/inc/tx_port.h index c47b27fd0..7b2a3d5ea 100644 --- a/ports/cortex_m7/gnu/inc/tx_port.h +++ b/ports/cortex_m7/gnu/inc/tx_port.h @@ -9,10 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). -// Some portions generated by Copilot (Claude Sonnet 4.6). -// Some portions generated by Claude Code (Opus 5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m7/gnu/src/tx_thread_schedule.S b/ports/cortex_m7/gnu/src/tx_thread_schedule.S index 66b033ac1..89700634e 100644 --- a/ports/cortex_m7/gnu/src/tx_thread_schedule.S +++ b/ports/cortex_m7/gnu/src/tx_thread_schedule.S @@ -8,8 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m7/gnu/src/tx_thread_system_return.S b/ports/cortex_m7/gnu/src/tx_thread_system_return.S index 180894b3b..6eb5a72d2 100644 --- a/ports/cortex_m7/gnu/src/tx_thread_system_return.S +++ b/ports/cortex_m7/gnu/src/tx_thread_system_return.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m7/iar/example_build/tx_initialize_low_level.s b/ports/cortex_m7/iar/example_build/tx_initialize_low_level.s index e9f14b2b9..b7d109ae1 100644 --- a/ports/cortex_m7/iar/example_build/tx_initialize_low_level.s +++ b/ports/cortex_m7/iar/example_build/tx_initialize_low_level.s @@ -8,7 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ -; Some portions generated by Copilot (Opus 5). +; Portions of this file were generated with AI assistance. ; ; ;/**************************************************************************/ diff --git a/ports/cortex_m7/iar/inc/tx_port.h b/ports/cortex_m7/iar/inc/tx_port.h index bd0c8507f..7a0d5b021 100644 --- a/ports/cortex_m7/iar/inc/tx_port.h +++ b/ports/cortex_m7/iar/inc/tx_port.h @@ -9,10 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). -// Some portions generated by Copilot (Claude Sonnet 4.6). -// Some portions generated by Claude Code (Opus 5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m7/iar/src/tx_iar.c b/ports/cortex_m7/iar/src/tx_iar.c index ddfdaf3dd..ab6c209cc 100644 --- a/ports/cortex_m7/iar/src/tx_iar.c +++ b/ports/cortex_m7/iar/src/tx_iar.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/cortex_m7/iar/src/tx_thread_schedule.s b/ports/cortex_m7/iar/src/tx_thread_schedule.s index 47aac1f86..847ab02d2 100644 --- a/ports/cortex_m7/iar/src/tx_thread_schedule.s +++ b/ports/cortex_m7/iar/src/tx_thread_schedule.s @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m7/iar/src/tx_thread_system_return.s b/ports/cortex_m7/iar/src/tx_thread_system_return.s index 345fca808..ab1f05ba1 100644 --- a/ports/cortex_m7/iar/src/tx_thread_system_return.s +++ b/ports/cortex_m7/iar/src/tx_thread_system_return.s @@ -9,7 +9,7 @@ ;* SPDX-License-Identifier: MIT ;************************************************************************** -; Some portions generated by Gemini (Gemini 2.0 Flash). +; Portions of this file were generated with AI assistance. ;************************************************************************** diff --git a/ports/cortex_m85/ac6/inc/tx_port.h b/ports/cortex_m85/ac6/inc/tx_port.h index bc9dff5d5..9b9e09544 100644 --- a/ports/cortex_m85/ac6/inc/tx_port.h +++ b/ports/cortex_m85/ac6/inc/tx_port.h @@ -9,9 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). -// Some portions generated by Claude Code (Opus 5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m85/ac6/src/tx_initialize_low_level.S b/ports/cortex_m85/ac6/src/tx_initialize_low_level.S index 453eae27d..31deaebbe 100644 --- a/ports/cortex_m85/ac6/src/tx_initialize_low_level.S +++ b/ports/cortex_m85/ac6/src/tx_initialize_low_level.S @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m85/ac6/src/tx_thread_schedule.S b/ports/cortex_m85/ac6/src/tx_thread_schedule.S index ab60b30e4..9132cc8d6 100644 --- a/ports/cortex_m85/ac6/src/tx_thread_schedule.S +++ b/ports/cortex_m85/ac6/src/tx_thread_schedule.S @@ -8,8 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m85/ac6/src/tx_thread_system_return.S b/ports/cortex_m85/ac6/src/tx_thread_system_return.S index 639af9fbb..40eb6626e 100644 --- a/ports/cortex_m85/ac6/src/tx_thread_system_return.S +++ b/ports/cortex_m85/ac6/src/tx_thread_system_return.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m85/gnu/example_build/tx_initialize_low_level.S b/ports/cortex_m85/gnu/example_build/tx_initialize_low_level.S index 3190cd117..eb6b5af70 100644 --- a/ports/cortex_m85/gnu/example_build/tx_initialize_low_level.S +++ b/ports/cortex_m85/gnu/example_build/tx_initialize_low_level.S @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m85/gnu/inc/tx_port.h b/ports/cortex_m85/gnu/inc/tx_port.h index 9a02f9405..02b93e1d6 100644 --- a/ports/cortex_m85/gnu/inc/tx_port.h +++ b/ports/cortex_m85/gnu/inc/tx_port.h @@ -9,9 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). -// Some portions generated by Claude Code (Opus 5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m85/gnu/src/tx_thread_schedule.S b/ports/cortex_m85/gnu/src/tx_thread_schedule.S index 1f1ded319..d9bcddee0 100644 --- a/ports/cortex_m85/gnu/src/tx_thread_schedule.S +++ b/ports/cortex_m85/gnu/src/tx_thread_schedule.S @@ -8,8 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m85/gnu/src/tx_thread_system_return.S b/ports/cortex_m85/gnu/src/tx_thread_system_return.S index 356300943..94090d14f 100644 --- a/ports/cortex_m85/gnu/src/tx_thread_system_return.S +++ b/ports/cortex_m85/gnu/src/tx_thread_system_return.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m85/iar/inc/tx_port.h b/ports/cortex_m85/iar/inc/tx_port.h index 1f8741cdc..afe9fc914 100644 --- a/ports/cortex_m85/iar/inc/tx_port.h +++ b/ports/cortex_m85/iar/inc/tx_port.h @@ -9,9 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). -// Some portions generated by Claude Code (Opus 5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m85/iar/src/tx_iar.c b/ports/cortex_m85/iar/src/tx_iar.c index ddfdaf3dd..ab6c209cc 100644 --- a/ports/cortex_m85/iar/src/tx_iar.c +++ b/ports/cortex_m85/iar/src/tx_iar.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/cortex_m85/iar/src/tx_initialize_low_level.s b/ports/cortex_m85/iar/src/tx_initialize_low_level.s index c75e6546e..60f5e18d6 100644 --- a/ports/cortex_m85/iar/src/tx_initialize_low_level.s +++ b/ports/cortex_m85/iar/src/tx_initialize_low_level.s @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m85/iar/src/tx_thread_schedule.s b/ports/cortex_m85/iar/src/tx_thread_schedule.s index 0d412f859..c9f85bc14 100644 --- a/ports/cortex_m85/iar/src/tx_thread_schedule.s +++ b/ports/cortex_m85/iar/src/tx_thread_schedule.s @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m85/iar/src/tx_thread_system_return.s b/ports/cortex_m85/iar/src/tx_thread_system_return.s index 8b62acc19..e3806f32a 100644 --- a/ports/cortex_m85/iar/src/tx_thread_system_return.s +++ b/ports/cortex_m85/iar/src/tx_thread_system_return.s @@ -9,7 +9,7 @@ ;* SPDX-License-Identifier: MIT ;************************************************************************** -; Some portions generated by Gemini (Gemini 2.0 Flash). +; Portions of this file were generated with AI assistance. ;************************************************************************** diff --git a/ports/cortex_r4/ac6/src/tx_thread_stack_build.S b/ports/cortex_r4/ac6/src/tx_thread_stack_build.S index ff916007a..57ae41520 100644 --- a/ports/cortex_r4/ac6/src/tx_thread_stack_build.S +++ b/ports/cortex_r4/ac6/src/tx_thread_stack_build.S @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_r4/gnu/inc/tx_port.h b/ports/cortex_r4/gnu/inc/tx_port.h index 44c6b8a41..0351c6835 100644 --- a/ports/cortex_r4/gnu/inc/tx_port.h +++ b/ports/cortex_r4/gnu/inc/tx_port.h @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Claude Code (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_r4/iar/src/tx_iar.c b/ports/cortex_r4/iar/src/tx_iar.c index ddfdaf3dd..ab6c209cc 100644 --- a/ports/cortex_r4/iar/src/tx_iar.c +++ b/ports/cortex_r4/iar/src/tx_iar.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/cortex_r5/ac5/inc/tx_port.h b/ports/cortex_r5/ac5/inc/tx_port.h index d1c69fba3..832866be2 100644 --- a/ports/cortex_r5/ac5/inc/tx_port.h +++ b/ports/cortex_r5/ac5/inc/tx_port.h @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_r5/ac6/inc/tx_port.h b/ports/cortex_r5/ac6/inc/tx_port.h index 8a905c9a7..674b7acdb 100644 --- a/ports/cortex_r5/ac6/inc/tx_port.h +++ b/ports/cortex_r5/ac6/inc/tx_port.h @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Claude Code (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_r5/gnu/inc/tx_port.h b/ports/cortex_r5/gnu/inc/tx_port.h index b5f81474d..012f75e1d 100644 --- a/ports/cortex_r5/gnu/inc/tx_port.h +++ b/ports/cortex_r5/gnu/inc/tx_port.h @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Claude Code (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_r5/iar/src/tx_iar.c b/ports/cortex_r5/iar/src/tx_iar.c index ddfdaf3dd..ab6c209cc 100644 --- a/ports/cortex_r5/iar/src/tx_iar.c +++ b/ports/cortex_r5/iar/src/tx_iar.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/demo_threadx.c b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/demo_threadx.c index 19d976b3e..90fe257db 100644 --- a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/demo_threadx.c +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/demo_threadx.c @@ -8,7 +8,7 @@ /* */ /* SPDX-License-Identifier: MIT */ /**************************************************************************/ -// Some portions generated by Claude Code (Opus 5). +// Portions of this file were generated with AI assistance. /* Copied unmodified from samples/demo_threadx.c for the Armv8-R AEM FVP example build, then extended with a verification thread and a bsp_main diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/entry.S b/ports/cortex_r52/gnu/example_build/s32z280_evb/entry.S index 3c85db9bf..24aa9cdce 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/entry.S +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/entry.S @@ -12,7 +12,7 @@ @ * @ * SPDX-License-Identifier: MIT and CC0-1.0 @ **************************************************************************/ -@ Some portions generated by Claude Code (Opus 5). +@ Portions of this file were generated with AI assistance. @ @/**************************************************************************/ @/* */ diff --git a/ports/cortex_r52/gnu/inc/tx_port.h b/ports/cortex_r52/gnu/inc/tx_port.h index 7feb2300a..2f0a67cf6 100644 --- a/ports/cortex_r52/gnu/inc/tx_port.h +++ b/ports/cortex_r52/gnu/inc/tx_port.h @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Claude Code (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_r52/gnu/src/tx_thread_context_restore.S b/ports/cortex_r52/gnu/src/tx_thread_context_restore.S index ed6230714..5c0e503d3 100644 --- a/ports/cortex_r52/gnu/src/tx_thread_context_restore.S +++ b/ports/cortex_r52/gnu/src/tx_thread_context_restore.S @@ -8,7 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ -@ Some portions generated by Claude Code (Opus 5). +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ diff --git a/ports/cortex_r52/gnu/src/tx_thread_context_save.S b/ports/cortex_r52/gnu/src/tx_thread_context_save.S index 9b61077e4..26443700a 100644 --- a/ports/cortex_r52/gnu/src/tx_thread_context_save.S +++ b/ports/cortex_r52/gnu/src/tx_thread_context_save.S @@ -8,7 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ -@ Some portions generated by Claude Code (Opus 5). +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ diff --git a/ports/cortex_r52/gnu/src/tx_thread_fiq_context_restore.S b/ports/cortex_r52/gnu/src/tx_thread_fiq_context_restore.S index 1d576f901..f47c96629 100644 --- a/ports/cortex_r52/gnu/src/tx_thread_fiq_context_restore.S +++ b/ports/cortex_r52/gnu/src/tx_thread_fiq_context_restore.S @@ -8,7 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ -@ Some portions generated by Claude Code (Opus 5). +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ diff --git a/ports/cortex_r52/gnu/src/tx_thread_fiq_context_save.S b/ports/cortex_r52/gnu/src/tx_thread_fiq_context_save.S index 9a4ec94bf..510fe36ee 100644 --- a/ports/cortex_r52/gnu/src/tx_thread_fiq_context_save.S +++ b/ports/cortex_r52/gnu/src/tx_thread_fiq_context_save.S @@ -8,7 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ -@ Some portions generated by Claude Code (Opus 5). +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ diff --git a/ports/cortex_r52/gnu/src/tx_thread_fiq_nesting_end.S b/ports/cortex_r52/gnu/src/tx_thread_fiq_nesting_end.S index 927f6307c..5b3232081 100644 --- a/ports/cortex_r52/gnu/src/tx_thread_fiq_nesting_end.S +++ b/ports/cortex_r52/gnu/src/tx_thread_fiq_nesting_end.S @@ -8,7 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ -@ Some portions generated by Claude Code (Opus 5). +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ diff --git a/ports/cortex_r52/gnu/src/tx_thread_fiq_nesting_start.S b/ports/cortex_r52/gnu/src/tx_thread_fiq_nesting_start.S index 7c9be8d31..516eef635 100644 --- a/ports/cortex_r52/gnu/src/tx_thread_fiq_nesting_start.S +++ b/ports/cortex_r52/gnu/src/tx_thread_fiq_nesting_start.S @@ -8,7 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ -@ Some portions generated by Claude Code (Opus 5). +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ diff --git a/ports/cortex_r52/gnu/src/tx_thread_interrupt_control.S b/ports/cortex_r52/gnu/src/tx_thread_interrupt_control.S index 430f6ea28..3bc0e54a6 100644 --- a/ports/cortex_r52/gnu/src/tx_thread_interrupt_control.S +++ b/ports/cortex_r52/gnu/src/tx_thread_interrupt_control.S @@ -8,7 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ -@ Some portions generated by Claude Code (Opus 5). +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ diff --git a/ports/cortex_r52/gnu/src/tx_thread_interrupt_disable.S b/ports/cortex_r52/gnu/src/tx_thread_interrupt_disable.S index 1e10b9582..9b3f215a2 100644 --- a/ports/cortex_r52/gnu/src/tx_thread_interrupt_disable.S +++ b/ports/cortex_r52/gnu/src/tx_thread_interrupt_disable.S @@ -8,7 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ -@ Some portions generated by Claude Code (Opus 5). +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ diff --git a/ports/cortex_r52/gnu/src/tx_thread_interrupt_restore.S b/ports/cortex_r52/gnu/src/tx_thread_interrupt_restore.S index ea95e57cb..b014afd9c 100644 --- a/ports/cortex_r52/gnu/src/tx_thread_interrupt_restore.S +++ b/ports/cortex_r52/gnu/src/tx_thread_interrupt_restore.S @@ -8,7 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ -@ Some portions generated by Claude Code (Opus 5). +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ diff --git a/ports/cortex_r52/gnu/src/tx_thread_irq_nesting_end.S b/ports/cortex_r52/gnu/src/tx_thread_irq_nesting_end.S index 6e34d110c..f14ce5cf9 100644 --- a/ports/cortex_r52/gnu/src/tx_thread_irq_nesting_end.S +++ b/ports/cortex_r52/gnu/src/tx_thread_irq_nesting_end.S @@ -8,7 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ -@ Some portions generated by Claude Code (Opus 5). +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ diff --git a/ports/cortex_r52/gnu/src/tx_thread_irq_nesting_start.S b/ports/cortex_r52/gnu/src/tx_thread_irq_nesting_start.S index 38134b7da..e300a5be9 100644 --- a/ports/cortex_r52/gnu/src/tx_thread_irq_nesting_start.S +++ b/ports/cortex_r52/gnu/src/tx_thread_irq_nesting_start.S @@ -8,7 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ -@ Some portions generated by Claude Code (Opus 5). +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ diff --git a/ports/cortex_r52/gnu/src/tx_thread_schedule.S b/ports/cortex_r52/gnu/src/tx_thread_schedule.S index 271667fb7..2dfc1da79 100644 --- a/ports/cortex_r52/gnu/src/tx_thread_schedule.S +++ b/ports/cortex_r52/gnu/src/tx_thread_schedule.S @@ -8,7 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ -@ Some portions generated by Claude Code (Opus 5). +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ diff --git a/ports/cortex_r52/gnu/src/tx_thread_stack_build.S b/ports/cortex_r52/gnu/src/tx_thread_stack_build.S index dc9238c43..1be3b5f33 100644 --- a/ports/cortex_r52/gnu/src/tx_thread_stack_build.S +++ b/ports/cortex_r52/gnu/src/tx_thread_stack_build.S @@ -8,7 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ -@ Some portions generated by Claude Code (Opus 5). +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ diff --git a/ports/cortex_r52/gnu/src/tx_thread_system_return.S b/ports/cortex_r52/gnu/src/tx_thread_system_return.S index c0ab615b4..ae0eac7d3 100644 --- a/ports/cortex_r52/gnu/src/tx_thread_system_return.S +++ b/ports/cortex_r52/gnu/src/tx_thread_system_return.S @@ -8,7 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ -@ Some portions generated by Claude Code (Opus 5). +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ diff --git a/ports/cortex_r52/gnu/src/tx_thread_vectored_context_save.S b/ports/cortex_r52/gnu/src/tx_thread_vectored_context_save.S index 68e945e06..60eeca7b5 100644 --- a/ports/cortex_r52/gnu/src/tx_thread_vectored_context_save.S +++ b/ports/cortex_r52/gnu/src/tx_thread_vectored_context_save.S @@ -8,7 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ -@ Some portions generated by Claude Code (Opus 5). +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ diff --git a/ports/cortex_r52/gnu/src/tx_timer_interrupt.S b/ports/cortex_r52/gnu/src/tx_timer_interrupt.S index 7d45de601..e70a4d022 100644 --- a/ports/cortex_r52/gnu/src/tx_timer_interrupt.S +++ b/ports/cortex_r52/gnu/src/tx_timer_interrupt.S @@ -8,7 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ -@ Some portions generated by Claude Code (Opus 5). +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ diff --git a/ports/linux/gnu/src/tx_thread_stack_build.c b/ports/linux/gnu/src/tx_thread_stack_build.c index 98c1ca716..d1d8b44fa 100644 --- a/ports/linux/gnu/src/tx_thread_stack_build.c +++ b/ports/linux/gnu/src/tx_thread_stack_build.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/risc-v32/gnu/src/tx_thread_context_save.S b/ports/risc-v32/gnu/src/tx_thread_context_save.S index 9a67520aa..e93d5870d 100644 --- a/ports/risc-v32/gnu/src/tx_thread_context_save.S +++ b/ports/risc-v32/gnu/src/tx_thread_context_save.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/risc-v32/iar/src/tx_thread_context_save.s b/ports/risc-v32/iar/src/tx_thread_context_save.s index 76672cde2..68bfdac98 100644 --- a/ports/risc-v32/iar/src/tx_thread_context_save.s +++ b/ports/risc-v32/iar/src/tx_thread_context_save.s @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -; Some portions generated by Copilot (Opus 5). +; Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/risc-v64/gnu/inc/tx_port.h b/ports/risc-v64/gnu/inc/tx_port.h index ad71694be..e771f4513 100644 --- a/ports/risc-v64/gnu/inc/tx_port.h +++ b/ports/risc-v64/gnu/inc/tx_port.h @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Claude Code (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/risc-v64/gnu/src/tx_thread_context_save.S b/ports/risc-v64/gnu/src/tx_thread_context_save.S index d85833b37..1924bd6ee 100644 --- a/ports/risc-v64/gnu/src/tx_thread_context_save.S +++ b/ports/risc-v64/gnu/src/tx_thread_context_save.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/win32/vs_2019/inc/tx_port.h b/ports/win32/vs_2019/inc/tx_port.h index 4d3e3b509..7c882a632 100644 --- a/ports/win32/vs_2019/inc/tx_port.h +++ b/ports/win32/vs_2019/inc/tx_port.h @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (gpt-5.6-sol). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/win32/vs_2019/src/tx_initialize_low_level.c b/ports/win32/vs_2019/src/tx_initialize_low_level.c index e531b1ca9..82bee7426 100644 --- a/ports/win32/vs_2019/src/tx_initialize_low_level.c +++ b/ports/win32/vs_2019/src/tx_initialize_low_level.c @@ -9,8 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (gpt 5.4). -// Some portions generated by Codex (gpt-5.6-sol). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/win32/vs_2019/src/tx_thread_context_restore.c b/ports/win32/vs_2019/src/tx_thread_context_restore.c index ae559bed8..215489c9e 100644 --- a/ports/win32/vs_2019/src/tx_thread_context_restore.c +++ b/ports/win32/vs_2019/src/tx_thread_context_restore.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (gpt-5.6-sol). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/win32/vs_2019/src/tx_thread_context_save.c b/ports/win32/vs_2019/src/tx_thread_context_save.c index 4574b8277..769c650b4 100644 --- a/ports/win32/vs_2019/src/tx_thread_context_save.c +++ b/ports/win32/vs_2019/src/tx_thread_context_save.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (gpt-5.6-sol). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/win32/vs_2019/src/tx_thread_interrupt_control.c b/ports/win32/vs_2019/src/tx_thread_interrupt_control.c index ca73b7fba..03a017fb8 100644 --- a/ports/win32/vs_2019/src/tx_thread_interrupt_control.c +++ b/ports/win32/vs_2019/src/tx_thread_interrupt_control.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (gpt-5.6-sol). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/win32/vs_2019/src/tx_thread_schedule.c b/ports/win32/vs_2019/src/tx_thread_schedule.c index 1fa11c596..e9dc43d77 100644 --- a/ports/win32/vs_2019/src/tx_thread_schedule.c +++ b/ports/win32/vs_2019/src/tx_thread_schedule.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (gpt-5.6-sol). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/win32/vs_2019/src/tx_thread_stack_build.c b/ports/win32/vs_2019/src/tx_thread_stack_build.c index f473ec953..94b924053 100644 --- a/ports/win32/vs_2019/src/tx_thread_stack_build.c +++ b/ports/win32/vs_2019/src/tx_thread_stack_build.c @@ -9,8 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (gpt-5.6-sol). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/win32/vs_2019/src/tx_thread_system_return.c b/ports/win32/vs_2019/src/tx_thread_system_return.c index 52f65b4f8..a14c326eb 100644 --- a/ports/win32/vs_2019/src/tx_thread_system_return.c +++ b/ports/win32/vs_2019/src/tx_thread_system_return.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (gpt-5.6-sol). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/win64/vs_2022/inc/tx_port.h b/ports/win64/vs_2022/inc/tx_port.h index 2b486ed95..412143546 100644 --- a/ports/win64/vs_2022/inc/tx_port.h +++ b/ports/win64/vs_2022/inc/tx_port.h @@ -13,7 +13,7 @@ * SPDX-License-Identifier: MIT and CC0-1.0 **************************************************************************/ -// Some portions generated by Codex (gpt-5.6-sol). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/win64/vs_2022/src/tx_initialize_low_level.c b/ports/win64/vs_2022/src/tx_initialize_low_level.c index b41477d75..0bb1f3e3d 100644 --- a/ports/win64/vs_2022/src/tx_initialize_low_level.c +++ b/ports/win64/vs_2022/src/tx_initialize_low_level.c @@ -13,8 +13,7 @@ * SPDX-License-Identifier: MIT and CC0-1.0 **************************************************************************/ -// Some portions generated by Codex (gpt 5.4). -// Some portions generated by Codex (gpt-5.6-sol). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ /** */ diff --git a/ports/win64/vs_2022/src/tx_thread_context_restore.c b/ports/win64/vs_2022/src/tx_thread_context_restore.c index f860d61f0..ae265da1a 100644 --- a/ports/win64/vs_2022/src/tx_thread_context_restore.c +++ b/ports/win64/vs_2022/src/tx_thread_context_restore.c @@ -13,8 +13,7 @@ * SPDX-License-Identifier: MIT and CC0-1.0 **************************************************************************/ -// Some portions generated by Codex (gpt 5.4). -// Some portions generated by Codex (gpt-5.6-sol). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/win64/vs_2022/src/tx_thread_interrupt_control.c b/ports/win64/vs_2022/src/tx_thread_interrupt_control.c index b38a0749b..ff6329d63 100644 --- a/ports/win64/vs_2022/src/tx_thread_interrupt_control.c +++ b/ports/win64/vs_2022/src/tx_thread_interrupt_control.c @@ -13,7 +13,7 @@ * SPDX-License-Identifier: MIT and CC0-1.0 **************************************************************************/ -// Some portions generated by Codex (gpt-5.6-sol). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/win64/vs_2022/src/tx_thread_schedule.c b/ports/win64/vs_2022/src/tx_thread_schedule.c index f6bef9495..204a1e90c 100644 --- a/ports/win64/vs_2022/src/tx_thread_schedule.c +++ b/ports/win64/vs_2022/src/tx_thread_schedule.c @@ -13,8 +13,7 @@ * SPDX-License-Identifier: MIT and CC0-1.0 **************************************************************************/ -// Some portions generated by Codex (gpt 5.4). -// Some portions generated by Codex (gpt-5.6-sol). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports/win64/vs_2022/src/tx_thread_stack_build.c b/ports/win64/vs_2022/src/tx_thread_stack_build.c index 4f6be75cf..20aa85240 100644 --- a/ports/win64/vs_2022/src/tx_thread_stack_build.c +++ b/ports/win64/vs_2022/src/tx_thread_stack_build.c @@ -13,10 +13,8 @@ * SPDX-License-Identifier: MIT and CC0-1.0 **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. -// Some portions generated by Codex (gpt 5.4). -// Some portions generated by Codex (gpt-5.6-sol). /**************************************************************************/ /**************************************************************************/ diff --git a/ports/win64/vs_2022/src/tx_thread_system_return.c b/ports/win64/vs_2022/src/tx_thread_system_return.c index 9b1fa210a..47249d0eb 100644 --- a/ports/win64/vs_2022/src/tx_thread_system_return.c +++ b/ports/win64/vs_2022/src/tx_thread_system_return.c @@ -13,8 +13,7 @@ * SPDX-License-Identifier: MIT and CC0-1.0 **************************************************************************/ -// Some portions generated by Codex (gpt 5.4). -// Some portions generated by Codex (gpt-5.6-sol). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_arch/ARMv7-A/threadx/common/src/tx_thread_system_return.S b/ports_arch/ARMv7-A/threadx/common/src/tx_thread_system_return.S index 9aa7e0e50..7671bba27 100644 --- a/ports_arch/ARMv7-A/threadx/common/src/tx_thread_system_return.S +++ b/ports_arch/ARMv7-A/threadx/common/src/tx_thread_system_return.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_arch/ARMv7-M/threadx/ac5/example_build/tx_initialize_low_level.s b/ports_arch/ARMv7-M/threadx/ac5/example_build/tx_initialize_low_level.s index 4b7611af8..5df0582ed 100644 --- a/ports_arch/ARMv7-M/threadx/ac5/example_build/tx_initialize_low_level.s +++ b/ports_arch/ARMv7-M/threadx/ac5/example_build/tx_initialize_low_level.s @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_schedule.s b/ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_schedule.s index 2f0f22821..3e237f31a 100644 --- a/ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_schedule.s +++ b/ports_arch/ARMv7-M/threadx/ac5/src/tx_thread_schedule.s @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_arch/ARMv7-M/threadx/ac6/example_build/sample_threadx/tx_initialize_low_level.S b/ports_arch/ARMv7-M/threadx/ac6/example_build/sample_threadx/tx_initialize_low_level.S index 9b89b732e..d14efe4d9 100644 --- a/ports_arch/ARMv7-M/threadx/ac6/example_build/sample_threadx/tx_initialize_low_level.S +++ b/ports_arch/ARMv7-M/threadx/ac6/example_build/sample_threadx/tx_initialize_low_level.S @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_schedule.S b/ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_schedule.S index edf3cea58..5f600c7df 100644 --- a/ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_schedule.S +++ b/ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_schedule.S @@ -8,8 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_system_return.S b/ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_system_return.S index ad07e2aa9..efa4e03f1 100644 --- a/ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_system_return.S +++ b/ports_arch/ARMv7-M/threadx/ac6/src/tx_thread_system_return.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_arch/ARMv7-M/threadx/gnu/example_build/tx_initialize_low_level.S b/ports_arch/ARMv7-M/threadx/gnu/example_build/tx_initialize_low_level.S index 220b8b6de..a8bb445bb 100644 --- a/ports_arch/ARMv7-M/threadx/gnu/example_build/tx_initialize_low_level.S +++ b/ports_arch/ARMv7-M/threadx/gnu/example_build/tx_initialize_low_level.S @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_schedule.S b/ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_schedule.S index 75c95d0bb..182eb81a0 100644 --- a/ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_schedule.S +++ b/ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_schedule.S @@ -8,8 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_system_return.S b/ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_system_return.S index af17e9a74..ab050566d 100644 --- a/ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_system_return.S +++ b/ports_arch/ARMv7-M/threadx/gnu/src/tx_thread_system_return.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_arch/ARMv7-M/threadx/iar/example_build/tx_initialize_low_level.s b/ports_arch/ARMv7-M/threadx/iar/example_build/tx_initialize_low_level.s index c7734a377..54aa42318 100644 --- a/ports_arch/ARMv7-M/threadx/iar/example_build/tx_initialize_low_level.s +++ b/ports_arch/ARMv7-M/threadx/iar/example_build/tx_initialize_low_level.s @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_arch/ARMv7-M/threadx/iar/src/tx_iar.c b/ports_arch/ARMv7-M/threadx/iar/src/tx_iar.c index ddfdaf3dd..ab6c209cc 100644 --- a/ports_arch/ARMv7-M/threadx/iar/src/tx_iar.c +++ b/ports_arch/ARMv7-M/threadx/iar/src/tx_iar.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_arch/ARMv7-M/threadx/iar/src/tx_thread_schedule.s b/ports_arch/ARMv7-M/threadx/iar/src/tx_thread_schedule.s index c3ce6e31d..f33e62775 100644 --- a/ports_arch/ARMv7-M/threadx/iar/src/tx_thread_schedule.s +++ b/ports_arch/ARMv7-M/threadx/iar/src/tx_thread_schedule.s @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_arch/ARMv7-M/threadx/iar/src/tx_thread_system_return.s b/ports_arch/ARMv7-M/threadx/iar/src/tx_thread_system_return.s index 18a449325..58be8f729 100644 --- a/ports_arch/ARMv7-M/threadx/iar/src/tx_thread_system_return.s +++ b/ports_arch/ARMv7-M/threadx/iar/src/tx_thread_system_return.s @@ -9,7 +9,7 @@ ;* SPDX-License-Identifier: MIT ;************************************************************************** -; Some portions generated by Gemini (Gemini 2.0 Flash). +; Portions of this file were generated with AI assistance. ;************************************************************************** diff --git a/ports_arch/ARMv7-M/threadx/inc/tx_port.h b/ports_arch/ARMv7-M/threadx/inc/tx_port.h index 1b1471397..088a8f91e 100644 --- a/ports_arch/ARMv7-M/threadx/inc/tx_port.h +++ b/ports_arch/ARMv7-M/threadx/inc/tx_port.h @@ -9,10 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). -// Some portions generated by Copilot (Claude Sonnet 4.6). -// Some portions generated by Claude Code (Opus 5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_arch/ARMv7-M/threadx_modules/ac5/module_manager/src/tx_thread_schedule.s b/ports_arch/ARMv7-M/threadx_modules/ac5/module_manager/src/tx_thread_schedule.s index f7e2bcb9d..bff9e4fd1 100644 --- a/ports_arch/ARMv7-M/threadx_modules/ac5/module_manager/src/tx_thread_schedule.s +++ b/ports_arch/ARMv7-M/threadx_modules/ac5/module_manager/src/tx_thread_schedule.s @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_arch/ARMv7-M/threadx_modules/ac6/module_manager/src/tx_thread_schedule.S b/ports_arch/ARMv7-M/threadx_modules/ac6/module_manager/src/tx_thread_schedule.S index cd030c9f9..77a7484fa 100644 --- a/ports_arch/ARMv7-M/threadx_modules/ac6/module_manager/src/tx_thread_schedule.S +++ b/ports_arch/ARMv7-M/threadx_modules/ac6/module_manager/src/tx_thread_schedule.S @@ -8,8 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_arch/ARMv7-M/threadx_modules/gnu/module_manager/src/tx_thread_schedule.S b/ports_arch/ARMv7-M/threadx_modules/gnu/module_manager/src/tx_thread_schedule.S index a4aa07ad0..ad2ad8f05 100644 --- a/ports_arch/ARMv7-M/threadx_modules/gnu/module_manager/src/tx_thread_schedule.S +++ b/ports_arch/ARMv7-M/threadx_modules/gnu/module_manager/src/tx_thread_schedule.S @@ -8,8 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_arch/ARMv7-M/threadx_modules/iar/module_manager/src/tx_iar.c b/ports_arch/ARMv7-M/threadx_modules/iar/module_manager/src/tx_iar.c index ddfdaf3dd..ab6c209cc 100644 --- a/ports_arch/ARMv7-M/threadx_modules/iar/module_manager/src/tx_iar.c +++ b/ports_arch/ARMv7-M/threadx_modules/iar/module_manager/src/tx_iar.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_arch/ARMv7-M/threadx_modules/iar/module_manager/src/tx_thread_schedule.s b/ports_arch/ARMv7-M/threadx_modules/iar/module_manager/src/tx_thread_schedule.s index 81c319b0e..00a279257 100644 --- a/ports_arch/ARMv7-M/threadx_modules/iar/module_manager/src/tx_thread_schedule.s +++ b/ports_arch/ARMv7-M/threadx_modules/iar/module_manager/src/tx_thread_schedule.s @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_arch/ARMv8-A/threadx/ports/gnu/src/tx_initialize_low_level.S b/ports_arch/ARMv8-A/threadx/ports/gnu/src/tx_initialize_low_level.S index 07e4ea111..f86568c5d 100644 --- a/ports_arch/ARMv8-A/threadx/ports/gnu/src/tx_initialize_low_level.S +++ b/ports_arch/ARMv8-A/threadx/ports/gnu/src/tx_initialize_low_level.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_arch/ARMv8-A/threadx_smp/common/src/tx_thread_smp_time_get.S b/ports_arch/ARMv8-A/threadx_smp/common/src/tx_thread_smp_time_get.S index 81286412e..4bb9f1cbf 100644 --- a/ports_arch/ARMv8-A/threadx_smp/common/src/tx_thread_smp_time_get.S +++ b/ports_arch/ARMv8-A/threadx_smp/common/src/tx_thread_smp_time_get.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_arch/ARMv8-M/threadx/ac6/src/tx_initialize_low_level.S b/ports_arch/ARMv8-M/threadx/ac6/src/tx_initialize_low_level.S index 417bd9330..4e81ac675 100644 --- a/ports_arch/ARMv8-M/threadx/ac6/src/tx_initialize_low_level.S +++ b/ports_arch/ARMv8-M/threadx/ac6/src/tx_initialize_low_level.S @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_schedule.S b/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_schedule.S index 29141833f..ba34803a8 100644 --- a/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_schedule.S +++ b/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_schedule.S @@ -8,8 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_system_return.S b/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_system_return.S index 5e2164cb0..c188969c9 100644 --- a/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_system_return.S +++ b/ports_arch/ARMv8-M/threadx/ac6/src/tx_thread_system_return.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_schedule.S b/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_schedule.S index b566fa2a1..285482464 100644 --- a/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_schedule.S +++ b/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_schedule.S @@ -8,8 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_system_return.S b/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_system_return.S index 420a6ef39..433b16ad7 100644 --- a/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_system_return.S +++ b/ports_arch/ARMv8-M/threadx/gnu/src/tx_thread_system_return.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_arch/ARMv8-M/threadx/iar/src/tx_iar.c b/ports_arch/ARMv8-M/threadx/iar/src/tx_iar.c index ddfdaf3dd..ab6c209cc 100644 --- a/ports_arch/ARMv8-M/threadx/iar/src/tx_iar.c +++ b/ports_arch/ARMv8-M/threadx/iar/src/tx_iar.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_arch/ARMv8-M/threadx/iar/src/tx_initialize_low_level.s b/ports_arch/ARMv8-M/threadx/iar/src/tx_initialize_low_level.s index e074ce8ea..9802be78b 100644 --- a/ports_arch/ARMv8-M/threadx/iar/src/tx_initialize_low_level.s +++ b/ports_arch/ARMv8-M/threadx/iar/src/tx_initialize_low_level.s @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_schedule.s b/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_schedule.s index adbb2d5aa..4fa3a10ed 100644 --- a/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_schedule.s +++ b/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_schedule.s @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_system_return.s b/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_system_return.s index 4bc165238..461d411a8 100644 --- a/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_system_return.s +++ b/ports_arch/ARMv8-M/threadx/iar/src/tx_thread_system_return.s @@ -9,7 +9,7 @@ ;* SPDX-License-Identifier: MIT ;************************************************************************** -; Some portions generated by Gemini (Gemini 2.0 Flash). +; Portions of this file were generated with AI assistance. ;************************************************************************** diff --git a/ports_arch/ARMv8-M/threadx/inc/tx_port.h b/ports_arch/ARMv8-M/threadx/inc/tx_port.h index cabf1c203..625ca2bec 100644 --- a/ports_arch/ARMv8-M/threadx/inc/tx_port.h +++ b/ports_arch/ARMv8-M/threadx/inc/tx_port.h @@ -9,9 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). -// Some portions generated by Claude Code (Opus 5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_a35/ac6/example_build/sample_threadx_module_manager/sample_threadx_module_manager.c b/ports_module/cortex_a35/ac6/example_build/sample_threadx_module_manager/sample_threadx_module_manager.c index c53fec02a..39598be4a 100644 --- a/ports_module/cortex_a35/ac6/example_build/sample_threadx_module_manager/sample_threadx_module_manager.c +++ b/ports_module/cortex_a35/ac6/example_build/sample_threadx_module_manager/sample_threadx_module_manager.c @@ -9,7 +9,7 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /* Small demonstration of the ThreadX module manager. */ diff --git a/ports_module/cortex_a35/gnu/example_build/sample_threadx/tx_initialize_low_level.S b/ports_module/cortex_a35/gnu/example_build/sample_threadx/tx_initialize_low_level.S index 834568ed2..d0bc4c0cd 100644 --- a/ports_module/cortex_a35/gnu/example_build/sample_threadx/tx_initialize_low_level.S +++ b/ports_module/cortex_a35/gnu/example_build/sample_threadx/tx_initialize_low_level.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_module/cortex_a35/gnu/example_build/sample_threadx_module_manager/sample_threadx_module_manager.c b/ports_module/cortex_a35/gnu/example_build/sample_threadx_module_manager/sample_threadx_module_manager.c index c53fec02a..39598be4a 100644 --- a/ports_module/cortex_a35/gnu/example_build/sample_threadx_module_manager/sample_threadx_module_manager.c +++ b/ports_module/cortex_a35/gnu/example_build/sample_threadx_module_manager/sample_threadx_module_manager.c @@ -9,7 +9,7 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /* Small demonstration of the ThreadX module manager. */ diff --git a/ports_module/cortex_a35/gnu/example_build/sample_threadx_module_manager/tx_initialize_low_level.S b/ports_module/cortex_a35/gnu/example_build/sample_threadx_module_manager/tx_initialize_low_level.S index 834568ed2..d0bc4c0cd 100644 --- a/ports_module/cortex_a35/gnu/example_build/sample_threadx_module_manager/tx_initialize_low_level.S +++ b/ports_module/cortex_a35/gnu/example_build/sample_threadx_module_manager/tx_initialize_low_level.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_module/cortex_a35_smp/ac6/example_build/sample_threadx_module_manager/sample_threadx_module_manager.c b/ports_module/cortex_a35_smp/ac6/example_build/sample_threadx_module_manager/sample_threadx_module_manager.c index c53fec02a..39598be4a 100644 --- a/ports_module/cortex_a35_smp/ac6/example_build/sample_threadx_module_manager/sample_threadx_module_manager.c +++ b/ports_module/cortex_a35_smp/ac6/example_build/sample_threadx_module_manager/sample_threadx_module_manager.c @@ -9,7 +9,7 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /* Small demonstration of the ThreadX module manager. */ diff --git a/ports_module/cortex_a35_smp/gnu/example_build/sample_threadx_module_manager/sample_threadx_module_manager.c b/ports_module/cortex_a35_smp/gnu/example_build/sample_threadx_module_manager/sample_threadx_module_manager.c index c53fec02a..39598be4a 100644 --- a/ports_module/cortex_a35_smp/gnu/example_build/sample_threadx_module_manager/sample_threadx_module_manager.c +++ b/ports_module/cortex_a35_smp/gnu/example_build/sample_threadx_module_manager/sample_threadx_module_manager.c @@ -9,7 +9,7 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /* Small demonstration of the ThreadX module manager. */ diff --git a/ports_module/cortex_a7/gnu/module_manager/src/tx_thread_system_return.S b/ports_module/cortex_a7/gnu/module_manager/src/tx_thread_system_return.S index fae8a96a2..b9d171684 100644 --- a/ports_module/cortex_a7/gnu/module_manager/src/tx_thread_system_return.S +++ b/ports_module/cortex_a7/gnu/module_manager/src/tx_thread_system_return.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_module/cortex_a7/iar/module_manager/src/tx_iar.c b/ports_module/cortex_a7/iar/module_manager/src/tx_iar.c index ddfdaf3dd..ab6c209cc 100644 --- a/ports_module/cortex_a7/iar/module_manager/src/tx_iar.c +++ b/ports_module/cortex_a7/iar/module_manager/src/tx_iar.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_module/cortex_a7/iar/module_manager/src/tx_thread_system_return.s b/ports_module/cortex_a7/iar/module_manager/src/tx_thread_system_return.s index dd041adc0..212a1f63d 100644 --- a/ports_module/cortex_a7/iar/module_manager/src/tx_thread_system_return.s +++ b/ports_module/cortex_a7/iar/module_manager/src/tx_thread_system_return.s @@ -9,7 +9,7 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ ; -; // Some portions generated by Copilot (Opus 5). +; Portions of this file were generated with AI assistance. ; ;/**************************************************************************/ ;/**************************************************************************/ diff --git a/ports_module/cortex_m0+/ac6/example_build/sample_threadx/tx_initialize_low_level.S b/ports_module/cortex_m0+/ac6/example_build/sample_threadx/tx_initialize_low_level.S index db06ba6e1..ce3148225 100644 --- a/ports_module/cortex_m0+/ac6/example_build/sample_threadx/tx_initialize_low_level.S +++ b/ports_module/cortex_m0+/ac6/example_build/sample_threadx/tx_initialize_low_level.S @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_m0+/ac6/example_build/sample_threadx_module_manager/tx_initialize_low_level.S b/ports_module/cortex_m0+/ac6/example_build/sample_threadx_module_manager/tx_initialize_low_level.S index e72056098..18cce85cd 100644 --- a/ports_module/cortex_m0+/ac6/example_build/sample_threadx_module_manager/tx_initialize_low_level.S +++ b/ports_module/cortex_m0+/ac6/example_build/sample_threadx_module_manager/tx_initialize_low_level.S @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_m0+/gnu/example_build/sample_threadx/tx_initialize_low_level.S b/ports_module/cortex_m0+/gnu/example_build/sample_threadx/tx_initialize_low_level.S index d229d6830..45f911be7 100644 --- a/ports_module/cortex_m0+/gnu/example_build/sample_threadx/tx_initialize_low_level.S +++ b/ports_module/cortex_m0+/gnu/example_build/sample_threadx/tx_initialize_low_level.S @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_m0+/gnu/example_build/sample_threadx_module/gcc_setup.s b/ports_module/cortex_m0+/gnu/example_build/sample_threadx_module/gcc_setup.s index 999b99eea..e5459dae0 100644 --- a/ports_module/cortex_m0+/gnu/example_build/sample_threadx_module/gcc_setup.s +++ b/ports_module/cortex_m0+/gnu/example_build/sample_threadx_module/gcc_setup.s @@ -1,5 +1,5 @@ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. .text .align 4 diff --git a/ports_module/cortex_m0+/gnu/example_build/sample_threadx_module_manager/tx_initialize_low_level.S b/ports_module/cortex_m0+/gnu/example_build/sample_threadx_module_manager/tx_initialize_low_level.S index 46ea9c3a5..3b38d6dae 100644 --- a/ports_module/cortex_m0+/gnu/example_build/sample_threadx_module_manager/tx_initialize_low_level.S +++ b/ports_module/cortex_m0+/gnu/example_build/sample_threadx_module_manager/tx_initialize_low_level.S @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_m0+/iar/example_build/tx_initialize_low_level.s b/ports_module/cortex_m0+/iar/example_build/tx_initialize_low_level.s index 35c3393ff..2f7c98c81 100644 --- a/ports_module/cortex_m0+/iar/example_build/tx_initialize_low_level.s +++ b/ports_module/cortex_m0+/iar/example_build/tx_initialize_low_level.s @@ -8,7 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ -; Some portions generated by Copilot (Opus 5). +; Portions of this file were generated with AI assistance. ; ; ;/**************************************************************************/ diff --git a/ports_module/cortex_m0+/iar/module_manager/src/tx_iar.c b/ports_module/cortex_m0+/iar/module_manager/src/tx_iar.c index ddfdaf3dd..ab6c209cc 100644 --- a/ports_module/cortex_m0+/iar/module_manager/src/tx_iar.c +++ b/ports_module/cortex_m0+/iar/module_manager/src/tx_iar.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_module/cortex_m23/ac6/example_build/tx_initialize_low_level.S b/ports_module/cortex_m23/ac6/example_build/tx_initialize_low_level.S index 4c6ae772d..99c998191 100644 --- a/ports_module/cortex_m23/ac6/example_build/tx_initialize_low_level.S +++ b/ports_module/cortex_m23/ac6/example_build/tx_initialize_low_level.S @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_m23/gnu/module_manager/src/tx_initialize_low_level.S b/ports_module/cortex_m23/gnu/module_manager/src/tx_initialize_low_level.S index 56dffa862..7e73dc96a 100644 --- a/ports_module/cortex_m23/gnu/module_manager/src/tx_initialize_low_level.S +++ b/ports_module/cortex_m23/gnu/module_manager/src/tx_initialize_low_level.S @@ -8,9 +8,8 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. -// Some portions generated by Claude Code (Opus 5). /**************************************************************************/ diff --git a/ports_module/cortex_m23/gnu/module_manager/src/tx_thread_context_restore.S b/ports_module/cortex_m23/gnu/module_manager/src/tx_thread_context_restore.S index f08f68fb0..bf3d7a5ba 100644 --- a/ports_module/cortex_m23/gnu/module_manager/src/tx_thread_context_restore.S +++ b/ports_module/cortex_m23/gnu/module_manager/src/tx_thread_context_restore.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Claude Code (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_m23/gnu/module_manager/src/tx_thread_context_save.S b/ports_module/cortex_m23/gnu/module_manager/src/tx_thread_context_save.S index b43467f7b..dc52d4154 100644 --- a/ports_module/cortex_m23/gnu/module_manager/src/tx_thread_context_save.S +++ b/ports_module/cortex_m23/gnu/module_manager/src/tx_thread_context_save.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Claude Code (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_m23/gnu/module_manager/src/tx_thread_secure_stack_initialize.S b/ports_module/cortex_m23/gnu/module_manager/src/tx_thread_secure_stack_initialize.S index 44cc33962..8e2bf2cdf 100644 --- a/ports_module/cortex_m23/gnu/module_manager/src/tx_thread_secure_stack_initialize.S +++ b/ports_module/cortex_m23/gnu/module_manager/src/tx_thread_secure_stack_initialize.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Claude Code (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_m23/iar/example_build/tx_initialize_low_level.s b/ports_module/cortex_m23/iar/example_build/tx_initialize_low_level.s index 14b78e58a..00e53af4d 100644 --- a/ports_module/cortex_m23/iar/example_build/tx_initialize_low_level.s +++ b/ports_module/cortex_m23/iar/example_build/tx_initialize_low_level.s @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_m3/ac5/example_build/tx_initialize_low_level.S b/ports_module/cortex_m3/ac5/example_build/tx_initialize_low_level.S index 2b1a96a71..c09961542 100644 --- a/ports_module/cortex_m3/ac5/example_build/tx_initialize_low_level.S +++ b/ports_module/cortex_m3/ac5/example_build/tx_initialize_low_level.S @@ -8,7 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ -; Some portions generated by Copilot (Opus 5). +; Portions of this file were generated with AI assistance. ; ; ;/**************************************************************************/ diff --git a/ports_module/cortex_m3/ac5/module_manager/src/tx_thread_schedule.s b/ports_module/cortex_m3/ac5/module_manager/src/tx_thread_schedule.s index fbc79a257..af6a96fe5 100644 --- a/ports_module/cortex_m3/ac5/module_manager/src/tx_thread_schedule.s +++ b/ports_module/cortex_m3/ac5/module_manager/src/tx_thread_schedule.s @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_m3/ac6/example_build/sample_threadx/tx_initialize_low_level.S b/ports_module/cortex_m3/ac6/example_build/sample_threadx/tx_initialize_low_level.S index 6f9f6cc70..43c3fe1ca 100644 --- a/ports_module/cortex_m3/ac6/example_build/sample_threadx/tx_initialize_low_level.S +++ b/ports_module/cortex_m3/ac6/example_build/sample_threadx/tx_initialize_low_level.S @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_m3/ac6/example_build/sample_threadx_module_manager/tx_initialize_low_level.S b/ports_module/cortex_m3/ac6/example_build/sample_threadx_module_manager/tx_initialize_low_level.S index 2a748d08d..43fa77497 100644 --- a/ports_module/cortex_m3/ac6/example_build/sample_threadx_module_manager/tx_initialize_low_level.S +++ b/ports_module/cortex_m3/ac6/example_build/sample_threadx_module_manager/tx_initialize_low_level.S @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_m3/ac6/module_manager/src/tx_thread_schedule.S b/ports_module/cortex_m3/ac6/module_manager/src/tx_thread_schedule.S index a62ac22fc..3ec031aac 100644 --- a/ports_module/cortex_m3/ac6/module_manager/src/tx_thread_schedule.S +++ b/ports_module/cortex_m3/ac6/module_manager/src/tx_thread_schedule.S @@ -8,8 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_m3/ac6/module_manager/src/tx_thread_system_return.S b/ports_module/cortex_m3/ac6/module_manager/src/tx_thread_system_return.S index 6d0e26afa..7b0c1df8c 100644 --- a/ports_module/cortex_m3/ac6/module_manager/src/tx_thread_system_return.S +++ b/ports_module/cortex_m3/ac6/module_manager/src/tx_thread_system_return.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_m3/gnu/example_build/gcc_setup.s b/ports_module/cortex_m3/gnu/example_build/gcc_setup.s index 1126df2d1..80ccb19b7 100644 --- a/ports_module/cortex_m3/gnu/example_build/gcc_setup.s +++ b/ports_module/cortex_m3/gnu/example_build/gcc_setup.s @@ -1,5 +1,5 @@ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. .text .align 4 diff --git a/ports_module/cortex_m3/gnu/example_build/tx_initialize_low_level.S b/ports_module/cortex_m3/gnu/example_build/tx_initialize_low_level.S index 63737c9cc..332adc4d8 100644 --- a/ports_module/cortex_m3/gnu/example_build/tx_initialize_low_level.S +++ b/ports_module/cortex_m3/gnu/example_build/tx_initialize_low_level.S @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_m3/gnu/module_manager/src/tx_thread_schedule.S b/ports_module/cortex_m3/gnu/module_manager/src/tx_thread_schedule.S index 00483552a..cc7eb3fdb 100644 --- a/ports_module/cortex_m3/gnu/module_manager/src/tx_thread_schedule.S +++ b/ports_module/cortex_m3/gnu/module_manager/src/tx_thread_schedule.S @@ -8,8 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_m3/gnu/module_manager/src/tx_thread_system_return.S b/ports_module/cortex_m3/gnu/module_manager/src/tx_thread_system_return.S index 92ad3f628..8d57c2e60 100644 --- a/ports_module/cortex_m3/gnu/module_manager/src/tx_thread_system_return.S +++ b/ports_module/cortex_m3/gnu/module_manager/src/tx_thread_system_return.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_m3/iar/example_build/tx_initialize_low_level.s b/ports_module/cortex_m3/iar/example_build/tx_initialize_low_level.s index 29ca88bbb..58f550812 100644 --- a/ports_module/cortex_m3/iar/example_build/tx_initialize_low_level.s +++ b/ports_module/cortex_m3/iar/example_build/tx_initialize_low_level.s @@ -8,7 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ -; Some portions generated by Copilot (Opus 5). +; Portions of this file were generated with AI assistance. ; ; ;/**************************************************************************/ diff --git a/ports_module/cortex_m3/iar/module_manager/src/tx_iar.c b/ports_module/cortex_m3/iar/module_manager/src/tx_iar.c index ddfdaf3dd..ab6c209cc 100644 --- a/ports_module/cortex_m3/iar/module_manager/src/tx_iar.c +++ b/ports_module/cortex_m3/iar/module_manager/src/tx_iar.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_module/cortex_m3/iar/module_manager/src/tx_thread_schedule.s b/ports_module/cortex_m3/iar/module_manager/src/tx_thread_schedule.s index efb1abf11..ce19b3513 100644 --- a/ports_module/cortex_m3/iar/module_manager/src/tx_thread_schedule.s +++ b/ports_module/cortex_m3/iar/module_manager/src/tx_thread_schedule.s @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_m3/iar/module_manager/src/tx_thread_system_return.s b/ports_module/cortex_m3/iar/module_manager/src/tx_thread_system_return.s index 7bc5f2ebc..5ff03c35c 100644 --- a/ports_module/cortex_m3/iar/module_manager/src/tx_thread_system_return.s +++ b/ports_module/cortex_m3/iar/module_manager/src/tx_thread_system_return.s @@ -9,7 +9,7 @@ ;* SPDX-License-Identifier: MIT ;************************************************************************** -; Some portions generated by Gemini (Gemini 2.0 Flash). +; Portions of this file were generated with AI assistance. ;************************************************************************** diff --git a/ports_module/cortex_m33/ac6/example_build/tx_initialize_low_level.S b/ports_module/cortex_m33/ac6/example_build/tx_initialize_low_level.S index f4a34575a..64af35f89 100644 --- a/ports_module/cortex_m33/ac6/example_build/tx_initialize_low_level.S +++ b/ports_module/cortex_m33/ac6/example_build/tx_initialize_low_level.S @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_m33/ac6/module_manager/src/tx_thread_schedule.S b/ports_module/cortex_m33/ac6/module_manager/src/tx_thread_schedule.S index f9885a5ff..7f64d5a4f 100644 --- a/ports_module/cortex_m33/ac6/module_manager/src/tx_thread_schedule.S +++ b/ports_module/cortex_m33/ac6/module_manager/src/tx_thread_schedule.S @@ -8,8 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_m33/gnu/example_build/gcc_setup.s b/ports_module/cortex_m33/gnu/example_build/gcc_setup.s index 1126df2d1..80ccb19b7 100644 --- a/ports_module/cortex_m33/gnu/example_build/gcc_setup.s +++ b/ports_module/cortex_m33/gnu/example_build/gcc_setup.s @@ -1,5 +1,5 @@ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. .text .align 4 diff --git a/ports_module/cortex_m33/gnu/module_manager/src/tx_initialize_low_level.S b/ports_module/cortex_m33/gnu/module_manager/src/tx_initialize_low_level.S index d735825e5..a75d4f111 100644 --- a/ports_module/cortex_m33/gnu/module_manager/src/tx_initialize_low_level.S +++ b/ports_module/cortex_m33/gnu/module_manager/src/tx_initialize_low_level.S @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_m33/gnu/module_manager/src/tx_thread_schedule.S b/ports_module/cortex_m33/gnu/module_manager/src/tx_thread_schedule.S index 6dcd33c5f..8b7936387 100644 --- a/ports_module/cortex_m33/gnu/module_manager/src/tx_thread_schedule.S +++ b/ports_module/cortex_m33/gnu/module_manager/src/tx_thread_schedule.S @@ -8,8 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_m33/iar/example_build/tx_initialize_low_level.s b/ports_module/cortex_m33/iar/example_build/tx_initialize_low_level.s index 4f4ae82c4..38e9c6875 100644 --- a/ports_module/cortex_m33/iar/example_build/tx_initialize_low_level.s +++ b/ports_module/cortex_m33/iar/example_build/tx_initialize_low_level.s @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_m33/iar/module_manager/src/tx_thread_schedule.s b/ports_module/cortex_m33/iar/module_manager/src/tx_thread_schedule.s index 5fcb99a4c..39cf644c8 100644 --- a/ports_module/cortex_m33/iar/module_manager/src/tx_thread_schedule.s +++ b/ports_module/cortex_m33/iar/module_manager/src/tx_thread_schedule.s @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_m4/ac5/example_build/tx_initialize_low_level.S b/ports_module/cortex_m4/ac5/example_build/tx_initialize_low_level.S index f14e718ea..c5c5ca973 100644 --- a/ports_module/cortex_m4/ac5/example_build/tx_initialize_low_level.S +++ b/ports_module/cortex_m4/ac5/example_build/tx_initialize_low_level.S @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_m4/ac5/module_manager/src/tx_thread_schedule.s b/ports_module/cortex_m4/ac5/module_manager/src/tx_thread_schedule.s index ddf5e8e5b..4b200b9a2 100644 --- a/ports_module/cortex_m4/ac5/module_manager/src/tx_thread_schedule.s +++ b/ports_module/cortex_m4/ac5/module_manager/src/tx_thread_schedule.s @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_m4/ac6/example_build/sample_threadx/tx_initialize_low_level.S b/ports_module/cortex_m4/ac6/example_build/sample_threadx/tx_initialize_low_level.S index aa03c18dd..c265b0cd4 100644 --- a/ports_module/cortex_m4/ac6/example_build/sample_threadx/tx_initialize_low_level.S +++ b/ports_module/cortex_m4/ac6/example_build/sample_threadx/tx_initialize_low_level.S @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_m4/ac6/example_build/sample_threadx_module_manager/tx_initialize_low_level.S b/ports_module/cortex_m4/ac6/example_build/sample_threadx_module_manager/tx_initialize_low_level.S index 36a865d1f..54d31042f 100644 --- a/ports_module/cortex_m4/ac6/example_build/sample_threadx_module_manager/tx_initialize_low_level.S +++ b/ports_module/cortex_m4/ac6/example_build/sample_threadx_module_manager/tx_initialize_low_level.S @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_m4/ac6/module_manager/src/tx_thread_schedule.S b/ports_module/cortex_m4/ac6/module_manager/src/tx_thread_schedule.S index 9d976db56..46419622b 100644 --- a/ports_module/cortex_m4/ac6/module_manager/src/tx_thread_schedule.S +++ b/ports_module/cortex_m4/ac6/module_manager/src/tx_thread_schedule.S @@ -8,8 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_m4/ac6/module_manager/src/tx_thread_system_return.S b/ports_module/cortex_m4/ac6/module_manager/src/tx_thread_system_return.S index 59a7210d5..e88861efc 100644 --- a/ports_module/cortex_m4/ac6/module_manager/src/tx_thread_system_return.S +++ b/ports_module/cortex_m4/ac6/module_manager/src/tx_thread_system_return.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_m4/gnu/example_build/gcc_setup.s b/ports_module/cortex_m4/gnu/example_build/gcc_setup.s index 1126df2d1..80ccb19b7 100644 --- a/ports_module/cortex_m4/gnu/example_build/gcc_setup.s +++ b/ports_module/cortex_m4/gnu/example_build/gcc_setup.s @@ -1,5 +1,5 @@ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. .text .align 4 diff --git a/ports_module/cortex_m4/gnu/example_build/tx_initialize_low_level.S b/ports_module/cortex_m4/gnu/example_build/tx_initialize_low_level.S index 6bb27823b..24cb0fa7c 100644 --- a/ports_module/cortex_m4/gnu/example_build/tx_initialize_low_level.S +++ b/ports_module/cortex_m4/gnu/example_build/tx_initialize_low_level.S @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_m4/gnu/module_manager/src/tx_thread_schedule.S b/ports_module/cortex_m4/gnu/module_manager/src/tx_thread_schedule.S index a5680bc21..a4c11abc1 100644 --- a/ports_module/cortex_m4/gnu/module_manager/src/tx_thread_schedule.S +++ b/ports_module/cortex_m4/gnu/module_manager/src/tx_thread_schedule.S @@ -8,8 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_m4/gnu/module_manager/src/tx_thread_system_return.S b/ports_module/cortex_m4/gnu/module_manager/src/tx_thread_system_return.S index 4709af37f..093493187 100644 --- a/ports_module/cortex_m4/gnu/module_manager/src/tx_thread_system_return.S +++ b/ports_module/cortex_m4/gnu/module_manager/src/tx_thread_system_return.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_m4/iar/example_build/tx_initialize_low_level.s b/ports_module/cortex_m4/iar/example_build/tx_initialize_low_level.s index ba580eae5..d066e08f7 100644 --- a/ports_module/cortex_m4/iar/example_build/tx_initialize_low_level.s +++ b/ports_module/cortex_m4/iar/example_build/tx_initialize_low_level.s @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_m4/iar/module_manager/src/tx_iar.c b/ports_module/cortex_m4/iar/module_manager/src/tx_iar.c index ddfdaf3dd..ab6c209cc 100644 --- a/ports_module/cortex_m4/iar/module_manager/src/tx_iar.c +++ b/ports_module/cortex_m4/iar/module_manager/src/tx_iar.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_module/cortex_m4/iar/module_manager/src/tx_thread_schedule.s b/ports_module/cortex_m4/iar/module_manager/src/tx_thread_schedule.s index 8006f7bcf..838fbfd39 100644 --- a/ports_module/cortex_m4/iar/module_manager/src/tx_thread_schedule.s +++ b/ports_module/cortex_m4/iar/module_manager/src/tx_thread_schedule.s @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_m4/iar/module_manager/src/tx_thread_system_return.s b/ports_module/cortex_m4/iar/module_manager/src/tx_thread_system_return.s index b466bacaa..dd2b38a6e 100644 --- a/ports_module/cortex_m4/iar/module_manager/src/tx_thread_system_return.s +++ b/ports_module/cortex_m4/iar/module_manager/src/tx_thread_system_return.s @@ -9,7 +9,7 @@ ;* SPDX-License-Identifier: MIT ;************************************************************************** -; Some portions generated by Gemini (Gemini 2.0 Flash). +; Portions of this file were generated with AI assistance. ;************************************************************************** diff --git a/ports_module/cortex_m7/ac5/example_build/tx_initialize_low_level.S b/ports_module/cortex_m7/ac5/example_build/tx_initialize_low_level.S index 20957edde..fa3603350 100644 --- a/ports_module/cortex_m7/ac5/example_build/tx_initialize_low_level.S +++ b/ports_module/cortex_m7/ac5/example_build/tx_initialize_low_level.S @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_m7/ac5/module_manager/src/tx_thread_schedule.s b/ports_module/cortex_m7/ac5/module_manager/src/tx_thread_schedule.s index 75771a45b..3e6b67935 100644 --- a/ports_module/cortex_m7/ac5/module_manager/src/tx_thread_schedule.s +++ b/ports_module/cortex_m7/ac5/module_manager/src/tx_thread_schedule.s @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_m7/ac6/example_build/sample_threadx/tx_initialize_low_level.S b/ports_module/cortex_m7/ac6/example_build/sample_threadx/tx_initialize_low_level.S index af0d05cbb..3ec0d1531 100644 --- a/ports_module/cortex_m7/ac6/example_build/sample_threadx/tx_initialize_low_level.S +++ b/ports_module/cortex_m7/ac6/example_build/sample_threadx/tx_initialize_low_level.S @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_m7/ac6/example_build/sample_threadx_module_manager/tx_initialize_low_level.S b/ports_module/cortex_m7/ac6/example_build/sample_threadx_module_manager/tx_initialize_low_level.S index 98e9b5375..9eb0bdf54 100644 --- a/ports_module/cortex_m7/ac6/example_build/sample_threadx_module_manager/tx_initialize_low_level.S +++ b/ports_module/cortex_m7/ac6/example_build/sample_threadx_module_manager/tx_initialize_low_level.S @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_m7/ac6/module_manager/src/tx_thread_schedule.S b/ports_module/cortex_m7/ac6/module_manager/src/tx_thread_schedule.S index 3019df1e3..958a739db 100644 --- a/ports_module/cortex_m7/ac6/module_manager/src/tx_thread_schedule.S +++ b/ports_module/cortex_m7/ac6/module_manager/src/tx_thread_schedule.S @@ -8,8 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_m7/ac6/module_manager/src/tx_thread_system_return.S b/ports_module/cortex_m7/ac6/module_manager/src/tx_thread_system_return.S index d0243dea6..4071b1a1e 100644 --- a/ports_module/cortex_m7/ac6/module_manager/src/tx_thread_system_return.S +++ b/ports_module/cortex_m7/ac6/module_manager/src/tx_thread_system_return.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_m7/gnu/example_build/gcc_setup.s b/ports_module/cortex_m7/gnu/example_build/gcc_setup.s index 1126df2d1..80ccb19b7 100644 --- a/ports_module/cortex_m7/gnu/example_build/gcc_setup.s +++ b/ports_module/cortex_m7/gnu/example_build/gcc_setup.s @@ -1,5 +1,5 @@ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. .text .align 4 diff --git a/ports_module/cortex_m7/gnu/example_build/tx_initialize_low_level.S b/ports_module/cortex_m7/gnu/example_build/tx_initialize_low_level.S index 1d0d2cea7..7252f7af6 100644 --- a/ports_module/cortex_m7/gnu/example_build/tx_initialize_low_level.S +++ b/ports_module/cortex_m7/gnu/example_build/tx_initialize_low_level.S @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_m7/gnu/module_manager/src/tx_thread_schedule.S b/ports_module/cortex_m7/gnu/module_manager/src/tx_thread_schedule.S index 8fc9307d5..0603be2f0 100644 --- a/ports_module/cortex_m7/gnu/module_manager/src/tx_thread_schedule.S +++ b/ports_module/cortex_m7/gnu/module_manager/src/tx_thread_schedule.S @@ -8,8 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_m7/gnu/module_manager/src/tx_thread_system_return.S b/ports_module/cortex_m7/gnu/module_manager/src/tx_thread_system_return.S index 180894b3b..6eb5a72d2 100644 --- a/ports_module/cortex_m7/gnu/module_manager/src/tx_thread_system_return.S +++ b/ports_module/cortex_m7/gnu/module_manager/src/tx_thread_system_return.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Gemini (Gemini 2.0 Flash). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_m7/iar/example_build/tx_initialize_low_level.s b/ports_module/cortex_m7/iar/example_build/tx_initialize_low_level.s index 631f41670..8c599aeff 100644 --- a/ports_module/cortex_m7/iar/example_build/tx_initialize_low_level.s +++ b/ports_module/cortex_m7/iar/example_build/tx_initialize_low_level.s @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_m7/iar/module_manager/src/tx_iar.c b/ports_module/cortex_m7/iar/module_manager/src/tx_iar.c index ddfdaf3dd..ab6c209cc 100644 --- a/ports_module/cortex_m7/iar/module_manager/src/tx_iar.c +++ b/ports_module/cortex_m7/iar/module_manager/src/tx_iar.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_module/cortex_m7/iar/module_manager/src/tx_thread_schedule.s b/ports_module/cortex_m7/iar/module_manager/src/tx_thread_schedule.s index 8a3da5c9b..5e2a95ad7 100644 --- a/ports_module/cortex_m7/iar/module_manager/src/tx_thread_schedule.s +++ b/ports_module/cortex_m7/iar/module_manager/src/tx_thread_schedule.s @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_m7/iar/module_manager/src/tx_thread_system_return.s b/ports_module/cortex_m7/iar/module_manager/src/tx_thread_system_return.s index 345fca808..ab1f05ba1 100644 --- a/ports_module/cortex_m7/iar/module_manager/src/tx_thread_system_return.s +++ b/ports_module/cortex_m7/iar/module_manager/src/tx_thread_system_return.s @@ -9,7 +9,7 @@ ;* SPDX-License-Identifier: MIT ;************************************************************************** -; Some portions generated by Gemini (Gemini 2.0 Flash). +; Portions of this file were generated with AI assistance. ;************************************************************************** diff --git a/ports_module/cortex_r4/ac6/module_manager/src/tx_thread_stack_build.S b/ports_module/cortex_r4/ac6/module_manager/src/tx_thread_stack_build.S index e3142ec4d..2e9049c0c 100644 --- a/ports_module/cortex_r4/ac6/module_manager/src/tx_thread_stack_build.S +++ b/ports_module/cortex_r4/ac6/module_manager/src/tx_thread_stack_build.S @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_r4/iar/module_manager/src/tx_iar.c b/ports_module/cortex_r4/iar/module_manager/src/tx_iar.c index ddfdaf3dd..ab6c209cc 100644 --- a/ports_module/cortex_r4/iar/module_manager/src/tx_iar.c +++ b/ports_module/cortex_r4/iar/module_manager/src/tx_iar.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_smp/arc_hs_smp/metaware/src/tx_thread_context_save.s b/ports_smp/arc_hs_smp/metaware/src/tx_thread_context_save.s index e24c15a48..13562cc82 100644 --- a/ports_smp/arc_hs_smp/metaware/src/tx_thread_context_save.s +++ b/ports_smp/arc_hs_smp/metaware/src/tx_thread_context_save.s @@ -9,7 +9,7 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ ; -; Some portions generated by Copilot (Opus 5). +; Portions of this file were generated with AI assistance. ; ;/**************************************************************************/ ;/**************************************************************************/ diff --git a/ports_smp/cortex_a34_smp/ac6/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a34_smp/ac6/src/tx_thread_smp_time_get.S index 81286412e..4bb9f1cbf 100644 --- a/ports_smp/cortex_a34_smp/ac6/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a34_smp/ac6/src/tx_thread_smp_time_get.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_smp/cortex_a34_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a34_smp/gnu/src/tx_thread_smp_time_get.S index 81286412e..4bb9f1cbf 100644 --- a/ports_smp/cortex_a34_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a34_smp/gnu/src/tx_thread_smp_time_get.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_smp/cortex_a35_smp/ac6/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a35_smp/ac6/src/tx_thread_smp_time_get.S index 81286412e..4bb9f1cbf 100644 --- a/ports_smp/cortex_a35_smp/ac6/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a35_smp/ac6/src/tx_thread_smp_time_get.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_smp/cortex_a35_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a35_smp/gnu/src/tx_thread_smp_time_get.S index 81286412e..4bb9f1cbf 100644 --- a/ports_smp/cortex_a35_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a35_smp/gnu/src/tx_thread_smp_time_get.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_smp/cortex_a53_smp/ac6/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a53_smp/ac6/src/tx_thread_smp_time_get.S index 81286412e..4bb9f1cbf 100644 --- a/ports_smp/cortex_a53_smp/ac6/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a53_smp/ac6/src/tx_thread_smp_time_get.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_smp/cortex_a53_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a53_smp/gnu/src/tx_thread_smp_time_get.S index 81286412e..4bb9f1cbf 100644 --- a/ports_smp/cortex_a53_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a53_smp/gnu/src/tx_thread_smp_time_get.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_smp/cortex_a55_smp/ac6/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a55_smp/ac6/src/tx_thread_smp_time_get.S index 81286412e..4bb9f1cbf 100644 --- a/ports_smp/cortex_a55_smp/ac6/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a55_smp/ac6/src/tx_thread_smp_time_get.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_smp/cortex_a55_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a55_smp/gnu/src/tx_thread_smp_time_get.S index 81286412e..4bb9f1cbf 100644 --- a/ports_smp/cortex_a55_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a55_smp/gnu/src/tx_thread_smp_time_get.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_smp/cortex_a57_smp/ac6/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a57_smp/ac6/src/tx_thread_smp_time_get.S index 81286412e..4bb9f1cbf 100644 --- a/ports_smp/cortex_a57_smp/ac6/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a57_smp/ac6/src/tx_thread_smp_time_get.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_smp/cortex_a57_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a57_smp/gnu/src/tx_thread_smp_time_get.S index 81286412e..4bb9f1cbf 100644 --- a/ports_smp/cortex_a57_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a57_smp/gnu/src/tx_thread_smp_time_get.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_context_restore.s b/ports_smp/cortex_a5_smp/ac5/src/tx_thread_context_restore.s index c639983bf..a3ca9ad71 100644 --- a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_context_restore.s +++ b/ports_smp/cortex_a5_smp/ac5/src/tx_thread_context_restore.s @@ -8,7 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ -; Some portions generated by Copilot (Opus 5). +; Portions of this file were generated with AI assistance. ; ; ;/**************************************************************************/ diff --git a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_context_save.s b/ports_smp/cortex_a5_smp/ac5/src/tx_thread_context_save.s index e3e0290e6..1217a5e55 100644 --- a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_context_save.s +++ b/ports_smp/cortex_a5_smp/ac5/src/tx_thread_context_save.s @@ -9,7 +9,7 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ ; -; // Some portions generated by Copilot (Opus 5). +; Portions of this file were generated with AI assistance. ; ;/**************************************************************************/ ;/**************************************************************************/ diff --git a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_schedule.s b/ports_smp/cortex_a5_smp/ac5/src/tx_thread_schedule.s index 4be82f138..b24e941e5 100644 --- a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_schedule.s +++ b/ports_smp/cortex_a5_smp/ac5/src/tx_thread_schedule.s @@ -9,7 +9,7 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ ; -; Some portions generated by Copilot (Opus 5). +; Portions of this file were generated with AI assistance. ; ; ;/**************************************************************************/ diff --git a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_smp_protect.s b/ports_smp/cortex_a5_smp/ac5/src/tx_thread_smp_protect.s index a1bb8b2fb..ca3eb3ea5 100644 --- a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_smp_protect.s +++ b/ports_smp/cortex_a5_smp/ac5/src/tx_thread_smp_protect.s @@ -8,7 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ -; Some portions generated by Copilot (Opus 5). +; Portions of this file were generated with AI assistance. ; ; ;/**************************************************************************/ diff --git a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_smp_time_get.s b/ports_smp/cortex_a5_smp/ac5/src/tx_thread_smp_time_get.s index 8c4b09710..f6e7f0665 100644 --- a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_smp_time_get.s +++ b/ports_smp/cortex_a5_smp/ac5/src/tx_thread_smp_time_get.s @@ -9,7 +9,7 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ ; -; Some portions generated by Codex (GPT-5). +; Portions of this file were generated with AI assistance. ; ;/**************************************************************************/ ;/**************************************************************************/ diff --git a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_smp_unprotect.s b/ports_smp/cortex_a5_smp/ac5/src/tx_thread_smp_unprotect.s index f19723e2c..5dad99a81 100644 --- a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_smp_unprotect.s +++ b/ports_smp/cortex_a5_smp/ac5/src/tx_thread_smp_unprotect.s @@ -8,7 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ -; Some portions generated by Copilot (Opus 5). +; Portions of this file were generated with AI assistance. ; ; ;/**************************************************************************/ diff --git a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_system_return.s b/ports_smp/cortex_a5_smp/ac5/src/tx_thread_system_return.s index cb527029f..a2880c1d8 100644 --- a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_system_return.s +++ b/ports_smp/cortex_a5_smp/ac5/src/tx_thread_system_return.s @@ -9,7 +9,7 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ ; -; // Some portions generated by Copilot (Opus 5). +; Portions of this file were generated with AI assistance. ; ;/**************************************************************************/ ;/**************************************************************************/ diff --git a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_vectored_context_save.s b/ports_smp/cortex_a5_smp/ac5/src/tx_thread_vectored_context_save.s index 586be818f..7e152dfe9 100644 --- a/ports_smp/cortex_a5_smp/ac5/src/tx_thread_vectored_context_save.s +++ b/ports_smp/cortex_a5_smp/ac5/src/tx_thread_vectored_context_save.s @@ -9,7 +9,7 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ ; -; // Some portions generated by Copilot (Opus 5). +; Portions of this file were generated with AI assistance. ; ;/**************************************************************************/ ;/**************************************************************************/ diff --git a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_context_restore.S b/ports_smp/cortex_a5_smp/gnu/src/tx_thread_context_restore.S index bd1b08ec8..e320303b4 100644 --- a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_context_restore.S +++ b/ports_smp/cortex_a5_smp/gnu/src/tx_thread_context_restore.S @@ -8,7 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ -@ Some portions generated by Copilot (Opus 5). +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ diff --git a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_context_save.S b/ports_smp/cortex_a5_smp/gnu/src/tx_thread_context_save.S index 0da2af21b..299d5a0d2 100644 --- a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_context_save.S +++ b/ports_smp/cortex_a5_smp/gnu/src/tx_thread_context_save.S @@ -9,7 +9,7 @@ @ * SPDX-License-Identifier: MIT @ **************************************************************************/ @ -@ // Some portions generated by Copilot (Opus 5). +@ Portions of this file were generated with AI assistance. @ @/**************************************************************************/ @/**************************************************************************/ diff --git a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_schedule.S b/ports_smp/cortex_a5_smp/gnu/src/tx_thread_schedule.S index dd34da804..5ef6af30e 100644 --- a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_schedule.S +++ b/ports_smp/cortex_a5_smp/gnu/src/tx_thread_schedule.S @@ -9,7 +9,7 @@ @ * SPDX-License-Identifier: MIT @ **************************************************************************/ @ -@ Some portions generated by Copilot (Opus 5). +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ diff --git a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_smp_protect.S b/ports_smp/cortex_a5_smp/gnu/src/tx_thread_smp_protect.S index 0a5373181..560fa8df0 100644 --- a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_smp_protect.S +++ b/ports_smp/cortex_a5_smp/gnu/src/tx_thread_smp_protect.S @@ -8,7 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ -@ Some portions generated by Copilot (Opus 5). +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ diff --git a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a5_smp/gnu/src/tx_thread_smp_time_get.S index 04099aeff..f9ecf1b5e 100644 --- a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a5_smp/gnu/src/tx_thread_smp_time_get.S @@ -9,7 +9,7 @@ @ * SPDX-License-Identifier: MIT @ **************************************************************************/ @ -@ Some portions generated by Codex (GPT-5). +@ Portions of this file were generated with AI assistance. @ @/**************************************************************************/ @/**************************************************************************/ diff --git a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_smp_unprotect.S b/ports_smp/cortex_a5_smp/gnu/src/tx_thread_smp_unprotect.S index 8facdc3cb..e00f53eca 100644 --- a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_smp_unprotect.S +++ b/ports_smp/cortex_a5_smp/gnu/src/tx_thread_smp_unprotect.S @@ -8,7 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ -@ Some portions generated by Copilot (Opus 5). +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ diff --git a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_system_return.S b/ports_smp/cortex_a5_smp/gnu/src/tx_thread_system_return.S index 33d1760eb..4451fdd5a 100644 --- a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_system_return.S +++ b/ports_smp/cortex_a5_smp/gnu/src/tx_thread_system_return.S @@ -9,7 +9,7 @@ @ * SPDX-License-Identifier: MIT @ **************************************************************************/ @ -@ // Some portions generated by Copilot (Opus 5). +@ Portions of this file were generated with AI assistance. @ @/**************************************************************************/ @/**************************************************************************/ diff --git a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_vectored_context_save.S b/ports_smp/cortex_a5_smp/gnu/src/tx_thread_vectored_context_save.S index 8a3eb6685..67711a9c0 100644 --- a/ports_smp/cortex_a5_smp/gnu/src/tx_thread_vectored_context_save.S +++ b/ports_smp/cortex_a5_smp/gnu/src/tx_thread_vectored_context_save.S @@ -9,7 +9,7 @@ @ * SPDX-License-Identifier: MIT @ **************************************************************************/ @ -@ // Some portions generated by Copilot (Opus 5). +@ Portions of this file were generated with AI assistance. @ @/**************************************************************************/ @/**************************************************************************/ diff --git a/ports_smp/cortex_a5x_smp/ac6/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a5x_smp/ac6/src/tx_thread_smp_time_get.S index 1c8ea3aeb..7a20db32d 100644 --- a/ports_smp/cortex_a5x_smp/ac6/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a5x_smp/ac6/src/tx_thread_smp_time_get.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_smp/cortex_a5x_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a5x_smp/gnu/src/tx_thread_smp_time_get.S index e0605debb..4b3ee1d44 100644 --- a/ports_smp/cortex_a5x_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a5x_smp/gnu/src/tx_thread_smp_time_get.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_smp/cortex_a5x_smp/iar/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a5x_smp/iar/src/tx_thread_smp_time_get.S index 4808149f7..16cdf26d3 100644 --- a/ports_smp/cortex_a5x_smp/iar/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a5x_smp/iar/src/tx_thread_smp_time_get.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_smp/cortex_a65_smp/ac6/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a65_smp/ac6/src/tx_thread_smp_time_get.S index 81286412e..4bb9f1cbf 100644 --- a/ports_smp/cortex_a65_smp/ac6/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a65_smp/ac6/src/tx_thread_smp_time_get.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_smp/cortex_a65_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a65_smp/gnu/src/tx_thread_smp_time_get.S index 81286412e..4bb9f1cbf 100644 --- a/ports_smp/cortex_a65_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a65_smp/gnu/src/tx_thread_smp_time_get.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_smp/cortex_a65ae_smp/ac6/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a65ae_smp/ac6/src/tx_thread_smp_time_get.S index 81286412e..4bb9f1cbf 100644 --- a/ports_smp/cortex_a65ae_smp/ac6/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a65ae_smp/ac6/src/tx_thread_smp_time_get.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_smp/cortex_a65ae_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a65ae_smp/gnu/src/tx_thread_smp_time_get.S index 81286412e..4bb9f1cbf 100644 --- a/ports_smp/cortex_a65ae_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a65ae_smp/gnu/src/tx_thread_smp_time_get.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_smp/cortex_a72_smp/ac6/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a72_smp/ac6/src/tx_thread_smp_time_get.S index 81286412e..4bb9f1cbf 100644 --- a/ports_smp/cortex_a72_smp/ac6/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a72_smp/ac6/src/tx_thread_smp_time_get.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_smp/cortex_a72_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a72_smp/gnu/src/tx_thread_smp_time_get.S index 81286412e..4bb9f1cbf 100644 --- a/ports_smp/cortex_a72_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a72_smp/gnu/src/tx_thread_smp_time_get.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_smp/cortex_a73_smp/ac6/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a73_smp/ac6/src/tx_thread_smp_time_get.S index 81286412e..4bb9f1cbf 100644 --- a/ports_smp/cortex_a73_smp/ac6/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a73_smp/ac6/src/tx_thread_smp_time_get.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_smp/cortex_a73_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a73_smp/gnu/src/tx_thread_smp_time_get.S index 81286412e..4bb9f1cbf 100644 --- a/ports_smp/cortex_a73_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a73_smp/gnu/src/tx_thread_smp_time_get.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_smp/cortex_a75_smp/ac6/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a75_smp/ac6/src/tx_thread_smp_time_get.S index 81286412e..4bb9f1cbf 100644 --- a/ports_smp/cortex_a75_smp/ac6/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a75_smp/ac6/src/tx_thread_smp_time_get.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_smp/cortex_a75_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a75_smp/gnu/src/tx_thread_smp_time_get.S index 81286412e..4bb9f1cbf 100644 --- a/ports_smp/cortex_a75_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a75_smp/gnu/src/tx_thread_smp_time_get.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_smp/cortex_a76_smp/ac6/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a76_smp/ac6/src/tx_thread_smp_time_get.S index 81286412e..4bb9f1cbf 100644 --- a/ports_smp/cortex_a76_smp/ac6/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a76_smp/ac6/src/tx_thread_smp_time_get.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_smp/cortex_a76_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a76_smp/gnu/src/tx_thread_smp_time_get.S index 81286412e..4bb9f1cbf 100644 --- a/ports_smp/cortex_a76_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a76_smp/gnu/src/tx_thread_smp_time_get.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_smp/cortex_a76ae_smp/ac6/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a76ae_smp/ac6/src/tx_thread_smp_time_get.S index 81286412e..4bb9f1cbf 100644 --- a/ports_smp/cortex_a76ae_smp/ac6/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a76ae_smp/ac6/src/tx_thread_smp_time_get.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_smp/cortex_a76ae_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a76ae_smp/gnu/src/tx_thread_smp_time_get.S index 81286412e..4bb9f1cbf 100644 --- a/ports_smp/cortex_a76ae_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a76ae_smp/gnu/src/tx_thread_smp_time_get.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_smp/cortex_a77_smp/ac6/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a77_smp/ac6/src/tx_thread_smp_time_get.S index 81286412e..4bb9f1cbf 100644 --- a/ports_smp/cortex_a77_smp/ac6/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a77_smp/ac6/src/tx_thread_smp_time_get.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_smp/cortex_a77_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a77_smp/gnu/src/tx_thread_smp_time_get.S index 81286412e..4bb9f1cbf 100644 --- a/ports_smp/cortex_a77_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a77_smp/gnu/src/tx_thread_smp_time_get.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_smp/cortex_a78_smp/ac6/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a78_smp/ac6/src/tx_thread_smp_time_get.S index 81286412e..4bb9f1cbf 100644 --- a/ports_smp/cortex_a78_smp/ac6/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a78_smp/ac6/src/tx_thread_smp_time_get.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_smp/cortex_a78_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a78_smp/gnu/src/tx_thread_smp_time_get.S index 81286412e..4bb9f1cbf 100644 --- a/ports_smp/cortex_a78_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a78_smp/gnu/src/tx_thread_smp_time_get.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_context_restore.s b/ports_smp/cortex_a7_smp/ac5/src/tx_thread_context_restore.s index 110958b14..de76d8e61 100644 --- a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_context_restore.s +++ b/ports_smp/cortex_a7_smp/ac5/src/tx_thread_context_restore.s @@ -8,7 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ -; Some portions generated by Copilot (Opus 5). +; Portions of this file were generated with AI assistance. ; ; ;/**************************************************************************/ diff --git a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_context_save.s b/ports_smp/cortex_a7_smp/ac5/src/tx_thread_context_save.s index 8c45f4a97..289c0ea1c 100644 --- a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_context_save.s +++ b/ports_smp/cortex_a7_smp/ac5/src/tx_thread_context_save.s @@ -9,7 +9,7 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ ; -; // Some portions generated by Copilot (Opus 5). +; Portions of this file were generated with AI assistance. ; ;/**************************************************************************/ ;/**************************************************************************/ diff --git a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_schedule.s b/ports_smp/cortex_a7_smp/ac5/src/tx_thread_schedule.s index a70110ece..8ac992cda 100644 --- a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_schedule.s +++ b/ports_smp/cortex_a7_smp/ac5/src/tx_thread_schedule.s @@ -9,7 +9,7 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ ; -; Some portions generated by Copilot (Opus 5). +; Portions of this file were generated with AI assistance. ; ; ;/**************************************************************************/ diff --git a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_smp_protect.s b/ports_smp/cortex_a7_smp/ac5/src/tx_thread_smp_protect.s index f59d04d2c..48cce36f5 100644 --- a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_smp_protect.s +++ b/ports_smp/cortex_a7_smp/ac5/src/tx_thread_smp_protect.s @@ -8,7 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ -; Some portions generated by Copilot (Opus 5). +; Portions of this file were generated with AI assistance. ; ; ;/**************************************************************************/ diff --git a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_smp_time_get.s b/ports_smp/cortex_a7_smp/ac5/src/tx_thread_smp_time_get.s index e3935200e..c63f6cc58 100644 --- a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_smp_time_get.s +++ b/ports_smp/cortex_a7_smp/ac5/src/tx_thread_smp_time_get.s @@ -9,7 +9,7 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ ; -; Some portions generated by Codex (GPT-5). +; Portions of this file were generated with AI assistance. ; ;/**************************************************************************/ ;/**************************************************************************/ diff --git a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_smp_unprotect.s b/ports_smp/cortex_a7_smp/ac5/src/tx_thread_smp_unprotect.s index 072200475..f132cb40b 100644 --- a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_smp_unprotect.s +++ b/ports_smp/cortex_a7_smp/ac5/src/tx_thread_smp_unprotect.s @@ -8,7 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ -; Some portions generated by Copilot (Opus 5). +; Portions of this file were generated with AI assistance. ; ; ;/**************************************************************************/ diff --git a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_system_return.s b/ports_smp/cortex_a7_smp/ac5/src/tx_thread_system_return.s index 75bea71e5..84c8e0363 100644 --- a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_system_return.s +++ b/ports_smp/cortex_a7_smp/ac5/src/tx_thread_system_return.s @@ -9,7 +9,7 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ ; -; // Some portions generated by Copilot (Opus 5). +; Portions of this file were generated with AI assistance. ; ;/**************************************************************************/ ;/**************************************************************************/ diff --git a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_vectored_context_save.s b/ports_smp/cortex_a7_smp/ac5/src/tx_thread_vectored_context_save.s index a46578ece..2d4b34a1a 100644 --- a/ports_smp/cortex_a7_smp/ac5/src/tx_thread_vectored_context_save.s +++ b/ports_smp/cortex_a7_smp/ac5/src/tx_thread_vectored_context_save.s @@ -9,7 +9,7 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ ; -; // Some portions generated by Copilot (Opus 5). +; Portions of this file were generated with AI assistance. ; ;/**************************************************************************/ ;/**************************************************************************/ diff --git a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_context_restore.S b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_context_restore.S index 398aac35c..b11e23ab2 100644 --- a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_context_restore.S +++ b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_context_restore.S @@ -8,7 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ -@ Some portions generated by Copilot (Opus 5). +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ diff --git a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_context_save.S b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_context_save.S index 6deb2371d..75a63ed4b 100644 --- a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_context_save.S +++ b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_context_save.S @@ -9,7 +9,7 @@ @ * SPDX-License-Identifier: MIT @ **************************************************************************/ @ -@ // Some portions generated by Copilot (Opus 5). +@ Portions of this file were generated with AI assistance. @ @/**************************************************************************/ @/**************************************************************************/ diff --git a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_schedule.S b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_schedule.S index 56bbd5eb5..a9e12749d 100644 --- a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_schedule.S +++ b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_schedule.S @@ -9,7 +9,7 @@ @ * SPDX-License-Identifier: MIT @ **************************************************************************/ @ -@ Some portions generated by Copilot (Opus 5). +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ diff --git a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_protect.S b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_protect.S index 5cf03be83..74dff8026 100644 --- a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_protect.S +++ b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_protect.S @@ -8,7 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ -@ Some portions generated by Copilot (Opus 5). +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ diff --git a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_time_get.S index 9eb5b12c1..e869c0e78 100644 --- a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_time_get.S @@ -9,7 +9,7 @@ @ * SPDX-License-Identifier: MIT @ **************************************************************************/ @ -@ Some portions generated by Codex (GPT-5). +@ Portions of this file were generated with AI assistance. @ @/**************************************************************************/ @/**************************************************************************/ diff --git a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_unprotect.S b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_unprotect.S index 8d47131a3..66c6689c3 100644 --- a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_unprotect.S +++ b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_smp_unprotect.S @@ -8,7 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ -@ Some portions generated by Copilot (Opus 5). +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ diff --git a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_system_return.S b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_system_return.S index 565390fce..7beaf661d 100644 --- a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_system_return.S +++ b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_system_return.S @@ -9,7 +9,7 @@ @ * SPDX-License-Identifier: MIT @ **************************************************************************/ @ -@ // Some portions generated by Copilot (Opus 5). +@ Portions of this file were generated with AI assistance. @ @/**************************************************************************/ @/**************************************************************************/ diff --git a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_vectored_context_save.S b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_vectored_context_save.S index a656be78b..ee9ca1c70 100644 --- a/ports_smp/cortex_a7_smp/gnu/src/tx_thread_vectored_context_save.S +++ b/ports_smp/cortex_a7_smp/gnu/src/tx_thread_vectored_context_save.S @@ -9,7 +9,7 @@ @ * SPDX-License-Identifier: MIT @ **************************************************************************/ @ -@ // Some portions generated by Copilot (Opus 5). +@ Portions of this file were generated with AI assistance. @ @/**************************************************************************/ @/**************************************************************************/ diff --git a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_context_restore.s b/ports_smp/cortex_a9_smp/ac5/src/tx_thread_context_restore.s index 6327d05dc..4451091b7 100644 --- a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_context_restore.s +++ b/ports_smp/cortex_a9_smp/ac5/src/tx_thread_context_restore.s @@ -8,7 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ -; Some portions generated by Copilot (Opus 5). +; Portions of this file were generated with AI assistance. ; ; ;/**************************************************************************/ diff --git a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_context_save.s b/ports_smp/cortex_a9_smp/ac5/src/tx_thread_context_save.s index 948748287..9c0477161 100644 --- a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_context_save.s +++ b/ports_smp/cortex_a9_smp/ac5/src/tx_thread_context_save.s @@ -9,7 +9,7 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ ; -; // Some portions generated by Copilot (Opus 5). +; Portions of this file were generated with AI assistance. ; ;/**************************************************************************/ ;/**************************************************************************/ diff --git a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_schedule.s b/ports_smp/cortex_a9_smp/ac5/src/tx_thread_schedule.s index 81f0b2848..45298ff35 100644 --- a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_schedule.s +++ b/ports_smp/cortex_a9_smp/ac5/src/tx_thread_schedule.s @@ -9,7 +9,7 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ ; -; Some portions generated by Copilot (Opus 5). +; Portions of this file were generated with AI assistance. ; ; ;/**************************************************************************/ diff --git a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_smp_protect.s b/ports_smp/cortex_a9_smp/ac5/src/tx_thread_smp_protect.s index 82fa0b914..fe92cb923 100644 --- a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_smp_protect.s +++ b/ports_smp/cortex_a9_smp/ac5/src/tx_thread_smp_protect.s @@ -8,7 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ -; Some portions generated by Copilot (Opus 5). +; Portions of this file were generated with AI assistance. ; ; ;/**************************************************************************/ diff --git a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_smp_time_get.s b/ports_smp/cortex_a9_smp/ac5/src/tx_thread_smp_time_get.s index d656d1c22..9da218214 100644 --- a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_smp_time_get.s +++ b/ports_smp/cortex_a9_smp/ac5/src/tx_thread_smp_time_get.s @@ -9,7 +9,7 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ ; -; Some portions generated by Codex (GPT-5). +; Portions of this file were generated with AI assistance. ; ;/**************************************************************************/ ;/**************************************************************************/ diff --git a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_smp_unprotect.s b/ports_smp/cortex_a9_smp/ac5/src/tx_thread_smp_unprotect.s index c161987cc..1b4b963a9 100644 --- a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_smp_unprotect.s +++ b/ports_smp/cortex_a9_smp/ac5/src/tx_thread_smp_unprotect.s @@ -8,7 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ -; Some portions generated by Copilot (Opus 5). +; Portions of this file were generated with AI assistance. ; ; ;/**************************************************************************/ diff --git a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_system_return.s b/ports_smp/cortex_a9_smp/ac5/src/tx_thread_system_return.s index 4b8b56ce0..485b0131c 100644 --- a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_system_return.s +++ b/ports_smp/cortex_a9_smp/ac5/src/tx_thread_system_return.s @@ -9,7 +9,7 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ ; -; // Some portions generated by Copilot (Opus 5). +; Portions of this file were generated with AI assistance. ; ;/**************************************************************************/ ;/**************************************************************************/ diff --git a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_vectored_context_save.s b/ports_smp/cortex_a9_smp/ac5/src/tx_thread_vectored_context_save.s index 8bd7dc61d..26acf6e44 100644 --- a/ports_smp/cortex_a9_smp/ac5/src/tx_thread_vectored_context_save.s +++ b/ports_smp/cortex_a9_smp/ac5/src/tx_thread_vectored_context_save.s @@ -9,7 +9,7 @@ ; * SPDX-License-Identifier: MIT ; **************************************************************************/ ; -; // Some portions generated by Copilot (Opus 5). +; Portions of this file were generated with AI assistance. ; ;/**************************************************************************/ ;/**************************************************************************/ diff --git a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_context_restore.S b/ports_smp/cortex_a9_smp/gnu/src/tx_thread_context_restore.S index c96d96380..c09d258d2 100644 --- a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_context_restore.S +++ b/ports_smp/cortex_a9_smp/gnu/src/tx_thread_context_restore.S @@ -8,7 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ -@ Some portions generated by Copilot (Opus 5). +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ diff --git a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_context_save.S b/ports_smp/cortex_a9_smp/gnu/src/tx_thread_context_save.S index 32a78bc8d..2cef910d9 100644 --- a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_context_save.S +++ b/ports_smp/cortex_a9_smp/gnu/src/tx_thread_context_save.S @@ -9,7 +9,7 @@ @ * SPDX-License-Identifier: MIT @ **************************************************************************/ @ -@ // Some portions generated by Copilot (Opus 5). +@ Portions of this file were generated with AI assistance. @ @/**************************************************************************/ @/**************************************************************************/ diff --git a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_schedule.S b/ports_smp/cortex_a9_smp/gnu/src/tx_thread_schedule.S index e59be021b..3e8a41e61 100644 --- a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_schedule.S +++ b/ports_smp/cortex_a9_smp/gnu/src/tx_thread_schedule.S @@ -9,7 +9,7 @@ @ * SPDX-License-Identifier: MIT @ **************************************************************************/ @ -@ Some portions generated by Copilot (Opus 5). +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ diff --git a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_smp_protect.S b/ports_smp/cortex_a9_smp/gnu/src/tx_thread_smp_protect.S index 05bf52566..9a3838f1c 100644 --- a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_smp_protect.S +++ b/ports_smp/cortex_a9_smp/gnu/src/tx_thread_smp_protect.S @@ -8,7 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ -@ Some portions generated by Copilot (Opus 5). +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ diff --git a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_smp_time_get.S b/ports_smp/cortex_a9_smp/gnu/src/tx_thread_smp_time_get.S index cf8374adc..55215b1ef 100644 --- a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_smp_time_get.S +++ b/ports_smp/cortex_a9_smp/gnu/src/tx_thread_smp_time_get.S @@ -9,7 +9,7 @@ @ * SPDX-License-Identifier: MIT @ **************************************************************************/ @ -@ Some portions generated by Codex (GPT-5). +@ Portions of this file were generated with AI assistance. @ @/**************************************************************************/ @/**************************************************************************/ diff --git a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_smp_unprotect.S b/ports_smp/cortex_a9_smp/gnu/src/tx_thread_smp_unprotect.S index a9baf0c80..c4f42dec3 100644 --- a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_smp_unprotect.S +++ b/ports_smp/cortex_a9_smp/gnu/src/tx_thread_smp_unprotect.S @@ -8,7 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ -@ Some portions generated by Copilot (Opus 5). +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ diff --git a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_system_return.S b/ports_smp/cortex_a9_smp/gnu/src/tx_thread_system_return.S index 7c0ba3d3b..02738e90b 100644 --- a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_system_return.S +++ b/ports_smp/cortex_a9_smp/gnu/src/tx_thread_system_return.S @@ -9,7 +9,7 @@ @ * SPDX-License-Identifier: MIT @ **************************************************************************/ @ -@ // Some portions generated by Copilot (Opus 5). +@ Portions of this file were generated with AI assistance. @ @/**************************************************************************/ @/**************************************************************************/ diff --git a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_vectored_context_save.S b/ports_smp/cortex_a9_smp/gnu/src/tx_thread_vectored_context_save.S index 8c85ddbd0..f887de910 100644 --- a/ports_smp/cortex_a9_smp/gnu/src/tx_thread_vectored_context_save.S +++ b/ports_smp/cortex_a9_smp/gnu/src/tx_thread_vectored_context_save.S @@ -9,7 +9,7 @@ @ * SPDX-License-Identifier: MIT @ **************************************************************************/ @ -@ // Some portions generated by Copilot (Opus 5). +@ Portions of this file were generated with AI assistance. @ @/**************************************************************************/ @/**************************************************************************/ diff --git a/ports_smp/cortex_r8_smp/ac5/src/tx_thread_context_save.s b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_context_save.s index f506f4e42..9ce969e25 100644 --- a/ports_smp/cortex_r8_smp/ac5/src/tx_thread_context_save.s +++ b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_context_save.s @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_smp/cortex_r8_smp/ac5/src/tx_thread_smp_time_get.s b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_smp_time_get.s index c17143896..11f7f4ff0 100644 --- a/ports_smp/cortex_r8_smp/ac5/src/tx_thread_smp_time_get.s +++ b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_smp_time_get.s @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_smp/cortex_r8_smp/ac5/src/tx_thread_system_return.s b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_system_return.s index fc1b59ed8..935d88fa6 100644 --- a/ports_smp/cortex_r8_smp/ac5/src/tx_thread_system_return.s +++ b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_system_return.s @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_smp/cortex_r8_smp/ac5/src/tx_thread_vectored_context_save.s b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_vectored_context_save.s index 9e82773c0..dfbe9bc21 100644 --- a/ports_smp/cortex_r8_smp/ac5/src/tx_thread_vectored_context_save.s +++ b/ports_smp/cortex_r8_smp/ac5/src/tx_thread_vectored_context_save.s @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_smp/linux/gnu/src/tx_thread_stack_build.c b/ports_smp/linux/gnu/src/tx_thread_stack_build.c index 787d07d47..9c0cffad2 100644 --- a/ports_smp/linux/gnu/src/tx_thread_stack_build.c +++ b/ports_smp/linux/gnu/src/tx_thread_stack_build.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_smp/win64/vs_2022/src/tx_initialize_low_level.c b/ports_smp/win64/vs_2022/src/tx_initialize_low_level.c index f517fd6ba..9752ec3d8 100644 --- a/ports_smp/win64/vs_2022/src/tx_initialize_low_level.c +++ b/ports_smp/win64/vs_2022/src/tx_initialize_low_level.c @@ -13,8 +13,7 @@ * SPDX-License-Identifier: MIT and CC0-1.0 **************************************************************************/ -// Some portions generated by Codex (gpt 5.5). -// Some portions generated by GitHub Copilot (claude-sonnet-4.6). +// Portions of this file were generated with AI assistance. #define TX_SOURCE_CODE #define TX_THREAD_SMP_SOURCE_CODE diff --git a/ports_smp/win64/vs_2022/src/tx_thread_context_restore.c b/ports_smp/win64/vs_2022/src/tx_thread_context_restore.c index d1b74c383..1a2cd1824 100644 --- a/ports_smp/win64/vs_2022/src/tx_thread_context_restore.c +++ b/ports_smp/win64/vs_2022/src/tx_thread_context_restore.c @@ -13,8 +13,7 @@ * SPDX-License-Identifier: MIT and CC0-1.0 **************************************************************************/ -// Some portions generated by Codex (gpt 5.5). -// Some portions generated by GitHub Copilot (claude-sonnet-4.6). +// Portions of this file were generated with AI assistance. #define TX_SOURCE_CODE #define TX_THREAD_SMP_SOURCE_CODE diff --git a/ports_smp/win64/vs_2022/src/tx_thread_context_save.c b/ports_smp/win64/vs_2022/src/tx_thread_context_save.c index 89d6cd75c..01a894c6b 100644 --- a/ports_smp/win64/vs_2022/src/tx_thread_context_save.c +++ b/ports_smp/win64/vs_2022/src/tx_thread_context_save.c @@ -13,8 +13,7 @@ * SPDX-License-Identifier: MIT and CC0-1.0 **************************************************************************/ -// Some portions generated by Codex (gpt 5.4). -// Some portions generated by GitHub Copilot (claude-sonnet-4.6). +// Portions of this file were generated with AI assistance. #define TX_SOURCE_CODE #define TX_THREAD_SMP_SOURCE_CODE diff --git a/ports_smp/win64/vs_2022/src/tx_thread_schedule.c b/ports_smp/win64/vs_2022/src/tx_thread_schedule.c index f33eb7b07..b247ee4ca 100644 --- a/ports_smp/win64/vs_2022/src/tx_thread_schedule.c +++ b/ports_smp/win64/vs_2022/src/tx_thread_schedule.c @@ -13,7 +13,7 @@ * SPDX-License-Identifier: MIT and CC0-1.0 **************************************************************************/ -// Some portions generated by Codex (gpt 5.5). +// Portions of this file were generated with AI assistance. #define TX_SOURCE_CODE #define TX_THREAD_SMP_SOURCE_CODE diff --git a/ports_smp/win64/vs_2022/src/tx_thread_smp_core_preempt.c b/ports_smp/win64/vs_2022/src/tx_thread_smp_core_preempt.c index 2da24fda3..4f0da5348 100644 --- a/ports_smp/win64/vs_2022/src/tx_thread_smp_core_preempt.c +++ b/ports_smp/win64/vs_2022/src/tx_thread_smp_core_preempt.c @@ -13,7 +13,7 @@ * SPDX-License-Identifier: MIT and CC0-1.0 **************************************************************************/ -// Some portions generated by Codex (gpt 5.4). +// Portions of this file were generated with AI assistance. #define TX_SOURCE_CODE #define TX_THREAD_SMP_SOURCE_CODE diff --git a/ports_smp/win64/vs_2022/src/tx_thread_smp_current_state_get.c b/ports_smp/win64/vs_2022/src/tx_thread_smp_current_state_get.c index bf1726dfb..ce937b19a 100644 --- a/ports_smp/win64/vs_2022/src/tx_thread_smp_current_state_get.c +++ b/ports_smp/win64/vs_2022/src/tx_thread_smp_current_state_get.c @@ -13,7 +13,7 @@ * SPDX-License-Identifier: MIT and CC0-1.0 **************************************************************************/ -// Some portions generated by Codex (gpt 5.4). +// Portions of this file were generated with AI assistance. #define TX_SOURCE_CODE #define TX_THREAD_SMP_SOURCE_CODE diff --git a/ports_smp/win64/vs_2022/src/tx_thread_smp_current_thread_get.c b/ports_smp/win64/vs_2022/src/tx_thread_smp_current_thread_get.c index ade6774f9..1f93f8a96 100644 --- a/ports_smp/win64/vs_2022/src/tx_thread_smp_current_thread_get.c +++ b/ports_smp/win64/vs_2022/src/tx_thread_smp_current_thread_get.c @@ -13,7 +13,7 @@ * SPDX-License-Identifier: MIT and CC0-1.0 **************************************************************************/ -// Some portions generated by Codex (gpt 5.4). +// Portions of this file were generated with AI assistance. #define TX_SOURCE_CODE #define TX_THREAD_SMP_SOURCE_CODE diff --git a/ports_smp/win64/vs_2022/src/tx_thread_smp_protect.c b/ports_smp/win64/vs_2022/src/tx_thread_smp_protect.c index e59caffc5..954b9e3c1 100644 --- a/ports_smp/win64/vs_2022/src/tx_thread_smp_protect.c +++ b/ports_smp/win64/vs_2022/src/tx_thread_smp_protect.c @@ -13,7 +13,7 @@ * SPDX-License-Identifier: MIT and CC0-1.0 **************************************************************************/ -// Some portions generated by Codex (gpt 5.5). +// Portions of this file were generated with AI assistance. #define TX_SOURCE_CODE #define TX_THREAD_SMP_SOURCE_CODE diff --git a/ports_smp/win64/vs_2022/src/tx_thread_smp_unprotect.c b/ports_smp/win64/vs_2022/src/tx_thread_smp_unprotect.c index b845767d9..ac553d669 100644 --- a/ports_smp/win64/vs_2022/src/tx_thread_smp_unprotect.c +++ b/ports_smp/win64/vs_2022/src/tx_thread_smp_unprotect.c @@ -13,7 +13,7 @@ * SPDX-License-Identifier: MIT and CC0-1.0 **************************************************************************/ -// Some portions generated by Codex (gpt 5.4). +// Portions of this file were generated with AI assistance. #define TX_SOURCE_CODE #define TX_THREAD_SMP_SOURCE_CODE diff --git a/ports_smp/win64/vs_2022/src/tx_thread_stack_build.c b/ports_smp/win64/vs_2022/src/tx_thread_stack_build.c index 0531fb3b6..60478e7be 100644 --- a/ports_smp/win64/vs_2022/src/tx_thread_stack_build.c +++ b/ports_smp/win64/vs_2022/src/tx_thread_stack_build.c @@ -13,7 +13,7 @@ * SPDX-License-Identifier: MIT and CC0-1.0 **************************************************************************/ -// Some portions generated by Codex (gpt 5.5). +// Portions of this file were generated with AI assistance. #define TX_SOURCE_CODE #define TX_THREAD_SMP_SOURCE_CODE diff --git a/ports_smp/win64/vs_2022/src/tx_thread_system_return.c b/ports_smp/win64/vs_2022/src/tx_thread_system_return.c index 8207f3450..b76904026 100644 --- a/ports_smp/win64/vs_2022/src/tx_thread_system_return.c +++ b/ports_smp/win64/vs_2022/src/tx_thread_system_return.c @@ -13,7 +13,7 @@ * SPDX-License-Identifier: MIT and CC0-1.0 **************************************************************************/ -// Some portions generated by Codex (gpt 5.5). +// Portions of this file were generated with AI assistance. #define TX_SOURCE_CODE #define TX_THREAD_SMP_SOURCE_CODE diff --git a/test/smp/regression/testcontrol.c b/test/smp/regression/testcontrol.c index caf06e0d7..c964dc03a 100644 --- a/test/smp/regression/testcontrol.c +++ b/test/smp/regression/testcontrol.c @@ -10,9 +10,7 @@ /***************************************************************************/ /* This is the test control routine of the ThreadX kernel. All tests are dispatched from this routine. */ -// Some portions generated by Codex (gpt 5.5). -// Some portions generated by Copilot (Opus 5). -// Some portions generated by Codex (gpt-5.6-sol). +// Portions of this file were generated with AI assistance. #define TX_THREAD_SMP_SOURCE_CODE diff --git a/test/smp/regression/threadx_block_memory_suspension_timeout_test.c b/test/smp/regression/threadx_block_memory_suspension_timeout_test.c index 434772853..1477cff79 100644 --- a/test/smp/regression/threadx_block_memory_suspension_timeout_test.c +++ b/test/smp/regression/threadx_block_memory_suspension_timeout_test.c @@ -11,7 +11,7 @@ /* This test is designed to test timeouts on suspension on memory block pools. */ -// Some portions generated by Codex (gpt 5.4). +// Portions of this file were generated with AI assistance. #include #include "tx_api.h" diff --git a/test/smp/regression/threadx_byte_memory_suspension_timeout_test.c b/test/smp/regression/threadx_byte_memory_suspension_timeout_test.c index c92f2be0f..aaf1ba514 100644 --- a/test/smp/regression/threadx_byte_memory_suspension_timeout_test.c +++ b/test/smp/regression/threadx_byte_memory_suspension_timeout_test.c @@ -11,7 +11,7 @@ /* This test is designed to test suspension timeout on a memory byte pool. */ -// Some portions generated by Codex (gpt 5.4). +// Portions of this file were generated with AI assistance. #include #include "tx_api.h" diff --git a/test/smp/regression/threadx_smp_random_resume_suspend_exclusion_pt_test.c b/test/smp/regression/threadx_smp_random_resume_suspend_exclusion_pt_test.c index a9ea93ad1..ed5874181 100644 --- a/test/smp/regression/threadx_smp_random_resume_suspend_exclusion_pt_test.c +++ b/test/smp/regression/threadx_smp_random_resume_suspend_exclusion_pt_test.c @@ -10,7 +10,7 @@ /***************************************************************************/ /* Define the ThreadX SMP random resume/suspend/exclude/pt test. */ -// Some portions generated by Codex (gpt 5.4). +// Portions of this file were generated with AI assistance. #include #include "tx_api.h" diff --git a/test/smp/regression/threadx_smp_time_slice_test.c b/test/smp/regression/threadx_smp_time_slice_test.c index 370f5e371..c5ab06159 100644 --- a/test/smp/regression/threadx_smp_time_slice_test.c +++ b/test/smp/regression/threadx_smp_time_slice_test.c @@ -11,7 +11,7 @@ /* Define the ThreadX SMP time-slice test. */ -// Some portions generated by Codex (gpt 5.4). +// Portions of this file were generated with AI assistance. #include #include "tx_api.h" diff --git a/test/smp/regression/threadx_thread_multiple_sleep_test.c b/test/smp/regression/threadx_thread_multiple_sleep_test.c index 4dfe5bdcc..778495a79 100644 --- a/test/smp/regression/threadx_thread_multiple_sleep_test.c +++ b/test/smp/regression/threadx_thread_multiple_sleep_test.c @@ -11,7 +11,7 @@ /* This test is designed to test multiple threads sleeping for 33 ticks. */ -// Some portions generated by Codex (gpt 5.4). +// Portions of this file were generated with AI assistance. #include #include "tx_api.h" diff --git a/test/smp/regression/threadx_thread_stack_checking_test.c b/test/smp/regression/threadx_thread_stack_checking_test.c index d30e624f1..2ef9a2df2 100644 --- a/test/smp/regression/threadx_thread_stack_checking_test.c +++ b/test/smp/regression/threadx_thread_stack_checking_test.c @@ -9,7 +9,7 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /* This test is for the thread stack checking services. */ diff --git a/test/smp/regression/threadx_thread_stack_fill_value_test.c b/test/smp/regression/threadx_thread_stack_fill_value_test.c index 896c0c7f7..fa6eda220 100644 --- a/test/smp/regression/threadx_thread_stack_fill_value_test.c +++ b/test/smp/regression/threadx_thread_stack_fill_value_test.c @@ -8,7 +8,7 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /* This test checks that the stack fill value recorded in a thread control block is the value that was actually written into that thread's stack. The two used to disagree diff --git a/test/tx/cmake/riscv/bsp/tx_initialize_low_level.S b/test/tx/cmake/riscv/bsp/tx_initialize_low_level.S index 5a1cbcd6a..d72c9b6ae 100644 --- a/test/tx/cmake/riscv/bsp/tx_initialize_low_level.S +++ b/test/tx/cmake/riscv/bsp/tx_initialize_low_level.S @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Claude Code (Opus 5). +// Portions of this file were generated with AI assistance. /* Trap entry and low-level init for RISC-V QEMU virt regression tests. Supports both RV32 and RV64 via __riscv_xlen conditionals. */ diff --git a/test/tx/regression/testcontrol.c b/test/tx/regression/testcontrol.c index 4e03dd55e..bec50ee76 100644 --- a/test/tx/regression/testcontrol.c +++ b/test/tx/regression/testcontrol.c @@ -10,8 +10,7 @@ /***************************************************************************/ /* This is the test control routine of the ThreadX kernel. All tests are dispatched from this routine. */ -// Some portions generated by Codex (gpt 5.4). -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. #include "tx_api.h" #include diff --git a/test/tx/regression/threadx_initialize_kernel_setup_test.c b/test/tx/regression/threadx_initialize_kernel_setup_test.c index 057ac2235..b69a26bd5 100644 --- a/test/tx/regression/threadx_initialize_kernel_setup_test.c +++ b/test/tx/regression/threadx_initialize_kernel_setup_test.c @@ -10,7 +10,7 @@ /***************************************************************************/ /* This test is designed to test kernel setup functionality in ThreadX. */ -// Some portions generated by Codex (gpt 5.4). +// Portions of this file were generated with AI assistance. #include #include diff --git a/test/tx/regression/threadx_thread_basic_execution_test.c b/test/tx/regression/threadx_thread_basic_execution_test.c index 8372fcd9d..8e9586f28 100644 --- a/test/tx/regression/threadx_thread_basic_execution_test.c +++ b/test/tx/regression/threadx_thread_basic_execution_test.c @@ -1,6 +1,6 @@ /***************************************************************************/ -/* Some portions generated by Codex (gpt-5.6-sol). */ +// Portions of this file were generated with AI assistance. /* Copyright (c) 2024 Microsoft Corporation */ /* Copyright (c) 2026 Eclipse ThreadX contributors */ /* */ diff --git a/test/tx/regression/threadx_thread_stack_checking_test.c b/test/tx/regression/threadx_thread_stack_checking_test.c index d30e624f1..2ef9a2df2 100644 --- a/test/tx/regression/threadx_thread_stack_checking_test.c +++ b/test/tx/regression/threadx_thread_stack_checking_test.c @@ -9,7 +9,7 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /* This test is for the thread stack checking services. */ diff --git a/test/tx/regression/threadx_thread_stack_fill_value_test.c b/test/tx/regression/threadx_thread_stack_fill_value_test.c index 896c0c7f7..fa6eda220 100644 --- a/test/tx/regression/threadx_thread_stack_fill_value_test.c +++ b/test/tx/regression/threadx_thread_stack_fill_value_test.c @@ -8,7 +8,7 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /* This test checks that the stack fill value recorded in a thread control block is the value that was actually written into that thread's stack. The two used to disagree diff --git a/test/tx/regression/threadx_trace_entry_update_test.c b/test/tx/regression/threadx_trace_entry_update_test.c index 6c6d96143..fe3074aae 100644 --- a/test/tx/regression/threadx_trace_entry_update_test.c +++ b/test/tx/regression/threadx_trace_entry_update_test.c @@ -12,7 +12,7 @@ * * SPDX-License-Identifier: MIT and CC0-1.0 **************************************************************************/ -// Some portions generated by Codex (gpt-5.6-sol). +// Portions of this file were generated with AI assistance. /* This test drives the trace entry update paths -- the blocks guarded by TX_ENABLE_EVENT_TRACE that go back and patch a trace entry after the call diff --git a/utility/execution_profile_kit/smp_version/tx_execution_profile.c b/utility/execution_profile_kit/smp_version/tx_execution_profile.c index 3739475c1..44e2b161a 100644 --- a/utility/execution_profile_kit/smp_version/tx_execution_profile.c +++ b/utility/execution_profile_kit/smp_version/tx_execution_profile.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/utility/rtos_compatibility_layers/FreeRTOS/tx_freertos.c b/utility/rtos_compatibility_layers/FreeRTOS/tx_freertos.c index f3a19a01d..1cceafb3b 100644 --- a/utility/rtos_compatibility_layers/FreeRTOS/tx_freertos.c +++ b/utility/rtos_compatibility_layers/FreeRTOS/tx_freertos.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Claude Code (Opus 5) +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/utility/rtos_compatibility_layers/posix/px_cond_broadcast.c b/utility/rtos_compatibility_layers/posix/px_cond_broadcast.c index a2babdbaa..fe54532c5 100644 --- a/utility/rtos_compatibility_layers/posix/px_cond_broadcast.c +++ b/utility/rtos_compatibility_layers/posix/px_cond_broadcast.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/utility/rtos_compatibility_layers/posix/px_cond_destroy.c b/utility/rtos_compatibility_layers/posix/px_cond_destroy.c index 2ae8421aa..5f9d8f8a9 100644 --- a/utility/rtos_compatibility_layers/posix/px_cond_destroy.c +++ b/utility/rtos_compatibility_layers/posix/px_cond_destroy.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/utility/rtos_compatibility_layers/posix/px_cond_init.c b/utility/rtos_compatibility_layers/posix/px_cond_init.c index 87ea12d69..27bfd41dc 100644 --- a/utility/rtos_compatibility_layers/posix/px_cond_init.c +++ b/utility/rtos_compatibility_layers/posix/px_cond_init.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/utility/rtos_compatibility_layers/posix/px_cond_signal.c b/utility/rtos_compatibility_layers/posix/px_cond_signal.c index 4b660feff..611202acb 100644 --- a/utility/rtos_compatibility_layers/posix/px_cond_signal.c +++ b/utility/rtos_compatibility_layers/posix/px_cond_signal.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Copilot (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ From 26e4aa182c600f77409db1e1a24d45bc5b48560a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Tue, 15 Sep 2026 23:08:23 -0400 Subject: [PATCH 144/181] Fixed the build of tx_misra.c with MISRA and event trace enabled (#746) tx_misra.c defines five pointer conversions for the trace component, and their prototypes sit in tx_trace.h behind TX_SOURCE_CODE. tx_misra.c is the one kernel source that does not define that macro, so it defines all five with no previous declaration. Under -Wmissing-declarations -Werror, which the kernel target is built with, the file does not compile at all, so TX_MISRA_ENABLE and TX_ENABLE_EVENT_TRACE cannot be enabled together. No build configuration defines both, which is why this has never surfaced. The five prototypes move out of the TX_SOURCE_CODE guard into their own block, next to where tx_api.h already declares _tx_misra_trace_event_insert - the sixth function of the same region, which escapes the problem for exactly that reason. Declarations only; no definition moves and no macro changes meaning. All 185 files in common/src now compile clean under all four combinations of the two macros with -Wall -Wextra -Wmissing-declarations -Werror, against five errors in tx_misra.c for the both-enabled case before. Object code is byte identical for the three combinations that already built: 0 of 185 files differ in each. Assisted-by: Claude Code (Opus 5) --- common/inc/tx_trace.h | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/common/inc/tx_trace.h b/common/inc/tx_trace.h index d85d5cc35..10b96761e 100644 --- a/common/inc/tx_trace.h +++ b/common/inc/tx_trace.h @@ -8,6 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. /**************************************************************************/ @@ -508,6 +509,21 @@ TRACE_DECLARE ULONG _tx_trace_registry_search_start #endif +#if defined(TX_ENABLE_EVENT_TRACE) && defined(TX_MISRA_ENABLE) + +/* Define the MISRA-specific conversion routines. These are defined in tx_misra.c, which is the + one source file in the kernel that does not compile as ThreadX source code, so the prototypes + cannot sit behind TX_SOURCE_CODE. */ + +UCHAR *_tx_misra_object_to_uchar_pointer_convert(TX_TRACE_OBJECT_ENTRY *pointer); +TX_TRACE_OBJECT_ENTRY *_tx_misra_uchar_to_object_pointer_convert(UCHAR *pointer); +TX_TRACE_HEADER *_tx_misra_uchar_to_header_pointer_convert(UCHAR *pointer); +TX_TRACE_BUFFER_ENTRY *_tx_misra_uchar_to_entry_pointer_convert(UCHAR *pointer); +UCHAR *_tx_misra_entry_to_uchar_pointer_convert(TX_TRACE_BUFFER_ENTRY *pointer); + +#endif + + #ifdef TX_SOURCE_CODE /* Define internal function prototypes of the trace component, only if compiling ThreadX source code. */ @@ -525,13 +541,6 @@ VOID _tx_trace_object_unregister(VOID *object_ptr); /* Define MISRA-specific routines. */ -UCHAR *_tx_misra_object_to_uchar_pointer_convert(TX_TRACE_OBJECT_ENTRY *pointer); -TX_TRACE_OBJECT_ENTRY *_tx_misra_uchar_to_object_pointer_convert(UCHAR *pointer); -TX_TRACE_HEADER *_tx_misra_uchar_to_header_pointer_convert(UCHAR *pointer); -TX_TRACE_BUFFER_ENTRY *_tx_misra_uchar_to_entry_pointer_convert(UCHAR *pointer); -UCHAR *_tx_misra_entry_to_uchar_pointer_convert(TX_TRACE_BUFFER_ENTRY *pointer); - - #define TX_OBJECT_TO_UCHAR_POINTER_CONVERT(a) _tx_misra_object_to_uchar_pointer_convert((a)) #define TX_UCHAR_TO_OBJECT_POINTER_CONVERT(a) _tx_misra_uchar_to_object_pointer_convert((a)) #define TX_UCHAR_TO_HEADER_POINTER_CONVERT(a) _tx_misra_uchar_to_header_pointer_convert((a)) From b93d1ee92ff2c3e720d6ed2c5dd7eaf3bdd7e8e2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Tue, 15 Sep 2026 23:19:32 -0400 Subject: [PATCH 145/181] Fixed the simulator ports and thread create paths so they compile when TX_MISRA_ENABLE is defined (#742) * Fixed the simulator ports so they compile when TX_MISRA_ENABLE is defined _tx_thread_stack_build() in the four simulator ports converts the fake stack pointer through TX_POINTER_TO_ALIGN_TYPE_CONVERT and TX_ALIGN_TYPE_TO_POINTER_CONVERT. tx_api.h defines both macros only in the non-MISRA branch of its #ifdef TX_MISRA_ENABLE, so with that macro defined the two names are undeclared and none of the four files compiles. Reproduced with: gcc -m32 -c -DTX_MISRA_ENABLE -I common/inc -I ports/linux/gnu/inc \ ports/linux/gnu/src/tx_thread_stack_build.c -o /dev/null which reports both names as implicit declarations and then an int to pointer assignment. The same command without the define compiles cleanly. No build configuration under test/tx/cmake or test/smp/cmake defines TX_MISRA_ENABLE, so CI never compiles these files in that mode. It surfaced on a branch that carries such a configuration. The conversions are now written inline, which is what the non-MISRA macros expand to and what the surrounding port code already does, including the line this replaced. The alternative would be the idiom common/src/tx_thread_create.c uses for the same conversion: an explicit #ifdef selecting the ULONG pair under MISRA. That is not equivalent here. On __x86_64__ this port defines ULONG as unsigned int and ALIGN_TYPE as unsigned long long, so a pointer round-tripped through the ULONG pair loses its top 32 bits. Writing the conversion inline keeps one form that is correct in both modes and on both widths. Verified by compiling the Linux port with and without TX_MISRA_ENABLE, both clean. Assisted-by: Claude Code (Opus 5) * Fixed the same MISRA build break in the SMP and module manager thread create _tx_thread_create() in common_smp and _txm_module_manager_thread_create() convert the thread's stack start through TX_POINTER_TO_ALIGN_TYPE_CONVERT and TX_ALIGN_TYPE_TO_POINTER_CONVERT with no conditional at all. tx_api.h defines both macros only in the non-MISRA branch, so with TX_MISRA_ENABLE and TX_ENABLE_STACK_CHECKING both defined neither file compiles. It is the same defect as the simulator ports in the previous commit, in two more files. Reproduced with: gcc -c -DTX_MISRA_ENABLE -DTX_ENABLE_STACK_CHECKING \ -I common_smp/inc -I ports_smp/linux/gnu/inc \ common_smp/src/tx_thread_create.c -o /dev/null which reports both names as implicit declarations. Both files now compile with and without TX_MISRA_ENABLE. The conversions are written inline for the same reason as the ports: the #ifdef idiom that common/src/tx_thread_create.c uses selects the ULONG pair under MISRA, which truncates a pointer wherever ALIGN_TYPE is wider than ULONG. That is reported separately. Verified: the SMP regression suite passes 117 of 117, and the ThreadX suite still builds. Assisted-by: Claude Code (Opus 5) --- .../module_manager/src/txm_module_manager_thread_create.c | 4 ++-- common_smp/src/tx_thread_create.c | 4 ++-- ports/linux/gnu/src/tx_thread_stack_build.c | 4 ++-- ports/win32/vs_2019/src/tx_thread_stack_build.c | 4 ++-- ports/win64/vs_2022/src/tx_thread_stack_build.c | 4 ++-- ports_smp/linux/gnu/src/tx_thread_stack_build.c | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/common_modules/module_manager/src/txm_module_manager_thread_create.c b/common_modules/module_manager/src/txm_module_manager_thread_create.c index 1f9bbc470..276f3c16d 100644 --- a/common_modules/module_manager/src/txm_module_manager_thread_create.c +++ b/common_modules/module_manager/src/txm_module_manager_thread_create.c @@ -294,7 +294,7 @@ ULONG i; stack_size = ((stack_size/(sizeof(ULONG))) * (sizeof(ULONG))) - (sizeof(ULONG)); /* Ensure the starting stack address is evenly aligned. */ - new_stack_start = TX_POINTER_TO_ALIGN_TYPE_CONVERT(stack_start); + new_stack_start = (ALIGN_TYPE) ((VOID *) stack_start); updated_stack_start = ((((ULONG) new_stack_start) + ((sizeof(ULONG)) - ((ULONG) 1)) ) & (~((sizeof(ULONG)) - ((ULONG) 1)))); /* Determine if the starting stack address is different. */ @@ -306,7 +306,7 @@ ULONG i; } /* Update the starting stack pointer. */ - stack_start = TX_ALIGN_TYPE_TO_POINTER_CONVERT(updated_stack_start); + stack_start = (VOID *) ((ALIGN_TYPE) updated_stack_start); #endif /* Allocate the thread entry information at the top of thread's stack - Leaving one diff --git a/common_smp/src/tx_thread_create.c b/common_smp/src/tx_thread_create.c index d7c8f507f..5be0d05b5 100644 --- a/common_smp/src/tx_thread_create.c +++ b/common_smp/src/tx_thread_create.c @@ -132,7 +132,7 @@ ULONG stack_fill_value; stack_size = ((stack_size/(sizeof(ULONG))) * (sizeof(ULONG))) - (sizeof(ULONG)); /* Ensure the starting stack address is evenly aligned. */ - new_stack_start = TX_POINTER_TO_ALIGN_TYPE_CONVERT(stack_start); + new_stack_start = (ALIGN_TYPE) ((VOID *) stack_start); updated_stack_start = (((new_stack_start) + ((sizeof(ULONG)) - ((ULONG) 1)) ) & (~((sizeof(ULONG)) - ((ULONG) 1)))); /* Determine if the starting stack address is different. */ @@ -144,7 +144,7 @@ ULONG stack_fill_value; } /* Update the starting stack pointer. */ - stack_start = TX_ALIGN_TYPE_TO_POINTER_CONVERT(updated_stack_start); + stack_start = (VOID *) ((ALIGN_TYPE) updated_stack_start); #endif /* Prepare the thread control block prior to placing it on the created diff --git a/ports/linux/gnu/src/tx_thread_stack_build.c b/ports/linux/gnu/src/tx_thread_stack_build.c index d1d8b44fa..102ded32d 100644 --- a/ports/linux/gnu/src/tx_thread_stack_build.c +++ b/ports/linux/gnu/src/tx_thread_stack_build.c @@ -125,9 +125,9 @@ struct sched_param sp; thread's stack area and is therefore not necessarily aligned, so round the result down to a ULONG boundary. This pointer is dereferenced as a ULONG below and is also the starting value of the stack checking logic's highest used pointer. */ - fake_stack_ptr = TX_POINTER_TO_ALIGN_TYPE_CONVERT(((CHAR *) thread_ptr -> tx_thread_stack_end) - 8); + fake_stack_ptr = (ALIGN_TYPE) ((VOID *) (((CHAR *) thread_ptr -> tx_thread_stack_end) - 8)); fake_stack_ptr = fake_stack_ptr & (~((ALIGN_TYPE) (sizeof(ULONG) - 1))); - thread_ptr -> tx_thread_stack_ptr = TX_ALIGN_TYPE_TO_POINTER_CONVERT(fake_stack_ptr); + thread_ptr -> tx_thread_stack_ptr = (VOID *) ((ALIGN_TYPE) fake_stack_ptr); /* Clear the first word of the stack. */ *(((ULONG *) thread_ptr -> tx_thread_stack_ptr) - 1) = 0; diff --git a/ports/win32/vs_2019/src/tx_thread_stack_build.c b/ports/win32/vs_2019/src/tx_thread_stack_build.c index 94b924053..7b6e139b6 100644 --- a/ports/win32/vs_2019/src/tx_thread_stack_build.c +++ b/ports/win32/vs_2019/src/tx_thread_stack_build.c @@ -140,9 +140,9 @@ ALIGN_TYPE fake_stack_ptr; thread's stack area and is therefore not necessarily aligned, so round the result down to a ULONG boundary. This pointer is dereferenced as a ULONG below and is also the starting value of the stack checking logic's highest used pointer. */ - fake_stack_ptr = TX_POINTER_TO_ALIGN_TYPE_CONVERT(((CHAR *) thread_ptr -> tx_thread_stack_end) - 8); + fake_stack_ptr = (ALIGN_TYPE) ((VOID *) (((CHAR *) thread_ptr -> tx_thread_stack_end) - 8)); fake_stack_ptr = fake_stack_ptr & (~((ALIGN_TYPE) (sizeof(ULONG) - 1))); - thread_ptr -> tx_thread_stack_ptr = TX_ALIGN_TYPE_TO_POINTER_CONVERT(fake_stack_ptr); + thread_ptr -> tx_thread_stack_ptr = (VOID *) ((ALIGN_TYPE) fake_stack_ptr); /* Clear the first word of the stack. */ *(((ULONG *) thread_ptr -> tx_thread_stack_ptr) - 1) = 0; diff --git a/ports/win64/vs_2022/src/tx_thread_stack_build.c b/ports/win64/vs_2022/src/tx_thread_stack_build.c index 20aa85240..c4f3f6ea3 100644 --- a/ports/win64/vs_2022/src/tx_thread_stack_build.c +++ b/ports/win64/vs_2022/src/tx_thread_stack_build.c @@ -144,9 +144,9 @@ ALIGN_TYPE fake_stack_ptr; thread's stack area and is therefore not necessarily aligned, so round the result down to a ULONG boundary. This pointer is dereferenced as a ULONG below and is also the starting value of the stack checking logic's highest used pointer. */ - fake_stack_ptr = TX_POINTER_TO_ALIGN_TYPE_CONVERT(((CHAR *) thread_ptr -> tx_thread_stack_end) - 8); + fake_stack_ptr = (ALIGN_TYPE) ((VOID *) (((CHAR *) thread_ptr -> tx_thread_stack_end) - 8)); fake_stack_ptr = fake_stack_ptr & (~((ALIGN_TYPE) (sizeof(ULONG) - 1))); - thread_ptr -> tx_thread_stack_ptr = TX_ALIGN_TYPE_TO_POINTER_CONVERT(fake_stack_ptr); + thread_ptr -> tx_thread_stack_ptr = (VOID *) ((ALIGN_TYPE) fake_stack_ptr); /* Clear the first word of the stack. */ *(((ULONG *) thread_ptr -> tx_thread_stack_ptr) - 1) = 0; diff --git a/ports_smp/linux/gnu/src/tx_thread_stack_build.c b/ports_smp/linux/gnu/src/tx_thread_stack_build.c index 9c0cffad2..65b8e25c0 100644 --- a/ports_smp/linux/gnu/src/tx_thread_stack_build.c +++ b/ports_smp/linux/gnu/src/tx_thread_stack_build.c @@ -127,9 +127,9 @@ pthread_attr_t attrs; thread's stack area and is therefore not necessarily aligned, so round the result down to a ULONG boundary. This pointer is dereferenced as a ULONG below and is also the starting value of the stack checking logic's highest used pointer. */ - fake_stack_ptr = TX_POINTER_TO_ALIGN_TYPE_CONVERT(((CHAR *) thread_ptr -> tx_thread_stack_end) - 8); + fake_stack_ptr = (ALIGN_TYPE) ((VOID *) (((CHAR *) thread_ptr -> tx_thread_stack_end) - 8)); fake_stack_ptr = fake_stack_ptr & (~((ALIGN_TYPE) (sizeof(ULONG) - 1))); - thread_ptr -> tx_thread_stack_ptr = TX_ALIGN_TYPE_TO_POINTER_CONVERT(fake_stack_ptr); + thread_ptr -> tx_thread_stack_ptr = (VOID *) ((ALIGN_TYPE) fake_stack_ptr); /* Clear the first word of the stack. */ *(((ULONG *) thread_ptr -> tx_thread_stack_ptr) - 1) = 0; From 24d1f278c23469dd381a32250977aa93997f7cb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Wed, 16 Sep 2026 09:18:41 -0400 Subject: [PATCH 146/181] Decorrelated the wait abort ISR test's interrupt source from the thread it samples (#743) threadx_thread_wait_abort_and_isr_test waits for the periodic timer interrupt to land while the preempt disable flag is set. The same interrupt also puts the semaphore that wakes the thread being sampled, so the two run in lockstep: the tick wakes thread 0, thread 0 does a fixed amount of work and suspends, and the next tick arrives a fixed interval later with thread 0 in the same place every time. That is the resonance the handler's own comment describes, and perturbing the handler's duration only shifts the phase rather than breaking the correlation. The window itself is a few instructions wide, so a sampler locked to the thread's own cycle can miss it indefinitely, which is what #644 and #649 measured and worked around. The simulator's timer thread waits on _tx_linux_timer_semaphore with a one-tick deadline and delivers an interrupt early when the semaphore is posted, which the port already relies on in _tx_thread_schedule. The test now runs a plain POSIX thread that posts it, injecting interrupts at moments unrelated to the tick grid and sampling thread 0 at arbitrary points in its cycle rather than the same one. The injector posts only when nothing is outstanding, so interrupts can never be queued faster than they are serviced. It is confined to the Linux simulation port and no port file changes. The count of windows asked for goes back to ten, on the same reasoning that lowered it to three: ask for what a run can actually reach. Measured over six build configurations of a branch carrying this change, every one reaches ten of ten in under a second, against one to three of three previously with three of the six pinned at the 180 second budget. The budget and the zero window ceiling are untouched, so a run that somehow still falls behind behaves exactly as it does today. The SMP copy deliberately does not get the injector, and its count stays at twenty. It has never been in the slow mode, and injecting interrupts there measurably hurts: 8.9 seconds against 0 to 1 for the same twenty windows, which is the extra interrupt traffic contending across the simulated cores. Only the tx copy has the problem this solves, so only the tx copy changes; the budget and ceiling logic stays identical between them. Verified on this branch: the tx suite passes 105 of 105 with the test at 0.44 seconds, and four direct runs reach ten of ten in 0 to 1 seconds. The SMP suite passes 117 of 117 unmodified, with its own test at 0 to 1 seconds over four runs. Assisted-by: Claude Code (Opus 5) --- .../threadx_thread_wait_abort_and_isr_test.c | 128 +++++++++++++++--- 1 file changed, 109 insertions(+), 19 deletions(-) diff --git a/test/tx/regression/threadx_thread_wait_abort_and_isr_test.c b/test/tx/regression/threadx_thread_wait_abort_and_isr_test.c index 0b1585080..6745ad0d9 100644 --- a/test/tx/regression/threadx_thread_wait_abort_and_isr_test.c +++ b/test/tx/regression/threadx_thread_wait_abort_and_isr_test.c @@ -32,6 +32,90 @@ extern UINT _tx_timer_system_clock; static TX_SEMAPHORE semaphore_0; +#ifdef __linux__ + +/* The window this test waits for is a few instructions wide, and the interrupt + that samples it is the same one that wakes the thread being sampled, so the + two run in lockstep: the tick wakes thread 0, thread 0 does a fixed amount of + work and suspends, and the next tick arrives a fixed interval later with + thread 0 in the same place every time. That is the resonance the handler below + describes, and perturbing the handler's duration only shifts the phase rather + than decorrelating it. + + The simulator's timer thread waits on _tx_linux_timer_semaphore with a + one-tick deadline and delivers an interrupt early if the semaphore is posted, + which the port itself relies on elsewhere. A plain POSIX thread posting it + therefore injects interrupts at moments unrelated to the tick grid, which + samples thread 0 at arbitrary points in its cycle instead of the same one. + + It posts only when nothing is outstanding, so interrupts can never be queued + faster than they are serviced and the injector cannot starve the system. */ + +#include +#include +#include + +extern sem_t _tx_linux_timer_semaphore; + +static volatile int injector_stop = 0; +static pthread_t injector_thread; + +#define INJECTOR_INTERVAL_USEC 100 + + +static void *interrupt_injector(void *p) +{ + +int pending; + + + (void) p; + + while (injector_stop == 0) + { + + if ((sem_getvalue(&_tx_linux_timer_semaphore, &pending) == 0) && (pending == 0)) + { + sem_post(&_tx_linux_timer_semaphore); + } + + usleep(INJECTOR_INTERVAL_USEC); + } + + return(NULL); +} + + +static void interrupt_injector_start(void) +{ + + injector_stop = 0; + if (pthread_create(&injector_thread, NULL, interrupt_injector, NULL) != 0) + { + + /* Without the injector the loop still runs, on its own budget. */ + injector_stop = 1; + } +} + + +static void interrupt_injector_stop(void) +{ + + if (injector_stop == 0) + { + + injector_stop = 1; + pthread_join(injector_thread, NULL); + } +} + +#else +#define interrupt_injector_start() +#define interrupt_injector_stop() +#endif + + /* Define thread prototypes. */ static void thread_0_entry(ULONG thread_input); @@ -192,17 +276,23 @@ UINT status; ticks, nominally 200 seconds, failed to stop a run that took 726 seconds, because fewer than 20000 ticks had passed. time() does not drift that way. - How many windows to ask for is set by what a run can actually reach. Four CI - runs of the same tree measured this loop in two modes: one where a window - arrives in milliseconds and every window asked for costs under a second in - total, and one where a single window costs around forty seconds. Seven of - twenty configuration-runs landed in the slow mode and ran out of budget, - reaching 0, 3, 3, 3, 4, 7 and 7 of the ten then asked for, every one of them - still reporting a pass. Asking for three keeps the count reachable in both - modes. The later hits repeat what the first ones establish, so the coverage - given up is small, and what is recorded is honest. The SMP copy asks for - twenty and reaches them in under half a second in all five of its - configurations, so it keeps its count. + How many windows to ask for is set by what a run can actually reach. Before the + injector above, four CI runs of the same tree measured this loop in two modes: + one where a window arrives in milliseconds, and one where a single window + costs around forty seconds. Seven of twenty configuration-runs landed in the + slow mode and ran out of budget, reaching 0, 3, 3, 3, 4, 7 and 7 of the ten + then asked for, every one of them still reporting a pass, and the count had to + come down to three to stay reachable. With the interrupt source decorrelated + from the thread it samples the slow mode does not occur: all six + configurations of a run reach ten of ten in under a second. The count is + therefore back to ten, on the same reasoning that lowered it. + + The SMP copy deliberately does not get the injector. It has never been in the + slow mode, reaching its twenty windows in about a second, and injecting + interrupts there measurably hurts: 8.9 seconds against 0 to 1 for the same + twenty, which is the extra interrupt traffic contending across the simulated + cores. Its budget and ceiling still match this one; only the injector differs, + because only this copy has the problem it solves. Reaching the window no times at all is different in kind, which is what the ceiling below is for. The check after the loop compares semaphore bookkeeping @@ -212,14 +302,11 @@ UINT status; reached the window once keeps trying up to the ceiling, and fails if it still has not. - The budget is 180 seconds rather than 120 because of what the slow mode costs - per window. The seven truncated runs reached their windows at between 17 and - 40 seconds each, so three of them can need 120 seconds, which is exactly what - the old budget allowed and would have truncated at two. 180 leaves margin at - the worst rate measured, and bounds five configurations at 15 minutes against - a 60 minute step timeout. Locally, where a window costs 2 to 5 seconds, three - of them take 5 to 14 seconds and the budget is never approached. */ -#define WAIT_ABORT_WINDOWS_WANTED ((ULONG) 3) + The budget and the ceiling stay as they were, as a net rather than a working + limit. They were sized for the slow mode: 180 seconds covers three windows at + the worst rate measured, 17 to 40 seconds each. Nothing should approach them + now, and if something does, the behaviour is what it was before. */ +#define WAIT_ABORT_WINDOWS_WANTED ((ULONG) 10) #define WAIT_ABORT_SECOND_BUDGET ((ULONG) 180) #define WAIT_ABORT_ZERO_WINDOW_CEILING ((ULONG) 300) @@ -234,6 +321,7 @@ time_t start_wall; /* Loop to exploit the probability window inside tx_thread_wait_abort. */ start_wall = time(TX_NULL); + interrupt_injector_start(); while (condition_count < WAIT_ABORT_WINDOWS_WANTED) { @@ -292,6 +380,8 @@ time_t start_wall; #endif } + interrupt_injector_stop(); + /* Clear ISR dispatch. */ test_isr_dispatch = TX_NULL; From e9b5aec65e7b7221394eeb845a3456c44676ce64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Wed, 16 Sep 2026 09:55:24 -0400 Subject: [PATCH 147/181] Added MISRA build configurations to the ThreadX regression matrix (#747) TX_MISRA_ENABLE routes the kernel's pointer conversions, its memset and its stack check through the shim in common/src/tx_misra.c. No build configuration defined it, so that file was never compiled or tested, and the source the MISRA analysis runs against was not the source the suite exercises. Adding event tracing alongside it reaches a further region of the shim that neither macro alone compiles. Both defects found in this area were invisible for the same reason: #741 broke under TX_MISRA_ENABLE and #745 under both macros together, and neither combination was built anywhere. misra_build and misra_trace_build fill that gap. Two things had to give way for them. TX_POINTER_TO_ALIGN_TYPE_CONVERT exists only when TX_MISRA_ENABLE is absent, so threadx_test_port.h writes the conversion out rather than taking it from the API; it is test scaffolding storing a pointer in a word wide enough to hold one, not kernel source. And thread_transition and module_manager compile hand-picked common/src sources directly instead of linking the library, which is what lets them reach feature macros the library-per-configuration model cannot; under TX_MISRA_ENABLE those sources call into the shim, and pulling the shim in pulls its own callees after it. Neither directory exists to test the shim, so the MISRA configurations skip them. 100/100 tests pass in each of the two new configurations, against 105/105 in the existing five - the five not run are the four thread transition tests and the module manager test, exactly the two directories skipped. Build is 4 to 5 seconds and the suites 13 and 15 seconds, against 4 seconds and 9 to 17 for the configurations already there, so the tx job grows by roughly forty seconds. Assisted-by: Claude Code (Opus 5) --- test/tx/cmake/CMakeLists.txt | 33 +++++++++++++++++++++++--- test/tx/regression/threadx_test_port.h | 7 +++++- 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/test/tx/cmake/CMakeLists.txt b/test/tx/cmake/CMakeLists.txt index f8e902efa..2f9c9b9f4 100644 --- a/test/tx/cmake/CMakeLists.txt +++ b/test/tx/cmake/CMakeLists.txt @@ -14,7 +14,8 @@ set(CMAKE_C_EXTENSIONS OFF) # Set build configurations set(BUILD_CONFIGURATIONS default_build_coverage disable_notify_callbacks_build - stack_checking_build stack_checking_rand_fill_build trace_build) + stack_checking_build stack_checking_rand_fill_build trace_build + misra_build misra_trace_build) set(CMAKE_CONFIGURATION_TYPES ${BUILD_CONFIGURATIONS} CACHE STRING "list of supported configuration types" FORCE) @@ -36,6 +37,21 @@ set(stack_checking_build TX_QUEUE_MESSAGE_MAX_SIZE=32 TX_ENABLE_STACK_CHECKING) set(stack_checking_rand_fill_build TX_QUEUE_MESSAGE_MAX_SIZE=32 TX_ENABLE_STACK_CHECKING TX_ENABLE_RANDOM_NUMBER_STACK_FILLING) set(trace_build TX_QUEUE_MESSAGE_MAX_SIZE=32 TX_ENABLE_EVENT_TRACE) +# TX_MISRA_ENABLE routes the kernel's pointer conversions, its memset and its +# stack check through the shim in common/src/tx_misra.c, which every +# configuration above compiles out entirely. It is also the source the MISRA +# analysis runs against, so without this the build that is analysed and the build +# that is tested are different builds of the same tree. +# +# The second adds event tracing, because the shim has a region behind +# TX_ENABLE_EVENT_TRACE that neither macro alone reaches. +# +# Both defects found here were invisible for the same reason: #741 broke under +# TX_MISRA_ENABLE and #745 under both macros together, and neither combination +# was built anywhere. +set(misra_build TX_QUEUE_MESSAGE_MAX_SIZE=32 TX_MISRA_ENABLE) +set(misra_trace_build TX_QUEUE_MESSAGE_MAX_SIZE=32 TX_MISRA_ENABLE TX_ENABLE_EVENT_TRACE) + add_compile_definitions( TX_REGRESSION_TEST TEST_STACK_SIZE_PRINTF=4096 @@ -68,12 +84,23 @@ add_subdirectory(samples) # beside regression on purpose: every branch in the current fix set adds an # add_subdirectory line immediately after regression, and putting a second one # there turns a set of clean merges into a set of one-line conflicts. -add_subdirectory(thread_transition) +# These two compile a hand-picked set of common/src sources directly instead of +# linking the threadx library, which is what lets them reach feature macros the +# library-per-configuration model cannot. That does not survive TX_MISRA_ENABLE: +# the kernel's TX_MEMSET and its conversions become calls into tx_misra.c, and +# pulling the shim into these targets pulls its own callees after it. Neither +# exists to test the shim, and the regression suite covers it, so the MISRA +# configurations skip them. +if(NOT ("TX_MISRA_ENABLE" IN_LIST ${CMAKE_BUILD_TYPE})) + add_subdirectory(thread_transition) +endif() # Host tests for the Module Manager. Listed after thread_transition for the reason # given above it: additions here are appended rather than inserted, so that branches # adding a directory of their own merge cleanly. -add_subdirectory(module_manager) +if(NOT ("TX_MISRA_ENABLE" IN_LIST ${CMAKE_BUILD_TYPE})) + add_subdirectory(module_manager) +endif() # Coverage # diff --git a/test/tx/regression/threadx_test_port.h b/test/tx/regression/threadx_test_port.h index b8502b4de..5d79c8e84 100644 --- a/test/tx/regression/threadx_test_port.h +++ b/test/tx/regression/threadx_test_port.h @@ -32,6 +32,11 @@ typedef ALIGN_TYPE TX_TEST_POINTER_WORD; -#define TX_TEST_STORE_POINTER(a, b) (a) = ((TX_TEST_POINTER_WORD) TX_POINTER_TO_ALIGN_TYPE_CONVERT(b)) +/* TX_POINTER_TO_ALIGN_TYPE_CONVERT is defined only when TX_MISRA_ENABLE is absent, + so the conversion is written out here rather than taken from the API. This is + test scaffolding storing a pointer in a word wide enough to hold one; it is not + kernel source and carries no MISRA obligation of its own. */ + +#define TX_TEST_STORE_POINTER(a, b) (a) = ((TX_TEST_POINTER_WORD) (ALIGN_TYPE) (b)) #endif From ad558a7b1faa7d32371901e7e2710d2e05f55f8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Wed, 16 Sep 2026 14:01:07 -0400 Subject: [PATCH 148/181] Fixed the zero trace time stamps in the Linux ports' MISRA builds (#749) Both Linux ports define TX_TRACE_TIME_SOURCE as _tx_misra_time_stamp_get() when TX_MISRA_ENABLE is set, and neither implements that function, so both inherit the generic `return(0);` from tx_misra.c. Every trace event is stamped zero. The buffer carries no timing, and the kernel's own check for an entry having been overwritten -- time_stamp against the entry's own stamp, in the block and byte allocates and in the system suspend and resume -- compares zero with zero, so it never fires and a service patches whatever now occupies the slot. Both ports now read in MISRA builds the clock they already read otherwise, _tx_linux_time_stamp.tv_nsec, which TX_TRACE_PORT_EXTENSION refreshes on every recorded event in both forms of the insert. The non-SMP port's non-MISRA macro carried a trailing semicolon, which made it a statement and is why the MISRA insert -- which takes the time source as a function argument -- could not use it; that is dropped and the two branches become one definition. Both headers keep the _tx_misra_time_stamp_get declaration, because tx_misra.c still defines it and is compiled for these ports. The MISRA insert evaluates its time source before the callee refreshes the clock, so each entry carries the reading taken at the previous recorded event. Stamps are real, distinct and ordered, which is what the overwrite check needs. The trace entry update test gains an assertion that the buffer holds an entry the port actually stamped. It fails on dev with ERROR #13 under misra_trace_build and passes with this change. Suites green: 7/7 ThreadX configurations, 5/5 SMP. Assisted-by: Claude Code (Opus 5) --- ports/linux/gnu/inc/tx_port.h | 18 +++++++-- ports_smp/linux/gnu/inc/tx_port.h | 16 ++++++-- .../threadx_trace_entry_update_test.c | 37 +++++++++++++++++++ 3 files changed, 64 insertions(+), 7 deletions(-) diff --git a/ports/linux/gnu/inc/tx_port.h b/ports/linux/gnu/inc/tx_port.h index 842afe0f3..1f7e25f39 100644 --- a/ports/linux/gnu/inc/tx_port.h +++ b/ports/linux/gnu/inc/tx_port.h @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. + /**************************************************************************/ /**************************************************************************/ @@ -317,13 +319,21 @@ void _tx_linux_debug_entry_insert(char *action, char *file, unsigned long lin */ -#ifndef TX_MISRA_ENABLE +/* The clock below is read for every trace event in both builds. The MISRA form + of the in-line insert takes the time stamp as an argument rather than reading + it itself, so the macro has to be an expression; that is why it carries no + trailing semicolon. */ + #ifndef TX_TRACE_TIME_SOURCE -#define TX_TRACE_TIME_SOURCE ((ULONG) (_tx_linux_time_stamp.tv_nsec)); +#define TX_TRACE_TIME_SOURCE ((ULONG) (_tx_linux_time_stamp.tv_nsec)) #endif -#else + +/* Declared here rather than used: this port supplies its own time stamp above, + but the generic definition in common/src/tx_misra.c is compiled for this port + and needs a declaration in scope. */ + +#ifdef TX_MISRA_ENABLE ULONG _tx_misra_time_stamp_get(VOID); -#define TX_TRACE_TIME_SOURCE _tx_misra_time_stamp_get() #endif #ifndef TX_TRACE_TIME_MASK diff --git a/ports_smp/linux/gnu/inc/tx_port.h b/ports_smp/linux/gnu/inc/tx_port.h index bb1021dd1..dc1aeade2 100644 --- a/ports_smp/linux/gnu/inc/tx_port.h +++ b/ports_smp/linux/gnu/inc/tx_port.h @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. + /**************************************************************************/ /**************************************************************************/ @@ -373,13 +375,21 @@ void _tx_linux_debug_entry_insert(char *action, char *file, unsigned long lin */ -#ifndef TX_MISRA_ENABLE +/* The clock below is read for every trace event in both builds. The MISRA form + of the in-line insert takes the time stamp as an argument rather than reading + it itself, so the macro has to be an expression; that is why it carries no + trailing semicolon. */ + #ifndef TX_TRACE_TIME_SOURCE #define TX_TRACE_TIME_SOURCE ((ULONG) (_tx_linux_time_stamp.tv_nsec)) #endif -#else + +/* Declared here rather than used: this port supplies its own time stamp above, + but the generic definition in common_smp/src/tx_misra.c is compiled for this + port and needs a declaration in scope. */ + +#ifdef TX_MISRA_ENABLE ULONG _tx_misra_time_stamp_get(VOID); -#define TX_TRACE_TIME_SOURCE _tx_misra_time_stamp_get() #endif #ifndef TX_TRACE_TIME_MASK diff --git a/test/tx/regression/threadx_trace_entry_update_test.c b/test/tx/regression/threadx_trace_entry_update_test.c index fe3074aae..f18c2d9bd 100644 --- a/test/tx/regression/threadx_trace_entry_update_test.c +++ b/test/tx/regression/threadx_trace_entry_update_test.c @@ -300,6 +300,43 @@ UINT i; test_control_return(1); } +#ifdef TX_ENABLE_EVENT_TRACE + + /* Every update block above compares a saved time stamp against the one in + the entry, so a port whose time source never changes makes all of them + take their true branch for the wrong reason: not because the entry + survived, but because every entry reads the same. Check the buffer holds + at least one entry with a time stamp the port actually supplied. The + events written by this point number in the dozens, so a single zero + reading from a real clock cannot fail this. */ + { + + TX_TRACE_BUFFER_ENTRY *entry_ptr; + UINT stamped; + + + stamped = TX_FALSE; + + for (entry_ptr = _tx_trace_buffer_start_ptr; entry_ptr < _tx_trace_buffer_end_ptr; entry_ptr++) + { + + if (entry_ptr -> tx_trace_buffer_entry_time_stamp != ((ULONG) 0)) + { + + stamped = TX_TRUE; + break; + } + } + + if (stamped != TX_TRUE) + { + + printf("Running Trace Entry Update Test..................................... ERROR #13\n"); + test_control_return(1); + } + } +#endif + if (error) { From 70a530097722665b7f3704cf5099b99f255b2e5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Thu, 17 Sep 2026 15:39:30 -0400 Subject: [PATCH 149/181] Added a ThreadX module manager port for the Cortex-R52 (#639) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added the first GNU ThreadX module port for an Arm R-profile core. The port combines the PMSAv8-R MPU model from Cortex-M33 with the AArch32 privilege and processor-mode handling from Cortex-R4. It provides the complete module path: headers, manager sources, scheduler integration, user-mode entry, SVC dispatch, data- and prefetch-abort capture, fault notification, relocatable module loading, and shared-memory regions. Module isolation uses eight MPU regions (8–15) with a 64-byte granule. The scheduler replaces those regions on each module switch and manages a separate privileged loading window in region 16. Assembly-visible structure offsets and region-layout assumptions are checked at build time. Added independent module demonstrations for the S32Z280-594EVB and Armv8-R AEM FVP. The automated FVP regressions cover: - Loading the same position-independent module at different addresses - User-mode data and instruction access violations - Fault capture and notification for both abort types - Shared-region access, alignment, exhaustion, empty-size, and overflow handling - Required module-property combinations - The GCC CLZ-based priority search The port requires user mode and memory protection together, at least 17 EL1 MPU regions, and currently validates A32 modules; Thumb module execution remains unvalidated. Validated with GNU Arm 14.3.1. The FVP suites pass 8/8 in the default configuration and 11/11 with hard-float, FIQ, and interrupt nesting enabled. The S32Z280 images build cleanly, and the module isolation and relocation paths were exercised on S32Z280 silicon during development. Matching user documentation is provided by rtos-docs-asciidoc PR #41. Assisted-by: Claude Code (Opus 5) --- .../fvp_baser_aemv8r/CMakeLists.txt | 358 +++- .../example_build/fvp_baser_aemv8r/cache.c | 149 ++ .../example_build/fvp_baser_aemv8r/cache.h | 72 + .../example_build/fvp_baser_aemv8r/demo_clz.c | 359 ++++ .../example_build/fvp_baser_aemv8r/entry.S | 51 + .../gnu/example_build/fvp_baser_aemv8r/mpu.c | 102 + .../gnu/example_build/fvp_baser_aemv8r/mpu.h | 50 + .../example_build/fvp_baser_aemv8r/platform.h | 53 + .../example_build/s32z280_evb/CMakeLists.txt | 275 +++ .../gnu/example_build/s32z280_evb/entry.S | 50 + .../gnu/example_build/s32z280_evb/link.lds | 5 +- .../gnu/example_build/s32z280_evb/mpu.c | 83 +- .../gnu/example_build/s32z280_evb/mpu.h | 24 + .../gnu/example_build/s32z280_evb/platform.h | 55 + .../example_build/s32z280_evb/thread_mpu.c | 52 +- ports/cortex_r52/gnu/inc/tx_port.h | 71 +- ports/cortex_r52/gnu/readme_threadx.txt | 42 +- .../fvp_baser_aemv8r/link_demo_module.lds | 208 ++ .../fvp_baser_aemv8r/link_module.lds | 295 +++ .../fvp_baser_aemv8r/module_blob.S | 69 + .../fvp_baser_aemv8r/sample_threadx_module.c | 319 +++ .../sample_threadx_module_manager.c | 1624 +++++++++++++++ .../sample_threadx_module_properties.c | 1086 +++++++++++ .../fvp_baser_aemv8r/txm_module_preamble.S | 151 ++ .../s32z280_evb/link_demo_module.lds | 199 ++ .../example_build/s32z280_evb/link_module.lds | 344 ++++ .../example_build/s32z280_evb/module_blob.S | 65 + .../s32z280_evb/sample_threadx_module.c | 319 +++ .../sample_threadx_module_manager.c | 1736 +++++++++++++++++ .../s32z280_evb/tools/diagnose_module.gdb | 252 +++ .../s32z280_evb/tools/run_module_demo.gdb | 657 +++++++ .../s32z280_evb/tools/run_module_demo.sh | 187 ++ .../s32z280_evb/txm_module_preamble.S | 151 ++ ports_module/cortex_r52/gnu/inc/tx_port.h | 442 +++++ .../cortex_r52/gnu/inc/txm_module_port.h | 491 +++++ .../gnu/module_lib/src/txm_module_gcc_setup.S | 211 ++ .../src/txm_module_thread_shell_entry.c | 168 ++ .../src/tx_thread_context_restore.S | 264 +++ .../src/tx_thread_context_save.S | 193 ++ .../module_manager/src/tx_thread_schedule.S | 504 +++++ .../src/tx_thread_stack_build.S | 191 ++ .../src/tx_thread_system_return.S | 169 ++ .../src/txm_module_manager_alignment_adjust.c | 97 + ...xm_module_manager_external_memory_enable.c | 228 +++ .../src/txm_module_manager_fault_capture.S | 285 +++ .../txm_module_manager_memory_fault_handler.c | 139 ++ .../txm_module_manager_memory_fault_notify.c | 78 + .../txm_module_manager_mm_register_setup.c | 219 +++ .../src/txm_module_manager_offset_check.c | 261 +++ .../src/txm_module_manager_svc_handler.S | 233 +++ .../txm_module_manager_thread_stack_build.S | 251 +++ .../src/txm_module_manager_user_mode_entry.S | 133 ++ 52 files changed, 14045 insertions(+), 25 deletions(-) create mode 100644 ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/cache.c create mode 100644 ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/cache.h create mode 100644 ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/demo_clz.c create mode 100644 ports_module/cortex_r52/gnu/example_build/fvp_baser_aemv8r/link_demo_module.lds create mode 100644 ports_module/cortex_r52/gnu/example_build/fvp_baser_aemv8r/link_module.lds create mode 100644 ports_module/cortex_r52/gnu/example_build/fvp_baser_aemv8r/module_blob.S create mode 100644 ports_module/cortex_r52/gnu/example_build/fvp_baser_aemv8r/sample_threadx_module.c create mode 100644 ports_module/cortex_r52/gnu/example_build/fvp_baser_aemv8r/sample_threadx_module_manager.c create mode 100644 ports_module/cortex_r52/gnu/example_build/fvp_baser_aemv8r/sample_threadx_module_properties.c create mode 100644 ports_module/cortex_r52/gnu/example_build/fvp_baser_aemv8r/txm_module_preamble.S create mode 100644 ports_module/cortex_r52/gnu/example_build/s32z280_evb/link_demo_module.lds create mode 100644 ports_module/cortex_r52/gnu/example_build/s32z280_evb/link_module.lds create mode 100644 ports_module/cortex_r52/gnu/example_build/s32z280_evb/module_blob.S create mode 100644 ports_module/cortex_r52/gnu/example_build/s32z280_evb/sample_threadx_module.c create mode 100644 ports_module/cortex_r52/gnu/example_build/s32z280_evb/sample_threadx_module_manager.c create mode 100644 ports_module/cortex_r52/gnu/example_build/s32z280_evb/tools/diagnose_module.gdb create mode 100644 ports_module/cortex_r52/gnu/example_build/s32z280_evb/tools/run_module_demo.gdb create mode 100755 ports_module/cortex_r52/gnu/example_build/s32z280_evb/tools/run_module_demo.sh create mode 100644 ports_module/cortex_r52/gnu/example_build/s32z280_evb/txm_module_preamble.S create mode 100644 ports_module/cortex_r52/gnu/inc/tx_port.h create mode 100644 ports_module/cortex_r52/gnu/inc/txm_module_port.h create mode 100644 ports_module/cortex_r52/gnu/module_lib/src/txm_module_gcc_setup.S create mode 100644 ports_module/cortex_r52/gnu/module_lib/src/txm_module_thread_shell_entry.c create mode 100644 ports_module/cortex_r52/gnu/module_manager/src/tx_thread_context_restore.S create mode 100644 ports_module/cortex_r52/gnu/module_manager/src/tx_thread_context_save.S create mode 100644 ports_module/cortex_r52/gnu/module_manager/src/tx_thread_schedule.S create mode 100644 ports_module/cortex_r52/gnu/module_manager/src/tx_thread_stack_build.S create mode 100644 ports_module/cortex_r52/gnu/module_manager/src/tx_thread_system_return.S create mode 100644 ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_alignment_adjust.c create mode 100644 ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_external_memory_enable.c create mode 100644 ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_fault_capture.S create mode 100644 ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_memory_fault_handler.c create mode 100644 ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_memory_fault_notify.c create mode 100644 ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_mm_register_setup.c create mode 100644 ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_offset_check.c create mode 100644 ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_svc_handler.S create mode 100644 ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_thread_stack_build.S create mode 100644 ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_user_mode_entry.S diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/CMakeLists.txt b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/CMakeLists.txt index c8339fa70..c7e15ec37 100644 --- a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/CMakeLists.txt +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/CMakeLists.txt @@ -131,6 +131,38 @@ target_link_options(demo_threadx.elf PRIVATE ${R52_LINK_QUIET_RWX} ) +# CLZ lowest-set-bit regression. tx_port.h replaces tx_thread.h's portable +# priority search with a CLZ instruction, and that macro decides which thread +# runs next on every suspend and resume -- so it gets an image of its own rather +# than being covered incidentally by demos that would merely hang if it broke. +# Needs the tick because the checks run in a thread; needs nothing else. +add_executable(demo_clz.elf EXCLUDE_FROM_ALL + ${FVP_DIR}/entry.S + ${R52_CONSOLE_SOURCES} + ${FVP_DIR}/gicv3.c + ${FVP_DIR}/timer.c + ${FVP_DIR}/irq_dispatch.c + ${FVP_DIR}/tx_initialize_low_level.S + ${FVP_DIR}/demo_clz.c +) + +target_compile_definitions(demo_clz.elf PRIVATE TX_R52_USE_THREADX_IRQ) + +target_link_libraries(demo_clz.elf PRIVATE threadx) + +target_include_directories(demo_clz.elf PRIVATE + ${FVP_DIR} + ${CMAKE_SOURCE_DIR}/common/inc + ${CMAKE_SOURCE_DIR}/ports/${THREADX_ARCH}/${THREADX_TOOLCHAIN}/inc +) + +target_link_options(demo_clz.elf PRIVATE + -T${FVP_DIR}/link.lds + -nostartfiles + -Wl,-Map=demo_clz.map + ${R52_LINK_QUIET_RWX} +) + # AR1/M5 -- lazy VFP context save and restore. Only meaningful when the # library was built with TX_R52_ENABLE_VFP and a floating-point ABI, so the # target exists only in that configuration. @@ -264,7 +296,8 @@ if(TX_R52_ENABLE_FIQ_NESTING) endif() # Every image built here, in the order they should be exercised. -set(R52_IMAGES boot_check.elf demo_m2.elf demo_m3.elf demo_threadx.elf demo_mpu.elf) +set(R52_IMAGES boot_check.elf demo_m2.elf demo_m3.elf demo_threadx.elf demo_mpu.elf + demo_clz.elf) # The linker script is passed with -T, which CMake does not treat as a # dependency, so editing it would not trigger a relink and stale images would @@ -303,6 +336,312 @@ if(TX_R52_CONSOLE_PL011) endforeach() endif() +# --------------------------------------------------------------------------- +# ThreadX modules: the module manager, with a sample module linked into the +# module area and loaded in place from there. +# +# This is the AR2 deliverable that the S32Z280 example cannot be: the silicon +# module demonstration is judged by a person reading a console through a debug +# probe, and this one is judged by ctest. The image below is the same port +# under the same three passes, reporting one result line the runner matches. +# +# This target deliberately does NOT link the threadx library's port assembly. +# The module port carries its own copies of the scheduler, context restore and +# stack build, because the region switch happens in the scheduler and a module +# thread starts in a different processor mode. Linking both would give two +# definitions of every one of them. +# +# Guarded by an option, off by default, because it is the only target that needs +# TXM_MODULE_MANAGER in entry.S and the only one that links common_modules. +# --------------------------------------------------------------------------- + +option(TX_R52_BUILD_FVP_MODULE_EXAMPLE + "Build the Armv8-R AEM FVP ThreadX module manager example" OFF) + +if(TX_R52_BUILD_FVP_MODULE_EXAMPLE) + + set(MOD_DIR ${CMAKE_SOURCE_DIR}/ports_module/cortex_r52/gnu) + set(MOD_FVP ${MOD_DIR}/example_build/fvp_baser_aemv8r) + + # --------------------------------------------------------------------- + # A second ThreadX library, built with the module port's headers. + # + # This is not optional and not a convenience. The module port's tx_port.h + # adds the owning module instance to TX_QUEUE, TX_SEMAPHORE, + # TX_EVENT_FLAGS_GROUP and TX_TIMER, and the module fields to TX_THREAD. + # Measured: TX_QUEUE is 68 bytes against the base port's 60, TX_SEMAPHORE 40 + # against 32, TX_THREAD 236 against 184. A kernel compiled against the base + # port and a manager compiled against this one disagree about every object, + # and they link without complaint, because C linking does not compare struct + # layouts. The result would be memory corruption at run time with nothing in + # the build to hint at it. + # + # Guarded by if(NOT TARGET) because the S32Z280 module example defines the + # same library from its own directory, and the two example options can be on + # at once. The definitions are identical -- both describe the module port, + # not a board -- so whichever directory CMake reaches first may create it. + # --------------------------------------------------------------------- + + if(NOT TARGET threadx_module) + + file(GLOB TX_COMMON_SRC ${CMAKE_SOURCE_DIR}/common/src/*.c) + + set(TX_R52_PORT_SRC ${CMAKE_SOURCE_DIR}/ports/cortex_r52/gnu/src) + + # The base port's assembly is reused except for the five files the module + # port replaces, and tx_port_offset_check.c is included deliberately: if + # the module headers moved any offset that assembly depends on, that check + # is what says so. + add_library(threadx_module STATIC EXCLUDE_FROM_ALL + ${TX_COMMON_SRC} + ${TX_R52_PORT_SRC}/tx_port_offset_check.c + ${TX_R52_PORT_SRC}/tx_thread_fiq_context_restore.S + ${TX_R52_PORT_SRC}/tx_thread_fiq_context_save.S + ${TX_R52_PORT_SRC}/tx_thread_fiq_nesting_end.S + ${TX_R52_PORT_SRC}/tx_thread_fiq_nesting_start.S + ${TX_R52_PORT_SRC}/tx_thread_interrupt_control.S + ${TX_R52_PORT_SRC}/tx_thread_interrupt_disable.S + ${TX_R52_PORT_SRC}/tx_thread_interrupt_restore.S + ${TX_R52_PORT_SRC}/tx_thread_irq_nesting_end.S + ${TX_R52_PORT_SRC}/tx_thread_irq_nesting_start.S + ${TX_R52_PORT_SRC}/tx_thread_vectored_context_save.S + ${TX_R52_PORT_SRC}/tx_timer_interrupt.S + ) + + target_include_directories(threadx_module PUBLIC + ${MOD_DIR}/inc + ${CMAKE_SOURCE_DIR}/common/inc + ${CMAKE_SOURCE_DIR}/common_modules/module_manager/inc + ${CMAKE_SOURCE_DIR}/common_modules/module_lib/inc + ${CMAKE_SOURCE_DIR}/common_modules/inc + ) + + target_compile_definitions(threadx_module PUBLIC TXM_MODULE_MANAGER) + + endif() + + # The portable half of the module manager. Globbed rather than listed: it is + # a whole upstream component, not a selection from one, and a file added to it + # upstream should not need a change here to be compiled. + + file(GLOB TXM_MANAGER_SRC ${CMAKE_SOURCE_DIR}/common_modules/module_manager/src/*.c) + + # The module-side library: the API shims that run inside the module. These + # belong to the module's image and must not reach the manager's link -- they + # define the same names as the kernel's own entry points, and as objects they + # beat the kernel's static library, so in one link every service call the + # manager makes is redirected into the module. + + file(GLOB TXM_MODULE_LIB_SRC ${CMAKE_SOURCE_DIR}/common_modules/module_lib/src/*.c) + + # ------------------------------------------------------------------------ + # The module, built as its own image and reduced to a raw binary. + # ------------------------------------------------------------------------ + + add_executable(fvp_demo_module.elf EXCLUDE_FROM_ALL + ${MOD_FVP}/txm_module_preamble.S + ${MOD_FVP}/sample_threadx_module.c + ${MOD_DIR}/module_lib/src/txm_module_thread_shell_entry.c + ${MOD_DIR}/module_lib/src/txm_module_gcc_setup.S + ${TXM_MODULE_LIB_SRC} + ) + + # No TXM_MODULE_MANAGER here: that define selects the kernel side of the + # shared headers, and this is the other side. + + target_include_directories(fvp_demo_module.elf PRIVATE + ${FVP_DIR} + ${MOD_DIR}/inc + ${CMAKE_SOURCE_DIR}/common_modules/module_lib/inc + ${CMAKE_SOURCE_DIR}/common_modules/inc + ${CMAKE_SOURCE_DIR}/common/inc + ) + + # Position independent, and only here. These five flags are what make the + # module relocatable, and putting any of them on the manager would be a bug: + # the manager is the resident image, linked absolutely at the address it + # boots from, and -msingle-pic-base in particular would have it treat r9 as + # a PIC base that nothing sets up. + # + # -fpic data references go through the GOT + # -msingle-pic-base r9 is the GOT base, and the caller sets + # it -- which is what the manager's + # thread stack build does + # -mno-pic-data-is-text-relative the module's data is NOT at a fixed + # offset from its code: code is loaded in + # place in the module area and data is + # allocated from the byte pool, so the gap + # between them is decided at run time + # -fno-plt no procedure linkage table, which a + # module has no loader to populate + # -mno-long-calls see below + # + # -mno-long-calls is the interesting one. The project-wide C flags carry + # -mlong-calls, and under -fpic that makes GCC route EVERY call through the + # GOT -- R_ARM_GOT32 instead of R_ARM_CALL -- including the shell entry's + # call to _gcc_setup, which is the function that fills the GOT in. The + # module would load, enter its shell entry, read a zero out of the + # not-yet-written GOT and branch to address 0. A module never needs long + # calls: it is one contiguous blob and it never calls out of itself, because + # kernel services go through the dispatcher function pointer in its entry + # info. + + target_compile_options(fvp_demo_module.elf PRIVATE + -g + -fpic + -fno-plt + -mno-pic-data-is-text-relative + -msingle-pic-base + -mno-long-calls + ) + + target_link_options(fvp_demo_module.elf PRIVATE + -T${MOD_FVP}/link_demo_module.lds + -nostartfiles + -nostdlib + -Wl,-Map=fvp_demo_module.map + ${R52_LINK_QUIET_RWX} + ) + + set_target_properties(fvp_demo_module.elf PROPERTIES + LINK_DEPENDS ${MOD_FVP}/link_demo_module.lds) + + # The raw image the manager embeds. Written into the binary directory + # because that is the include path module_blob.S searches. + + add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/demo_module.bin + COMMAND ${CMAKE_OBJCOPY} -O binary + $ + ${CMAKE_CURRENT_BINARY_DIR}/demo_module.bin + DEPENDS fvp_demo_module.elf + COMMENT "Converting the demonstration module to a raw image" + VERBATIM + ) + + add_custom_target(fvp_demo_module_bin + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/demo_module.bin + ) + + # ------------------------------------------------------------------------ + # The manager images. + # + # Two of them, and everything except the application file is the same, so + # the shared part is a list and a function rather than a second copy. The + # duplicate that a copy would create is not a style question here: an image + # built with a different set of module manager sources, or without + # TX_R52_ENABLE_MPU, would still link and would test something other than + # what its name says. + # ------------------------------------------------------------------------ + + set(TX_R52_MODULE_IMAGE_SRC + # Board support, shared with the other FVP examples + ${FVP_DIR}/entry.S + ${FVP_DIR}/console.c + ${FVP_DIR}/uart_pl011.c + ${FVP_DIR}/mpu.c + ${FVP_DIR}/cache.c + ${FVP_DIR}/gicv3.c + ${FVP_DIR}/timer.c + ${FVP_DIR}/irq_dispatch.c + ${FVP_DIR}/tx_initialize_low_level.S + + # Module manager port + ${MOD_DIR}/module_manager/src/tx_thread_schedule.S + ${MOD_DIR}/module_manager/src/tx_thread_context_save.S + ${MOD_DIR}/module_manager/src/tx_thread_context_restore.S + ${MOD_DIR}/module_manager/src/tx_thread_stack_build.S + ${MOD_DIR}/module_manager/src/tx_thread_system_return.S + ${MOD_DIR}/module_manager/src/txm_module_manager_svc_handler.S + ${MOD_DIR}/module_manager/src/txm_module_manager_fault_capture.S + ${MOD_DIR}/module_manager/src/txm_module_manager_user_mode_entry.S + ${MOD_DIR}/module_manager/src/txm_module_manager_thread_stack_build.S + ${MOD_DIR}/module_manager/src/txm_module_manager_mm_register_setup.c + ${MOD_DIR}/module_manager/src/txm_module_manager_memory_fault_handler.c + ${MOD_DIR}/module_manager/src/txm_module_manager_memory_fault_notify.c + ${MOD_DIR}/module_manager/src/txm_module_manager_alignment_adjust.c + ${MOD_DIR}/module_manager/src/txm_module_manager_external_memory_enable.c + ${MOD_DIR}/module_manager/src/txm_module_manager_offset_check.c + + # The module, as bytes rather than as objects. module_blob.S includes the + # raw image built by fvp_demo_module.elf, so none of the module's symbols + # enter this link. + ${MOD_FVP}/module_blob.S + + # The portable module manager + ${TXM_MANAGER_SRC} + ) + + # .incbin searches the assembler's include paths, not the source tree, and + # demo_module.bin is generated -- so the build directory has to be on that + # path or module_blob.S cannot find the image. Set on the file rather than + # per target, because both images include the same blob the same way. + + set_source_files_properties(${MOD_FVP}/module_blob.S PROPERTIES + OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/demo_module.bin + COMPILE_OPTIONS "-Wa,-I${CMAKE_CURRENT_BINARY_DIR}" + ) + + function(threadx_r52_add_module_image target_name application) + + add_executable(${target_name} EXCLUDE_FROM_ALL + ${TX_R52_MODULE_IMAGE_SRC} + ${application} + ) + + target_include_directories(${target_name} PRIVATE + ${FVP_DIR} + ${MOD_DIR}/inc + ${CMAKE_SOURCE_DIR}/common_modules/module_manager/inc + ${CMAKE_SOURCE_DIR}/common_modules/module_lib/inc + ${CMAKE_SOURCE_DIR}/common_modules/inc + ) + + # TX_R52_ENABLE_MPU is not optional for these images, unlike the AR1 demos + # where it is a switch: without protection there is no module boundary to + # test, and the manager's load window over the module area is programmed by + # mpu_init. TX_R52_USE_THREADX_IRQ brings up the tick, which the module + # needs for the tx_thread_sleep that proves a kernel call returns. + + target_compile_definitions(${target_name} PRIVATE + TXM_MODULE_MANAGER + TX_R52_USE_THREADX_IRQ + TX_R52_ENABLE_MPU + ) + + target_compile_options(${target_name} PRIVATE -g) + + add_dependencies(${target_name} fvp_demo_module_bin) + + target_link_options(${target_name} PRIVATE + -T${MOD_FVP}/link_module.lds + -nostartfiles + -Wl,-Map=${target_name}.map + ${R52_LINK_QUIET_RWX} + ) + + set_target_properties(${target_name} PROPERTIES + LINK_DEPENDS ${MOD_FVP}/link_module.lds) + + target_link_libraries(${target_name} PRIVATE threadx_module) + + endfunction() + + # AR2. What the hardware does about a module that misbehaves. + + threadx_r52_add_module_image(fvp_module.elf + ${MOD_FVP}/sample_threadx_module_manager.c) + + # And what the LOADER does about a module whose property word is not the + # 0x02000003 every example in the tree ships. A separate image because four + # of its six cases never run a module at all, so it has a different subject + # and a different verdict; it shares the blob and nothing else. + + threadx_r52_add_module_image(fvp_module_properties.elf + ${MOD_FVP}/sample_threadx_module_properties.c) + +endif() + # Run a target on the FVP. Each image exits by itself through the # semihosting SYS_EXIT call, so no host-side timeout is needed. UART0 is # routed to stdout unconditionally so that PL011-console images are visible @@ -334,6 +673,14 @@ if(FVP_BASER_AEMV8R) "Running AR1/M3 tick and preemption demo on FVP_BaseR_AEMv8R...") threadx_r52_add_fvp_run(demo_threadx.elf run-demo-threadx-r52 "Running the standard ThreadX demo on FVP_BaseR_AEMv8R...") + threadx_r52_add_fvp_run(demo_clz.elf run-demo-clz-r52 + "Running the CLZ lowest-set-bit regression on FVP_BaseR_AEMv8R...") + if(TX_R52_BUILD_FVP_MODULE_EXAMPLE) + threadx_r52_add_fvp_run(fvp_module.elf run-module-r52 + "Running the AR2 module isolation example on FVP_BaseR_AEMv8R...") + threadx_r52_add_fvp_run(fvp_module_properties.elf run-module-properties-r52 + "Running the AR2 module property contract regression on FVP_BaseR_AEMv8R...") + endif() # Automated checks. The runner judges each image by its self-reported # result and treats a missing result line as failure, so a hang cannot @@ -344,6 +691,15 @@ if(FVP_BASER_AEMV8R) set(R52_RUNNER ${FVP_DIR}/test/run_fvp_test.py) set(R52_TEST_IMAGES ${R52_IMAGES}) + # AR2. Kept out of R52_IMAGES above rather than added to it, because + # that list is what the TX_R52_ENABLE_MPU and TX_R52_CONSOLE_PL011 + # options are applied to and neither is optional for this image: the + # module boundary IS the MPU, and the result line has to reach the + # runner whichever console the rest of the suite was built with. + if(TX_R52_BUILD_FVP_MODULE_EXAMPLE) + list(APPEND R52_TEST_IMAGES fvp_module.elf fvp_module_properties.elf) + endif() + enable_testing() foreach(image IN LISTS R52_TEST_IMAGES) add_test(NAME r52-fvp-${image} diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/cache.c b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/cache.c new file mode 100644 index 000000000..6632096ad --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/cache.c @@ -0,0 +1,149 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* BOARD SUPPORT RELEASE */ +/* */ +/* cache.c Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frédéric Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Cache maintenance for a loader that copies code. See cache.h for */ +/* why only these three functions exist. */ +/* */ +/* MISRA C:2012 deviations (justified) */ +/* */ +/* Directive 4.3 -- cache maintenance and CTR are reachable only */ +/* through CP15; every access is encapsulated in a one-line accessor */ +/* below and nowhere else in this file. */ +/* Rule 11.6 (conversion between a pointer and an integer) -- a cache */ +/* maintenance operation takes a virtual address as a register value, */ +/* so the conversion is what the instruction requires. */ +/* */ +/**************************************************************************/ + +#include "cache.h" + +/* The smallest data-cache line in the machine, from CTR.DminLine. Held as a + log2 of the number of 32-bit words, so the byte count is 4 << DminLine. + DminLine and not the L1 geometry: a maintenance-by-address walk has to step + by the smallest line any level implements, or it skips lines in that level. */ + +#define CTR_DMINLINE_SHIFT 16U +#define CTR_DMINLINE_MASK 0xFUL + + +/**************************************************************************/ +/* CP15 accessors. The only assembly in this file (MISRA C:2012 Dir 4.3).*/ +/**************************************************************************/ + +static unsigned long read_ctr(void) +{ + unsigned long value; + __asm__ volatile("mrc p15, 0, %0, c0, c0, 1" : "=r"(value)); + return value; +} + +static void clean_dcache_line(unsigned long address) +{ + __asm__ volatile("mcr p15, 0, %0, c7, c10, 1" :: "r"(address) : "memory"); +} + +static void invalidate_icache_all_op(void) +{ + unsigned long zero = 0UL; + __asm__ volatile("mcr p15, 0, %0, c7, c5, 0" :: "r"(zero) : "memory"); +} + +static void data_sync_barrier(void) +{ + __asm__ volatile("dsb sy" ::: "memory"); +} + +static void instruction_barrier(void) +{ + __asm__ volatile("isb" ::: "memory"); +} + + +/**************************************************************************/ +/* cache_dcache_line_bytes */ +/**************************************************************************/ + +unsigned long cache_dcache_line_bytes(void) +{ + return 4UL << ((read_ctr() >> CTR_DMINLINE_SHIFT) & CTR_DMINLINE_MASK); +} + + +/**************************************************************************/ +/* cache_clean_range */ +/* */ +/* Clean by virtual address over [start, start + length). */ +/* */ +/* The start is rounded DOWN to a line boundary and the walk continues */ +/* past the end until the last line containing a requested byte has been */ +/* cleaned. Rounding the start up instead would leave the first partial */ +/* line dirty, which is the whole failure this exists to prevent and is */ +/* invisible whenever the caller happens to be line aligned. */ +/**************************************************************************/ + +void cache_clean_range(const void *start_address, unsigned long length) +{ + unsigned long line = cache_dcache_line_bytes(); + unsigned long address; + unsigned long end; + + if (length == 0UL) + { + return; + } + + address = (unsigned long) start_address; + end = address + length; + + address &= ~(line - 1UL); + + while (address < end) + { + clean_dcache_line(address); + address += line; + } + + /* The stores have to be complete before anything fetches from the range. */ + + data_sync_barrier(); +} + + +/**************************************************************************/ +/* cache_invalidate_icache_all */ +/**************************************************************************/ + +void cache_invalidate_icache_all(void) +{ + invalidate_icache_all_op(); + + /* DSB then ISB: the invalidate must complete, and the pipeline must be + flushed of anything fetched before it did. */ + + data_sync_barrier(); + instruction_barrier(); +} diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/cache.h b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/cache.h new file mode 100644 index 000000000..0ed8dcfc0 --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/cache.h @@ -0,0 +1,72 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* BOARD SUPPORT RELEASE */ +/* */ +/* cache.h Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frédéric Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* The cache maintenance a loader owes the instruction side, and */ +/* nothing else. */ +/* */ +/* The S32Z280 board support carries a full cache driver -- enable, */ +/* disable, geometry, set/way sweeps -- because silicon bring-up needed */ +/* to ask the hardware what it had. None of that is needed here: the */ +/* caches are turned on once in mpu_init and never turned off, and the */ +/* model's geometry is not in question. What IS needed is the pair of */ +/* operations that make copied code executable, so that is all this is. */ +/* */ +/* Why it is needed at all: the module area is Normal write-back memory, */ +/* so a byte copy of module code leaves the bytes in dirty data-cache */ +/* lines while the instruction side -- which is not coherent with the */ +/* data cache on this core -- fetches whatever main memory still holds. */ +/* Cleaning by address range and then invalidating the instruction cache */ +/* is what closes that gap. */ +/* */ +/* By range rather than by set/way, deliberately. A set/way sweep needs */ +/* the cache geometry and touches every line in the machine; the loader */ +/* knows exactly which bytes it wrote, so the range form is both tighter */ +/* and shorter to get right. */ +/* */ +/**************************************************************************/ + +#ifndef CACHE_H +#define CACHE_H + +/* Clean (write back) the data cache over one address range, so that main + memory holds what the copy wrote. Rounds outwards to cache-line + boundaries; a length of zero does nothing. */ + +void cache_clean_range(const void *start_address, unsigned long length); + +/* Invalidate the whole instruction cache, so no stale line from a previous + image at the same address can be served. Invalidate-all rather than by + range because it is one register write and this runs once per load. */ + +void cache_invalidate_icache_all(void); + +/* Data cache line length in bytes, from CTR.DminLine. Published because the + range walk above depends on it and a caller may want to report it. */ + +unsigned long cache_dcache_line_bytes(void); + +#endif /* CACHE_H */ diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/demo_clz.c b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/demo_clz.c new file mode 100644 index 000000000..a156f4ec7 --- /dev/null +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/demo_clz.c @@ -0,0 +1,359 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* DEMONSTRATION RELEASE */ +/* */ +/* demo_clz.c Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frédéric Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Regression test for this port's CLZ implementation of */ +/* TX_LOWEST_SET_BIT_CALCULATE, which replaces the portable loop in */ +/* tx_thread.h and which the scheduler's priority search runs on */ +/* every suspend and resume. */ +/* */ +/* Why this image exists. The macro was DEAD until 20 Aug 2026: */ +/* tx_port.h guarded it with __TARGET_ARCH_ARM > 4, an Arm Compiler 5 */ +/* predefine that GCC never defines, so the test read 0 > 4 and the */ +/* portable loop ran on a core that has had CLZ since Armv5. Turning */ +/* it on means hand-written inline assembly now decides which thread */ +/* runs next, so it gets a test that pins the answer for every input */ +/* class rather than a build that merely compiles. */ +/* */ +/* What is checked, against an obvious linear-scan reference rather */ +/* than against the implementation being tested: */ +/* */ +/* 1. Each of the 32 single-bit maps returns its own bit position. */ +/* 2. Each bit position with a deterministic spray of HIGHER bits */ +/* set still returns that position -- the macro must find the */ +/* LOWEST set bit, and a single-bit test cannot tell the */ +/* difference between "lowest" and "only". */ +/* 3. A table of hand-picked patterns, including the two the */ +/* respelled isolation step could plausibly break: 0x80000000, */ +/* the one input for which upstream's signed negation was */ +/* undefined, and 0xFFFFFFFF. */ +/* 4. Every group is run twice, once through a UINT result and once */ +/* through a ULONG one, because the kernel calls the macro with */ +/* both and the closing 31 - b is where a width mistake would */ +/* hide. */ +/* 5. The m == 0 divergence is PINNED, not fixed. CLZ(0) is 32, so */ +/* this implementation yields 31 - 32 while the portable loop */ +/* yields 0. Every one of the twelve call sites in common/src */ +/* reaches the macro only on a map already tested against zero, */ +/* so the difference is unreachable -- and a test that records */ +/* it is how it stays a decision instead of becoming a surprise. */ +/* */ +/* The checks run inside a ThreadX thread on purpose. By the time the */ +/* thread's entry is reached the scheduler has already executed the */ +/* macro on the way to dispatching it, so a macro broken badly enough */ +/* to misdirect the priority search shows up as a hang -- which the */ +/* runner scores as a failure -- before any check is evaluated. */ +/* */ +/**************************************************************************/ + +#include "tx_api.h" +#include "console.h" +#include "board.h" + +/* The port's definition must be the one in scope. tx_thread.h supplies a + portable fallback under #ifndef, so an image that reached this file with the + macro undefined would be testing that fallback and reporting a pass for it -- + the exact failure mode this whole image exists to rule out. */ + +#ifndef TX_LOWEST_SET_BIT_CALCULATE +#error "demo_clz: tx_port.h did not define TX_LOWEST_SET_BIT_CALCULATE, so this image would test the portable loop and call it a pass." +#endif + +/* And it must be defined for the reason we think it is. These are the two + conditions tx_port.h uses; asserting them here means a future edit that + silently drops the CLZ path cannot leave this image passing. */ + +#if !defined(__ARM_FEATURE_CLZ) +#error "demo_clz: __ARM_FEATURE_CLZ is not defined, so the CLZ path in tx_port.h is not the definition under test." +#endif + +#if defined(__thumb__) +#error "demo_clz: built for Thumb, where tx_port.h deliberately keeps the portable loop. Build this image -marm." +#endif + + +#define DEMO_STACK_SIZE 2048 + +static TX_THREAD check_thread; +static UCHAR check_stack[DEMO_STACK_SIZE]; + +/* Failure detail, kept as counters rather than printed per case: 32 passing + lines tell a reader nothing and would bury the one failing line. */ + +static UINT failures; + + +/**************************************************************************/ +/* reference_lowest_bit */ +/* */ +/* The ground truth, written to be read rather than to be fast. It is */ +/* deliberately NOT the portable macro from tx_thread.h: comparing an */ +/* implementation against a cleverer implementation of the same idea */ +/* tests that they share their mistakes. A linear scan has nowhere to */ +/* hide one. */ +/**************************************************************************/ + +static ULONG reference_lowest_bit(ULONG map) +{ + ULONG index; + ULONG result = 0xFFFFFFFFUL; /* No bit set. */ + + for (index = 0UL; index < 32UL; index++) + { + if ((map & (1UL << index)) != 0UL) + { + result = index; + break; + } + } + + return result; +} + + +/**************************************************************************/ +/* next_pattern */ +/* */ +/* A fixed linear congruential sequence. A regression test must produce */ +/* the same inputs on every run, so the spray of high bits in group 2 is */ +/* pseudo-random and seeded, never actually random. */ +/**************************************************************************/ + +static ULONG next_pattern(ULONG state) +{ + return (state * 1103515245UL) + 12345UL; +} + + +/**************************************************************************/ +/* check_one */ +/* */ +/* Runs one map through the macro twice, once landing in a UINT and once */ +/* in a ULONG, and compares both against the reference. The macro */ +/* CONSUMES its first argument -- both implementations rewrite the map */ +/* in place -- so each call gets its own copy, which is also the trap a */ +/* caller reusing the variable afterwards would fall into. */ +/**************************************************************************/ + +static void check_one(ULONG map, ULONG expected, const char *group_ptr) +{ + ULONG working; + UINT bit_as_uint; + ULONG bit_as_ulong; + + working = map; + TX_LOWEST_SET_BIT_CALCULATE(working, bit_as_uint) + + working = map; + TX_LOWEST_SET_BIT_CALCULATE(working, bit_as_ulong) + + if (((ULONG) bit_as_uint != expected) || (bit_as_ulong != expected)) + { + failures++; + + console_puts("[FAIL] "); + console_puts(group_ptr); + console_puts(" map="); + console_puthex(map); + console_puts(" expected="); + console_puthex(expected); + console_puts(" got UINT="); + console_puthex((unsigned long) bit_as_uint); + console_puts(" ULONG="); + console_puthex(bit_as_ulong); + console_puts("\n"); + } +} + + +/**************************************************************************/ +/* report */ +/**************************************************************************/ + +static void report(const char *label_ptr, UINT failures_before) +{ + console_puts(label_ptr); + console_puts((failures == failures_before) ? "PASS\n" : "FAIL\n"); +} + + +/**************************************************************************/ +/* thread_check_entry */ +/**************************************************************************/ + +static void thread_check_entry(ULONG thread_input) +{ + ULONG index; + ULONG spray; + ULONG state; + ULONG map; + ULONG working; + ULONG bit; + UINT before; + + /* Hand-picked patterns. 0x80000000 is the one input for which upstream's + (ULONG)(-((LONG) m)) isolation was undefined behaviour, and 0xFFFFFFFF is + the densest map the scheduler can present. */ + + static const ULONG patterns[] = + { + 0xFFFFFFFFUL, 0x80000000UL, 0xAAAAAAAAUL, 0x55555555UL, + 0xF0F0F000UL, 0x00000003UL, 0x7FFFFFFFUL, 0xC0000000UL, + 0x00010000UL, 0xFFFF0000UL + }; + + (void) thread_input; + + console_puts("\n=== ThreadX Cortex-R52 CLZ lowest-set-bit regression ===\n\n"); + + /* Group 1 -- every single-bit map. */ + + before = failures; + for (index = 0UL; index < 32UL; index++) + { + check_one(1UL << index, index, "single bit"); + } + report("[check] 32 single-bit maps ................ ", before); + + /* Group 2 -- every bit position with higher bits sprayed above it. This is + the group that distinguishes "lowest set bit" from "only set bit". */ + + before = failures; + state = 0x12345678UL; + for (index = 0UL; index < 32UL; index++) + { + state = next_pattern(state); + + /* Keep only bits strictly above index, then put index back. Shifting a + 32-bit value by 32 is undefined, so the top position is special-cased + to no spray at all -- there is nothing above bit 31 to set. */ + + if (index < 31UL) + { + spray = (state << (index + 1UL)) & 0xFFFFFFFFUL; + } + else + { + spray = 0UL; + } + + check_one(spray | (1UL << index), index, "lowest of many"); + } + report("[check] 32 sprayed maps, lowest bit wins .. ", before); + + /* Group 3 -- the hand-picked table. */ + + before = failures; + for (index = 0UL; index < (ULONG) (sizeof(patterns) / sizeof(patterns[0])); index++) + { + check_one(patterns[index], reference_lowest_bit(patterns[index]), "pattern"); + } + report("[check] 10 hand-picked patterns .......... ", before); + + /* Group 4 -- the pinned divergence at zero. Not a fix: a record. CLZ(0) + is 32 and the closing subtraction is unsigned, so the answer is 31 - 32 + taken modulo 2^32. The portable loop in tx_thread.h answers 0 for the + same input. Neither is reachable from the kernel, and this check exists + so that changing which one is true has to be deliberate. */ + + before = failures; + working = 0UL; + TX_LOWEST_SET_BIT_CALCULATE(working, bit) + + if (bit != 0xFFFFFFFFUL) + { + failures++; + console_puts("[FAIL] map=0 answered "); + console_puthex(bit); + console_puts(", documented answer for the CLZ implementation is 0xFFFFFFFF\n"); + } + report("[check] map = 0 answers as documented .... ", before); + + /* Group 5 -- the macro consumes its first argument, in both + implementations. Stated as a check because it is a property callers rely + on by never relying on it, and a "fix" that stopped rewriting the map + would quietly change what every call site's variable holds afterwards. */ + + before = failures; + map = 0x00000280UL; /* Lowest set bit is 7. */ + working = map; + TX_LOWEST_SET_BIT_CALCULATE(working, bit) + + if ((bit != 7UL) || (working != (1UL << 7))) + { + failures++; + console_puts("[FAIL] expected bit 7 and map reduced to 0x80, got bit "); + console_puthex(bit); + console_puts(" map "); + console_puthex(working); + console_puts("\n"); + } + report("[check] map is reduced to its lowest bit . ", before); + + console_puts("\n[info] 75 maps checked, each through a UINT and a ULONG result.\n"); + + if (failures == 0U) + { + console_puts("\nCLZ RESULT: ALL CHECKS PASSED\n"); + } + else + { + console_puts("\nCLZ RESULT: FAILED\n"); + } + + console_exit(failures); +} + + +/**************************************************************************/ +/* tx_application_define */ +/**************************************************************************/ + +void tx_application_define(void *first_unused_memory) +{ + (void) first_unused_memory; + + tx_thread_create(&check_thread, "clz check", thread_check_entry, 0UL, + check_stack, DEMO_STACK_SIZE, + 1U, 1U, TX_NO_TIME_SLICE, TX_AUTO_START); +} + + +/**************************************************************************/ +/* bsp_main -- entered at EL1 from entry.S. Does not return. */ +/**************************************************************************/ + +void bsp_main(void) +{ + tx_kernel_enter(); + + /* Not reached. */ + + for (;;) + { + /* Nothing. */ + } +} diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/entry.S b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/entry.S index d59183f8f..77d813361 100644 --- a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/entry.S +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/entry.S @@ -101,6 +101,20 @@ .equ HSR_EC_SHIFT, 26 .equ HSR_EC_HVC, 0x12 /* HVC executed in AArch32 */ +#ifdef TXM_MODULE_MANAGER + +/* The module manager owns three of the EL1 vectors in a manager build: the + supervisor call, which is the privilege boundary a module crosses to reach + the kernel, and the two aborts, which are how a module that reaches outside + its regions is caught. Declared rather than merely referenced so that a + build with the manager half-configured fails at the link with a name in it. */ + + .extern __tx_module_svc_interrupt + .extern _txm_module_manager_data_abort + .extern _txm_module_manager_prefetch_abort + +#endif + /* Report which vector was taken, then halt. The FVP offers no GDB stub (Iris only), so a self-identifying fault is the primary debugging tool for this port. Uses no stack: only r0/r1 and a semihosting call. */ @@ -144,7 +158,11 @@ el2_vectors: el1_vectors: b el1_trap_reset /* 0x00 reset */ b el1_trap_undef /* 0x04 undefined instruction */ +#ifdef TXM_MODULE_MANAGER + b __tx_module_svc_interrupt /* 0x08 module kernel boundary */ +#else b el1_trap_svc /* 0x08 supervisor call */ +#endif b el1_trap_pabt /* 0x0C prefetch abort */ b el1_trap_dabt /* 0x10 data abort */ b el1_trap_reserved /* 0x14 reserved */ @@ -476,6 +494,26 @@ el1_trap_svc: FAULT_REPORT msg_el1_svc and this handler returns there, restoring the pre-fault mode from SPSR. */ el1_trap_pabt: +#ifdef TXM_MODULE_MANAGER + + /* A fault from User mode is a module reaching outside its code region, and + it belongs to the module manager, which records it and terminates the + thread. A fault from a privileged mode falls through to the paths below, + which the MPU self-test depends on. + + r0 is pushed and popped around the test rather than simply used: the + capture in the manager records the faulting registers, and clobbering one + here would have it record ours instead. LDM does not affect the flags, + so the comparison still holds after the pop. */ + + stmdb sp!, {r0} + mrs r0, spsr + and r0, r0, #0x1F + cmp r0, #0x10 /* User mode? */ + ldmia sp!, {r0} + beq _txm_module_manager_prefetch_abort + +#endif #ifdef TX_R52_MPU_FAULT_TEST push {r0, r1} ldr r0, =mpu_expect_pabt @@ -532,6 +570,19 @@ mpu_try_execute_land: Runs on the Abort-mode stack set up above. */ el1_trap_dabt: +#ifdef TXM_MODULE_MANAGER + + /* A fault from User mode is a module reaching outside its data region. See + el1_trap_pabt above for why r0 is saved across the test. */ + + stmdb sp!, {r0} + mrs r0, spsr + and r0, r0, #0x1F + cmp r0, #0x10 /* User mode? */ + ldmia sp!, {r0} + beq _txm_module_manager_data_abort + +#endif #ifdef TX_R52_MPU_FAULT_TEST push {r0, r1} ldr r0, =mpu_expect_abort diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/mpu.c b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/mpu.c index 29f9fe25f..4fad2f7eb 100644 --- a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/mpu.c +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/mpu.c @@ -294,6 +294,80 @@ static void program_region(unsigned int index, const MPU_REGION *region_ptr) } +#ifdef TXM_MODULE_MANAGER + +/**************************************************************************/ +/* mpu_module_window_init */ +/* */ +/* A window over the module area, for the manager to load through. */ +/* */ +/* No region in the table above covers the module area, which is what */ +/* stops every thread from reaching a module's memory -- but the manager */ +/* has to read the preamble and write the module's data to load it at */ +/* all. Without this the load faults on its first read of the image. */ +/* */ +/* Not opened and closed around the load. It is left enabled here and */ +/* the SCHEDULER owns it from then on: it turns this region on for every */ +/* thread that owns no module and off for every thread that does, which */ +/* is what keeps it and a module's own regions -- which cover the same */ +/* memory -- from ever being enabled together. PMSAv8-R has no region */ +/* priority, so an access hitting more than one enabled region takes a */ +/* translation fault (TRM 8.1), and mutual exclusion by ownership is the */ +/* only form of it that does not depend on remembering to bracket a call. */ +/* */ +/* EL1 read/write with no EL0 access, and execute-never: the manager can */ +/* load through it, and a module cannot use it to reach anything. */ +/**************************************************************************/ + +unsigned long mpu_module_window_prbar; +unsigned long mpu_module_window_prlar; + + +unsigned int mpu_module_window_init(void) +{ + MPU_REGION window; + + /* Asked of the hardware rather than assumed. See MPU_MODULE_REGIONS_REQUIRED + in mpu.h: this model reports a region count no real Cortex-R52 can have, + so the number is checked here and the shortfall is a refusal. */ + + if (mpu_region_count() < MPU_MODULE_REGIONS_REQUIRED) + { + return 0U; + } + + window.mpu_region_base = FVP_MODULE_AREA_BASE; + window.mpu_region_limit = FVP_MODULE_AREA_BASE + + FVP_MODULE_AREA_SIZE - 1UL; + window.mpu_region_ap = MPU_AP_RW_EL1; + window.mpu_region_execute_never = 1U; + window.mpu_region_shareability = MPU_SH_NON; + window.mpu_region_attr_index = MPU_ATTR_NORMAL_WB; + window.mpu_region_name = "module window RW NX EL1"; + + /* Published for the scheduler, which turns this region on and off on every + dispatch and has no business computing register layouts in assembly. */ + + mpu_module_window_prbar = (window.mpu_region_base & 0xFFFFFFC0UL) + | (((unsigned long) window.mpu_region_shareability & 0x3UL) << 3) + | (((unsigned long) window.mpu_region_ap & 0x3UL) << 1) + | ((unsigned long) window.mpu_region_execute_never & 0x1UL); + + mpu_module_window_prlar = (window.mpu_region_limit & 0xFFFFFFC0UL) + | (((unsigned long) window.mpu_region_attr_index & 0x7UL) << 1) + | 1UL; + + program_region(MPU_MODULE_LOAD_REGION, &window); + + data_sync_barrier(); + instruction_barrier(); + + return 1U; +} + +#endif /* TXM_MODULE_MANAGER */ + + /**************************************************************************/ /* mpu_init */ /**************************************************************************/ @@ -311,6 +385,20 @@ unsigned int mpu_init(void) return 0U; } +#ifdef TXM_MODULE_MANAGER + + /* A module manager build needs regions the table above does not describe: + the eight handed to a module and the window over the module area. If the + implementation cannot supply them, stop here rather than enable a + protection map that is missing the half a module depends on. */ + + if (available < MPU_MODULE_REGIONS_REQUIRED) + { + return 0U; + } + +#endif + /* Memory types first: a region's attribute index is meaningless until MAIR is populated. */ @@ -332,6 +420,20 @@ unsigned int mpu_init(void) write_prlar(0UL); } +#ifdef TXM_MODULE_MANAGER + + /* After the loop above, which would otherwise disable it again: the module + window lives above the regions this table uses, so it counts as unused + here. The region count was checked at the top of this function, so the + call cannot fail at this point. */ + + if (mpu_module_window_init() == 0U) + { + return 0U; + } + +#endif + data_sync_barrier(); /* Caches are invalidated before enabling. The instruction cache has a diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/mpu.h b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/mpu.h index aaca31761..d52a03a6e 100644 --- a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/mpu.h +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/mpu.h @@ -116,4 +116,54 @@ const MPU_REGION *mpu_region_table(unsigned int *count_ptr); void mpu_read_region(unsigned int index, unsigned long *prbar_ptr, unsigned long *prlar_ptr); +/* --------------------------------------------------------------------------- + ThreadX modules. + + Kept in this header rather than behind TXM_MODULE_MANAGER because + txm_module_manager_offset_check.c includes it to check the region number + against the one tx_thread_schedule.S writes in assembly, and a definition + that appears only in some builds cannot be checked in the others. + --------------------------------------------------------------------------- */ + +/* Region index for the manager's load window over the module area. Above the + kernel's 0-2 and above the eight the manager hands to a module (8-15), so + neither the boot table nor the scheduler's per-thread region load can + disturb it. tx_thread_schedule.S spells the same number in an MCR to + PRSELR; the offset check asserts the two agree. */ + +#define MPU_MODULE_LOAD_REGION 16U + +/* How many EL1 regions a module manager build needs: 0-2 kernel, 8-15 for the + module block, 16 for the window. Region 16 is the highest index used, so + seventeen regions is the requirement. + + Checked against MPUIR rather than assumed, even though the AEMv8-R model + reports 32. The model reports a region count NO Cortex-R52 can have -- the + TRM gives MPUIR.DREGION as 16, 20 or 24 -- so a green run here says nothing + about whether the budget fits silicon, and a part configured with 16 regions + cannot run this port at all. The check is here so that the shortfall is a + refusal rather than a region that silently does not exist. */ + +#define MPU_MODULE_REGIONS_REQUIRED 17U + +/* The module area window, which is what lets privileged code reach module + memory at all -- no other kernel region covers it. + + PMSAv8-R has no region priority, so this must never be enabled at the same + time as the regions a module is given, which cover the same memory. That is + guaranteed by who owns it rather than by careful calling: the scheduler turns + this region on for every thread that is not a module thread and off for every + thread that is, so the window is enabled exactly when no module regions are + loaded. The two register words are published for it below. + + Enabled at boot, because everything before the first module thread is + privileged code that may need to reach module memory. Returns 0 if the + implementation has fewer than MPU_MODULE_REGIONS_REQUIRED regions, in which + case nothing was programmed. */ + +unsigned int mpu_module_window_init(void); + +extern unsigned long mpu_module_window_prbar; +extern unsigned long mpu_module_window_prlar; + #endif /* MPU_H */ diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/platform.h b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/platform.h index 913befdb8..151f732d4 100644 --- a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/platform.h +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/platform.h @@ -71,6 +71,59 @@ #define SYSTEM_COUNTER_HZ 100000000 +/* --------------------------------------------------------------------------- + Memory for ThreadX modules. + + Only the module manager build uses this, but the addresses are stated here + rather than in the module example because they are a property of the board's + memory map: a module's code and data are handed to it as MPU regions, and + PMSAv8-R will not allow those to overlap a kernel region. So module memory + has to be memory NO kernel region covers, and deciding that is the memory + map's job. + + link_module.lds ends the kernel's DRAM region at this base and gives the + 64 KB above it to the module area; mpu.c covers exactly the same range with + the manager's load window (region 16), which is the only mapping privileged + code has over it. The three have to agree, so all three read these two + values. + + Chosen at 0x003F0000 -- just under 4 MB -- because the manager image with its + stacks and its 1 MB of heap is far smaller than that, and the link script + asserts the two do not meet rather than trusting the margin. */ + +#define FVP_MODULE_AREA_BASE 0x003F0000 +#define FVP_MODULE_AREA_SIZE 0x00010000 /* 64 KB */ + +/* The shared granules the sample module reports its progress through, at the + base of the module area. + + The first of them exists because the FVP has no debugger seam: on silicon a + GDB harness reads the module's own progress variable out of its data area, + and here nothing outside the image can read anything. So the manager grants + the module a shared region over this word and reads it back afterwards, which + is what lets the FVP test judge what the module actually managed to do rather + than only that it faulted. + + The rest exist to exercise the shared-region machinery itself. A module may + be granted TXM_MODULE_MPU_SHARED_ENTRIES regions, and one grant proves only + that the first entry works, so the area holds one granule per entry -- plus + one more that the manager NEVER grants, sandwiched between two that it does. + A limit register masked the wrong way, or a base off by a granule, leaks into + that gap from one side or the other, and a module that can write it is a + module whose grant covered more than was asked for. + + FVP_MODULE_STATUS_SIZE is the size of ONE granule, which is the length of + each individual grant; the area is FVP_MODULE_STATUS_GRANULES of them. + + Fixed addresses on both sides, and checked at run time rather than trusted: + the manager grants the regions from the linker's symbol and refuses to + continue if that symbol is not this address. */ + +#define FVP_MODULE_STATUS_BASE 0x003F0000 +#define FVP_MODULE_STATUS_SIZE 0x40 /* one MPU granule */ +#define FVP_MODULE_STATUS_GRANULES 6 /* five granted, one not */ +#define FVP_MODULE_STATUS_UNGRANTED 2 /* the one never granted */ + #ifndef __ASSEMBLER__ /* 32-bit device register access. */ diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/CMakeLists.txt b/ports/cortex_r52/gnu/example_build/s32z280_evb/CMakeLists.txt index 7f216700c..ae0a8b73f 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/CMakeLists.txt +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/CMakeLists.txt @@ -244,3 +244,278 @@ if(TX_R52_ENABLE_FIQ_NESTING) ${EVB_LINK_QUIET_RWX} ) endif() + +# --------------------------------------------------------------------------- +# ThreadX modules: the module manager, with a sample module linked into the +# module area and loaded in place from there. +# +# This target deliberately does NOT link the threadx library's port assembly. +# The module port carries its own copies of the scheduler, context restore and +# stack build, because the region switch happens in the scheduler and a module +# thread starts in a different processor mode. Linking both would give two +# definitions of every one of them. +# +# Guarded by an option, off by default, because it is the only target that needs +# TXM_MODULE_MANAGER in entry.S and the only one that links common_modules. +# --------------------------------------------------------------------------- + +option(TX_R52_BUILD_S32Z280_MODULE_EXAMPLE + "Build the NXP S32Z280-594EVB ThreadX module manager example" OFF) + +if(TX_R52_BUILD_S32Z280_MODULE_EXAMPLE) + + set(MOD_DIR ${CMAKE_SOURCE_DIR}/ports_module/cortex_r52/gnu) + set(MOD_EVB ${MOD_DIR}/example_build/s32z280_evb) + + # --------------------------------------------------------------------- + # A second ThreadX library, built with the module port's headers. + # + # This is not optional and not a convenience. The module port's tx_port.h + # adds the owning module instance to TX_QUEUE, TX_SEMAPHORE, + # TX_EVENT_FLAGS_GROUP and TX_TIMER, and the module fields to TX_THREAD. + # Measured: TX_QUEUE is 60 bytes against the base port's, TX_SEMAPHORE 40 + # against 32, TX_THREAD 236 against 184. A kernel compiled against the base + # port and a manager compiled against this one disagree about every object, + # and they link without complaint, because C linking does not compare struct + # layouts. The result would be memory corruption at run time with nothing in + # the build to hint at it. + # + # The base port's assembly is reused except for the five files the module port + # replaces, and tx_port_offset_check.c is included deliberately: if the module + # headers moved any offset that assembly depends on, that check is what says + # so, and it is better to find out here than on the board. + # --------------------------------------------------------------------- + + # Guarded by if(NOT TARGET) because the FVP module example defines the same + # library from its own directory, and the two example options can be on at + # once. The definitions are identical -- both describe the module port, not + # a board -- so whichever directory CMake reaches first may create it. + + if(NOT TARGET threadx_module) + + file(GLOB TX_COMMON_SRC ${CMAKE_SOURCE_DIR}/common/src/*.c) + + set(TX_R52_PORT_SRC ${CMAKE_SOURCE_DIR}/ports/cortex_r52/gnu/src) + + add_library(threadx_module STATIC EXCLUDE_FROM_ALL + ${TX_COMMON_SRC} + ${TX_R52_PORT_SRC}/tx_port_offset_check.c + ${TX_R52_PORT_SRC}/tx_thread_fiq_context_restore.S + ${TX_R52_PORT_SRC}/tx_thread_fiq_context_save.S + ${TX_R52_PORT_SRC}/tx_thread_fiq_nesting_end.S + ${TX_R52_PORT_SRC}/tx_thread_fiq_nesting_start.S + ${TX_R52_PORT_SRC}/tx_thread_interrupt_control.S + ${TX_R52_PORT_SRC}/tx_thread_interrupt_disable.S + ${TX_R52_PORT_SRC}/tx_thread_interrupt_restore.S + ${TX_R52_PORT_SRC}/tx_thread_irq_nesting_end.S + ${TX_R52_PORT_SRC}/tx_thread_irq_nesting_start.S + ${TX_R52_PORT_SRC}/tx_thread_vectored_context_save.S + ${TX_R52_PORT_SRC}/tx_timer_interrupt.S + ) + + target_include_directories(threadx_module PUBLIC + ${MOD_DIR}/inc + ${CMAKE_SOURCE_DIR}/common/inc + ${CMAKE_SOURCE_DIR}/common_modules/module_manager/inc + ${CMAKE_SOURCE_DIR}/common_modules/module_lib/inc + ${CMAKE_SOURCE_DIR}/common_modules/inc + ) + + target_compile_definitions(threadx_module PUBLIC TXM_MODULE_MANAGER) + + endif() + + # The portable half of the module manager. Globbed rather than listed: it is + # a whole upstream component, not a selection from one, and a file added to it + # upstream should not need a change here to be compiled. + + file(GLOB TXM_MANAGER_SRC ${CMAKE_SOURCE_DIR}/common_modules/module_manager/src/*.c) + + # The module-side library: the API shims that run inside the module. These + # belong to the module's image and must not reach the manager's link -- they + # define the same names as the kernel's own entry points, and as objects they + # beat the kernel's static library, so in one link every service call the + # manager makes is redirected into the module. See link_demo_module.lds. + + file(GLOB TXM_MODULE_LIB_SRC ${CMAKE_SOURCE_DIR}/common_modules/module_lib/src/*.c) + + # ------------------------------------------------------------------------ + # The module, built as its own image and reduced to a raw binary. + # ------------------------------------------------------------------------ + + add_executable(s32z280_demo_module.elf EXCLUDE_FROM_ALL + ${MOD_EVB}/txm_module_preamble.S + ${MOD_EVB}/sample_threadx_module.c + ${MOD_DIR}/module_lib/src/txm_module_thread_shell_entry.c + ${MOD_DIR}/module_lib/src/txm_module_gcc_setup.S + ${TXM_MODULE_LIB_SRC} + ) + + # No TXM_MODULE_MANAGER here: that define selects the kernel side of the + # shared headers, and this is the other side. + + target_include_directories(s32z280_demo_module.elf PRIVATE + ${EVB_DIR} + ${MOD_DIR}/inc + ${CMAKE_SOURCE_DIR}/common_modules/module_lib/inc + ${CMAKE_SOURCE_DIR}/common_modules/inc + ${CMAKE_SOURCE_DIR}/common/inc + ) + + # Position independent, and only here. These four flags are what make the + # module relocatable, and putting any of them on the manager would be a bug: + # the manager is the resident image, linked absolutely at the address it + # boots from, and -msingle-pic-base in particular would have it treat r9 as + # a PIC base that nothing sets up. + # + # -fpic data references go through the GOT + # -msingle-pic-base r9 is the GOT base, and the caller sets + # it -- which is what the manager's + # thread stack build now does + # -mno-pic-data-is-text-relative the module's data is NOT at a fixed + # offset from its code. It is not: code + # is loaded in place in the module area + # and data is allocated from the byte + # pool, so the gap between them is + # decided at run time + # -fno-plt no procedure linkage table, which a + # module has no loader to populate + # -mno-long-calls see below -- this one is ours, not the + # reference port's, and without it the + # module cannot start at all + # + # -mno-long-calls is the interesting one, and it is here because of a bug + # this build found before silicon did. The project-wide C flags carry + # -mlong-calls, which the manager needs: its image spans TCM at 0x30000000 + # and code at 0x79900000, far beyond the +/-32 MB a direct BL reaches. But + # -mlong-calls under -fpic makes GCC route EVERY call through the GOT -- + # R_ARM_GOT32 instead of R_ARM_CALL -- and one of those calls is the shell + # entry's call to _gcc_setup, which is the function that fills the GOT in. + # The module would have loaded, entered its shell entry, loaded a zero out + # of the not-yet-written GOT and branched to address 0. + # + # A module does not need long calls. It is one contiguous blob under two + # kilobytes, every internal call is a few hundred bytes away, and it never + # calls out of itself: kernel services go through the dispatcher function + # pointer in its entry info, which is data and reached through the GOT + # either way. So the flag is pure cost here, and dropping it is what makes + # the bootstrap possible rather than a workaround for it. + # + # The same four, in the same order, are what the Cortex-A7 GNU module + # example uses. Verified on the generated code rather than assumed: with + # these flags every reference to a module global comes out as an R_ARM_GOT32 + # and loads through LDR rX, [r9, rY], while calls stay direct R_ARM_CALL. + + target_compile_options(s32z280_demo_module.elf PRIVATE + -g + -fpic + -fno-plt + -mno-pic-data-is-text-relative + -msingle-pic-base + -mno-long-calls + ) + + target_link_options(s32z280_demo_module.elf PRIVATE + -T${MOD_EVB}/link_demo_module.lds + -nostartfiles + -nostdlib + -Wl,-Map=s32z280_demo_module.map + ${EVB_LINK_QUIET_RWX} + ) + + # The raw image the manager embeds. Written into the binary directory + # because that is the include path module_blob.S searches. + + add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/demo_module.bin + COMMAND ${CMAKE_OBJCOPY} -O binary + $ + ${CMAKE_CURRENT_BINARY_DIR}/demo_module.bin + DEPENDS s32z280_demo_module.elf + COMMENT "Converting the demonstration module to a raw image" + VERBATIM + ) + + add_custom_target(s32z280_demo_module_bin + DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/demo_module.bin + ) + + add_executable(s32z280_module.elf EXCLUDE_FROM_ALL + # Board support, shared with the other examples + ${EVB_DIR}/entry.S + ${EVB_DIR}/linflexd.c + ${EVB_DIR}/timer.c + ${EVB_DIR}/mpu.c + ${EVB_DIR}/gicv3.c + ${EVB_DIR}/irq_dispatch.c + ${EVB_DIR}/gic_probe.c + ${EVB_DIR}/cache.c + ${EVB_DIR}/tcm.c + ${EVB_DIR}/thread_mpu.c + ${EVB_DIR}/tx_initialize_low_level.S + + # Module manager port + ${MOD_DIR}/module_manager/src/tx_thread_schedule.S + ${MOD_DIR}/module_manager/src/tx_thread_context_save.S + ${MOD_DIR}/module_manager/src/tx_thread_context_restore.S + ${MOD_DIR}/module_manager/src/tx_thread_stack_build.S + ${MOD_DIR}/module_manager/src/tx_thread_system_return.S + ${MOD_DIR}/module_manager/src/txm_module_manager_svc_handler.S + ${MOD_DIR}/module_manager/src/txm_module_manager_fault_capture.S + ${MOD_DIR}/module_manager/src/txm_module_manager_user_mode_entry.S + ${MOD_DIR}/module_manager/src/txm_module_manager_thread_stack_build.S + ${MOD_DIR}/module_manager/src/txm_module_manager_mm_register_setup.c + ${MOD_DIR}/module_manager/src/txm_module_manager_memory_fault_handler.c + ${MOD_DIR}/module_manager/src/txm_module_manager_memory_fault_notify.c + ${MOD_DIR}/module_manager/src/txm_module_manager_alignment_adjust.c + ${MOD_DIR}/module_manager/src/txm_module_manager_external_memory_enable.c + ${MOD_DIR}/module_manager/src/txm_module_manager_offset_check.c + + # The module, as bytes rather than as objects. module_blob.S includes the + # raw image built by s32z280_demo_module.elf, so none of the module's + # symbols enter this link. + ${MOD_EVB}/module_blob.S + + # The application + ${MOD_EVB}/sample_threadx_module_manager.c + + # The portable module manager + ${TXM_MANAGER_SRC} + ) + + target_include_directories(s32z280_module.elf PRIVATE + ${EVB_DIR} + ${MOD_DIR}/inc + ${CMAKE_SOURCE_DIR}/common_modules/module_manager/inc + ${CMAKE_SOURCE_DIR}/common_modules/module_lib/inc + ${CMAKE_SOURCE_DIR}/common_modules/inc + ) + + target_compile_definitions(s32z280_module.elf PRIVATE + TXM_MODULE_MANAGER + TX_R52_USE_THREADX_IRQ + ) + + target_compile_options(s32z280_module.elf PRIVATE -g) + + # .incbin searches the assembler's include paths, not the source tree, and + # demo_module.bin is generated -- so the build directory has to be on that + # path or module_blob.S cannot find the image. + + set_source_files_properties(${MOD_EVB}/module_blob.S PROPERTIES + OBJECT_DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/demo_module.bin + COMPILE_OPTIONS "-Wa,-I${CMAKE_CURRENT_BINARY_DIR}" + ) + + add_dependencies(s32z280_module.elf s32z280_demo_module_bin) + + target_link_options(s32z280_module.elf PRIVATE + -T${MOD_EVB}/link_module.lds + -nostartfiles + -Wl,-Map=s32z280_module.map + ${EVB_LINK_QUIET_RWX} + ) + + target_link_libraries(s32z280_module.elf PRIVATE threadx_module) + +endif() diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/entry.S b/ports/cortex_r52/gnu/example_build/s32z280_evb/entry.S index 24aa9cdce..6601b25ec 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/entry.S +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/entry.S @@ -149,6 +149,12 @@ cntfrq_at_el2: .word 0 hmpuir_at_el2: .word 0 .global probe_stage probe_stage: .word 0 +#ifdef TXM_MODULE_MANAGER + .extern __tx_module_svc_interrupt + .extern _txm_module_manager_data_abort + .extern _txm_module_manager_prefetch_abort +#endif + .global fault_expected fault_expected: .word 0 .global fault_taken @@ -197,7 +203,11 @@ el2_vectors: el1_vectors: b fault_el1_reset /* 0x00 */ b fault_el1_undef /* 0x04 */ +#ifdef TXM_MODULE_MANAGER + b __tx_module_svc_interrupt /* 0x08 module kernel boundary */ +#else b fault_el1_svc /* 0x08 */ +#endif b fault_el1_pabt /* 0x0C */ b fault_el1_dabt /* 0x10 */ b fault_el1_reserved /* 0x14 */ @@ -891,6 +901,26 @@ fault_el1_svc: mov r3, lr FAULT_TAIL 0x48 fault_el1_pabt: +#ifdef TXM_MODULE_MANAGER + /* A fault from User mode is a module reaching outside its regions, and it + belongs to the module manager, which will record it and terminate the + thread. A fault from a privileged mode continues on the recoverable path + below, which the boot probes depend on. + + r0 is pushed and popped around the test rather than simply used. The code + below clobbers r0 through r2 without saving them, which is tolerable for a + probe that provokes its own fault, but the module capture records the + faulting registers and would record ours instead. LDM does not affect the + flags, so the comparison still holds after the pop. */ + + stmdb sp!, {r0} + mrs r0, spsr + and r0, r0, #0x1F + cmp r0, #0x10 /* User mode? */ + ldmia sp!, {r0} + beq _txm_module_manager_prefetch_abort +#endif + /* Recoverable when a test has armed fault_expected_pabt. * * Recovery differs from the data-abort case in kind, not degree. There, @@ -932,6 +962,26 @@ fault_el1_pabt_fatal: mrc p15, 0, r3, c6, c0, 2 /* IFAR */ FAULT_TAIL 0x4C fault_el1_dabt: +#ifdef TXM_MODULE_MANAGER + /* A fault from User mode is a module reaching outside its regions, and it + belongs to the module manager, which will record it and terminate the + thread. A fault from a privileged mode continues on the recoverable path + below, which the boot probes depend on. + + r0 is pushed and popped around the test rather than simply used. The code + below clobbers r0 through r2 without saving them, which is tolerable for a + probe that provokes its own fault, but the module capture records the + faulting registers and would record ours instead. LDM does not affect the + flags, so the comparison still holds after the pop. */ + + stmdb sp!, {r0} + mrs r0, spsr + and r0, r0, #0x1F + cmp r0, #0x10 /* User mode? */ + ldmia sp!, {r0} + beq _txm_module_manager_data_abort +#endif + /* Recoverable when a test has armed fault_expected. The protection map is only meaningful if a violation actually faults, so the test provokes one deliberately and this path lets it continue: record the syndrome and diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/link.lds b/ports/cortex_r52/gnu/example_build/s32z280_evb/link.lds index cb73bb35a..796cb88d7 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/link.lds +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/link.lds @@ -54,7 +54,10 @@ MEMORY Used for data that wants deterministic access without depending on a cache -- an enabled TCM is never cached. */ BTCM (rw) : ORIGIN = 0x30100000, LENGTH = 0x00004000 /* 16 KB */ - DATA (rwx) : ORIGIN = 0x31780000, LENGTH = 0x00080000 /* 512 KB: DRAM0 + DRAM1, both full core speed */ + DATA (rwx) : ORIGIN = 0x31780000, LENGTH = 0x00070000 /* 448 KB: DRAM0 + DRAM1 below the module area */ + /* Module memory, uncovered by any kernel MPU region on purpose. See + S32Z_MODULE_AREA_BASE in platform.h. */ + MODULE (rwx) : ORIGIN = 0x317F0000, LENGTH = 0x00010000 /* 64 KB */ } ENTRY(_start) diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/mpu.c b/ports/cortex_r52/gnu/example_build/s32z280_evb/mpu.c index 2073d0db5..c8277fc47 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/mpu.c +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/mpu.c @@ -302,8 +302,12 @@ static void build_table(void) Reference Manual and confirmed on the board. */ mpu_regions[1].mpu_region_base = S32Z_DATA_SRAM_BASE; + /* Stops before the module area at the top of DRAM1. A module's memory must + not be covered by a kernel region, or every thread could reach it and the + manager's own regions would be decoration. */ + mpu_regions[1].mpu_region_limit = S32Z_DATA_SRAM_BASE - + S32Z_DATA_SRAM_SIZE - 1UL; + + S32Z_DATA_SRAM_SHARED_SIZE - 1UL; mpu_regions[1].mpu_region_ap = MPU_AP_RW_EL1; mpu_regions[1].mpu_region_execute_never = 1U; mpu_regions[1].mpu_region_shareability = MPU_SH_NON; @@ -453,6 +457,73 @@ static void program_region(unsigned int index, const MPU_REGION *region_ptr) } +/**************************************************************************/ +/* mpu_module_load_window_open / mpu_module_load_window_close */ +/* */ +/* A window over the module area, for the manager to load through. */ +/* */ +/* No kernel region covers the module area, which is what stops every */ +/* thread from reaching a module's memory -- but the manager has to read */ +/* the preamble and write the module's data to load it at all. Without */ +/* this the load faulted on its first read of the image, and because a */ +/* privileged data abort ends in a handler that only spins, that looked */ +/* exactly like the load hanging. */ +/* */ +/* Opened around the load and closed straight after, rather than left in */ +/* place, because PMSAv8-R has no region priority: if this region were */ +/* still enabled when a module thread ran it would overlap the module's */ +/* own regions, and an access hitting both takes a translation fault */ +/* (TRM 8.1). */ +/* Closing it before any module thread starts is what keeps the two from */ +/* ever being enabled together. */ +/* */ +/* Region 16, above both the kernel's 0-7 and the eight the manager */ +/* hands to a module, so neither the scheduler's per-thread region load */ +/* nor the boot table can disturb it. MPUIR reports 20 EL1 regions on */ +/* this part. EL1 read/write with no EL0 access: the manager can load */ +/* through it and a module cannot use it to reach anything. */ +/**************************************************************************/ + +unsigned long mpu_module_window_prbar; +unsigned long mpu_module_window_prlar; + + +void mpu_module_window_init(void) +{ + MPU_REGION window; + + window.mpu_region_base = S32Z_MODULE_AREA_BASE; + window.mpu_region_limit = S32Z_MODULE_AREA_BASE + + S32Z_MODULE_AREA_SIZE - 1UL; + window.mpu_region_ap = MPU_AP_RW_EL1; + window.mpu_region_execute_never = 1U; + window.mpu_region_shareability = MPU_SH_NON; + window.mpu_region_attr_index = MPU_ATTR_NORMAL_WB; + window.mpu_region_name = "module window RW NX EL1"; + + /* Published for the scheduler, which turns this region on and off on every + dispatch and has no business computing register layouts in assembly. */ + + mpu_module_window_prbar = (window.mpu_region_base & 0xFFFFFFC0UL) + | (((unsigned long) window.mpu_region_shareability & 0x3UL) << 3) + | (((unsigned long) window.mpu_region_ap & 0x3UL) << 1) + | ((unsigned long) window.mpu_region_execute_never & 0x1UL); + + mpu_module_window_prlar = (window.mpu_region_limit & 0xFFFFFFC0UL) + | (((unsigned long) window.mpu_region_attr_index & 0x7UL) << 1) + | 1UL; + + /* Enabled now, because everything running before the first module thread is + privileged code that may need to reach module memory -- the manager loads + a module from a kernel thread. */ + + program_region(MPU_MODULE_LOAD_REGION, &window); + + data_sync_barrier(); + instruction_barrier(); +} + + /**************************************************************************/ /* mpu_init */ /**************************************************************************/ @@ -499,6 +570,16 @@ unsigned int mpu_init(void) write_prlar(0UL); } +#ifdef TXM_MODULE_MANAGER + + /* After the loop above, which would otherwise disable it again: the module + window lives above the regions this table uses, so it counts as unused + here. */ + + mpu_module_window_init(); + +#endif + MARK(0x40); data_sync_barrier(); diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/mpu.h b/ports/cortex_r52/gnu/example_build/s32z280_evb/mpu.h index a9911e92e..19d183cce 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/mpu.h +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/mpu.h @@ -115,4 +115,28 @@ const MPU_REGION *mpu_region_table(unsigned int *count_ptr); void mpu_read_region(unsigned int index, unsigned long *prbar_ptr, unsigned long *prlar_ptr); +/* Region index for the manager's load window over the module area. Above the + kernel's 0-7 and above the eight the manager hands to a module, so neither + the boot table nor the scheduler's per-thread region load can disturb it. */ + +#define MPU_MODULE_LOAD_REGION 16U + +/* The module area window, which is what lets privileged code reach module + memory at all -- no other kernel region covers it. + + PMSAv8-R has no region priority, so this must never be enabled at the same + time as the regions a module is given, which cover the same memory. That is + guaranteed by who owns it rather than by careful calling: the scheduler turns + this region on for every thread that is not a module thread and off for every + thread that is, so the window is enabled exactly when no module regions are + loaded. The two register words are published for it below. + + Enabled here at boot, because everything before the first module thread is + privileged code that may need to reach module memory. */ + +void mpu_module_window_init(void); + +extern unsigned long mpu_module_window_prbar; +extern unsigned long mpu_module_window_prlar; + #endif /* MPU_H */ diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/platform.h b/ports/cortex_r52/gnu/example_build/s32z280_evb/platform.h index 4adbe55ec..1440fbd10 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/platform.h +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/platform.h @@ -130,6 +130,61 @@ #define S32Z_DRAM0_SIZE 0x00040000UL #define S32Z_DRAM1_BASE 0x317C0000UL #define S32Z_DRAM1_SIZE 0x00040000UL +/* Memory for loadable modules: the top 64 KB of DRAM1, deliberately left out of + the broad data region in mpu.c. + + It has to be outside every region the board support package programs. The + manager gives a module its own regions, and if the kernel's map already covered + that memory then every thread could reach the module and back -- the isolation + would be nominal. Carving a hole is the only way to make it real. + + DRAM1 rather than DRAM2 because it runs at full core speed (S32Z2 RM 6.3.6), + and because code and data can be contiguous here. Putting module code in the + code RAM region instead would have been the obvious choice and does not work: + that region is read-only, so a module's data would have to live somewhere else + and the module would straddle two carve-outs. + + 64 KB is arbitrary but not accidental: it leaves 448 KB of full-speed RAM for + the kernel's data, stacks and bss, which currently use about 14 KB. */ + +#define S32Z_MODULE_AREA_BASE 0x317F0000UL +#define S32Z_MODULE_AREA_SIZE 0x00010000UL /* 64 KB */ + +/* The shared granules the sample module reports its progress through, at the + base of the module area. + + A module cannot print -- the console belongs to the board support package and + lies outside every region a module owns -- so the manager grants it shared + regions and reads them back. On this board a GDB harness reads the module's + own progress variable as well, out of the data area the manager allocated; + these granules are the channel that needs no debugger, and having both means + the two agree or the run says so. + + Six granules rather than one, because a module may be granted + TXM_MODULE_MPU_SHARED_ENTRIES regions and one grant only ever exercises the + first of them. Five are granted, one granule per entry, and + S32Z_MODULE_STATUS_UNGRANTED -- index 2, so a granted granule sits on either + side of it -- is never granted to anything. A limit register masked the wrong + way, or a base off by a granule, extends a region into that gap from one side + or the other, and a module that can write it was given more than was asked + for. + + S32Z_MODULE_STATUS_SIZE is the size of ONE granule, which is also the length + of each individual grant; the area is GRANULES of them. Fixed addresses on + both sides, checked at run time against the linker's symbol rather than + trusted. */ + +#define S32Z_MODULE_STATUS_BASE 0x317F0000UL +#define S32Z_MODULE_STATUS_SIZE 0x40UL /* one MPU granule */ +#define S32Z_MODULE_STATUS_GRANULES 6UL /* five granted, one not */ +#define S32Z_MODULE_STATUS_UNGRANTED 2UL /* the one never granted */ + +/* What is left of the full-speed pair for the kernel itself. link.lds sizes its + DATA region from this, so the linker cannot place kernel data in the module + area by accident. */ + +#define S32Z_DATA_SRAM_SHARED_SIZE (S32Z_MODULE_AREA_BASE - S32Z_DRAM0_BASE) + /* The top 8 KB of DRAM2 is deliberately left out of the broad data region in mpu.c and mapped one window at a time, per thread, instead. Isolation is only meaningful in memory that no other region already grants access to, and every diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/thread_mpu.c b/ports/cortex_r52/gnu/example_build/s32z280_evb/thread_mpu.c index 9042aeb98..5681754f9 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/thread_mpu.c +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/thread_mpu.c @@ -66,16 +66,59 @@ static unsigned int max_cycles; /* CP15 accessors. */ /**************************************************************************/ +/* Direct per-region access rather than PRSELR. + + The Cortex-R52 TRM 8.4 encodes the region number into CRm and opc2: CRm is + 0b1rrr where rrr is region_number[3:1], with opc2 0 and 1 for an even region + and 4 and 5 for an odd one. Regions 0 through 15 take CP15 op1 0 and regions + 16 through 24 take op1 1. PRBAR and PRLAR without a number are the indirect + view selected by PRSELR. + + Region 8 is therefore op1 0, CRm c12, opc2 0 and 1. Using it removes the + PRSELR write and, more importantly, the ISB that has to follow PRSELR before + the region registers can be written. + + Measured on this part: 542 to 604 cycles through PRSELR against 434 to 470 + direct, for the same region and the same isolation result. The saving matters + most where several regions are programmed at once, which is what a module + switch does -- there the PRSELR route pays an ISB per region while the direct + route pays one barrier pair for the whole block. + + The TRM disagrees with itself about the range, and the next reader should not + have to rediscover that. The register descriptions at 3.3.85 and 3.3.86 say + "Direct access is provided to PRBAR0 to PRBAR15" and list only the op1 0 + form; 8.4 and Table 8-9 list both forms. Table 8-9 also prints opc2 0 for + the even limit registers where the prose of 8.4 says 1. What is written here + uses op1 0 only, which is the half of the manual this part has been measured + against. */ + +/* Kept for regions 16 and above. Those have direct op1 1 encodings in TRM 8.4, + but only the selector route is proven on this part, and nothing here needs a + region that high while the per-thread window lives at region 8. */ + +__attribute__((unused)) static void write_prselr(unsigned long value) { __asm__ volatile("mcr p15, 0, %0, c6, c2, 1" : : "r"(value) : "memory"); } +static void write_prbar8_direct(unsigned long value) +{ + __asm__ volatile("mcr p15, 0, %0, c6, c12, 0" : : "r"(value) : "memory"); +} + +static void write_prlar8_direct(unsigned long value) +{ + __asm__ volatile("mcr p15, 0, %0, c6, c12, 1" : : "r"(value) : "memory"); +} + +__attribute__((unused)) static void write_prbar(unsigned long value) { __asm__ volatile("mcr p15, 0, %0, c6, c3, 0" : : "r"(value) : "memory"); } +__attribute__((unused)) static void write_prlar(unsigned long value) { __asm__ volatile("mcr p15, 0, %0, c6, c3, 1" : : "r"(value) : "memory"); @@ -154,9 +197,6 @@ void thread_mpu_activate(TX_THREAD *thread_ptr) } } - write_prselr(THREAD_MPU_REGION); - __asm__ volatile("isb" ::: "memory"); - if (base == 0UL) { /* No window for this thread: disable the region rather than leaving the @@ -164,16 +204,16 @@ void thread_mpu_activate(TX_THREAD *thread_ptr) protection silently becomes no protection -- the last thread to run would leave its window open to whatever ran next. */ - write_prlar(0UL); + write_prlar8_direct(0UL); } else { - write_prbar((base & ~0x3FUL) + write_prbar8_direct((base & ~0x3FUL) | ((unsigned long) MPU_SH_NON << 3) | ((unsigned long) MPU_AP_RW_EL1 << 1) | 1UL); /* XN: data only */ - write_prlar(((base + S32Z_THREAD_WINDOW_SIZE - 1UL) & ~0x3FUL) + write_prlar8_direct(((base + S32Z_THREAD_WINDOW_SIZE - 1UL) & ~0x3FUL) | ((unsigned long) MPU_ATTR_NORMAL_WB << 1) | 1UL); /* EN */ } diff --git a/ports/cortex_r52/gnu/inc/tx_port.h b/ports/cortex_r52/gnu/inc/tx_port.h index 2f0a67cf6..207d9c66b 100644 --- a/ports/cortex_r52/gnu/inc/tx_port.h +++ b/ports/cortex_r52/gnu/inc/tx_port.h @@ -255,17 +255,72 @@ typedef unsigned short USHORT; #define TX_TIMER_DELETE_EXTENSION(timer_ptr) -/* Determine if the ARM architecture has the CLZ instruction. This is available on - architectures v5 and above. If available, redefine the macro for calculating the - lowest bit set. */ - -#if __TARGET_ARCH_ARM > 4 +/* Determine whether this core has the CLZ instruction and this compiler will + admit to it, and if so replace the portable lowest-set-bit search with it. + + The guard is not upstream's. Upstream asks __TARGET_ARCH_ARM > 4, which is an + Arm Compiler 5 predefine. GCC does not define it -- it predefines the ACLE + macros __ARM_ARCH and __ARM_FEATURE_CLZ instead -- so under GCC the test reads + 0 > 4, this whole block is dropped and tx_thread.h's portable loop runs on a + core that has had the instruction since Armv5. Measured with + arm-none-eabi-gcc 14.3 on 20 Aug 2026: zero CLZ instructions in the built + scheduler objects. + + That was not a dormant path. Half the TX_LOWEST_SET_BIT_CALCULATE call sites + in tx_thread_suspend.c and tx_thread_system_suspend.c sit OUTSIDE the + TX_MAX_PRIORITIES > 32 guards, so the portable loop was running in the + scheduler's priority search in the default 32-priority configuration, which is + the one every R52 build uses. + + __ARM_FEATURE_CLZ is the ACLE answer to the question actually being asked, and + the compiler defines it exactly when the architecture has the instruction, so + a core without CLZ is excluded by construction rather than by an architecture + number. Arm Compiler 5's spelling is kept beside it, now wrapped in defined() + so the test no longer leans on an undefined identifier evaluating to zero -- + which is what -Wundef reports and how this was found. + + The __thumb__ guard stays, and it is load-bearing rather than inherited + caution: __ARM_FEATURE_CLZ describes the ARCHITECTURE, not the instruction + set. Checked on 20 Aug 2026 -- GCC defines it for -mthumb -march=armv5te, + where Thumb-1 has no CLZ at all and this asm would fail to assemble. A Thumb + build therefore keeps the portable loop on purpose. (On this core it is moot: + the R52 toolchain file builds -marm.) + + Two deliberate deviations, per AGENTS.md: + + - Rule 1.2, language extensions. Inline assembly is the entire point of the + macro; there is no conforming way to reach CLZ. Spelled __asm__ and not + asm, because the asm keyword is rejected under -std=c99 -- verified, it is + an "'asm' undeclared" error -- and AGENTS.md requires C99 compatibility. + + - Rule 10.1 / 10.3 on the isolation step, which is why it is respelled. + Upstream isolates the lowest set bit with (ULONG) (-((LONG) m)): that + converts an unsigned map to signed and negates it, which is undefined for + the one input whose top bit is set. (~(m)) + 1 is the same value in + well-defined unsigned arithmetic, and it is character-for-character what + tx_thread.h's portable version uses -- so the two implementations now + visibly compute the same thing instead of merely agreeing. + + Rule 20.7 is a straight fix rather than a deviation: upstream leaves m and b + unparenthesised in the expansion. + + PRECONDITION: m must be non-zero, and the two implementations DISAGREE when it + is not. CLZ(0) is 32, so this yields 31 - 32; the portable loop yields 0. + All twelve call sites in common/src reach the macro only on a map already + tested against zero -- every one checked on 20 Aug 2026 -- so the divergence is + unreachable today. It is written down because a new call site is exactly how + it would stop being unreachable, and demo_clz.c pins both answers so that + changing this has to be a decision. */ + +#if defined(__ARM_FEATURE_CLZ) || (defined(__TARGET_ARCH_ARM) && (__TARGET_ARCH_ARM > 4)) #ifndef __thumb__ -#define TX_LOWEST_SET_BIT_CALCULATE(m, b) m = m & ((ULONG) (-((LONG) m))); \ - asm volatile (" CLZ %0,%1 ": "=r" (b) : "r" (m) ); \ - b = 31 - b; +#define TX_LOWEST_SET_BIT_CALCULATE(m, b) \ + (m) = (m) & ((~(m)) + ((ULONG) 1)); \ + __asm__ volatile (" CLZ %0,%1 " : "=r" (b) : "r" (m)); \ + (b) = 31 - (b); + #endif #endif diff --git a/ports/cortex_r52/gnu/readme_threadx.txt b/ports/cortex_r52/gnu/readme_threadx.txt index 4ad3cc344..73e0dbfe9 100644 --- a/ports/cortex_r52/gnu/readme_threadx.txt +++ b/ports/cortex_r52/gnu/readme_threadx.txt @@ -51,7 +51,7 @@ baseline selects the soft ABI rather than removing the FPU. -DCMAKE_TOOLCHAIN_FILE=cmake/cortex_r52.cmake \ -DTX_R52_BUILD_FVP_EXAMPLE=ON . ninja -C build_r52 boot_check.elf demo_m2.elf demo_m3.elf \ - demo_threadx.elf demo_mpu.elf + demo_threadx.elf demo_mpu.elf demo_clz.elf ctest --test-dir build_r52 The images target the free Armv8-R AEM FVP (FVP_BaseR_AEMv8R): @@ -61,6 +61,7 @@ The images target the free Armv8-R AEM FVP (FVP_BaseR_AEMv8R): demo_m3.elf generic timer tick, GICv3 and preemption demo_threadx.elf the standard eight-thread demo plus verification demo_mpu.elf PMSAv8-R protection and cache enable + demo_clz.elf the CLZ lowest-set-bit priority search demo_m5.elf lazy VFP context save (needs TX_R52_ENABLE_VFP) Each image reports its own result and terminates the model through the @@ -135,6 +136,20 @@ and the thread stack pointer and run counter offsets, at compile time: a layout change becomes a build failure instead of silent corruption. +Also worth knowing: this port replaces tx_thread.h's portable lowest-set-bit +search with the CLZ instruction, which is what the scheduler uses to pick the +next thread to run. Upstream gates that on __TARGET_ARCH_ARM, an Arm Compiler +5 predefine that GCC does not define, so the optimisation had never once been +compiled in under GCC; the guard here asks __ARM_FEATURE_CLZ instead. It is +worth 40% of the priority search's code size (2188 to 1316 bytes in +tx_thread_system_suspend.o) and it applies in the default 32-priority +configuration, not only above 32. A Thumb build deliberately keeps the +portable loop, because __ARM_FEATURE_CLZ describes the architecture rather +than the instruction set and Thumb-1 has no CLZ. demo_clz.elf is the +regression test, and it fails to build rather than silently testing the +portable loop if the CLZ path is ever disabled again. + + 7. Memory Protection PMSAv8-R regions are described by a table rather than a sequence of @@ -145,13 +160,24 @@ disables the regions it does not use. Two cautions for anyone reusing this code on silicon: - - The PRBAR.AP encoding used here was calibrated against the hardware. - The low bit is read-only and the high bit grants EL0 access, which is - the reverse of the widely-published Armv8-R AArch64 macro set. Getting - it wrong produces regions that report as read-only and accept writes, - because region coverage is still enforced: an unmapped address faults - while a "read-only" region does not. Re-calibrate before trusting - these values on a different implementation. + - The PRBAR.AP encoding is the standard Armv8-R one, as published: + AP[2] selects read-only and AP[1] grants EL0 access. No calibration is + needed, and an earlier revision of this file said otherwise -- it + claimed the two bits were reversed, on the strength of a real + measurement with a wrong cause. program_region() had been shifting + every PRBAR field one bit too far left, so the AP value's low bit + landed in the true AP[2] and writes faulted exactly when that bit was + set, which looks precisely like a reversed encoding. The shift is + fixed; see the comment on the MPU_AP_* macros in mpu.h for the full + calibration table and what it actually proved. + + The reason it took a silicon run to notice: region coverage is enforced + even when permissions are not what you asked for, so an unmapped + address faults while a "read-only" region quietly accepts writes. A + configuration-only review cannot tell the two apart -- provoke a real + fault instead. Verified on S32Z280 silicon: a write to an RO region + faults and execution from an XN region takes a prefetch abort, the + latter never having worked under the old shift. - The code and data regions must not share a 64-byte granule. The linker script separates them with ".data ALIGN(64) :" on the output diff --git a/ports_module/cortex_r52/gnu/example_build/fvp_baser_aemv8r/link_demo_module.lds b/ports_module/cortex_r52/gnu/example_build/fvp_baser_aemv8r/link_demo_module.lds new file mode 100644 index 000000000..dbe1e069f --- /dev/null +++ b/ports_module/cortex_r52/gnu/example_build/fvp_baser_aemv8r/link_demo_module.lds @@ -0,0 +1,208 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/* Link map for the demonstration module alone, for the Armv8-R AEM FVP. + * + * Nothing in this file is board specific: the module is position independent + * and the two segment origins below are fictions. It is a separate copy from + * the S32Z280 one all the same, because the two examples are deliberately + * independent -- silicon bring-up must not be able to perturb the FVP + * regression, and vice versa -- and because a module example is free to change + * its own layout. The two are byte-identical apart from this paragraph today, + * so `diff` is the right way to see whether they have drifted. + * + * The module is a separate link unit from the manager, and it has to be. Both + * sides define the ThreadX API: the kernel defines the real _txe_* entry points + * and the module library defines shims of the same names that trap into the + * kernel instead. Linking them together does not produce a duplicate-symbol + * error, because the kernel arrives as a static library and the module library + * as ordinary objects, and an object always beats an archive member. The module + * shims therefore win for the whole image, and the manager's own calls to + * tx_thread_create and friends are quietly redirected into the module. + * + * That was not a theory. On the S32Z280 it put _txe_thread_create inside the + * module area, which no kernel MPU region covers -- so tx_application_define + * called into unmapped memory and the core took a prefetch abort with nothing on + * the console to say so. + * + * POSITION INDEPENDENT, and the two addresses below are fictions + * ============================================================== + * + * The module is built -fpic -msingle-pic-base, so every reference it makes to + * its own data goes through the global offset table with r9 as the base. It + * therefore does not run at the addresses in this file and is not meant to: the + * two segment origins are nominal, chosen only so that the loader can tell a + * code address from a data address by comparing against __data_segment_start__. + * What actually happens at run time is that _gcc_setup rewrites every GOT entry + * from these nominal addresses to the addresses the manager decided on. + * + * That is why they are far apart and why neither is zero. Far apart, because + * the whole discrimination is "below the data origin means code"; non-zero, + * because _gcc_setup treats a zero GOT entry as one the linker never filled in + * and skips it, so a real address of zero would be silently dropped. + * + * 0x01000000 code preamble, text, rodata, and the load images of the + * GOT and .data -- this is the blob the manager embeds + * 0x02000000 data the GOT the module runs against, .data and .bss, all + * of which live in memory the manager allocates + * + * The load images matter. A module's .data cannot be used where it was linked, + * because the manager never copies it there: _txm_module_manager_internal_load + * allocates the module's data area from its byte pool and TX_MEMSETs it to zero, + * and that is the only memory the module is given a region for. The module's + * own .data, wherever it was linked, is outside every region the module owns. + * On silicon that faulted at the first write to an initialised variable, with + * DFAR pointing into the gap between the granted code and the granted data. + * The same arrangement fails the same way on the model. + * + * So .data and .got have their VMAs in the data segment, where the module will + * run, and their LMAs in the code segment, inside the blob, where _gcc_setup can + * find them and copy them out. AT>CODE is what says that. + */ + +MEMORY +{ + /* Nominal. See the note above: the module runs where the manager puts it, + not here. Sized generously because nothing is reserved by being large -- + the raw binary is only as long as the sections actually emitted. */ + + CODE (rx) : ORIGIN = 0x01000000, LENGTH = 0x00100000 + DATA (rw) : ORIGIN = 0x02000000, LENGTH = 0x00100000 +} + +__code_segment_start__ = 0x01000000; +__data_segment_start__ = 0x02000000; + +SECTIONS +{ + /* --------------------------------------------------------------------- + The code segment, which is the blob byte for byte. + --------------------------------------------------------------------- */ + + .module_image : ALIGN(64) + { + __module_image_start__ = .; + + /* The preamble is first because that is where the manager looks for it: + it reads the properties, the entry points and the two sizes from the + first words of the image. KEEP because nothing references it. */ + + KEEP(*(.txm_module_preamble)) + + *(.text .text.*) + *(.glue_7) + *(.glue_7t) + *(.rodata .rodata.*) + + . = ALIGN(4); + } >CODE AT>CODE + + /* --------------------------------------------------------------------- + The data segment. VMAs here, load images back in the code segment. + --------------------------------------------------------------------- */ + + /* The GOT, and it must be first in the data segment. r9 is the GOT base as + far as the compiler is concerned -- every R_ARM_GOT32 is an offset from + it -- and the manager sets r9 to txm_module_instance_module_data_base_address, + which is the start of the module's data area. So GOT origin and data + origin have to be the same address, or every offset the compiler emitted + is measured from the wrong place. __data_segment_start__ above is that + address on the nominal side; r9 is that address on the real side, and + _gcc_setup's rebase is the difference between the two. */ + + .got : ALIGN(4) + { + __new_got_start__ = .; + *(.got.plt) + *(.igot.plt) + *(.got) + __new_got_end__ = .; + } >DATA AT>CODE + + __got_load_start__ = LOADADDR(.got); + + .data : ALIGN(4) + { + __data_start__ = .; + *(.data .data.*) + *(.gnu.linkonce.d.*) + . = ALIGN(4); + __data_end__ = .; + } >DATA AT>CODE + + __data_load_start__ = LOADADDR(.data); + + /* NOLOAD, so .bss contributes nothing to the blob. The manager has already + zeroed the whole data allocation by the time the module runs -- but + _gcc_setup zeroes .bss anyway, because "the manager happens to memset it" + is a property of one loader and not something a module may rely on. */ + + .bss (NOLOAD) : ALIGN(4) + { + __bss_start__ = .; + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(64); + __bss_end__ = .; + } >DATA + + /* --------------------------------------------------------------------- + The two sizes the preamble declares. + --------------------------------------------------------------------- */ + + /* Code covers everything in the blob, the load images of the GOT and .data + included, because the module has to be able to read them to copy them out + and the code region is the only mapping it has over the blob. Ending it + at .rodata instead would put the GOT template outside every region the + module owns and _gcc_setup would fault on its first read. */ + + __txm_module_code_end__ = __data_load_start__ + SIZEOF(.data); + __txm_module_code_size = __txm_module_code_end__ - __code_segment_start__; + + /* Data covers the GOT, .data and .bss. Not the thread stacks: the manager + adds the start/stop and callback stack sizes to this figure itself, from + the two stack-size words further down the preamble. Counting them here + as well would double them. */ + + __txm_module_data_size = __bss_end__ - __data_segment_start__; + + /* Unwind tables and toolchain notes would otherwise land at address zero and + be carried into the raw binary. A module has no unwinder. + + .rel.dyn and friends are discarded because this is a static link: ld + resolves every R_ARM_GOT32 itself and writes the finished address into the + GOT, so there is nothing left for a dynamic loader to do. If one of these + ever stops being empty, the assumption above has broken and the module + needs relocation processing rather than a rebase -- so they are listed + explicitly, to be found by whoever goes looking. */ + + /DISCARD/ : + { + *(.ARM.exidx*) + *(.ARM.extab*) + *(.comment) + *(.note.*) + *(.dynsym) + *(.dynstr) + *(.hash) + *(.gnu.hash) + *(.dynamic) + *(.interp) + *(.rel.dyn) + *(.rel.plt) + *(.plt) + } +} diff --git a/ports_module/cortex_r52/gnu/example_build/fvp_baser_aemv8r/link_module.lds b/ports_module/cortex_r52/gnu/example_build/fvp_baser_aemv8r/link_module.lds new file mode 100644 index 000000000..14ced186c --- /dev/null +++ b/ports_module/cortex_r52/gnu/example_build/fvp_baser_aemv8r/link_module.lds @@ -0,0 +1,295 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/* Link map for the module manager on the Armv8-R AEM FVP (BaseR platform). + * + * The BaseR memory map is the Base platform map with its two 2 GB halves + * swapped: Base DRAM at 0x80000000 appears at 0x00000000 here, and the upper + * half holds peripherals and is not executable by default. Code therefore has + * to be linked into low DRAM -- linking at 0x80000000 produces a silent fault + * loop with no output. + * + * This is the AR1 link.lds with three differences, and each of them is a + * requirement of the module port rather than a preference. + * + * 1. DRAM stops below a MODULE region. A module's code and data are handed + * to it as MPU regions, and PMSAv8-R has no region priority: an access + * hitting more than one enabled region takes a translation fault + * (TRM 8.1). So module memory has to be memory no kernel region covers, + * and the only way to guarantee that is to end the kernel's data region + * where the module area begins. __data_end__ below is ORIGIN(MODULE) for + * exactly that reason, not the "1 MB of heap past the image" the AR1 + * script uses. + * + * 2. .txm_user_entry sits between the code region and the data region, in a + * gap belonging to neither. It holds the module's gateway into the + * kernel, and a module is given a region covering exactly it -- which + * would overlap the kernel's code region if it were inside .text. + * + * 3. The MODULE region is subdivided into four fixed pieces. See each. + * + * The two addresses here are also in platform.h as FVP_MODULE_AREA_BASE and + * FVP_MODULE_AREA_SIZE, because mpu.c programs the manager's load window over + * the same range. A linker script cannot include a C header, so the ASSERT at + * the bottom of this file pins the two spellings together at link time. + */ + +ENTRY(_start) + +__hyp_stack_size__ = 0x0800; +__svc_stack_size__ = 0x1000; +__irq_stack_size__ = 0x0800; +__fiq_stack_size__ = 0x0400; +__abt_stack_size__ = 0x0400; +__und_stack_size__ = 0x0400; +__sys_stack_size__ = 0x0800; + +MEMORY +{ + DRAM (rwx) : ORIGIN = 0x00000000, LENGTH = 0x003F0000 /* ~4 MB less the module area */ + MODULE (rwx) : ORIGIN = 0x003F0000, LENGTH = 0x00010000 /* 64 KB */ +} + +SECTIONS +{ + /* PMSAv8-R regions have a 64-byte granule and their limits are inclusive, + so every boundary the MPU has to describe is aligned to it. */ + + . = ALIGN(64); + __code_start__ = .; + + .text : + { + KEEP(*(.vectors_el2)) + KEEP(*(.vectors_el1)) + *(.text*) + *(.glue_7) + *(.glue_7t) + } > DRAM + + .rodata : + { + . = ALIGN(4); + *(.rodata*) + . = ALIGN(4); + } > DRAM + + /* The module's gateway into the kernel. + * + * __code_end__ is taken at the START of this section, so the kernel's code + * region stops just below it: the region limit is __code_end__ - 1, masked + * down to the granule by PRLAR, and PRLAR's limit is inclusive with the low + * six bits implied as ones -- so the region ends at __code_end__ - 1 exactly + * and this section is outside it. A module gets its own region covering + * exactly this function, and that region would otherwise overlap the + * kernel's. + * + * Alone in its own section on purpose: anything sharing it would become + * executable by every module. ALIGN(64) after the colon aligns the SECTION, + * which is what is wanted. Written as ".txm_user_entry ALIGN(64) :" the + * expression would be the section's ADDRESS instead, and while that form + * happens to work in a region based at zero, it silently overrides "> DRAM" + * and is the wrong habit to leave in a file that will be copied. + */ + + .txm_user_entry : ALIGN(64) + { + __code_end__ = .; + __txm_user_entry_start__ = .; + KEEP(*(.txm_user_entry)) + . = ALIGN(64); + __txm_user_entry_end__ = .; + } > DRAM + + .data : ALIGN(64) + { + __data_start__ = .; + *(.data*) + . = ALIGN(4); + } > DRAM + + .bss (NOLOAD) : + { + . = ALIGN(4); + __bss_start__ = .; + *(.bss*) + *(COMMON) + . = ALIGN(4); + __bss_end__ = .; + } > DRAM + + /* One stack per AArch32 processor mode. SP must stay 8-byte aligned + (AAPCS), so each region is aligned before its top symbol is taken. */ + + .stacks (NOLOAD) : + { + . = ALIGN(8); + . = . + __hyp_stack_size__; + __hyp_stack_top = .; + + . = ALIGN(8); + . = . + __svc_stack_size__; + __svc_stack_top = .; + + . = ALIGN(8); + . = . + __irq_stack_size__; + __irq_stack_top = .; + + . = ALIGN(8); + . = . + __fiq_stack_size__; + __fiq_stack_top = .; + + . = ALIGN(8); + . = . + __abt_stack_size__; + __abt_stack_top = .; + + . = ALIGN(8); + . = . + __und_stack_size__; + __und_stack_top = .; + + . = ALIGN(8); + . = . + __sys_stack_size__; + __sys_stack_top = .; + } > DRAM + + . = ALIGN(8); + _end = .; + PROVIDE(end = .); + + /* ------------------------------------------------------------------ + The module area. Four pieces, none of which may overlap another: + each becomes an enabled MPU region while a module runs. + ------------------------------------------------------------------ */ + + /* The shared granules the module reports its progress through, and the one + it is not allowed to reach. + + The first granule exists because the FVP has no debugger seam. On + silicon a GDB harness reads the module's own progress variable out of the + data area the manager allocated for it; here nothing outside the image + can read anything, and the manager deliberately knows no symbol of the + module. So the manager grants the module a shared MPU region over this + word and reads it back afterwards, which is what lets the test judge what + the module managed to do rather than only that it faulted. + + Six granules rather than one, because a module may be granted five shared + regions and granting a single one exercises only the first entry of the + five. Five of these are granted, one granule per entry, and the sixth -- + FVP_MODULE_STATUS_UNGRANTED, index 2, so that a granted granule sits on + either side of it -- is never granted to anything. The module writes + every granted granule, reads them all back, and then writes the gap, + which must fault. A limit masked the wrong way or a base off by a + granule leaks into that gap from one side or the other. + + First in the module area, so the base address is ORIGIN(MODULE) and the + module can carry it as a constant. A shared region is a region like any + other and cannot overlap the image below it, hence whole granules and the + alignment at the end. */ + + .module_status (NOLOAD) : + { + __module_status_start__ = .; + . = . + 0x180; /* six 64-byte granules */ + . = ALIGN(64); + __module_status_end__ = .; + } > MODULE + + /* The module image. + + The module is not linked here. It is built as its own image by the + fvp_demo_module.elf target, objcopied to a raw binary and included as + bytes by module_blob.S; this section only decides where those bytes land. + Keeping the module out of the link is not tidiness: the module library + defines shims named after the same ThreadX entry points the kernel + defines, and in one link the shims win, because they arrive as objects and + the kernel arrives as a static library. The manager's own service calls + would then be redirected into the module. */ + + .module_image : + { + . = ALIGN(64); + __module_image_start__ = .; + KEEP(*(.module_blob)) + . = ALIGN(64); + __module_image_end__ = .; + } > MODULE + + /* The pool the manager allocates module data from, in the module area for + the same reason the image is: whatever the manager hands to a module + becomes an MPU region, and that region may not overlap a kernel one. + + NOLOAD because nothing is copied in -- the byte pool writes its own + headers when it is created. */ + + .module_pool (NOLOAD) : + { + . = ALIGN(64); + __module_pool_start__ = .; + *(.module_pool) + . = ALIGN(64); + __module_pool_end__ = .; + } > MODULE + + /* A second place to load the same module from, which is how this example + proves the module is relocatable rather than merely built to be. + + A module that runs correctly at the address it was linked for proves + nothing: the GOT rebase would produce the addresses it started with, and a + rebase that did nothing would look identical. So the manager copies the + blob here and loads it a second time. + + NOLOAD, and deliberately not filled by the linker: if the blob were placed + here too, a failure to copy would be invisible because the right bytes + would already be present. */ + + .module_stage (NOLOAD) : + { + . = ALIGN(64); + __module_stage_start__ = .; + . = . + 0x1000; + . = ALIGN(64); + __module_stage_end__ = .; + } > MODULE + + /* The writable area the MPU describes: data, bss, the stacks and everything + tx_application_define carves out above _end, ending where the module area + begins. Not "_end plus a heap": the kernel's data region has to stop + below the module area or it overlaps every region a module is given. */ + + __data_end__ = ORIGIN(MODULE); + + /* The image must not have grown into the module area. Without this the + overlap appears as a module whose data the kernel also owns, which + PMSAv8-R reports as an abort from an address that looks perfectly legal. */ + + ASSERT(_end <= ORIGIN(MODULE), + "the manager image has grown into the module area; move FVP_MODULE_AREA_BASE up") + + /* The module carries the status address as a constant and platform.h names + it as FVP_MODULE_STATUS_BASE. Neither can see this script, so the + agreement is pinned here. The manager checks the same thing again at run + time, against the symbol, so a build that skipped this file still says so. */ + + ASSERT(__module_status_start__ == 0x003F0000, + "the module status word is not at FVP_MODULE_STATUS_BASE") + + /* And its size, for the same reason: the manager grants one region per + granule from this base and the module addresses them by index, so an area + that is not exactly FVP_MODULE_STATUS_GRANULES granules long would leave + a grant, or a module write, outside it. */ + + ASSERT(__module_status_end__ - __module_status_start__ == 0x180, + "the module status area is not FVP_MODULE_STATUS_GRANULES granules long") +} diff --git a/ports_module/cortex_r52/gnu/example_build/fvp_baser_aemv8r/module_blob.S b/ports_module/cortex_r52/gnu/example_build/fvp_baser_aemv8r/module_blob.S new file mode 100644 index 000000000..b3c2d44df --- /dev/null +++ b/ports_module/cortex_r52/gnu/example_build/fvp_baser_aemv8r/module_blob.S @@ -0,0 +1,69 @@ +@/*************************************************************************** +@ * 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. +@ * +@ * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +@ * The AI-generated portions may be considered public domain (CC0-1.0) +@ * and not subject to the project's licence. The human contributor has +@ * reviewed and verified that the code is correct. +@ * +@ * SPDX-License-Identifier: MIT and CC0-1.0 +@ **************************************************************************/ +@ +@/**************************************************************************/ +@/* */ +@/* MODULE MANAGER RELEASE */ +@/* */ +@/* module_blob.S Cortex-R52/GNU */ +@/* 6.5.2 */ +@/* AUTHOR */ +@/* */ +@/* Frédéric Desbiens, Eclipse Foundation */ +@/* */ +@/* DESCRIPTION */ +@/* */ +@/* Carries the demonstration module into the manager image as data. */ +@/* */ +@/* The module is built as its own link unit and objcopied to a raw */ +@/* binary, which is included here verbatim. It has to be a separate */ +@/* link: the module library defines shims named after the ThreadX API */ +@/* entry points the kernel also defines, and in one link the shims win */ +@/* -- objects beat archive members -- so the manager's own service calls */ +@/* end up trapping into the module. */ +@/* */ +@/* Included as bytes rather than linked as objects, so the module's */ +@/* symbols never enter the manager's link at all. Nothing here is */ +@/* called: the manager finds the preamble at the start of the image and */ +@/* reaches everything else through that. */ +@/* */ +@/* A separate copy from the S32Z280 one, and identical to it: the two */ +@/* module examples are deliberately independent builds, and each names */ +@/* its own raw image through its own assembler include path. */ +@/* */ +@/**************************************************************************/ + + .section .module_blob, "a" + +@ 64-byte aligned, the PMSAv8-R granule, so the image starts where a region +@ can start. The linker script places this section at the module area base, +@ which is the address the module itself was linked for. + + .align 6 + + .global __demo_module_image + .global __demo_module_image_end + +__demo_module_image: + +@ demo_module.bin is produced by the fvp_demo_module.elf target. The +@ assembler finds it through an include path pointing at the build directory, +@ set in CMakeLists.txt -- .incbin searches the -I paths, not the source tree. + + .incbin "demo_module.bin" + +__demo_module_image_end: + + .align 6 diff --git a/ports_module/cortex_r52/gnu/example_build/fvp_baser_aemv8r/sample_threadx_module.c b/ports_module/cortex_r52/gnu/example_build/fvp_baser_aemv8r/sample_threadx_module.c new file mode 100644 index 000000000..e2fd2508f --- /dev/null +++ b/ports_module/cortex_r52/gnu/example_build/fvp_baser_aemv8r/sample_threadx_module.c @@ -0,0 +1,319 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* SAMPLE MODULE RELEASE */ +/* */ +/* sample_threadx_module.c Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frédéric Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* A module that exercises the protection boundary rather than */ +/* demonstrating features, for the Armv8-R AEM FVP. */ +/* */ +/* The S32Z280 copy of this file is the same module for the same port; */ +/* what differs is the two addresses at the bottom and the board named */ +/* here, so `diff` is the tool for telling whether the two have drifted. */ +/* */ +/* Four steps: */ +/* */ +/* 1. Writes and reads its own data, which must succeed. */ +/* 2. Makes a kernel call, which must succeed -- proving a module in */ +/* User mode can reach the kernel through the supervisor call */ +/* boundary and come back. */ +/* 3. Violates its protection in one of three ways the manager */ +/* selects, which must fault. */ +/* 4. Never reaches step 4, because step 3 terminates it. */ +/* */ +/* THE THREE VIOLATIONS. Two of them are the two aborts the hardware */ +/* distinguishes: reading the kernel's data is a DATA abort reported */ +/* through DFSR and DFAR, branching out of the code region is a */ +/* PREFETCH abort reported through IFSR and IFAR. The third writes a */ +/* granule of the SHARED area that the manager deliberately did not */ +/* grant, after writing and reading back every granule it did -- so it */ +/* is the shared-region machinery under test rather than the kernel's */ +/* own memory, and a grant that covered one granule too many is what it */ +/* is looking for. */ +/* */ +/* Steps 1 and 2 passing without step 3 faulting would mean the module */ +/* is running unprotected, which is the failure this example exists to */ +/* detect. A module that only ever touched its own memory would pass */ +/* identically with the MPU switched off. */ +/* */ +/* HOW PROGRESS GETS OUT. A module cannot print: the console belongs */ +/* to the board support package, outside every region a module owns, so */ +/* reaching it would fault as surely as step 3 does. So progress is */ +/* recorded twice -- in the module's own data, and in the first granule */ +/* of the shared area the manager granted it. */ +/* */ +/* Which of the two can be read depends on the board. On silicon a GDB */ +/* harness reads the module's own copy out of the data area the manager */ +/* allocated for it; the FVP has no such seam -- it exposes an Iris */ +/* server and no GDB stub -- so there only the shared copy is readable */ +/* and everything the run reports has to be reported by the image */ +/* itself. Both writes are kept on both boards deliberately: if the */ +/* shared write were the only one, a module that could not reach its own */ +/* data would still report progress. */ +/* */ +/* The shared address is a literal on this side. The module has no */ +/* loader to tell it anything and the manager deliberately knows no */ +/* symbol of the module, so the two agree by convention -- and the */ +/* manager checks that they do, against the linker's own symbol, rather */ +/* than trusting them to. */ +/* */ +/**************************************************************************/ + +#include "txm_module.h" + +/* Progress, recorded in two places. See the header: the shared copy is what + the manager reads, and the module's own copy is what proves it could write + its own data at all. */ + +#define MODULE_PROGRESS_OWN_DATA 0x00000001UL +#define MODULE_PROGRESS_KERNEL_CALL 0x00000002UL +#define MODULE_PROGRESS_ATTEMPTED_STEAL 0x00000004UL +#define MODULE_PROGRESS_SURVIVED_STEAL 0x00000008UL +#define MODULE_PROGRESS_ATTEMPTED_JUMP 0x00000010UL +#define MODULE_PROGRESS_SURVIVED_JUMP 0x00000020UL +#define MODULE_PROGRESS_SHARED_WROTE 0x00000040UL +#define MODULE_PROGRESS_ATTEMPTED_GAP 0x00000080UL +#define MODULE_PROGRESS_SURVIVED_GAP 0x00000100UL + +/* Which violation to commit, taken from the low byte of the module ID the + manager passes to the start thread. The rest of that word is left alone: the + preamble ships it as 0x52520001, so a manager that sets nothing still gets a + working data-abort test rather than a module that does nothing. */ + +#define MODULE_TEST_MASK 0x000000FFUL +#define MODULE_TEST_DATA_ABORT 0x00000001UL +#define MODULE_TEST_PREFETCH_ABORT 0x00000002UL +#define MODULE_TEST_SHARED_ABORT 0x00000003UL + +/* The shared status word, at the base of the module area. + + A literal address rather than anything reached through the GOT, because it is + not the module's own memory: it is memory the manager granted, and the module + has no channel through which to be told where it is. The same number is + FVP_MODULE_STATUS_BASE in platform.h and ORIGIN(MODULE) in link_module.lds; + the manager checks all three agree before it starts this module, so a + disagreement is a reported failure rather than a fault at the first write. + + MISRA C:2012 Rule 11.6 (conversion between an integer and a pointer to void) + is deliberately violated: an address agreed between two separately linked + images can only be written as a literal, and there is no conforming way to + express it. */ + +#define MODULE_STATUS_ADDRESS 0x003F0000UL + +#define MODULE_STATUS (*((volatile ULONG *) MODULE_STATUS_ADDRESS)) + +/* And the rest of the shared area, which exists to exercise the shared-region + machinery rather than to report anything. + + The manager may grant a module TXM_MODULE_MPU_SHARED_ENTRIES regions and one + grant only ever proves the first entry works, so the area holds one granule + per entry -- five granted, and a sixth that the manager never grants. The + ungranted one is index 2, which puts a granted granule on either side of it: + a limit register masked the wrong way, or a base off by a granule, leaks into + that gap from below or from above, and either way a module that can write it + was given more than was asked for. + + The mark for each granule goes at WORD 1, because word 0 of granule 0 is the + progress word above. Uniform across all six so the address the gap write + faults on is one expression on both sides of the agreement. */ + +#define MODULE_STATUS_GRANULE 0x40UL +#define MODULE_STATUS_GRANULES 6UL +#define MODULE_STATUS_UNGRANTED 2UL +#define MODULE_STATUS_MARK_OFFSET 4UL + +#define MODULE_SHARED_SIGNATURE 0x5A5A0000UL + +#define MODULE_SHARED_MARK(index) \ + (*((volatile ULONG *) (MODULE_STATUS_ADDRESS \ + + ((index) * MODULE_STATUS_GRANULE) \ + + MODULE_STATUS_MARK_OFFSET))) + +volatile ULONG module_progress; +volatile ULONG module_scratch[16]; + +/* An address the module has no business touching, used by step 3. + + The last protection granule below the module area, which on this map is + inside the manager's data region: that region is EL1 read/write and + execute-never, so a User-mode read of it is a permission fault and a + User-mode instruction fetch from it is one too. Both are what step 3 needs, + and both prove the KERNEL'S memory is what a module cannot reach -- which is + the property being demonstrated, rather than the absence of a mapping. + + Held in initialised data rather than written as a literal, deliberately and + unlike the status address above. The module reads it through its rebased + GOT, so the value arriving in DFAR or IFAR also proves the GOT was rewritten + and .data was copied. The manager knows the same number and checks it. */ + +volatile ULONG module_forbidden_address = 0x003EFFC0UL; + + +/* Declared as well as defined because the only caller is assembly: + txm_module_preamble.S names it with .extern and stores its offset in the + START entry-point word. An assembly caller supplies no prototype, so + without this the definition has external linkage and no visible + declaration -- prohibited by MISRA C:2012 Rule 8.4 and reported by + -Wmissing-prototypes. Same reason the board support has board.h. */ + +void demo_module_start(ULONG id); + + +void demo_module_start(ULONG id) +{ + ULONG i; + ULONG sum = 0UL; + ULONG shared_ok = 1UL; + + /* 1. The module's own data. If this faults, the data region is wrong and + nothing else in this file will be reached. */ + + for (i = 0UL; i < 16UL; i++) + { + module_scratch[i] = i * 3UL; + } + + for (i = 0UL; i < 16UL; i++) + { + sum += module_scratch[i]; + } + + if (sum == 360UL) /* 3 * (0 + 1 + ... + 15) */ + { + module_progress |= MODULE_PROGRESS_OWN_DATA; + MODULE_STATUS |= MODULE_PROGRESS_OWN_DATA; + } + + /* 2. A kernel call, which leaves User mode through the supervisor call + boundary and must come back. A sleep is used because it is the + simplest service with an observable effect and it yields, so the + scheduler runs a module thread and reloads its regions on the way + back -- exercising the region switch as well as the call. */ + + if (tx_thread_sleep(2UL) == TX_SUCCESS) + { + module_progress |= MODULE_PROGRESS_KERNEL_CALL; + MODULE_STATUS |= MODULE_PROGRESS_KERNEL_CALL; + } + + /* 3. The violation, and 4. the flag that says it was tolerated. Each is + marked before the access rather than after, because after is not + reached if the port is working. The SURVIVED flags are what the + manager fails on: they can only appear if the hardware allowed an + access it was configured to refuse. */ + + if ((id & MODULE_TEST_MASK) == MODULE_TEST_SHARED_ABORT) + { + /* Write every granule the manager granted, read all of them back, and + then write the one it did not grant. + + The readback matters as much as the write. A shared entry programmed + with the wrong base still accepts a store -- it just lands somewhere + else -- so a write that is never read back proves only that the core + did not object. Reading each granule's own mark out of its own + granule is what says the five entries describe five distinct + extents. */ + + for (i = 0UL; i < MODULE_STATUS_GRANULES; i++) + { + if (i != MODULE_STATUS_UNGRANTED) + { + MODULE_SHARED_MARK(i) = MODULE_SHARED_SIGNATURE | i; + } + } + + for (i = 0UL; i < MODULE_STATUS_GRANULES; i++) + { + if ((i != MODULE_STATUS_UNGRANTED) && + (MODULE_SHARED_MARK(i) != (MODULE_SHARED_SIGNATURE | i))) + { + shared_ok = 0UL; + } + } + + if (shared_ok != 0UL) + { + module_progress |= MODULE_PROGRESS_SHARED_WROTE; + MODULE_STATUS |= MODULE_PROGRESS_SHARED_WROTE; + } + + /* The gap. A WRITE rather than a read, so DFSR reports WnR set and the + fault cannot be confused with the read the data-abort passes do. It + lies between two granules this module was granted, so surviving it + means a grant covered a granule nobody asked for -- which is the + whole reason this pass exists. */ + + module_progress |= MODULE_PROGRESS_ATTEMPTED_GAP; + MODULE_STATUS |= MODULE_PROGRESS_ATTEMPTED_GAP; + + MODULE_SHARED_MARK(MODULE_STATUS_UNGRANTED) = + MODULE_SHARED_SIGNATURE | MODULE_STATUS_UNGRANTED; + + module_progress |= MODULE_PROGRESS_SURVIVED_GAP; + MODULE_STATUS |= MODULE_PROGRESS_SURVIVED_GAP; + } + else if ((id & MODULE_TEST_MASK) == MODULE_TEST_PREFETCH_ABORT) + { + /* Branch outside the code region: a prefetch abort, reported through + IFSR and IFAR. Nothing is executed at the target -- the fault is on + the fetch itself, so the thread never arrives. */ + + module_progress |= MODULE_PROGRESS_ATTEMPTED_JUMP; + MODULE_STATUS |= MODULE_PROGRESS_ATTEMPTED_JUMP; + + /* MISRA C:2012 Rule 11.1 (no conversion between a pointer to a function + and any other type) is deliberately violated here, and Rule 11.6 + (no conversion between an integer and a pointer to void) with it. + Provoking a fetch from an address that holds no function is the entire + purpose of these three lines; there is no conforming way to write it. */ + + ((void (*)(void)) module_forbidden_address)(); + + module_progress |= MODULE_PROGRESS_SURVIVED_JUMP; + MODULE_STATUS |= MODULE_PROGRESS_SURVIVED_JUMP; + } + else + { + /* Read outside the data region: a data abort, reported through DFSR and + DFAR. */ + + module_progress |= MODULE_PROGRESS_ATTEMPTED_STEAL; + MODULE_STATUS |= MODULE_PROGRESS_ATTEMPTED_STEAL; + + sum += *((volatile ULONG *) module_forbidden_address); + + module_progress |= MODULE_PROGRESS_SURVIVED_STEAL; + MODULE_STATUS |= MODULE_PROGRESS_SURVIVED_STEAL; + } + + /* Keep the compiler from discarding the read above. */ + + module_scratch[0] = sum; + + while (1) + { + (void) tx_thread_sleep(100UL); + } +} diff --git a/ports_module/cortex_r52/gnu/example_build/fvp_baser_aemv8r/sample_threadx_module_manager.c b/ports_module/cortex_r52/gnu/example_build/fvp_baser_aemv8r/sample_threadx_module_manager.c new file mode 100644 index 000000000..365dfecf9 --- /dev/null +++ b/ports_module/cortex_r52/gnu/example_build/fvp_baser_aemv8r/sample_threadx_module_manager.c @@ -0,0 +1,1624 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* MODULE MANAGER SAMPLE RELEASE */ +/* */ +/* sample_threadx_module_manager.c Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frédéric Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Loads the sample module four times, lets it misbehave every time, */ +/* and reports what the hardware did about it -- on the Armv8-R AEM */ +/* FVP, with no debugger and no person in the loop. */ +/* */ +/* This is the S32Z280 module demonstration turned into a regression. */ +/* The silicon version is judged by a human reading a console and by a */ +/* GDB harness that reads the module's memory between passes; neither */ +/* exists here. The model offers an Iris server and no GDB stub, so */ +/* the image has to judge itself and say so in one line the runner can */ +/* match. Everything below that differs from the silicon sample */ +/* differs for that reason. */ +/* */ +/* THE RESULT THIS EXAMPLE EXISTS TO PRODUCE IS THE FAULT. A module */ +/* that starts and runs proves the loader works; a module that is */ +/* stopped by the memory protection unit when it reaches outside its */ +/* own memory proves the port works. So the fault notification is not */ +/* an error path here, it is the expected outcome, and its absence is */ +/* the failure. */ +/* */ +/* TWO PASSES, because one proves nothing about relocation. The module */ +/* is position independent: it is linked against nominal addresses it */ +/* never runs at, and _gcc_setup rewrites its global offset table to */ +/* wherever the manager actually put it. A single run at the linked */ +/* address would exercise a rebase whose input and output are the same */ +/* number, and would look identical if the rebase did nothing at all. */ +/* */ +/* So pass 1 loads the blob where the linker placed it and pass 2 loads */ +/* a byte-for-byte copy of it from the staging area, with pass 1 still */ +/* holding its pool memory so that pass 2's data lands somewhere else */ +/* too. Both bases therefore differ between the passes, which is what */ +/* makes the comparison at the end mean something. */ +/* */ +/* THEN A THIRD PASS, which faults the other way. The two passes above */ +/* make the module read an address it does not own: a data abort, */ +/* reported through DFSR and DFAR. A module can equally leave its code */ +/* region, which is a prefetch abort reported through IFSR and IFAR and */ +/* arrives at the handler by a different vector. Both halves of the */ +/* port's fault path are therefore exercised, and neither is inferred */ +/* from the other. The third pass also runs after the first two have */ +/* been unloaded, which is the other half of what this file shows: a */ +/* module fault must leave the manager able to load and run the next */ +/* module. */ +/* */ +/* AND WHAT THE MODULE ACHIEVED IS READ BACK, not inferred. The manager */ +/* grants each pass a shared MPU region over one granule at a fixed */ +/* address and the module records its progress there. That is what */ +/* replaces the GDB harness, and it is what lets this file fail on the */ +/* two flags that matter -- SURVIVED_STEAL and SURVIVED_JUMP -- by name */ +/* rather than only on the absence of a fault. The two are the same */ +/* event seen from both ends, and a regression that showed one without */ +/* the other would be worth knowing about. */ +/* */ +/* AND A FOURTH PASS FOR THE SHARED REGIONS. The three above are each */ +/* granted one shared region -- the status granule -- which exercises */ +/* the first of the five shared entries the port provides and says */ +/* nothing about the other four. The fourth pass is granted all five, */ +/* one 64-byte granule each, and is NOT granted the granule that sits */ +/* between two of them. It writes every granule it was given, reads */ +/* every one of them back, and then writes the gap, which must fault. */ +/* */ +/* That shape is chosen against a specific defect. A limit register */ +/* masked the wrong way, or a base off by one granule, extends a region */ +/* past what was asked for -- and with the gap sandwiched between two */ +/* granted granules it is reachable from either side if that happens. */ +/* The readback matters as much as the write: a region programmed with */ +/* the wrong base accepts a store and puts it elsewhere, so five marks */ +/* read out of five granules is what says five distinct extents were */ +/* programmed rather than one of them five times. */ +/* */ +/* The same pass probes the two ways the manager refuses a grant, which */ +/* nothing had ever called: an unaligned address must come back */ +/* TXM_MODULE_ALIGNMENT_ERROR, and one grant past the entry count must */ +/* come back TX_NO_MEMORY. Both are checked by name. The order is not */ +/* free -- the entry-count check runs before the alignment check, so the */ +/* unaligned probe has to happen while entries remain. */ +/* */ +/* WHAT A GREEN RUN HERE DOES NOT PROVE. The model reports 32 EL1 MPU */ +/* regions. The Cortex-R52 TRM gives MPUIR.DREGION as 16, 20 or 24, so */ +/* 32 is not an architecturally permitted value for this core and the */ +/* model is the generic AEMv8-R rather than an R52. It is strictly more */ +/* permissive than every real part: this port needs seventeen regions, */ +/* which the S32Z280's twenty supply and a legal 16-region R52 does not, */ +/* and no result from this image can tell you that. The count is */ +/* reported below so the log says what it was rather than implying it. */ +/* */ +/**************************************************************************/ + +#include "tx_api.h" +#include "txm_module.h" +#include "console.h" +#include "platform.h" +#include "mpu.h" +#include "cache.h" + +/* For bsp_main, which entry.S calls and therefore never declares. Every + other example in the board support package includes this header for the + same reason; MISRA C:2012 Rule 8.4 wants the declaration visible at the + definition, and -Wmissing-prototypes reports it when it is not. */ + +#include "board.h" + +/* The fault information the abort vector captured. Declared here because the + module manager expands it into the port's fault handler through the + TXM_MODULE_MANAGER_FAULT_INFO macro rather than declaring it in a header, so an + application that wants to read it has to say so itself. */ + +extern TXM_MODULE_MANAGER_MEMORY_FAULT_INFO _txm_module_manager_memory_fault_info; + +/* Where the module image sits. Provided by the linker script, which places the + module's preamble first so this address is also the preamble address. */ + +extern unsigned char __module_image_start__; +extern unsigned char __module_image_end__; + +/* The second address the same blob is loaded from, so relocation can be shown + rather than assumed. Reserved by the linker script and left empty by it -- + see .module_stage in link_module.lds for why it is not pre-filled. */ + +extern unsigned char __module_stage_start__; +extern unsigned char __module_stage_end__; + +/* The shared status granule the module reports its progress through. */ + +extern unsigned char __module_status_start__; +extern unsigned char __module_status_end__; + +/* The kernel's own writable region, used to check that the address the module + is told to reach for really is memory it must not have. */ + +extern unsigned char __data_start__; +extern unsigned char __data_end__; + +/* The address the module is going to reach for and must not be allowed to have. + The value lives in the module's own initialised data, which is the point -- + the module reads it through its rebased GOT, so seeing it arrive in DFAR + proves the rebase and the .data copy both worked. Kept in step with + sample_threadx_module.c by hand, and checked at run time twice: that it is + what the module faulted on, and that it lies inside the kernel's data region + in the first place. An address in no region at all would fault too, and + would prove much less. */ + +#define MODULE_FORBIDDEN_ADDRESS 0x003EFFC0UL + +/* The shared status word. The same number is FVP_MODULE_STATUS_BASE in + platform.h, ORIGIN(MODULE) in link_module.lds and MODULE_STATUS_ADDRESS in + the module. Three spellings of one address, checked against the linker + symbol below rather than trusted. */ + +#define MODULE_STATUS_ADDRESS FVP_MODULE_STATUS_BASE +#define MODULE_STATUS_LENGTH FVP_MODULE_STATUS_SIZE + +/* The rest of the shared area, which is there to exercise the shared-region + machinery rather than to report anything. + + MODULE_STATUS_LENGTH is one granule and also the length of one grant. The + area is MODULE_STATUS_GRANULES of them: five the shared pass is granted, one + entry each, and MODULE_STATUS_UNGRANTED -- index 2, so that a granted granule + sits on either side of it -- which is never granted to anything. Both sides + of the agreement compute a granule's address the same way from the same base, + and each granule's mark goes at word 1 because word 0 of granule 0 is the + progress word. */ + +#define MODULE_STATUS_GRANULES FVP_MODULE_STATUS_GRANULES +#define MODULE_STATUS_UNGRANTED FVP_MODULE_STATUS_UNGRANTED +#define MODULE_STATUS_AREA_LENGTH (MODULE_STATUS_GRANULES * MODULE_STATUS_LENGTH) +#define MODULE_STATUS_MARK_OFFSET 4UL + +#define MODULE_SHARED_SIGNATURE 0x5A5A0000UL + +/* How many grants the shared pass makes, which must be every entry the port + provides -- granting fewer would leave an entry unexercised, and the point of + the pass is that all of them work. */ + +#define MODULE_SHARED_GRANTS (MODULE_STATUS_GRANULES - 1U) + +/* The two grants that must be refused on size, and the one that must not be. + + The top granule is the boundary case of the overflow guard: its inclusive end + is exactly 0xFFFFFFFF, so a guard written as (address + length) < address, or + one that tested the end against the top with the wrong comparison, would + refuse a perfectly legal grant. The wrapping grant starts at the same place + and asks for twice the room that is left. + + Neither address is ever programmed into the MPU: the guard probes run on an + instance that is loaded and unloaded without being started, so the accepted + grant is recorded in the instance and nothing more. That is deliberate -- + the top granule sits inside the 0x80000000..0xFFFFFFFF device region the BSP + maps at boot, and two enabled regions over one address is exactly the overlap + this image checks for everywhere else. */ + +#define MODULE_TOP_GRANULE_ADDRESS (0xFFFFFFFFUL - (TXM_MODULE_MPU_ALIGNMENT - 1UL)) +#define MODULE_TOP_GRANULE_LENGTH TXM_MODULE_MPU_ALIGNMENT +#define MODULE_WRAP_LENGTH (2UL * TXM_MODULE_MPU_ALIGNMENT) + +/* MISRA C:2012 Rule 11.6 is deliberately violated by the second of these: the + address is an agreement between two separately linked images and there is no + conforming way to express it. */ + +#define MODULE_GRANULE_ADDRESS(index) \ + (MODULE_STATUS_ADDRESS + ((index) * MODULE_STATUS_LENGTH)) + +#define MODULE_SHARED_MARK(index) \ + (*((volatile ULONG *) (MODULE_GRANULE_ADDRESS(index) \ + + MODULE_STATUS_MARK_OFFSET))) + +/* The progress bits the module sets, mirrored from sample_threadx_module.c. + The two SURVIVED flags can only ever be set if the hardware allowed an access + it was configured to refuse, so they are checked for by name. */ + +#define MODULE_PROGRESS_OWN_DATA 0x00000001UL +#define MODULE_PROGRESS_KERNEL_CALL 0x00000002UL +#define MODULE_PROGRESS_ATTEMPTED_STEAL 0x00000004UL +#define MODULE_PROGRESS_SURVIVED_STEAL 0x00000008UL +#define MODULE_PROGRESS_ATTEMPTED_JUMP 0x00000010UL +#define MODULE_PROGRESS_SURVIVED_JUMP 0x00000020UL +#define MODULE_PROGRESS_SHARED_WROTE 0x00000040UL +#define MODULE_PROGRESS_ATTEMPTED_GAP 0x00000080UL +#define MODULE_PROGRESS_SURVIVED_GAP 0x00000100UL + +#define MODULE_PROGRESS_SURVIVED (MODULE_PROGRESS_SURVIVED_STEAL | \ + MODULE_PROGRESS_SURVIVED_JUMP | \ + MODULE_PROGRESS_SURVIVED_GAP) + +/* Which violation a pass tells the module to commit. Written into the module + instance's application-defined ID after the load and before the start, because + that word is what the manager hands the module's start thread. The high half + is the fingerprint the preamble ships; only the low byte selects the test. */ + +#define MODULE_ID_BASE 0x52520000UL +#define MODULE_TEST_DATA_ABORT 0x00000001UL +#define MODULE_TEST_PREFETCH_ABORT 0x00000002UL +#define MODULE_TEST_SHARED_ABORT 0x00000003UL + +/* Memory the manager hands out to modules: object memory, and the data region a + module's own variables live in. It has to be outside every region a module is + given, or a module could reach another module's data. */ + +#ifndef MODULE_POOL_SIZE +#define MODULE_POOL_SIZE (16U * 1024U) +#endif + +/* In the module area, not in .bss. The manager carves a module's data out of + this pool, and that data is handed to the module as an MPU region -- so if the + pool lived in .bss it would sit inside the kernel's data region and the two + would overlap, which PMSAv8-R does not allow. */ + +static unsigned char module_pool[MODULE_POOL_SIZE] + __attribute__((aligned(64), section(".module_pool"))); + +/* The object pool, which is a separate allocation from the module pool above and + is not optional here. A module that runs in User mode needs a kernel stack + for the privileged side of each system call, and the manager allocates that + from this pool -- txm_module_manager_initialize deliberately leaves the pool + uncreated, so without this a User-mode module fails to start with + TX_NOT_AVAILABLE from deep inside the thread create. */ + +#ifndef MODULE_OBJECT_POOL_SIZE +#define MODULE_OBJECT_POOL_SIZE (8U * 1024U) +#endif + +static unsigned char module_object_pool[MODULE_OBJECT_POOL_SIZE] + __attribute__((aligned(64))); + +/* One instance per pass. Passes 1 and 2 are loaded at once for part of the run: + pass 1 is stopped but still holds its data allocation while pass 2 loads, which + is what pushes pass 2's data base somewhere different. */ + +#define MODULE_PASSES 4U +#define MODULE_RELOCATION_PASSES 2U + +static TXM_MODULE_INSTANCE demo_module[MODULE_PASSES]; + +/* What each pass produced. Recorded rather than printed as it happens, because + the comparison between the passes is the actual result and it cannot be made + until they have all run. */ + +typedef struct PASS_RESULT_STRUCT +{ + CHAR *pass_name; + ULONG pass_test; /* MODULE_TEST_*: which abort is expected */ + ULONG pass_load_status; + ULONG pass_share_status; + ULONG pass_start_status; + ULONG pass_stop_status; + ULONG pass_code_start; + ULONG pass_code_end; + ULONG pass_data_start; + ULONG pass_data_end; + ULONG pass_data_base; + ULONG pass_faults; + ULONG pass_captured; + ULONG pass_progress; + ULONG pass_expect_progress; + + /* The shared-region results. Only the shared pass fills these in, so the + judge reads them only for that pass -- zero is TX_SUCCESS and a pass that + never probed would otherwise read as one that probed and was refused + nothing. */ + + ULONG pass_shared_grants; /* grants that succeeded */ + ULONG pass_shared_count; /* entries the instance holds after */ + ULONG pass_align_status; /* refusing an unaligned grant */ + ULONG pass_exhaust_status; /* refusing one grant too many */ + ULONG pass_marks[MODULE_STATUS_GRANULES]; + + /* The address this pass must fault on. Per pass rather than one constant, + because the shared pass faults on the granule it was not granted and the + other three fault on the kernel's data. */ + + ULONG pass_expect_fault; + ULONG pass_fault_r9; + ULONG pass_dfsr; + ULONG pass_dfar; + ULONG pass_ifsr; + ULONG pass_ifar; + ULONG pass_spsr; + ULONG pass_code_location; + + /* What the notify callback was told, against what it should have been told. + Recorded as plain words rather than pointers so the console can print them + and a mismatch names both values. */ + + ULONG pass_notify_thread; + ULONG pass_notify_instance; + ULONG pass_expect_thread; + ULONG pass_expect_instance; +} PASS_RESULT; + +static PASS_RESULT pass_results[MODULE_PASSES]; + +/* The shared-grant size guards, which are about the manager and not about the + module. They need a LOADED instance and nothing else, so they get their own + -- loaded after the four passes are done with the pool, never started, and + unloaded again. Not folded into the shared pass because that pass grants + every entry the port has and has none to spare for a grant that is meant to + succeed, and not folded into one of the other three because a grant they + accepted would be programmed into the MPU when their module ran. */ + +typedef struct GUARD_RESULT_STRUCT +{ + ULONG guard_load_status; + ULONG guard_count_start; /* entries held before any probe */ + ULONG guard_zero_status; /* refusing a zero-length grant */ + ULONG guard_count_zero; /* entries held after it */ + ULONG guard_wrap_status; /* refusing a grant that runs off 4 GB */ + ULONG guard_count_wrap; + ULONG guard_top_status; /* accepting one that ends exactly at it */ + ULONG guard_count_top; + ULONG guard_unload_status; +} GUARD_RESULT; + +static TXM_MODULE_INSTANCE guard_module; +static GUARD_RESULT guard_result; + +/* What the fault handler saw. Read by the reporting thread after the module has + been terminated. */ + +static volatile ULONG fault_count; +static volatile ULONG fault_notify_thread; +static volatile ULONG fault_notify_instance; + +static TX_THREAD report_thread; +static unsigned char report_stack[2048] __attribute__((aligned(8))); + + +/**************************************************************************/ +/* Fault notification. */ +/* */ +/* Called by the module manager after it has terminated the offending */ +/* thread. Records rather than prints: this runs in Abort mode on the */ +/* Abort stack, which is a kilobyte and already carries the terminate */ +/* underneath this frame. A callback that printed would work here and */ +/* would still be the wrong shape to copy. */ +/* */ +/* Its two arguments are the point of the hook, so they are recorded and */ +/* checked rather than discarded: an application is being told WHICH */ +/* thread and WHICH module faulted, and a callback that fires with the */ +/* wrong pair is no more use than one that never fires. */ +/**************************************************************************/ + +static void module_fault_notify(TX_THREAD *thread_ptr, TXM_MODULE_INSTANCE *module_instance) +{ + fault_count++; + fault_notify_thread = (ULONG) thread_ptr; + fault_notify_instance = (ULONG) module_instance; +} + + +static void put_field(const char *label, unsigned long value) +{ + console_puts(label); + console_puthex(value); + console_puts("\n"); +} + + +/**************************************************************************/ +/* The shared status word, reached through the manager's load window. */ +/* */ +/* No kernel region covers the module area; region 16 does, and the */ +/* scheduler enables it for every thread that owns no module. This */ +/* thread owns none, so the window is open on it and these two functions */ +/* need no bracketing of their own -- which is the whole reason the */ +/* window is owned by the scheduler rather than by whoever calls. */ +/* */ +/* MISRA C:2012 Rule 11.6 is deliberately violated: the address is an */ +/* agreement between two separately linked images. */ +/**************************************************************************/ + +static void module_status_clear(void) +{ + ULONG granule; + + /* The WHOLE area, not just the progress word. The gap granule has to start + at a known zero, because "the module never wrote it" is one of the results + and a leftover mark from the previous pass would read as a module that + reached memory it was never granted -- or hide one that did. */ + + for (granule = 0UL; granule < MODULE_STATUS_GRANULES; granule++) + { + *((volatile ULONG *) MODULE_GRANULE_ADDRESS(granule)) = 0UL; + MODULE_SHARED_MARK(granule) = 0UL; + } +} + + +static ULONG module_status_read(void) +{ + return *((volatile ULONG *) MODULE_STATUS_ADDRESS); +} + + +/**************************************************************************/ +/* A byte copy, written out rather than called for. */ +/* */ +/* The manager links -nostartfiles and nothing else in this image reaches */ +/* for a C library, so calling memcpy would pull one in for a single */ +/* copy. The blob is under two kilobytes and this runs once. */ +/**************************************************************************/ + +static void copy_bytes(unsigned char *destination, const unsigned char *source, + unsigned long length) +{ + unsigned long i; + + for (i = 0UL; i < length; i++) + { + destination[i] = source[i]; + } +} + + +/**************************************************************************/ +/* The shared grants a pass gets, and the two ways a grant is refused. */ +/* */ +/* Every pass is granted the first granule, which is the progress word it */ +/* reports through. The shared pass is granted one granule per shared */ +/* entry the port provides, skipping the gap, because a single grant only */ +/* ever exercises the first of the five and this port has never run the */ +/* other four. */ +/* */ +/* It also probes the two ways a grant is refused, which can only be done */ +/* on a LOADED instance. ORDER MATTERS: the manager checks the entry */ +/* count BEFORE it checks alignment, so the unaligned probe has to happen */ +/* while entries remain -- after five grants it would come back */ +/* TX_NO_MEMORY and say nothing about alignment at all. */ +/* */ +/* Returns the first grant status that was not TX_SUCCESS, or TX_SUCCESS. */ +/**************************************************************************/ + +static UINT grant_shared_regions(TXM_MODULE_INSTANCE *instance, PASS_RESULT *result) +{ + UINT status; + UINT first_failure = TX_SUCCESS; + ULONG granule; + + if (result -> pass_test != MODULE_TEST_SHARED_ABORT) + { + /* The progress word, and nothing else. */ + + return txm_module_manager_external_memory_enable(instance, + (VOID *) &__module_status_start__, + MODULE_STATUS_LENGTH, + TXM_MODULE_ATTRIBUTE_READ_WRITE); + } + + /* Refused for alignment. One word into the first granule: an address + inside the area, so what is being tested is the 64-byte granule rule and + not the range. It must also consume no entry, which the five grants + below prove by all succeeding. */ + + result -> pass_align_status = + (ULONG) txm_module_manager_external_memory_enable( + instance, + (VOID *) (&__module_status_start__ + MODULE_STATUS_MARK_OFFSET), + MODULE_STATUS_LENGTH, + TXM_MODULE_ATTRIBUTE_READ_WRITE); + + /* One region per granule, every entry the port has, and never the gap. */ + + for (granule = 0UL; granule < MODULE_STATUS_GRANULES; granule++) + { + if (granule != MODULE_STATUS_UNGRANTED) + { + status = txm_module_manager_external_memory_enable( + instance, + (VOID *) (&__module_status_start__ + (granule * MODULE_STATUS_LENGTH)), + MODULE_STATUS_LENGTH, + TXM_MODULE_ATTRIBUTE_READ_WRITE); + + if (status == TX_SUCCESS) + { + result -> pass_shared_grants++; + } + else if (first_failure == TX_SUCCESS) + { + first_failure = status; + } + else + { + /* Already recorded; the first failure is the informative one. */ + } + } + } + + /* And one grant too many, which must be refused. Not cosmetic: the entry + written is TXM_MODULE_MPU_SHARED_INDEX plus the count, so a sixth grant + that got past the check would write one past the end of the region table + and into the instance fields that follow it. + + Aimed at the GAP, deliberately. It overlaps nothing, so a refusal costs + nothing -- and if the check ever failed, the gap would become a granted + region and the module would go on to survive writing it. The same defect + would then be reported twice, once as this status and once by name as + MODULE_PROGRESS_SURVIVED_GAP, rather than only as a status nobody reads. */ + + result -> pass_exhaust_status = + (ULONG) txm_module_manager_external_memory_enable( + instance, + (VOID *) (&__module_status_start__ + + (MODULE_STATUS_UNGRANTED * MODULE_STATUS_LENGTH)), + MODULE_STATUS_LENGTH, + TXM_MODULE_ATTRIBUTE_READ_WRITE); + + result -> pass_shared_count = instance -> txm_module_instance_shared_memory_count; + + return first_failure; +} + + +/**************************************************************************/ +/* The size guards on a shared grant. */ +/* */ +/* A grant of no bytes and a grant whose inclusive end wraps past the top */ +/* of the address space both used to compute a limit BELOW the base, */ +/* program it, return TX_SUCCESS and spend one of the five entries on a */ +/* region the hardware cannot honour. Both must now be refused as */ +/* TX_SIZE_ERROR, and -- the half that a status code alone does not say -- */ +/* must leave the entry count exactly where they found it, because an */ +/* entry spent on a refused grant is one the caller can never get back. */ +/* */ +/* The third probe is the one that must SUCCEED: a grant ending exactly */ +/* at 0xFFFFFFFF is legal, and a guard that refused it would be a new bug */ +/* in place of the old one. It is checked last so that the count it does */ +/* move is unambiguous. */ +/* */ +/* Loaded here and unloaded below without ever being started, so nothing */ +/* these probes accept is programmed into an MPU region. See the comment */ +/* on MODULE_TOP_GRANULE_ADDRESS for why that matters. */ +/**************************************************************************/ + +static void run_guard_probes(VOID *location) +{ + GUARD_RESULT *result = &guard_result; + TXM_MODULE_INSTANCE *instance = &guard_module; + + result -> guard_load_status = (ULONG) txm_module_manager_in_place_load(instance, + "shared-grant guards", + location); + + if (result -> guard_load_status != (ULONG) TX_SUCCESS) + { + return; + } + + result -> guard_count_start = instance -> txm_module_instance_shared_memory_count; + + /* No bytes at all, at an address that is otherwise perfectly grantable -- + the progress granule every other pass is given. So what is refused is + the length and nothing else. */ + + result -> guard_zero_status = + (ULONG) txm_module_manager_external_memory_enable( + instance, + (VOID *) &__module_status_start__, + 0UL, + TXM_MODULE_ATTRIBUTE_READ_WRITE); + + result -> guard_count_zero = instance -> txm_module_instance_shared_memory_count; + + /* Twice the room left above the base, so the inclusive end wraps to a low + address. Aligned, so again it is the length that is being refused. */ + + result -> guard_wrap_status = + (ULONG) txm_module_manager_external_memory_enable( + instance, + (VOID *) MODULE_TOP_GRANULE_ADDRESS, + MODULE_WRAP_LENGTH, + TXM_MODULE_ATTRIBUTE_READ_WRITE); + + result -> guard_count_wrap = instance -> txm_module_instance_shared_memory_count; + + /* And the boundary: the same base, asking for exactly the room there is. */ + + result -> guard_top_status = + (ULONG) txm_module_manager_external_memory_enable( + instance, + (VOID *) MODULE_TOP_GRANULE_ADDRESS, + MODULE_TOP_GRANULE_LENGTH, + TXM_MODULE_ATTRIBUTE_READ_WRITE); + + result -> guard_count_top = instance -> txm_module_instance_shared_memory_count; + + /* Unloaded, not stopped: it was never started. Recorded rather than + discarded, because a module that will not unload holds the pool the + nothing-after-it would need. */ + + result -> guard_unload_status = (ULONG) txm_module_manager_unload(instance); +} + + +/**************************************************************************/ +/* One pass: load the blob from a given address, grant it the shared */ +/* granules it is entitled to, start it, wait for the fault it is written */ +/* to provoke, and stop it. */ +/* */ +/* The module is left loaded. Its data allocation is what moves the next */ +/* pass's data base, and releasing it here would defeat half the test. */ +/**************************************************************************/ + +/* name is CHAR * and not const CHAR *, because txm_module_manager_in_place_load + takes it that way -- the manager stores the pointer in the instance and the API + has never promised not to write through it. */ + +static void run_one_pass(UINT index, CHAR *name, VOID *location, ULONG test) +{ + PASS_RESULT *result = &pass_results[index]; + TXM_MODULE_INSTANCE *instance = &demo_module[index]; + unsigned int waited; + ULONG granule; + + result -> pass_name = name; + result -> pass_test = test; + + /* What the module should manage before the hardware stops it: its own data, + a kernel call, and the attempt -- plus, for the shared pass, the five + granules it wrote and read back on the way. Never a SURVIVED bit; that + one is the failure. + + The address it must fault on goes with it, because the three tests do not + share one. Two of them reach into the kernel's data; the shared pass + writes the mark word of the granule it was not granted, and that address + is computed here exactly as the module computes it. */ + + if (test == MODULE_TEST_SHARED_ABORT) + { + result -> pass_expect_progress = MODULE_PROGRESS_OWN_DATA + | MODULE_PROGRESS_KERNEL_CALL + | MODULE_PROGRESS_SHARED_WROTE + | MODULE_PROGRESS_ATTEMPTED_GAP; + + result -> pass_expect_fault = MODULE_GRANULE_ADDRESS(MODULE_STATUS_UNGRANTED) + + MODULE_STATUS_MARK_OFFSET; + } + else if (test == MODULE_TEST_PREFETCH_ABORT) + { + result -> pass_expect_progress = MODULE_PROGRESS_OWN_DATA + | MODULE_PROGRESS_KERNEL_CALL + | MODULE_PROGRESS_ATTEMPTED_JUMP; + + result -> pass_expect_fault = MODULE_FORBIDDEN_ADDRESS; + } + else + { + result -> pass_expect_progress = MODULE_PROGRESS_OWN_DATA + | MODULE_PROGRESS_KERNEL_CALL + | MODULE_PROGRESS_ATTEMPTED_STEAL; + + result -> pass_expect_fault = MODULE_FORBIDDEN_ADDRESS; + } + + /* Cleared before the module starts, so a fault or a progress bit counted + here belongs to this pass and not the previous one. */ + + fault_count = 0UL; + fault_notify_thread = 0UL; + fault_notify_instance = 0UL; + module_status_clear(); + + result -> pass_load_status = (ULONG) txm_module_manager_in_place_load(instance, name, location); + + if (result -> pass_load_status != (ULONG) TX_SUCCESS) + { + return; + } + + /* Read from the instance rather than computed here. Where the code ended up + is what the manager decided, and the whole point of the comparison at the + end is to check the module against the manager's own numbers. + + Recorded HERE, immediately after the load and before anything that can + fail, because the load is what decided them. Taken any later, a pass that + failed to be granted its shared regions would carry zeros into the overlap + comparison at the end of the run -- and zero against zero overlaps, so a + grant failure was reported a second time as "its code and data regions + overlap", which is not true and points at the wrong thing. */ + + result -> pass_code_start = (ULONG) instance -> txm_module_instance_code_start; + result -> pass_code_end = (ULONG) instance -> txm_module_instance_code_end; + result -> pass_data_start = (ULONG) instance -> txm_module_instance_data_start; + result -> pass_data_end = (ULONG) instance -> txm_module_instance_data_end; + result -> pass_data_base = (ULONG) instance -> txm_module_instance_module_data_base_address; + + /* The shared granules the module reports through, and for the shared pass + every other entry as well. Granted while the module is LOADED and before + it is STARTED, which is the only window the manager accepts, and granted + per pass because each pass is its own instance with its own region table + -- an instance is memset by the load, so nothing carries over. */ + + result -> pass_share_status = (ULONG) grant_shared_regions(instance, result); + + if (result -> pass_share_status != (ULONG) TX_SUCCESS) + { + return; + } + + /* Which violation this pass provokes. Written after the load, which is what + filled the field in from the preamble, and before the start, which is what + hands it to the module's start thread. */ + + instance -> txm_module_instance_application_module_id = MODULE_ID_BASE | test; + + /* What the notify callback must be told, recorded before the module runs so + the comparison afterwards is against an expectation and not against + whatever the callback happened to write. */ + + result -> pass_expect_thread = (ULONG) &(instance -> txm_module_instance_start_stop_thread); + result -> pass_expect_instance = (ULONG) instance; + + result -> pass_start_status = (ULONG) txm_module_manager_start(instance); + + if (result -> pass_start_status != (ULONG) TX_SUCCESS) + { + return; + } + + /* Wait for the abort vector to capture a fault belonging to THIS pass. + + The captured fault info is waited on rather than the notify callback, even + though the callback works. The capture happens in the abort vector before + anything else runs, so it is the earliest and most direct evidence that a + fault occurred; the callback is a later consequence of the same event, and + this file checks it separately. Waiting on the earlier of the two means a + regression in the callback path shows up as "notified 0" next to a + captured fault, rather than as "no fault occurred" -- which is the opposite + of the truth. + + Attribution is by thread pointer: each pass has its own module instance and + therefore its own start thread, so a captured fault naming this pass's + thread cannot be a leftover from the previous pass. */ + + waited = 0U; + while ((_txm_module_manager_memory_fault_info.txm_module_manager_memory_fault_info_thread_ptr + != &(instance -> txm_module_instance_start_stop_thread)) && + (waited < 50U)) + { + tx_thread_sleep(2UL); + waited++; + } + + if (_txm_module_manager_memory_fault_info.txm_module_manager_memory_fault_info_thread_ptr + == &(instance -> txm_module_instance_start_stop_thread)) + { + result -> pass_captured = 1UL; + result -> pass_dfsr = _txm_module_manager_memory_fault_info.txm_module_manager_memory_fault_info_dfsr; + result -> pass_dfar = _txm_module_manager_memory_fault_info.txm_module_manager_memory_fault_info_dfar; + result -> pass_ifsr = _txm_module_manager_memory_fault_info.txm_module_manager_memory_fault_info_ifsr; + result -> pass_ifar = _txm_module_manager_memory_fault_info.txm_module_manager_memory_fault_info_ifar; + result -> pass_spsr = _txm_module_manager_memory_fault_info.txm_module_manager_memory_fault_info_spsr; + result -> pass_fault_r9 = _txm_module_manager_memory_fault_info.txm_module_manager_memory_fault_info_r9; + result -> pass_code_location = (ULONG) _txm_module_manager_memory_fault_info.txm_module_manager_memory_fault_info_code_location; + } + + /* What the module reached, and what the notify callback saw. Both read + after the wait above, so what ran is recorded and what did not shows as + zero. The status word is read while THIS pass is still the last thing to + have written it, which is the same discipline the silicon harness needs + for a different reason: there, the byte pool reuses a freed block and a + later pass's data lands where an earlier one's was. */ + + result -> pass_progress = module_status_read(); + result -> pass_faults = fault_count; + result -> pass_notify_thread = fault_notify_thread; + result -> pass_notify_instance = fault_notify_instance; + + /* Every granule's mark, granted or not. The granted ones say the module + wrote and read back the granule it meant to, which is what proves five + distinct entries were programmed rather than one entry five times; the + gap's says whether it stayed untouched. Read here, while this pass is + still the last thing to have written the area. */ + + for (granule = 0UL; granule < MODULE_STATUS_GRANULES; granule++) + { + result -> pass_marks[granule] = MODULE_SHARED_MARK(granule); + } + + /* Stopped, not unloaded. The fault terminated the module's start thread but + left the module STARTED, and unload refuses anything that is not LOADED or + STOPPED -- so this is required, not tidiness. */ + + result -> pass_stop_status = (ULONG) txm_module_manager_stop(instance); +} + + +static void report_one_pass(const PASS_RESULT *result) +{ + console_puts("\n--- "); + console_puts(result -> pass_name); + console_puts(" ---\n"); + + console_puts(" expected abort = "); + if (result -> pass_test == MODULE_TEST_PREFETCH_ABORT) + { + console_puts("prefetch (IFSR/IFAR)\n"); + } + else if (result -> pass_test == MODULE_TEST_SHARED_ABORT) + { + console_puts("data (DFSR/DFAR), writing an ungranted shared granule\n"); + } + else + { + console_puts("data (DFSR/DFAR)\n"); + } + + put_field(" load status = ", result -> pass_load_status); + put_field(" share status = ", result -> pass_share_status); + put_field(" start status = ", result -> pass_start_status); + put_field(" stop status = ", result -> pass_stop_status); + put_field(" code region = ", result -> pass_code_start); + put_field(" .. to = ", result -> pass_code_end); + put_field(" data region = ", result -> pass_data_start); + put_field(" .. to = ", result -> pass_data_end); + put_field(" data base (r9) = ", result -> pass_data_base); + put_field(" fault captured = ", result -> pass_captured); + put_field(" module progress = ", result -> pass_progress); + put_field(" should be = ", result -> pass_expect_progress); + put_field(" fault address = ", result -> pass_expect_fault); + put_field(" notify callbacks = ", result -> pass_faults); + put_field(" notified thread = ", result -> pass_notify_thread); + put_field(" should be = ", result -> pass_expect_thread); + put_field(" notified module = ", result -> pass_notify_instance); + put_field(" should be = ", result -> pass_expect_instance); + put_field(" r9 at the fault = ", result -> pass_fault_r9); + put_field(" DFSR = ", result -> pass_dfsr); + put_field(" DFAR = ", result -> pass_dfar); + put_field(" IFSR = ", result -> pass_ifsr); + put_field(" IFAR = ", result -> pass_ifar); + put_field(" SPSR = ", result -> pass_spsr); + put_field(" faulting pc = ", result -> pass_code_location); + + /* Meaningful for a data abort, where the module faulted inside its own code. + A prefetch abort faults ON the address it branched to, so the faulting pc + is outside the module and the difference is not an offset into it. */ + + if (result -> pass_test != MODULE_TEST_PREFETCH_ABORT) + { + put_field(" pc - code base = ", result -> pass_code_location - result -> pass_code_start); + } + + /* The shared-region half, reported only by the pass that produces it. */ + + if (result -> pass_test == MODULE_TEST_SHARED_ABORT) + { + ULONG granule; + + put_field(" shared grants = ", result -> pass_shared_grants); + put_field(" should be = ", (unsigned long) MODULE_SHARED_GRANTS); + put_field(" entries held = ", result -> pass_shared_count); + put_field(" unaligned grant = ", result -> pass_align_status); + put_field(" should be = ", (unsigned long) TXM_MODULE_ALIGNMENT_ERROR); + put_field(" one grant too many = ", result -> pass_exhaust_status); + put_field(" should be = ", (unsigned long) TX_NO_MEMORY); + + for (granule = 0UL; granule < MODULE_STATUS_GRANULES; granule++) + { + if (granule == MODULE_STATUS_UNGRANTED) + { + put_field(" gap granule mark = ", result -> pass_marks[granule]); + put_field(" should be = ", 0UL); + } + else + { + put_field(" granule mark = ", result -> pass_marks[granule]); + put_field(" should be = ", MODULE_SHARED_SIGNATURE | granule); + } + } + } +} + + +/**************************************************************************/ +/* Per-pass verdict. Returns the number of failures it found. */ +/**************************************************************************/ + +static UINT judge_one_pass(const PASS_RESULT *result) +{ + if ((result -> pass_load_status != (ULONG) TX_SUCCESS) || + (result -> pass_share_status != (ULONG) TX_SUCCESS) || + (result -> pass_start_status != (ULONG) TX_SUCCESS)) + { + console_puts("FAIL "); + console_puts(result -> pass_name); + console_puts(": did not load, share and start\n"); + return 1U; + } + + /* First, and named explicitly: the module must not have survived what it + was told to attempt. This is the one result that means the protection + did not hold, and it is checked before anything else so that a run in + which the MPU did nothing says so in those words rather than through + some downstream symptom. */ + + if ((result -> pass_progress & MODULE_PROGRESS_SURVIVED) != 0UL) + { + console_puts("FAIL "); + console_puts(result -> pass_name); + console_puts(": the module SURVIVED its violation -- it is not protected\n"); + return 1U; + } + + if (result -> pass_captured == 0UL) + { + console_puts("FAIL "); + console_puts(result -> pass_name); + console_puts(": reached outside its memory and was not stopped\n"); + return 1U; + } + + /* What it did manage, from the shared granule. A module that faulted + without having read its own data or made a kernel call faulted for the + wrong reason, and the fault alone would not have said so. */ + + if (result -> pass_progress != result -> pass_expect_progress) + { + console_puts("FAIL "); + console_puts(result -> pass_name); + console_puts(": did not reach the point it was supposed to fault at\n"); + return 1U; + } + + /* r9 is the module's PIC base and the manager seeded it from the thread + entry info. If the value captured at the fault is not the data base the + manager handed out, the seeding is wrong and every data reference the + module made went somewhere unintended. */ + + if (result -> pass_fault_r9 != result -> pass_data_base) + { + console_puts("FAIL "); + console_puts(result -> pass_name); + console_puts(": r9 was not the module's data base\n"); + return 1U; + } + + /* A fault from anywhere but User mode is not this test passing: the module + runs unprivileged, so a privileged fault means the fault came from the + kernel and something else is wrong. */ + + if ((result -> pass_spsr & 0x1FUL) != 0x10UL) + { + console_puts("FAIL "); + console_puts(result -> pass_name); + console_puts(": faulted, but not from User mode\n"); + return 1U; + } + + /* The module got this address out of its own initialised data, through its + rebased GOT. Any other value means it faulted somewhere unintended -- + most likely on its own data, which is what a bad rebase looks like. + + Which register carries it depends on the abort: a data abort reports the + address it tried to touch in DFAR, a prefetch abort reports the address it + tried to fetch in IFAR. Checking the wrong one of the two passes for a + stale value left by an earlier fault, which is why this is selected on the + expected type rather than on whichever register happens to be non-zero. */ + + if (((result -> pass_test == MODULE_TEST_PREFETCH_ABORT) + ? result -> pass_ifar : result -> pass_dfar) != result -> pass_expect_fault) + { + console_puts("FAIL "); + console_puts(result -> pass_name); + console_puts(": faulted at the wrong address, so .data or the GOT is wrong\n"); + return 1U; + } + + /* The shared-region results, for the one pass that produces them. Checked + after the progress word above, so a pass that never got as far as the + granules is reported as that rather than as a grant problem. */ + + if (result -> pass_test == MODULE_TEST_SHARED_ABORT) + { + ULONG granule; + + /* Every entry the port provides, granted. Fewer means an entry past + the first is not usable, which is the state this port was in before + this pass existed. */ + + if (result -> pass_shared_grants != (ULONG) MODULE_SHARED_GRANTS) + { + console_puts("FAIL "); + console_puts(result -> pass_name); + console_puts(": not every shared entry could be granted\n"); + return 1U; + } + + if (result -> pass_shared_count != (ULONG) TXM_MODULE_MPU_SHARED_ENTRIES) + { + console_puts("FAIL "); + console_puts(result -> pass_name); + console_puts(": the instance does not hold the entries it granted\n"); + return 1U; + } + + /* An unaligned grant must be refused BY NAME. Accepting it would not + fault: the low six bits of PRBAR are the shareability, permission and + execute-never fields, so an under-aligned base silently changes what + the region permits instead of where it is. */ + + if (result -> pass_align_status != (ULONG) TXM_MODULE_ALIGNMENT_ERROR) + { + console_puts("FAIL "); + console_puts(result -> pass_name); + console_puts(": an unaligned shared grant was not refused as such\n"); + return 1U; + } + + if (result -> pass_exhaust_status != (ULONG) TX_NO_MEMORY) + { + console_puts("FAIL "); + console_puts(result -> pass_name); + console_puts(": one grant too many was not refused\n"); + return 1U; + } + + /* And what the module actually managed to write where. Each granted + granule must hold its own mark -- a region programmed with the wrong + base accepts the store and puts it somewhere else -- and the gap must + still hold the zero the manager left in it. */ + + for (granule = 0UL; granule < MODULE_STATUS_GRANULES; granule++) + { + if (granule == MODULE_STATUS_UNGRANTED) + { + if (result -> pass_marks[granule] != 0UL) + { + console_puts("FAIL "); + console_puts(result -> pass_name); + console_puts(": the ungranted granule was written -- a grant covered too much\n"); + return 1U; + } + } + else if (result -> pass_marks[granule] != (MODULE_SHARED_SIGNATURE | granule)) + { + console_puts("FAIL "); + console_puts(result -> pass_name); + console_puts(": a granted granule does not hold its own mark\n"); + return 1U; + } + else + { + /* This granule is as it should be. */ + } + } + } + + /* The notify callback is a public API of the module manager, so it is + checked and not merely reported. Zero here with a captured fault above + means the fault path reached the hardware's evidence and never reached the + application: on this port that used to be the case for every fault, + because the shared fault handler terminates the offending thread before + calling the hook and the terminate only returns if the abort vector has + told the kernel it is inside an exception. More than one means a single + violation was reported twice. */ + + if (result -> pass_faults != 1UL) + { + console_puts("FAIL "); + console_puts(result -> pass_name); + console_puts(": the fault-notify callback did not run exactly once\n"); + return 1U; + } + + /* Being told that something faulted is not the service; being told which + thread and which module is. */ + + if ((result -> pass_notify_thread != result -> pass_expect_thread) || + (result -> pass_notify_instance != result -> pass_expect_instance)) + { + console_puts("FAIL "); + console_puts(result -> pass_name); + console_puts(": notified about the wrong thread or module\n"); + return 1U; + } + + console_puts("PASS "); + console_puts(result -> pass_name); + console_puts(": ran, faulted in User mode at the forbidden address, and was reported\n"); + + return 0U; +} + + +/**************************************************************************/ +/* The size guards, reported and judged. Returns failures found. */ +/**************************************************************************/ + +static UINT report_and_judge_guards(void) +{ + const GUARD_RESULT *result = &guard_result; + + console_puts("\n--- shared-grant size guards ---\n"); + + put_field(" load status = ", result -> guard_load_status); + put_field(" entries at start = ", result -> guard_count_start); + put_field(" zero length = ", result -> guard_zero_status); + put_field(" should be = ", (unsigned long) TX_SIZE_ERROR); + put_field(" entries after = ", result -> guard_count_zero); + put_field(" wrapping end = ", result -> guard_wrap_status); + put_field(" should be = ", (unsigned long) TX_SIZE_ERROR); + put_field(" entries after = ", result -> guard_count_wrap); + put_field(" ends at 0xFFFFFFFF = ", result -> guard_top_status); + put_field(" should be = ", (unsigned long) TX_SUCCESS); + put_field(" entries after = ", result -> guard_count_top); + put_field(" unload status = ", result -> guard_unload_status); + + if (result -> guard_load_status != (ULONG) TX_SUCCESS) + { + console_puts("FAIL shared-grant guards: the probe module did not load\n"); + return 1U; + } + + if (result -> guard_count_start != 0UL) + { + console_puts("FAIL shared-grant guards: a fresh instance already held entries\n"); + return 1U; + } + + if (result -> guard_zero_status != (ULONG) TX_SIZE_ERROR) + { + console_puts("FAIL shared-grant guards: a zero-length grant was not refused as a size error\n"); + return 1U; + } + + if (result -> guard_wrap_status != (ULONG) TX_SIZE_ERROR) + { + console_puts("FAIL shared-grant guards: a grant running off the top of memory was not refused\n"); + return 1U; + } + + /* The half a status code does not say. A refused grant that still spent an + entry would report exactly the same two codes above and quietly cost the + caller one of the five, with nothing to show for it. */ + + if ((result -> guard_count_zero != 0UL) || (result -> guard_count_wrap != 0UL)) + { + console_puts("FAIL shared-grant guards: a refused grant consumed an entry\n"); + return 1U; + } + + /* And the boundary the guard must not overreach into. */ + + if (result -> guard_top_status != (ULONG) TX_SUCCESS) + { + console_puts("FAIL shared-grant guards: a grant ending at 0xFFFFFFFF was refused\n"); + return 1U; + } + + if (result -> guard_count_top != 1UL) + { + console_puts("FAIL shared-grant guards: the accepted grant did not consume exactly one entry\n"); + return 1U; + } + + if (result -> guard_unload_status != (ULONG) TX_SUCCESS) + { + console_puts("FAIL shared-grant guards: the probe module did not unload\n"); + return 1U; + } + + console_puts("PASS shared-grant guards: empty and wrapping grants refused, the boundary grant accepted\n"); + + return 0U; +} + + +/**************************************************************************/ +/* The manager thread. */ +/**************************************************************************/ + +static void manager_entry(ULONG input) +{ + UINT status; + UINT i; + unsigned long blob_size; + ULONG offset_0; + ULONG offset_1; + UINT failures = 0U; + + (void) input; + + /* Every manager call happens here, in a thread, and not in + tx_application_define. Loading a module takes the manager's mutex, and a + service that can block cannot be called before the scheduler runs. */ + + /* ------------------------------------------------------------------ + What the platform actually provides. Reported before anything is + loaded, because a shortfall here explains every failure below it. + ------------------------------------------------------------------ */ + + put_field("MPUIR regions available = ", (unsigned long) mpu_region_count()); + put_field("regions this port needs = ", (unsigned long) MPU_MODULE_REGIONS_REQUIRED); + put_field("D-cache line bytes = ", cache_dcache_line_bytes()); + + if (mpu_region_count() < MPU_MODULE_REGIONS_REQUIRED) + { + console_puts("FAIL the implementation has too few MPU regions for this port\n"); + failures++; + } + + /* The three spellings of the shared status address, and the forbidden + address, checked rather than trusted. Both are constants agreed between + separately linked images, and a disagreement in either would present as a + module faulting somewhere unexpected -- which is exactly what the pass + verdicts are trying to distinguish. */ + + if ((unsigned long) &__module_status_start__ != MODULE_STATUS_ADDRESS) + { + console_puts("FAIL the linker put the status word somewhere the module will not look\n"); + failures++; + } + + if ((unsigned long) (&__module_status_end__ - &__module_status_start__) + < MODULE_STATUS_AREA_LENGTH) + { + console_puts("FAIL the status area is smaller than the granules granted over it\n"); + failures++; + } + + if ((MODULE_FORBIDDEN_ADDRESS < (unsigned long) &__data_start__) || + (MODULE_FORBIDDEN_ADDRESS >= (unsigned long) &__data_end__)) + { + /* The point of the test is that a module cannot reach the KERNEL'S + memory. An address in no region at all would fault too, and would + prove much less, so the address is checked to be inside the kernel's + writable region before anything relies on the fault it causes. */ + + console_puts("FAIL the forbidden address is not inside the kernel's data region\n"); + failures++; + } + + console_puts("\nM1 initialize\n"); + status = txm_module_manager_initialize((VOID *) module_pool, MODULE_POOL_SIZE); + + put_field("initialize = ", status); + put_field("ready = ", (unsigned long) _txm_module_manager_ready); + + /* The pool the module's kernel stacks come from. See module_object_pool. */ + + status = txm_module_manager_object_pool_create((VOID *) module_object_pool, + MODULE_OBJECT_POOL_SIZE); + + put_field("object pool create = ", status); + + /* Registered before anything is loaded, so there is no window in which a + module could fault with nobody listening. */ + + console_puts("M2 fault notify\n"); + txm_module_manager_memory_fault_notify(module_fault_notify); + + /* The copy that makes pass 2 a relocation test. The staging area is left + empty by the linker on purpose: if the blob were already there, a failure + to copy would be invisible because the right bytes would be present. */ + + blob_size = (unsigned long) (&__module_image_end__ - &__module_image_start__); + + console_puts("M3 staging the blob\n"); + put_field(" blob size = ", blob_size); + put_field(" from = ", (unsigned long) &__module_image_start__); + put_field(" to = ", (unsigned long) &__module_stage_start__); + + if (blob_size > (unsigned long) (&__module_stage_end__ - &__module_stage_start__)) + { + /* Reported rather than allowed to overrun. The staging area is a fixed + size in the linker script and the module is free to grow. */ + + console_puts("FAIL the module image does not fit the staging area\n"); + failures++; + } + else + { + copy_bytes(&__module_stage_start__, &__module_image_start__, blob_size); + + /* Those were data writes to memory that is about to be fetched as + instructions, and the module area is mapped Normal write-back. So the + copied bytes may sit in dirty D-cache lines while the instruction + side, which is not coherent with the D cache on this core, fetches + whatever main memory still holds. Clean the range so memory is + correct, then invalidate the I cache so no stale line from a previous + image can be served. + + Not a precaution the passing run justifies: a cold I cache over a + never-executed address happens to work, and keeps happening to work + until the staging area is reused or an eviction lands differently. + Any loader that copies code owes this pair. */ + + cache_clean_range(&__module_stage_start__, blob_size); + cache_invalidate_icache_all(); + + console_puts("M4 pass 1, at the linked address\n"); + run_one_pass(0U, "linked address, data abort", (VOID *) &__module_image_start__, + MODULE_TEST_DATA_ABORT); + + console_puts("M5 pass 2, relocated\n"); + run_one_pass(1U, "relocated, data abort", (VOID *) &__module_stage_start__, + MODULE_TEST_DATA_ABORT); + + /* Both relocation passes are done with their memory now. Unloaded here + rather than at the end, so that the pass below is a load that follows + two faults and two unloads -- which is the state a manager is in after + a module has misbehaved, and the state the next load has to work in. */ + + for (i = 0U; i < MODULE_RELOCATION_PASSES; i++) + { + (void) txm_module_manager_unload(&demo_module[i]); + } + + /* The other abort type, from the staging area so that it is also a + relocated module: the address arriving in IFAR came out of the + module's own initialised data through its rebased GOT, exactly as DFAR + does above. */ + + console_puts("M6 pass 3, prefetch abort\n"); + run_one_pass(2U, "relocated, prefetch abort", (VOID *) &__module_stage_start__, + MODULE_TEST_PREFETCH_ABORT); + + (void) txm_module_manager_unload(&demo_module[2]); + + /* The shared-region pass. Granted every entry the port provides, one + granule each, and never the granule between two of them -- which it + then writes. This is the only pass that exercises a shared entry + past the first, the granule-alignment refusal, and what happens when + the entries run out; the three passes above grant one region each and + would look identical if four of the five entries did not work. */ + + console_puts("M7 pass 4, shared regions\n"); + run_one_pass(3U, "relocated, shared-region gap", (VOID *) &__module_stage_start__, + MODULE_TEST_SHARED_ABORT); + + (void) txm_module_manager_unload(&demo_module[3]); + + /* The size guards on a grant, which are the manager's business and not + the module's. Last, because it wants the pool to itself: every pass + above has released its data allocation by now. */ + + console_puts("M8 shared-grant size guards\n"); + run_guard_probes((VOID *) &__module_image_start__); + } + + /* ------------------------------------------------------------------ + The verdict. + ------------------------------------------------------------------ */ + + console_puts("\n=== ThreadX modules on the Armv8-R AEM FVP: " + "isolation and relocation ===\n"); + + for (i = 0U; i < MODULE_PASSES; i++) + { + report_one_pass(&pass_results[i]); + } + + failures += report_and_judge_guards(); + + console_puts("\n"); + + /* Before anything else: a module's code, data and shared regions are enabled + at the same time, and PMSAv8-R has no region priority -- an access that + hits more than one enabled region takes a translation fault (TRM 8.1), so + an overlap means aborts from addresses that look perfectly legal. Nothing + in the manager checks for it, so this example does. + + The risk is real here and not theoretical: the image, the pool and the + staging area all live in one 64 KB area. A module grown large enough, or + a pool sized differently, and two of them would meet. */ + + for (i = 0U; i < MODULE_PASSES; i++) + { + const PASS_RESULT *result = &pass_results[i]; + + if (result -> pass_load_status != (ULONG) TX_SUCCESS) + { + continue; + } + + if ((result -> pass_code_start <= result -> pass_data_end) && + (result -> pass_data_start <= result -> pass_code_end)) + { + console_puts("FAIL "); + console_puts(result -> pass_name); + console_puts(": its code and data regions overlap\n"); + failures++; + } + + if ((result -> pass_code_start <= (MODULE_STATUS_ADDRESS + MODULE_STATUS_AREA_LENGTH - 1UL)) && + (MODULE_STATUS_ADDRESS <= result -> pass_code_end)) + { + console_puts("FAIL "); + console_puts(result -> pass_name); + console_puts(": the shared status area overlaps its code\n"); + failures++; + } + + if ((result -> pass_data_start <= (MODULE_STATUS_ADDRESS + MODULE_STATUS_AREA_LENGTH - 1UL)) && + (MODULE_STATUS_ADDRESS <= result -> pass_data_end)) + { + console_puts("FAIL "); + console_puts(result -> pass_name); + console_puts(": the shared status area overlaps its data\n"); + failures++; + } + + /* And what _txm_module_manager_alignment_adjust produced. It is called + by every load and has never been checked, because nothing it gets + wrong faults: it rounds a module's code and data sizes up to the + protection granule and declares the granule as their alignment, and + the loader allocates on that. Get it wrong and the region bases are + written into PRBAR with their low six bits landing on the shareability, + permission and execute-never fields -- so the module runs with + attributes nobody asked for rather than at the wrong address. + + The data region's end is checked as well as its base, because the data + region's length is the rounded size; the CODE region's end is not, it + is the true end of the image and is not rounded to anything. */ + + if (((result -> pass_code_start & (TXM_MODULE_MPU_ALIGNMENT - 1UL)) != 0UL) || + ((result -> pass_data_start & (TXM_MODULE_MPU_ALIGNMENT - 1UL)) != 0UL) || + (((result -> pass_data_end + 1UL) & (TXM_MODULE_MPU_ALIGNMENT - 1UL)) != 0UL)) + { + console_puts("FAIL "); + console_puts(result -> pass_name); + console_puts(": its regions are not aligned to the protection granule\n"); + failures++; + } + } + + /* Each pass on its own. */ + + for (i = 0U; i < MODULE_PASSES; i++) + { + failures += judge_one_pass(&pass_results[i]); + } + + /* And the first two passes against each other, which is the relocation + result. The third is not in this comparison: it faults on the address it + branched to rather than inside its own code, so its faulting pc is not an + offset into the module and there is nothing to compare. */ + + offset_0 = pass_results[0].pass_code_location - pass_results[0].pass_code_start; + offset_1 = pass_results[1].pass_code_location - pass_results[1].pass_code_start; + + if ((pass_results[0].pass_captured == 0UL) || (pass_results[1].pass_captured == 0UL)) + { + console_puts("FAIL relocation: a pass did not fault, nothing to compare\n"); + failures++; + } + else if (pass_results[0].pass_code_start == pass_results[1].pass_code_start) + { + console_puts("FAIL relocation: both passes ran from the same address\n"); + failures++; + } + else if (offset_0 != offset_1) + { + console_puts("FAIL relocation: the two passes faulted at different offsets\n"); + failures++; + } + else + { + console_puts("PASS relocation: the same blob ran correctly from two addresses\n"); + + if (pass_results[0].pass_data_base == pass_results[1].pass_data_base) + { + /* Not a failure -- the code rebase is still proven -- but worth + saying, because it means the data rebase produced the same numbers + twice and was not exercised as thoroughly. */ + + console_puts("NOTE both passes shared a data base; the data rebase was not varied\n"); + } + } + + /* Both abort types, stated as its own line. Each pass above already checked + its own registers; this says that between them the two vectors were both + taken, which is the claim a reader of the log wants to be able to make + without working out what each pass did. */ + + if ((pass_results[0].pass_captured != 0UL) && (pass_results[0].pass_dfsr != 0UL) && + (pass_results[2].pass_captured != 0UL) && (pass_results[2].pass_ifsr != 0UL)) + { + console_puts("PASS both abort types: data through DFSR/DFAR, prefetch through IFSR/IFAR\n"); + } + else + { + console_puts("FAIL only one kind of abort was exercised\n"); + failures++; + } + + /* The manager is still alive to print this, which is itself the last + result: three module faults did not take the kernel with them. */ + + put_field("\nfailures = ", (unsigned long) failures); + + if (failures == 0U) + { + console_puts("\nMODULE RESULT: ALL CHECKS PASSED\n"); + } + else + { + console_puts("\nMODULE RESULT: FAILED\n"); + } + + /* Terminates the model. Every FVP image in this port exits through + semihosting SYS_EXIT, so the runner needs no host-side timeout and a hang + cannot be mistaken for a slow run. */ + + console_exit(failures); +} + + +/**************************************************************************/ +/* Application definition. */ +/**************************************************************************/ + +void tx_application_define(void *first_unused_memory) +{ + UINT status; + + (void) first_unused_memory; + + console_puts("\n=== module manager starting ===\n"); + + /* Nothing but the thread. See manager_entry for why the manager cannot be + driven from here. */ + + status = tx_thread_create(&report_thread, "module manager", manager_entry, 0UL, + report_stack, sizeof(report_stack), + 20U, 20U, TX_NO_TIME_SLICE, TX_AUTO_START); + + /* Reported rather than discarded. A thread that was never created and a + thread that was created but never scheduled produce exactly the same + silence on the console, and telling those two apart is most of the work + when the port itself is what is under test. */ + + if (status == TX_SUCCESS) + { + console_puts("M0 thread created\n"); + } + else + { + put_field("FAIL tx_thread_create status = ", (unsigned long) status); + } +} + + +/**************************************************************************/ +/* bsp_main -- entered at EL1 from entry.S. Does not return. */ +/**************************************************************************/ + +void bsp_main(void) +{ + console_puts("\n=== ThreadX modules :: Armv8-R AEM FVP (Cortex-R52) ===\n"); + console_puts("entering kernel\n"); + + tx_kernel_enter(); + + /* Not reached. */ + + console_puts("FAIL tx_kernel_enter returned\n"); + + console_exit(1U); +} diff --git a/ports_module/cortex_r52/gnu/example_build/fvp_baser_aemv8r/sample_threadx_module_properties.c b/ports_module/cortex_r52/gnu/example_build/fvp_baser_aemv8r/sample_threadx_module_properties.c new file mode 100644 index 000000000..a24934098 --- /dev/null +++ b/ports_module/cortex_r52/gnu/example_build/fvp_baser_aemv8r/sample_threadx_module_properties.c @@ -0,0 +1,1086 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* MODULE MANAGER SAMPLE RELEASE */ +/* */ +/* sample_threadx_module_properties.c Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frédéric Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Walks the module property combinations this port accepts and */ +/* refuses, and checks each one against the documented contract, on */ +/* the Armv8-R AEM FVP with no debugger and no person in the loop. */ +/* */ +/* WHY THIS IS A SEPARATE IMAGE from fvp_module.elf. That one loads */ +/* one property word -- 0x02000003, the only combination any example */ +/* in the tree ships -- and asks what the hardware does about a module */ +/* that misbehaves. This one asks what the LOADER does about a module */ +/* whose property word is something else, which is a question about a */ +/* module that never runs at all in four of the six cases below. The */ +/* two have different subjects and different verdicts, and the only */ +/* thing they share is the module blob. */ +/* */ +/* WHAT THE CONTRACT IS. TXM_MODULE_MANAGER_REQUIRED_OPTIONS in */ +/* txm_module_port.h requires TXM_MODULE_USER_MODE and */ +/* TXM_MODULE_MEMORY_PROTECTION together, which every other module port */ +/* in the tree leaves at zero. The reason is PMSAv8-R and not policy: */ +/* the port programs a module's region table only when both bits are */ +/* set, the scheduler closes the kernel's window over module memory */ +/* before it dispatches a module thread, and per the Cortex-R52 TRM */ +/* section 8.2.1 there is no background region to fall back on -- EL0 */ +/* accesses are faulted whenever the MPU is enabled, and EL1 needs */ +/* SCTLR.BR, which neither board support package sets. So a module */ +/* that asks for user mode without protection is not an unprotected */ +/* module. It is a module with no mapping, and it aborts on the fetch */ +/* of its own first instruction. */ +/* */ +/* TXM_MODULE_SHARED_EXTERNAL_MEMORY_ACCESS is supported and optional, */ +/* and both halves of that are checked below rather than asserted. */ +/* */ +/* ONE BLOB, SIX PROPERTY WORDS. The property word is a field of the */ +/* preamble, and the preamble is the first thing in the module image, so */ +/* a case is set up by copying the blob into the staging area and */ +/* writing one word of the copy. Nothing else about the module changes */ +/* between cases, which is what makes the six verdicts comparable: the */ +/* only variable is the word under test. Six separately built module */ +/* images would each also carry their own code, and a difference in */ +/* outcome could then be blamed on any of it. */ +/* */ +/* THE FOUR REFUSALS ARE CHECKED BY NAME, not by "it did not run". A */ +/* load that failed with TX_NO_MEMORY, or one that succeeded and then */ +/* faulted in the module's first instruction, would both leave the */ +/* module not running. The whole point of the contract is that the */ +/* refusal arrives from txm_module_manager_in_place_load as */ +/* TXM_MODULE_INVALID_PROPERTIES, at the moment the property word can */ +/* still be corrected, so that status is what is compared. */ +/* */ +/* A REFUSAL MUST ALSO COST NOTHING. Each case gets its own instance */ +/* out of .bss, and a refused case's instance is checked to be */ +/* untouched and the manager's loaded count to be unmoved. The port */ +/* would still be wrong if it rejected the module and left half an */ +/* instance behind, and the four refusals run before the two loads for */ +/* the same reason: what follows them proves the manager is still able */ +/* to load. */ +/* */ +/* THE TWO ACCEPTED CASES ARE RUN, not merely loaded. A load that */ +/* returns TX_SUCCESS says nothing about whether the region table it */ +/* programmed describes anything, which is exactly the defect this file */ +/* exists for. So both accepted cases start the module and wait for the */ +/* abort it is written to provoke, and the abort is attributed to the */ +/* case by thread pointer and checked for its address, its mode and its */ +/* offset into the module's own code. */ +/* */ +/* The two differ in what they are granted, which is the optional half */ +/* of the contract: */ +/* */ +/* 0x03, user mode and protection. Granted NOTHING. It reports */ +/* through no shared granule, so what is read back is the abort: the */ +/* module wrote its own data, then reached the status word it was */ +/* never granted, and faulted there. A module that did not ask for */ +/* shared access and was given none cannot reach the shared area, and */ +/* the fault address says so. */ +/* */ +/* 0x07, and the status granule granted. The module reports its */ +/* progress through that granule, gets as far as a kernel call, and */ +/* faults where fvp_module.elf's first pass does -- on the kernel's */ +/* data. So the shared grant is what is under test here, and the */ +/* progress word is the evidence that it worked. */ +/* */ +/* WHAT A GREEN RUN HERE DOES NOT PROVE. Two things, and both are */ +/* limits of the contract rather than gaps in the checking. */ +/* */ +/* The port does not gate txm_module_manager_external_memory_enable on */ +/* TXM_MODULE_SHARED_EXTERNAL_MEMORY_ACCESS, and neither does any other */ +/* module port; a manager that granted a region to the 0x03 module would */ +/* be obliged. That is why the 0x03 case above is granted nothing rather */ +/* than granted something and expected to be refused: this file checks */ +/* the contract the port states, and the port does not state that one. */ +/* */ +/* And nothing here exercises the property-flag test in */ +/* tx_thread_schedule.S, which decides the same question a second time */ +/* for a thread being dispatched. It cannot: the loader refuses every */ +/* combination that would reach the scheduler with an unprogrammed region */ +/* table, so the assembly's test is unreachable by construction while */ +/* TXM_MODULE_MANAGER_REQUIRED_OPTIONS stands. That redundancy is the */ +/* point of it -- the scheduler stops depending on a loader invariant it */ +/* cannot see -- but it does mean the test is covered by the offset */ +/* assertion in txm_module_manager_offset_check.c and by reading it, and */ +/* not by any run of this image. */ +/* */ +/**************************************************************************/ + +#include "tx_api.h" +#include "txm_module.h" +#include "console.h" +#include "platform.h" +#include "mpu.h" +#include "cache.h" + +/* For bsp_main, which entry.S calls and therefore never declares. Every other + example in the board support package includes this header for the same + reason; MISRA C:2012 Rule 8.4 wants the declaration visible at the definition, + and -Wmissing-prototypes reports it when it is not. */ + +#include "board.h" + +/* The fault information the abort vector captured. Declared here because the + module manager expands it into the port's fault handler through the + TXM_MODULE_MANAGER_FAULT_INFO macro rather than declaring it in a header. */ + +extern TXM_MODULE_MANAGER_MEMORY_FAULT_INFO _txm_module_manager_memory_fault_info; + +/* How many modules the manager believes are loaded. Read rather than inferred: + a refused load that still linked an instance into the loaded list would be a + defect this file is in a position to see. The upstream spelling of the symbol + has "manger" in it. */ + +extern ULONG _txm_module_manger_loaded_count; + +/* Where the module image sits, and the writable copy every case is built in. + Both provided by link_module.lds, which places the module's preamble first -- + so __module_image_start__ is also the preamble address. */ + +extern unsigned char __module_image_start__; +extern unsigned char __module_image_end__; + +extern unsigned char __module_stage_start__; +extern unsigned char __module_stage_end__; + +/* The shared granule the 0x07 case reports its progress through, and the one + address the 0x03 case is expected to fault on. */ + +extern unsigned char __module_status_start__; +extern unsigned char __module_status_end__; + +/* The kernel's own writable region, used to check that the address the module + reaches for really is memory it must not have. */ + +extern unsigned char __data_start__; +extern unsigned char __data_end__; + +/* The address the module reaches for in step 3, kept in step with + sample_threadx_module.c by hand and checked at run time to lie inside the + kernel's data region. An address in no region at all would fault too, and + would prove much less. */ + +#define MODULE_FORBIDDEN_ADDRESS 0x003EFFC0UL + +/* The shared status granule. The same number is FVP_MODULE_STATUS_BASE in + platform.h, ORIGIN(MODULE) in link_module.lds and MODULE_STATUS_ADDRESS in the + module. Checked against the linker symbol below rather than trusted. + + MISRA C:2012 Rule 11.6 is deliberately violated when this is dereferenced: + the address is an agreement between two separately linked images and there is + no conforming way to express it. */ + +#define MODULE_STATUS_ADDRESS FVP_MODULE_STATUS_BASE +#define MODULE_STATUS_LENGTH FVP_MODULE_STATUS_SIZE +#define MODULE_STATUS_GRANULES FVP_MODULE_STATUS_GRANULES +#define MODULE_STATUS_AREA_LENGTH (MODULE_STATUS_GRANULES * MODULE_STATUS_LENGTH) + +/* The progress bits the module sets, mirrored from sample_threadx_module.c. The + SURVIVED bits can only ever appear if the hardware allowed an access it was + configured to refuse, so they are checked for by name. */ + +#define MODULE_PROGRESS_OWN_DATA 0x00000001UL +#define MODULE_PROGRESS_KERNEL_CALL 0x00000002UL +#define MODULE_PROGRESS_ATTEMPTED_STEAL 0x00000004UL +#define MODULE_PROGRESS_SURVIVED_STEAL 0x00000008UL +#define MODULE_PROGRESS_ATTEMPTED_JUMP 0x00000010UL +#define MODULE_PROGRESS_SURVIVED_JUMP 0x00000020UL +#define MODULE_PROGRESS_SHARED_WROTE 0x00000040UL +#define MODULE_PROGRESS_ATTEMPTED_GAP 0x00000080UL +#define MODULE_PROGRESS_SURVIVED_GAP 0x00000100UL + +#define MODULE_PROGRESS_SURVIVED (MODULE_PROGRESS_SURVIVED_STEAL | \ + MODULE_PROGRESS_SURVIVED_JUMP | \ + MODULE_PROGRESS_SURVIVED_GAP) + +/* What the module does when it gets that far, selected from the low byte of the + application-defined module ID. The preamble ships 0x52520001, so the default + is the data abort on the kernel's data and no case here has to set anything. */ + +#define MODULE_PROGRESS_RAN_AND_STOLE (MODULE_PROGRESS_OWN_DATA | \ + MODULE_PROGRESS_KERNEL_CALL | \ + MODULE_PROGRESS_ATTEMPTED_STEAL) + +/* Memory the manager hands out to modules. In the module area, not in .bss: a + module's data becomes an MPU region, and a region may not overlap a kernel + one. See the same declaration in sample_threadx_module_manager.c. */ + +#ifndef MODULE_POOL_SIZE +#define MODULE_POOL_SIZE (16U * 1024U) +#endif + +static unsigned char module_pool[MODULE_POOL_SIZE] + __attribute__((aligned(64), section(".module_pool"))); + +/* The object pool the kernel stacks of a User-mode module's threads come from. + Not optional: txm_module_manager_initialize deliberately leaves this pool + uncreated, and without it a User-mode module fails to start with + TX_NOT_AVAILABLE from deep inside the thread create. */ + +#ifndef MODULE_OBJECT_POOL_SIZE +#define MODULE_OBJECT_POOL_SIZE (8U * 1024U) +#endif + +static unsigned char module_object_pool[MODULE_OBJECT_POOL_SIZE] + __attribute__((aligned(64))); + + +/**************************************************************************/ +/* The cases. */ +/* */ +/* Every low-byte combination the port has an opinion about, and the */ +/* opinion. The compiler field is ORed in when the word is written, so */ +/* the option bits stay legible here. */ +/**************************************************************************/ + +typedef struct PROPERTY_CASE_STRUCT +{ + CHAR *case_name; + ULONG case_options; /* the option bits under test */ + UINT case_expect_load; /* what in_place_load must return */ + UINT case_grant_status; /* grant the status granule? */ + ULONG case_expect_fault; /* where it must fault, when it runs */ + ULONG case_expect_progress; /* what the granule must show, if any */ +} PROPERTY_CASE; + +/* The four refusals come first, and the two loads after them, so that what + follows a refusal proves the manager is still able to load a module. The + order is otherwise free: every case unloads before the next one starts. */ + +static const PROPERTY_CASE property_cases[] = +{ + { + "0x00 nothing asked for", + 0UL, + TXM_MODULE_INVALID_PROPERTIES, + 0U, 0UL, 0UL + }, + { + "0x01 user mode without protection", + TXM_MODULE_USER_MODE, + TXM_MODULE_INVALID_PROPERTIES, + 0U, 0UL, 0UL + }, + { + "0x02 protection without user mode", + TXM_MODULE_MEMORY_PROTECTION, + TXM_MODULE_INVALID_PROPERTIES, + 0U, 0UL, 0UL + }, + { + "0x05 user mode and shared, without protection", + TXM_MODULE_USER_MODE | TXM_MODULE_SHARED_EXTERNAL_MEMORY_ACCESS, + TXM_MODULE_INVALID_PROPERTIES, + 0U, 0UL, 0UL + }, + + /* Accepted, and granted nothing. It faults on the status word, which is + the shared area it never asked for and was never given. */ + + { + "0x03 user mode and protection", + TXM_MODULE_USER_MODE | TXM_MODULE_MEMORY_PROTECTION, + TX_SUCCESS, + 0U, MODULE_STATUS_ADDRESS, 0UL + }, + + /* Accepted, and granted the status granule. It therefore reports its + progress and gets as far as the kernel's data before it faults. */ + + { + "0x07 user mode, protection and shared memory", + TXM_MODULE_USER_MODE | TXM_MODULE_MEMORY_PROTECTION + | TXM_MODULE_SHARED_EXTERNAL_MEMORY_ACCESS, + TX_SUCCESS, + 1U, MODULE_FORBIDDEN_ADDRESS, MODULE_PROGRESS_RAN_AND_STOLE + }, +}; + +#define PROPERTY_CASES (sizeof(property_cases) / sizeof(property_cases[0])) + +/* One instance per case, so that a refused case's instance can be checked to + have been left alone. Sharing one would make that unprovable. */ + +static TXM_MODULE_INSTANCE demo_module[PROPERTY_CASES]; + + +/**************************************************************************/ +/* What each case produced. */ +/**************************************************************************/ + +typedef struct CASE_RESULT_STRUCT +{ + ULONG result_properties; /* the whole word that was written */ + ULONG result_load_status; + ULONG result_share_status; + ULONG result_start_status; + ULONG result_stop_status; + ULONG result_unload_status; + + /* What a refused load must not have done. */ + + ULONG result_instance_id; + ULONG result_loaded_count; + + /* Where the manager put it, for the cases that loaded. */ + + ULONG result_code_start; + ULONG result_code_end; + ULONG result_data_start; + ULONG result_data_end; + ULONG result_data_base; + + /* What the hardware and the module said, for the cases that ran. */ + + ULONG result_captured; + ULONG result_dfsr; + ULONG result_dfar; + ULONG result_ifsr; + ULONG result_ifar; + ULONG result_spsr; + ULONG result_fault_r9; + ULONG result_code_location; + ULONG result_progress; + ULONG result_faults; + ULONG result_notify_thread; + ULONG result_notify_instance; + ULONG result_expect_thread; + ULONG result_expect_instance; +} CASE_RESULT; + +static CASE_RESULT case_results[PROPERTY_CASES]; + +/* What the fault handler saw. */ + +static volatile ULONG fault_count; +static volatile ULONG fault_notify_thread; +static volatile ULONG fault_notify_instance; + +static TX_THREAD report_thread; +static unsigned char report_stack[2048] __attribute__((aligned(8))); + + +/**************************************************************************/ +/* Fault notification. */ +/* */ +/* Records rather than prints: this runs in Abort mode on the Abort */ +/* stack, which is a kilobyte and already carries the terminate */ +/* underneath this frame. */ +/**************************************************************************/ + +static void module_fault_notify(TX_THREAD *thread_ptr, TXM_MODULE_INSTANCE *module_instance) +{ + fault_count++; + fault_notify_thread = (ULONG) thread_ptr; + fault_notify_instance = (ULONG) module_instance; +} + + +static void put_field(const char *label, unsigned long value) +{ + console_puts(label); + console_puthex(value); + console_puts("\n"); +} + + +/**************************************************************************/ +/* The shared status granule, reached through the manager's load window. */ +/* */ +/* No kernel region covers the module area; region 16 does, and the */ +/* scheduler enables it for every thread that owns no module. This */ +/* thread owns none, so the window is open on it. */ +/* */ +/* MISRA C:2012 Rule 11.6 is deliberately violated: the address is an */ +/* agreement between two separately linked images. */ +/**************************************************************************/ + +static void module_status_clear(void) +{ + ULONG word; + + /* The whole area, not just the progress word. A case that is granted + nothing must be seen to have written nothing, and a mark left by the + previous case would read as one that reached memory it never held. */ + + for (word = 0UL; word < (MODULE_STATUS_AREA_LENGTH / 4UL); word++) + { + ((volatile ULONG *) MODULE_STATUS_ADDRESS)[word] = 0UL; + } +} + + +static ULONG module_status_read(void) +{ + return *((volatile ULONG *) MODULE_STATUS_ADDRESS); +} + + +/**************************************************************************/ +/* A byte copy, written out rather than called for. The manager links */ +/* -nostartfiles and nothing else in this image reaches for a C library, */ +/* so calling memcpy would pull one in for a copy of under two kilobytes */ +/* that happens six times. */ +/**************************************************************************/ + +static void copy_bytes(unsigned char *destination, const unsigned char *source, + unsigned long length) +{ + unsigned long i; + + for (i = 0UL; i < length; i++) + { + destination[i] = source[i]; + } +} + + +/**************************************************************************/ +/* Build one case in the staging area: the blob, with one word replaced. */ +/* */ +/* Copied afresh for every case rather than patched in place, so that a */ +/* case cannot inherit anything from the one before it -- including the */ +/* previous property word, which is the single variable under test. */ +/* */ +/* The cache maintenance is not a precaution the passing run justifies. */ +/* These are data writes to memory that is about to be fetched as */ +/* instructions, and the module area is mapped Normal write-back, so the */ +/* copied bytes may sit in dirty D-cache lines while the instruction side */ +/* -- which is not coherent with the D cache on this core -- fetches what */ +/* main memory still holds. A cold I cache over a never-executed address */ +/* happens to work, and keeps happening to work until the staging area is */ +/* reused, which is exactly what this file does six times. */ +/**************************************************************************/ + +static ULONG stage_module(ULONG options) +{ + unsigned long blob_size; + TXM_MODULE_PREAMBLE *preamble; + ULONG properties; + + blob_size = (unsigned long) (&__module_image_end__ - &__module_image_start__); + + copy_bytes(&__module_stage_start__, &__module_image_start__, blob_size); + + /* The preamble is the first thing in the image, so the staged copy's base is + the preamble's address. Written through the structure rather than at a + hard-coded word offset: txm_module_manager_in_place_load reads the same + structure, and a field that moved would move for both. */ + + preamble = (TXM_MODULE_PREAMBLE *) (VOID *) &__module_stage_start__; + + /* The compiler field is preserved and the option bits replaced. Rebuilding + the whole word from TXM_MODULE_GNU_COMPILER would work today and would + silently stop testing what it means to test if the module were ever built + with something else. */ + + properties = (preamble -> txm_module_preamble_property_flags + & ~((ULONG) TXM_MODULE_OPTIONS_MASK)) | options; + + preamble -> txm_module_preamble_property_flags = properties; + + cache_clean_range(&__module_stage_start__, blob_size); + cache_invalidate_icache_all(); + + return properties; +} + + +/**************************************************************************/ +/* One case: stage it, load it, and -- if the contract says it loads -- */ +/* start it and wait for the abort it is written to provoke. */ +/**************************************************************************/ + +static void run_one_case(UINT index) +{ + const PROPERTY_CASE *test = &property_cases[index]; + CASE_RESULT *result = &case_results[index]; + TXM_MODULE_INSTANCE *instance = &demo_module[index]; + unsigned int waited; + + /* Cleared before the module starts, so a fault or a progress bit counted + here belongs to this case and not the previous one. */ + + fault_count = 0UL; + fault_notify_thread = 0UL; + fault_notify_instance = 0UL; + module_status_clear(); + + result -> result_properties = stage_module(test -> case_options); + + /* name is CHAR * and not const CHAR *, because in_place_load takes it that + way -- the manager stores the pointer in the instance and the API has + never promised not to write through it. */ + + result -> result_load_status = + (ULONG) txm_module_manager_in_place_load(instance, test -> case_name, + (VOID *) &__module_stage_start__); + + /* Read for every case, and it is the refused ones that need it: a refusal + must leave the instance as .bss had it and the loaded count where it was. + Taken immediately, before anything else can move either. */ + + result -> result_instance_id = instance -> txm_module_instance_id; + result -> result_loaded_count = _txm_module_manger_loaded_count; + + if (result -> result_load_status != (ULONG) TX_SUCCESS) + { + return; + } + + result -> result_code_start = (ULONG) instance -> txm_module_instance_code_start; + result -> result_code_end = (ULONG) instance -> txm_module_instance_code_end; + result -> result_data_start = (ULONG) instance -> txm_module_instance_data_start; + result -> result_data_end = (ULONG) instance -> txm_module_instance_data_end; + result -> result_data_base = + (ULONG) instance -> txm_module_instance_module_data_base_address; + + /* The shared granule, for the case that asked for shared access. Granted + while the module is LOADED and before it is STARTED, which is the only + window the manager accepts. */ + + if (test -> case_grant_status != 0U) + { + result -> result_share_status = + (ULONG) txm_module_manager_external_memory_enable( + instance, (VOID *) &__module_status_start__, + MODULE_STATUS_LENGTH, TXM_MODULE_ATTRIBUTE_READ_WRITE); + + if (result -> result_share_status != (ULONG) TX_SUCCESS) + { + return; + } + } + + /* What the notify callback must be told, recorded before the module runs so + the comparison afterwards is against an expectation. */ + + result -> result_expect_thread = + (ULONG) &(instance -> txm_module_instance_start_stop_thread); + result -> result_expect_instance = (ULONG) instance; + + result -> result_start_status = (ULONG) txm_module_manager_start(instance); + + if (result -> result_start_status != (ULONG) TX_SUCCESS) + { + return; + } + + /* Wait for the abort vector to capture a fault belonging to THIS case. + Attribution is by thread pointer: each case has its own instance and + therefore its own start thread, so a captured fault naming this case's + thread cannot be a leftover from the previous one. */ + + waited = 0U; + while ((_txm_module_manager_memory_fault_info.txm_module_manager_memory_fault_info_thread_ptr + != &(instance -> txm_module_instance_start_stop_thread)) && + (waited < 50U)) + { + tx_thread_sleep(2UL); + waited++; + } + + if (_txm_module_manager_memory_fault_info.txm_module_manager_memory_fault_info_thread_ptr + == &(instance -> txm_module_instance_start_stop_thread)) + { + result -> result_captured = 1UL; + result -> result_dfsr = _txm_module_manager_memory_fault_info.txm_module_manager_memory_fault_info_dfsr; + result -> result_dfar = _txm_module_manager_memory_fault_info.txm_module_manager_memory_fault_info_dfar; + result -> result_ifsr = _txm_module_manager_memory_fault_info.txm_module_manager_memory_fault_info_ifsr; + result -> result_ifar = _txm_module_manager_memory_fault_info.txm_module_manager_memory_fault_info_ifar; + result -> result_spsr = _txm_module_manager_memory_fault_info.txm_module_manager_memory_fault_info_spsr; + result -> result_fault_r9 = _txm_module_manager_memory_fault_info.txm_module_manager_memory_fault_info_r9; + result -> result_code_location = (ULONG) _txm_module_manager_memory_fault_info.txm_module_manager_memory_fault_info_code_location; + } + + result -> result_progress = module_status_read(); + result -> result_faults = fault_count; + result -> result_notify_thread = fault_notify_thread; + result -> result_notify_instance = fault_notify_instance; + + /* Stopped, then unloaded. The fault terminated the module's start thread + but left the module STARTED, and unload refuses anything that is not + LOADED or STOPPED -- so the stop is required, not tidiness. Unloaded + because the next case must start from a manager holding nothing, which is + what makes its loaded count comparable. */ + + result -> result_stop_status = (ULONG) txm_module_manager_stop(instance); + result -> result_unload_status = (ULONG) txm_module_manager_unload(instance); +} + + +/**************************************************************************/ +/* What one case produced, printed whether it passed or not. */ +/**************************************************************************/ + +static void report_one_case(UINT index) +{ + const PROPERTY_CASE *test = &property_cases[index]; + const CASE_RESULT *result = &case_results[index]; + + console_puts("\n--- "); + console_puts(test -> case_name); + console_puts(" ---\n"); + + put_field(" property word = ", result -> result_properties); + put_field(" load status = ", result -> result_load_status); + put_field(" should be = ", (unsigned long) test -> case_expect_load); + put_field(" instance id = ", result -> result_instance_id); + put_field(" modules loaded = ", result -> result_loaded_count); + + if (result -> result_load_status != (ULONG) TX_SUCCESS) + { + return; + } + + put_field(" code start = ", result -> result_code_start); + put_field(" code end = ", result -> result_code_end); + put_field(" data start = ", result -> result_data_start); + put_field(" data end = ", result -> result_data_end); + put_field(" data base (r9) = ", result -> result_data_base); + put_field(" share status = ", result -> result_share_status); + put_field(" start status = ", result -> result_start_status); + put_field(" stop status = ", result -> result_stop_status); + put_field(" unload status = ", result -> result_unload_status); + put_field(" faults notified = ", result -> result_faults); + put_field(" fault captured = ", result -> result_captured); + put_field(" progress = ", result -> result_progress); + put_field(" should be = ", test -> case_expect_progress); + put_field(" DFSR = ", result -> result_dfsr); + put_field(" DFAR = ", result -> result_dfar); + put_field(" should be = ", test -> case_expect_fault); + put_field(" SPSR = ", result -> result_spsr); + put_field(" faulting pc = ", result -> result_code_location); + put_field(" pc - code base = ", + result -> result_code_location - result -> result_code_start); +} + + +/**************************************************************************/ +/* And whether it is what the contract says. */ +/**************************************************************************/ + +static UINT judge_one_case(UINT index) +{ + const PROPERTY_CASE *test = &property_cases[index]; + const CASE_RESULT *result = &case_results[index]; + + /* The status, by name, first. Every other verdict below depends on the + load having done what the contract says, and "it did not run" is not the + same claim as "it was refused for its properties". */ + + if (result -> result_load_status != (ULONG) test -> case_expect_load) + { + console_puts("FAIL "); + console_puts(test -> case_name); + console_puts(": the load did not return what the contract says\n"); + return 1U; + } + + if (test -> case_expect_load != TX_SUCCESS) + { + /* A refusal must cost nothing. The property check in the portable + loader runs before it memsets the instance, so a refused case's + instance is still whatever .bss made it -- and if it were not, the + application would be holding a half-built module the manager does not + know about. */ + + if (result -> result_instance_id != 0UL) + { + console_puts("FAIL "); + console_puts(test -> case_name); + console_puts(": refused, but the instance was written to anyway\n"); + return 1U; + } + + if (result -> result_loaded_count != 0UL) + { + console_puts("FAIL "); + console_puts(test -> case_name); + console_puts(": refused, but the manager counts a loaded module\n"); + return 1U; + } + + console_puts("PASS "); + console_puts(test -> case_name); + console_puts(": refused as TXM_MODULE_INVALID_PROPERTIES, and cost nothing\n"); + return 0U; + } + + /* From here on the module was accepted, so it has to have RUN. A load that + returns TX_SUCCESS and programs a region table describing nothing is + exactly the defect this file exists for, and it looks identical to a + correct load until the module is dispatched. */ + + if ((test -> case_grant_status != 0U) && + (result -> result_share_status != (ULONG) TX_SUCCESS)) + { + console_puts("FAIL "); + console_puts(test -> case_name); + console_puts(": asked for shared access and could not be granted any\n"); + return 1U; + } + + if (result -> result_start_status != (ULONG) TX_SUCCESS) + { + console_puts("FAIL "); + console_puts(test -> case_name); + console_puts(": loaded but would not start\n"); + return 1U; + } + + if ((result -> result_progress & MODULE_PROGRESS_SURVIVED) != 0UL) + { + console_puts("FAIL "); + console_puts(test -> case_name); + console_puts(": the module SURVIVED its violation -- it is not protected\n"); + return 1U; + } + + if (result -> result_captured == 0UL) + { + console_puts("FAIL "); + console_puts(test -> case_name); + console_puts(": started, and then never reached its own first fault\n"); + return 1U; + } + + /* The faulting pc must be an address inside the code region the manager + handed out. This is what separates "the module ran" from "the module was + dispatched and aborted immediately", which is the shape the property + contract exists to prevent: a zeroed region table faults on the fetch of + the first instruction, and that fault is reported at an address the + manager never mapped. */ + + if ((result -> result_code_location < result -> result_code_start) || + (result -> result_code_location > result -> result_code_end)) + { + console_puts("FAIL "); + console_puts(test -> case_name); + console_puts(": faulted outside its own code, so it never really ran\n"); + return 1U; + } + + /* A fault from anywhere but User mode is not this test passing: the module + runs unprivileged, so a privileged fault means the fault came from the + kernel and something else is wrong. */ + + if ((result -> result_spsr & 0x1FUL) != 0x10UL) + { + console_puts("FAIL "); + console_puts(test -> case_name); + console_puts(": faulted, but not from User mode\n"); + return 1U; + } + + /* Both accepted cases fault on a data access, so DFAR is the register that + carries the address in both. Which address differs, and that difference + IS the optional half of the contract: the case granted nothing faults on + the shared area it was never given, and the case granted the status + granule gets past it and faults on the kernel's data instead. */ + + if (result -> result_dfar != test -> case_expect_fault) + { + console_puts("FAIL "); + console_puts(test -> case_name); + console_puts(": faulted at the wrong address\n"); + return 1U; + } + + /* r9 is the module's PIC base, seeded by the manager from the thread entry + info. If the value captured at the fault is not the data base the manager + handed out, every data reference the module made went somewhere + unintended -- including the ones that appeared to work. */ + + if (result -> result_fault_r9 != result -> result_data_base) + { + console_puts("FAIL "); + console_puts(test -> case_name); + console_puts(": r9 was not the module's data base\n"); + return 1U; + } + + /* And what it managed on the way, for the case that could report. The case + granted nothing cannot write the granule, so its expectation is zero and + this comparison says the granule stayed as module_status_clear left it -- + which is the same claim as the fault address above, made from the other + end. */ + + if (result -> result_progress != test -> case_expect_progress) + { + console_puts("FAIL "); + console_puts(test -> case_name); + console_puts(": did not reach the point it was supposed to fault at\n"); + return 1U; + } + + if (result -> result_faults != 1UL) + { + console_puts("FAIL "); + console_puts(test -> case_name); + console_puts(": the fault-notify callback did not run exactly once\n"); + return 1U; + } + + if ((result -> result_notify_thread != result -> result_expect_thread) || + (result -> result_notify_instance != result -> result_expect_instance)) + { + console_puts("FAIL "); + console_puts(test -> case_name); + console_puts(": notified about the wrong thread or module\n"); + return 1U; + } + + /* And the manager took it back. A module that cannot be unloaded leaves the + next case's loaded count wrong, so this is checked here rather than + inferred from the next verdict. */ + + if ((result -> result_stop_status != (ULONG) TX_SUCCESS) || + (result -> result_unload_status != (ULONG) TX_SUCCESS)) + { + console_puts("FAIL "); + console_puts(test -> case_name); + console_puts(": ran, but could not be stopped and unloaded\n"); + return 1U; + } + + console_puts("PASS "); + console_puts(test -> case_name); + console_puts(": loaded, ran in User mode, and faulted where it should\n"); + + return 0U; +} + + +/**************************************************************************/ +/* The manager thread. */ +/**************************************************************************/ + +static void manager_entry(ULONG input) +{ + UINT status; + UINT i; + unsigned long blob_size; + UINT failures = 0U; + + (void) input; + + /* Every manager call happens here, in a thread, and not in + tx_application_define. Loading a module takes the manager's mutex, and a + service that can block cannot be called before the scheduler runs. */ + + put_field("MPUIR regions available = ", (unsigned long) mpu_region_count()); + put_field("regions this port needs = ", (unsigned long) MPU_MODULE_REGIONS_REQUIRED); + + if (mpu_region_count() < MPU_MODULE_REGIONS_REQUIRED) + { + console_puts("FAIL the implementation has too few MPU regions for this port\n"); + failures++; + } + + /* The contract this image checks, printed so the log states it rather than + leaving a reader to infer it from six verdicts. */ + + put_field("supported options = ", (unsigned long) TXM_MODULE_MANAGER_SUPPORTED_OPTIONS); + put_field("required options = ", (unsigned long) TXM_MODULE_MANAGER_REQUIRED_OPTIONS); + + if (TXM_MODULE_MANAGER_REQUIRED_OPTIONS + != (TXM_MODULE_USER_MODE | TXM_MODULE_MEMORY_PROTECTION)) + { + /* Every case below encodes this contract in its expected load status, so + they are all stale the moment it changes and none of their verdicts + would mean anything. Reported and abandoned here rather than run: + relaxing the requirement makes the loader accept a module whose region + table was never programmed, and this image would then sit for the + runner's whole timeout waiting for a fault that a privileged module + under the kernel's window never takes. A stale contract is a result, + and it should arrive in a second rather than in three minutes. */ + + console_puts("FAIL this port no longer requires user mode and memory " + "protection together; every case below is stale\n"); + console_puts("\nMODULE PROPERTY RESULT: FAILED\n"); + console_exit(1U); + } + + /* The addresses agreed between separately linked images, checked rather than + trusted. A disagreement here would present as a module faulting somewhere + unexpected, which is exactly what the verdicts are trying to distinguish. */ + + if ((unsigned long) &__module_status_start__ != MODULE_STATUS_ADDRESS) + { + console_puts("FAIL the linker put the status word somewhere the module will not look\n"); + failures++; + } + + if ((unsigned long) (&__module_status_end__ - &__module_status_start__) + < MODULE_STATUS_AREA_LENGTH) + { + console_puts("FAIL the status area is smaller than the granules over it\n"); + failures++; + } + + if ((MODULE_FORBIDDEN_ADDRESS < (unsigned long) &__data_start__) || + (MODULE_FORBIDDEN_ADDRESS >= (unsigned long) &__data_end__)) + { + console_puts("FAIL the forbidden address is not inside the kernel's data region\n"); + failures++; + } + + console_puts("\nM1 initialize\n"); + status = txm_module_manager_initialize((VOID *) module_pool, MODULE_POOL_SIZE); + + put_field("initialize = ", status); + put_field("ready = ", (unsigned long) _txm_module_manager_ready); + + status = txm_module_manager_object_pool_create((VOID *) module_object_pool, + MODULE_OBJECT_POOL_SIZE); + + put_field("object pool create = ", status); + + console_puts("M2 fault notify\n"); + txm_module_manager_memory_fault_notify(module_fault_notify); + + /* Every case is built in the staging area, so the blob has to fit it before + any of them runs. Reported rather than allowed to overrun: the staging + area is a fixed size in the linker script and the module is free to grow. */ + + blob_size = (unsigned long) (&__module_image_end__ - &__module_image_start__); + + console_puts("M3 the blob\n"); + put_field(" blob size = ", blob_size); + put_field(" staging area = ", + (unsigned long) (&__module_stage_end__ - &__module_stage_start__)); + + if (blob_size > (unsigned long) (&__module_stage_end__ - &__module_stage_start__)) + { + console_puts("FAIL the module image does not fit the staging area\n"); + failures++; + } + else + { + for (i = 0U; i < (UINT) PROPERTY_CASES; i++) + { + console_puts("M4 case: "); + console_puts(property_cases[i].case_name); + console_puts("\n"); + + run_one_case(i); + } + } + + /* ------------------------------------------------------------------ + The verdict. + ------------------------------------------------------------------ */ + + console_puts("\n=== ThreadX module properties on the Armv8-R AEM FVP ===\n"); + + for (i = 0U; i < (UINT) PROPERTY_CASES; i++) + { + report_one_case(i); + } + + console_puts("\n"); + + for (i = 0U; i < (UINT) PROPERTY_CASES; i++) + { + failures += judge_one_case(i); + } + + /* The manager is still alive to print this, which is itself the last + result: four refusals and two module faults did not take the kernel with + them, and the manager ends holding nothing. */ + + if (_txm_module_manger_loaded_count != 0UL) + { + console_puts("FAIL the manager still believes a module is loaded\n"); + failures++; + } + + put_field("\nfailures = ", (unsigned long) failures); + + if (failures == 0U) + { + console_puts("\nMODULE PROPERTY RESULT: ALL CHECKS PASSED\n"); + } + else + { + console_puts("\nMODULE PROPERTY RESULT: FAILED\n"); + } + + /* Terminates the model. Every FVP image in this port exits through + semihosting SYS_EXIT, so the runner needs no host-side timeout and a hang + cannot be mistaken for a slow run. */ + + console_exit(failures); +} + + +/**************************************************************************/ +/* Application definition. */ +/**************************************************************************/ + +void tx_application_define(void *first_unused_memory) +{ + UINT status; + + (void) first_unused_memory; + + console_puts("\n=== module property manager starting ===\n"); + + status = tx_thread_create(&report_thread, "property manager", manager_entry, 0UL, + report_stack, sizeof(report_stack), + 20U, 20U, TX_NO_TIME_SLICE, TX_AUTO_START); + + /* Reported rather than discarded. A thread that was never created and a + thread that was created but never scheduled produce exactly the same + silence on the console. */ + + if (status == TX_SUCCESS) + { + console_puts("M0 thread created\n"); + } + else + { + put_field("FAIL tx_thread_create status = ", (unsigned long) status); + } +} + + +/**************************************************************************/ +/* bsp_main -- entered at EL1 from entry.S. Does not return. */ +/**************************************************************************/ + +void bsp_main(void) +{ + console_puts("\n=== ThreadX module properties :: Armv8-R AEM FVP (Cortex-R52) ===\n"); + console_puts("entering kernel\n"); + + tx_kernel_enter(); + + /* Not reached. */ + + console_puts("FAIL tx_kernel_enter returned\n"); + + console_exit(1U); +} diff --git a/ports_module/cortex_r52/gnu/example_build/fvp_baser_aemv8r/txm_module_preamble.S b/ports_module/cortex_r52/gnu/example_build/fvp_baser_aemv8r/txm_module_preamble.S new file mode 100644 index 000000000..19bd89318 --- /dev/null +++ b/ports_module/cortex_r52/gnu/example_build/fvp_baser_aemv8r/txm_module_preamble.S @@ -0,0 +1,151 @@ +@/*************************************************************************** +@ * 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. +@ * +@ * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +@ * The AI-generated portions may be considered public domain (CC0-1.0) +@ * and not subject to the project's licence. The human contributor has +@ * reviewed and verified that the code is correct. +@ * +@ * SPDX-License-Identifier: MIT and CC0-1.0 +@ **************************************************************************/ +@ +@/**************************************************************************/ +@/* */ +@/* MODULE PREAMBLE RELEASE */ +@/* */ +@/* txm_module_preamble.S Cortex-R52/GNU */ +@/* 6.5.2 */ +@/* AUTHOR */ +@/* */ +@/* Frédéric Desbiens, Eclipse Foundation */ +@/* */ +@/* DESCRIPTION */ +@/* */ +@/* The header the module manager reads before it will load a module. */ +@/* */ +@/* It must be the first thing in the module image, which is what the */ +@/* linker script arranges, and every entry point in it is an offset */ +@/* from the start of the preamble rather than an address. A module is */ +@/* position independent: the manager decides where it lands, so the */ +@/* module cannot know its own addresses at link time. */ +@/* */ +@/* Code and data sizes come from the linker script rather than being */ +@/* written in by hand. The Cortex-R4 preamble carries literal numbers */ +@/* for them, which is a standing invitation to grow a module past its */ +@/* declared size and have the manager map less memory than it uses -- */ +@/* a fault in a module that did nothing wrong, whose cause is a */ +@/* constant in a file nobody thought to change. */ +@/* */ +@/**************************************************************************/ + + .syntax unified + .arm + + .global __txm_module_preamble + + .extern _txm_module_thread_shell_entry + .extern _txm_module_callback_request_thread_entry + .extern demo_module_start + +@ Supplied by the module's linker script. + + .extern __txm_module_code_size + .extern __txm_module_data_size + +@ Properties. The compiler field tells the manager which set of entry-point +@ adjustments to apply, and the option bits say what the module is asking for: +@ user mode and memory protection, which together are the point of this port. +@ +@ 0x02000000 TXM_MODULE_GNU_COMPILER +@ 0x00000001 TXM_MODULE_USER_MODE +@ 0x00000002 TXM_MODULE_MEMORY_PROTECTION +@ +@ Both option bits are REQUIRED here, unlike on every other module port, and a +@ preamble that carries either alone is refused by the loader with +@ TXM_MODULE_INVALID_PROPERTIES. On PMSAv8-R that is not a policy: the port +@ programs a module's regions only when both bits are set, the scheduler closes +@ the kernel's window over module memory before it dispatches a module thread, +@ and there is no background region to fall back on -- so a module that asked +@ for user mode without protection would have no mapping at all rather than a +@ weaker one. See TXM_MODULE_MANAGER_REQUIRED_OPTIONS in txm_module_port.h. +@ +@ 0x00000004 TXM_MODULE_SHARED_EXTERNAL_MEMORY_ACCESS +@ +@ is supported and optional. A module that does not ask for it simply never has +@ a shared region granted to it. + + .equ MODULE_PROPERTIES, 0x02000003 + + .section .txm_module_preamble, "a" + .align 6 + +__txm_module_preamble: + + .word 0x4D4F4455 @ Module ID, "MODU" + .word 0x6 @ Major version + .word 0x1 @ Minor version + .word 32 @ Preamble size, 32-bit words + .word 0x52520001 @ Application-defined ID + .word MODULE_PROPERTIES @ Properties, see above + +@ Entry points, as offsets from the preamble. + +@ Entry points are stored relative to the word that holds them, not to the +@ start of the preamble. That is what the manager expects: it recovers the +@ offset from the module base by adding the field's own byte offset back -- +@ TXM_MODULE_GNU_SHELL_ADJUST 24, START 28, STOP 32, CALLBACK 44, which are +@ exactly the offsets of the four words below. Storing these relative to +@ __txm_module_preamble instead counts that offset twice, and the module is +@ then entered that many bytes into its shell entry: past the prologue, with +@ the arguments never saved and the frame pointer never set up, so the first +@ dereference goes through a register the stack build had zeroed. On silicon +@ that read faulted at 0x1C, which is offset 0x1C from a null r3. +@ +@ Every other GNU module port writes these the same way; cortex_m33's +@ preamble, which this port was seeded from, spells it "symbol - . - 0". + + .word _txm_module_thread_shell_entry - . + .word demo_module_start - . + .word 0 @ No stop thread + .word 1 @ Start/stop thread priority + .word 1024 @ Start/stop thread stack size + .word _txm_module_callback_request_thread_entry - . + .word 1 @ Callback thread priority + .word 1024 @ Callback thread stack size + +@ Sizes, from the linker script. The manager rounds both up to the 64-byte MPU +@ granule and maps exactly this much; anything the module touches beyond it +@ faults, which is the intended behaviour and not a bug to work around by +@ inflating these numbers. + + .word __txm_module_code_size + .word __txm_module_data_size + + .word 0 @ Reserved 0 + .word 0 @ Reserved 1 + .word 0 @ Reserved 2 + .word 0 @ Reserved 3 + .word 0 @ Reserved 4 + .word 0 @ Reserved 5 + .word 0 @ Reserved 6 + .word 0 @ Reserved 7 + .word 0 @ Reserved 8 + .word 0 @ Reserved 9 + .word 0 @ Reserved 10 + .word 0 @ Reserved 11 + .word 0 @ Reserved 12 + .word 0 @ Reserved 13 + .word 0 @ Reserved 14 + .word 0 @ Reserved 15 + +@ The preamble declares its own length in its fourth word, and the manager +@ believes it. If the two ever disagree the manager reads entry points from the +@ wrong offsets, so the assembler checks rather than the reader. + + .if (. - __txm_module_preamble) != (32 * 4) + .error "txm_module_preamble is not the 32 words its size field declares" + .endif diff --git a/ports_module/cortex_r52/gnu/example_build/s32z280_evb/link_demo_module.lds b/ports_module/cortex_r52/gnu/example_build/s32z280_evb/link_demo_module.lds new file mode 100644 index 000000000..3fc17ef86 --- /dev/null +++ b/ports_module/cortex_r52/gnu/example_build/s32z280_evb/link_demo_module.lds @@ -0,0 +1,199 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/* Link map for the demonstration module alone, for the S32Z280-594EVB. + * + * The module is a separate link unit from the manager, and it has to be. Both + * sides define the ThreadX API: the kernel defines the real _txe_* entry points + * and the module library defines shims of the same names that trap into the + * kernel instead. Linking them together does not produce a duplicate-symbol + * error, because the kernel arrives as a static library and the module library + * as ordinary objects, and an object always beats an archive member. The module + * shims therefore win for the whole image, and the manager's own calls to + * tx_thread_create and friends are quietly redirected into the module. + * + * That was not a theory. It put _txe_thread_create at 0x317F1700, inside the + * module area, which no kernel MPU region covers -- so tx_application_define + * called into unmapped memory and the core took a prefetch abort with nothing on + * the console to say so. + * + * POSITION INDEPENDENT, and the two addresses below are fictions + * ============================================================== + * + * The module is built -fpic -msingle-pic-base, so every reference it makes to + * its own data goes through the global offset table with r9 as the base. It + * therefore does not run at the addresses in this file and is not meant to: the + * two segment origins are nominal, chosen only so that the loader can tell a + * code address from a data address by comparing against __data_segment_start__. + * What actually happens at run time is that _gcc_setup rewrites every GOT entry + * from these nominal addresses to the addresses the manager decided on. + * + * That is why they are far apart and why neither is zero. Far apart, because + * the whole discrimination is "below the data origin means code"; non-zero, + * because _gcc_setup treats a zero GOT entry as one the linker never filled in + * and skips it, so a real address of zero would be silently dropped. + * + * 0x01000000 code preamble, text, rodata, and the load images of the + * GOT and .data -- this is the blob the manager embeds + * 0x02000000 data the GOT the module runs against, .data and .bss, all + * of which live in memory the manager allocates + * + * The load images matter. A module's .data cannot be used where it was linked, + * because the manager never copies it there: _txm_module_manager_internal_load + * allocates the module's data area from its byte pool and TX_MEMSETs it to zero, + * and that is the only memory the module is given a region for. The module's + * own .data, wherever it was linked, is outside every region the module owns. + * On silicon that faulted at the first write to an initialised variable, with + * DFAR pointing into the gap between the granted code and the granted data. + * + * So .data and .got have their VMAs in the data segment, where the module will + * run, and their LMAs in the code segment, inside the blob, where _gcc_setup can + * find them and copy them out. AT>CODE is what says that. + */ + +MEMORY +{ + /* Nominal. See the note above: the module runs where the manager puts it, + not here. Sized generously because nothing is reserved by being large -- + the raw binary is only as long as the sections actually emitted. */ + + CODE (rx) : ORIGIN = 0x01000000, LENGTH = 0x00100000 + DATA (rw) : ORIGIN = 0x02000000, LENGTH = 0x00100000 +} + +__code_segment_start__ = 0x01000000; +__data_segment_start__ = 0x02000000; + +SECTIONS +{ + /* --------------------------------------------------------------------- + The code segment, which is the blob byte for byte. + --------------------------------------------------------------------- */ + + .module_image : ALIGN(64) + { + __module_image_start__ = .; + + /* The preamble is first because that is where the manager looks for it: + it reads the properties, the entry points and the two sizes from the + first words of the image. KEEP because nothing references it. */ + + KEEP(*(.txm_module_preamble)) + + *(.text .text.*) + *(.glue_7) + *(.glue_7t) + *(.rodata .rodata.*) + + . = ALIGN(4); + } >CODE AT>CODE + + /* --------------------------------------------------------------------- + The data segment. VMAs here, load images back in the code segment. + --------------------------------------------------------------------- */ + + /* The GOT, and it must be first in the data segment. r9 is the GOT base as + far as the compiler is concerned -- every R_ARM_GOT32 is an offset from + it -- and the manager sets r9 to txm_module_instance_module_data_base_address, + which is the start of the module's data area. So GOT origin and data + origin have to be the same address, or every offset the compiler emitted + is measured from the wrong place. __data_segment_start__ above is that + address on the nominal side; r9 is that address on the real side, and + _gcc_setup's rebase is the difference between the two. */ + + .got : ALIGN(4) + { + __new_got_start__ = .; + *(.got.plt) + *(.igot.plt) + *(.got) + __new_got_end__ = .; + } >DATA AT>CODE + + __got_load_start__ = LOADADDR(.got); + + .data : ALIGN(4) + { + __data_start__ = .; + *(.data .data.*) + *(.gnu.linkonce.d.*) + . = ALIGN(4); + __data_end__ = .; + } >DATA AT>CODE + + __data_load_start__ = LOADADDR(.data); + + /* NOLOAD, so .bss contributes nothing to the blob. The manager has already + zeroed the whole data allocation by the time the module runs -- but + _gcc_setup zeroes .bss anyway, because "the manager happens to memset it" + is a property of one loader and not something a module may rely on. */ + + .bss (NOLOAD) : ALIGN(4) + { + __bss_start__ = .; + *(.bss .bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) + . = ALIGN(64); + __bss_end__ = .; + } >DATA + + /* --------------------------------------------------------------------- + The two sizes the preamble declares. + --------------------------------------------------------------------- */ + + /* Code covers everything in the blob, the load images of the GOT and .data + included, because the module has to be able to read them to copy them out + and the code region is the only mapping it has over the blob. Ending it + at .rodata instead would put the GOT template outside every region the + module owns and _gcc_setup would fault on its first read. */ + + __txm_module_code_end__ = __data_load_start__ + SIZEOF(.data); + __txm_module_code_size = __txm_module_code_end__ - __code_segment_start__; + + /* Data covers the GOT, .data and .bss. Not the thread stacks: the manager + adds the start/stop and callback stack sizes to this figure itself, from + the two stack-size words further down the preamble. Counting them here + as well would double them. */ + + __txm_module_data_size = __bss_end__ - __data_segment_start__; + + /* Unwind tables and toolchain notes would otherwise land at address zero and + be carried into the raw binary. A module has no unwinder. + + .rel.dyn and friends are discarded because this is a static link: ld + resolves every R_ARM_GOT32 itself and writes the finished address into the + GOT, so there is nothing left for a dynamic loader to do. If one of these + ever stops being empty, the assumption above has broken and the module + needs relocation processing rather than a rebase -- so they are listed + explicitly, to be found by whoever goes looking. */ + + /DISCARD/ : + { + *(.ARM.exidx*) + *(.ARM.extab*) + *(.comment) + *(.note.*) + *(.dynsym) + *(.dynstr) + *(.hash) + *(.gnu.hash) + *(.dynamic) + *(.interp) + *(.rel.dyn) + *(.rel.plt) + *(.plt) + } +} diff --git a/ports_module/cortex_r52/gnu/example_build/s32z280_evb/link_module.lds b/ports_module/cortex_r52/gnu/example_build/s32z280_evb/link_module.lds new file mode 100644 index 000000000..a8962763e --- /dev/null +++ b/ports_module/cortex_r52/gnu/example_build/s32z280_evb/link_module.lds @@ -0,0 +1,344 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/* Link map for the NXP S32Z280-594EVB, RTU0 core 0. + * + * Code goes to the RTU code SRAM at its instruction-fetch address, 0x79900000, + * which is also where the core resets: MC_ME_PRTN0_CORE0_ADDR reads 0x79900000 + * on this board, so a debugger-loaded image needs no relocation to be reached + * by the reset vector. That window is writable over the debug AXI port even + * though NXP's debugger memory map declares it read-only, so plain `load` + * works and no LMA alias is required. A flash-booted image is different: it + * would have to be written through the data alias at 0x32100000. + * + * Data, bss and the per-mode stacks go to the RTU-local data SRAM at + * 0x31780000. Keeping them out of the code SRAM avoids the boundary problem + * the FVP build hit, where an aligned .data start straddled the code/data + * split, and RTU-local traffic does not leave the RTU. + * + * The TCMs are deliberately unused: they are not accessible at reset until + * their region registers are programmed, so nothing needed for early boot can + * live there. + */ + +__hyp_stack_size__ = 0x0800; +__svc_stack_size__ = 0x1000; +__irq_stack_size__ = 0x0800; +__fiq_stack_size__ = 0x0400; +__abt_stack_size__ = 0x0400; +__und_stack_size__ = 0x0400; +__sys_stack_size__ = 0x0800; + +MEMORY +{ + CODE (rx) : ORIGIN = 0x79900000, LENGTH = 0x00700000 /* 7 MB */ + /* ATCM. entry.S programmes IMP_ATCMREGIONR to this base and enables the + bank before anything runs from it, and mpu.c maps it executable. Code + placed here runs at full core speed with one wait state, where CODE is + RTU code RAM and runs at half the core frequency (S32Z2 RM 6.3.6). */ + ATCM (rwx) : ORIGIN = 0x30000000, LENGTH = 0x00010000 /* 64 KB */ + /* BTCM. 16 KB at zero wait states, enabled by entry.S, and preloaded there + as well because ECC means a location must be written before it is read. + Used for data that wants deterministic access without depending on a + cache -- an enabled TCM is never cached. */ + BTCM (rw) : ORIGIN = 0x30100000, LENGTH = 0x00004000 /* 16 KB */ + DATA (rwx) : ORIGIN = 0x31780000, LENGTH = 0x00070000 /* 448 KB: DRAM0 + DRAM1 below the module area */ + /* Module memory, uncovered by any kernel MPU region on purpose. See + S32Z_MODULE_AREA_BASE in platform.h. */ + MODULE (rwx) : ORIGIN = 0x317F0000, LENGTH = 0x00010000 /* 64 KB */ +} + +ENTRY(_start) + +SECTIONS +{ + /* .text.boot must come FIRST: MC_ME_PRTN0_CORE0_ADDR is 0x79900000 on + * this board, so whatever lands at the start of CODE is what the core + * executes out of reset, and that has to be _start. It must also be a + * T32 instruction, since the core resets in Thumb state. The vector + * tables need alignment but not a fixed address, because HVBAR and VBAR + * are programmed at run time -- so they follow rather than lead. + */ + /* No ALIGN() address expression on any output section below. Written as + * " ALIGN(n) : { }" the ALIGN is the section's *address*, evaluated + * from a location counter that starts at zero, and it silently overrides + * "> CODE" -- every section then lands near address 0 and the link fails + * with "not within region". The FVP script uses that form harmlessly only + * because its region starts at 0x00000000. Alignment comes from the input + * sections (the vector tables carry .align 5) or from an explicit + * ". = ALIGN(n);" inside the braces. + */ + .boot : + { + KEEP(*(.text.boot)) + } > CODE + + .vectors_el2 : + { + KEEP(*(.vectors_el2)) + } > CODE + + .vectors_el1 : + { + KEEP(*(.vectors_el1)) + } > CODE + + /* The shared granules the module reports its progress through, and the one + it is not allowed to reach. + + FIRST in the module area, so the base address is ORIGIN(MODULE) and the + module can carry it as a constant -- the manager deliberately knows no + symbol of the module and has no channel through which to tell it anything. + S32Z_MODULE_STATUS_BASE in platform.h is the same number, and the ASSERTs + at the bottom of this file pin the two together at link time. + + Six granules. Five are granted, one per shared entry the port provides, + because granting a single region only ever exercises the first of the five; + the sixth -- index 2, so a granted granule sits on either side of it -- is + never granted, and the module writes it to prove it still faults. + + NOLOAD: the manager clears the area before every pass, and a granule that + arrived pre-filled would make a module that never wrote one look as though + it had. */ + + .module_status (NOLOAD) : + { + __module_status_start__ = .; + . = . + 0x180; /* six 64-byte granules */ + . = ALIGN(64); + __module_status_end__ = .; + } > MODULE + + /* The module image, in the module area, just above the shared granules. + + The module is not linked here. It is built as its own image by the + s32z280_demo_module.elf target, objcopied to a raw binary and included as + bytes by module_blob.S, and this section only decides where those bytes + land. Which address that is does not matter any more: since the module + became relocatable it is linked against nominal addresses it never runs + at and _gcc_setup rebases it to wherever it was put, so this only has to + be inside the module area and disjoint from everything else in it. + + The earlier arrangement compiled the module's sources into this image and + gathered them here by object name. That cannot work. The module library + defines shims named after the same ThreadX entry points the kernel + defines, and in a single link the shims win, because they arrive as + objects and the kernel arrives as a static library. The manager's own + tx_thread_create resolved to the module's copy at 0x317F1700, called into + the module area that no kernel region covers, and took a silent prefetch + abort before the first thread ever ran. + + Keeping the module out of the link also removes a whole class of quiet + failure that arrangement had: matching input sections by object-file name + fails open. A missing suffix or a wildcard that does not match produces an + empty section, a link that succeeds and an image with no module in it, + twice over here -- and the block had to sit before .text, because + placement is first match and the kernel's *(.text*) would otherwise + swallow the module's code while leaving its data behind. + + This block still sits before .text: harmless now, and it keeps the module + at the head of the map where it is easy to find. */ + + .module_image : + { + __module_image_start__ = .; + KEEP(*(.module_blob)) + . = ALIGN(64); + __module_image_end__ = .; + } > MODULE + + /* The pool the manager allocates module data from, in the module area for + the same reason the image is: whatever the manager hands to a module + becomes an MPU region, and PMSAv8-R will not allow that region to overlap + a kernel one. Anything a module can be given has to live outside every + region in the boot table, and this area is the only such memory. + + NOLOAD because nothing is copied in -- the byte pool writes its own + headers when it is created. */ + + .module_pool (NOLOAD) : + { + . = ALIGN(64); + __module_pool_start__ = .; + *(.module_pool) + . = ALIGN(64); + __module_pool_end__ = .; + } > MODULE + + /* A second place to load the same module from, which is how this example + proves the module is relocatable rather than merely built to be. + + A module that runs correctly at the address it was linked for proves + nothing about relocation -- the GOT rebase would produce the same + addresses it started with and a broken rebase would look identical. So + the manager copies the blob here and loads it a second time, and the two + runs are compared. Any address in the module area would do; what matters + is that it is not __module_image_start__ and that it does not overlap the + pool, because the code region of the second instance and the data regions + the pool hands out are live at the same time and PMSAv8-R does not permit + two enabled regions to overlap. + + NOLOAD, and deliberately not initialised at link time: if the blob were + placed here by the linker as well, a failure to copy it would be invisible + because the right bytes would already be present. */ + + .module_stage (NOLOAD) : + { + . = ALIGN(64); + __module_stage_start__ = .; + . = . + 0x1000; + . = ALIGN(64); + __module_stage_end__ = .; + } > MODULE + + /* The code and data sizes are not computed here any more. They belong to + the module's own link, which is where its preamble is assembled and where + the boundary between its code and its data is actually known. */ + + .text : + { + *(.text*) + *(.glue_7) + *(.glue_7t) + } > CODE + + /* Code that runs from tightly-coupled memory. Loaded into CODE and copied + to ATCM by atcm_copy_text() before it is called, because ECC is enabled + on this part and a TCM location must be written before it is read + (Cortex-R52 TRM 6.2.2). The copy uses 64-bit stores for the same + reason: ATCM requires them where BTCM and CTCM accept 32-bit. + + ALIGN(8) at both ends so the copy can move whole 64-bit units without a + tail case, which is what keeps the ECC requirement satisfied for every + location written. */ + + .atcm_text : ALIGN(8) + { + __atcm_text_start__ = .; + *(.atcm_text*) + . = ALIGN(8); + __atcm_text_end__ = .; + } > ATCM AT> CODE + + __atcm_text_load__ = LOADADDR(.atcm_text); + + .rodata : + { + *(.rodata*) + . = ALIGN(4); + __code_end__ = .; + } > CODE + + /* The module's gateway into the kernel, deliberately after __code_end__ and + therefore outside the kernel code region, which ends there. A module gets + its own region covering exactly this function; that region would otherwise + overlap the kernel's, which PMSAv8-R does not allow. + + Alone in its own section on purpose: anything sharing it would become + executable by every module. 64-byte aligned at both ends, the PMSAv8-R + granule, so a region can start and stop on it without covering + neighbours. */ + + .txm_user_entry : ALIGN(64) + { + __txm_user_entry_start__ = .; + KEEP(*(.txm_user_entry)) + . = ALIGN(64); + __txm_user_entry_end__ = .; + } > CODE + + .data : + { + . = ALIGN(8); + __data_start__ = .; + *(.data*) + . = ALIGN(8); + __data_end__ = .; + } > DATA + + /* Data placed in BTCM. NOLOAD: nothing is copied in, and entry.S has + already written every location in the bank to establish ECC check bits, + so anything here is safe to read before it is written by the program. */ + + .btcm_bss (NOLOAD) : ALIGN(8) + { + __btcm_bss_start__ = .; + *(.btcm_bss*) + . = ALIGN(8); + __btcm_bss_end__ = .; + } > BTCM + + .bss (NOLOAD) : + { + . = ALIGN(8); + __bss_start__ = .; + *(.bss*) + *(COMMON) + . = ALIGN(8); + __bss_end__ = .; + } > DATA + + /* Per-mode stacks. Each mode needs its own on an R-profile core: an + * exception taken while a handler is running would otherwise reuse the + * interrupted mode's stack pointer. + */ + .stacks (NOLOAD) : + { + . = ALIGN(8); + . = . + __hyp_stack_size__; + __hyp_stack_top = .; + . = ALIGN(8); + . = . + __svc_stack_size__; + __svc_stack_top = .; + . = ALIGN(8); + . = . + __irq_stack_size__; + __irq_stack_top = .; + . = ALIGN(8); + . = . + __fiq_stack_size__; + __fiq_stack_top = .; + . = ALIGN(8); + . = . + __abt_stack_size__; + __abt_stack_top = .; + . = ALIGN(8); + . = . + __und_stack_size__; + __und_stack_top = .; + . = ALIGN(8); + . = . + __sys_stack_size__; + __sys_stack_top = .; + } > DATA + + /* Both spellings: _tx_initialize_low_level publishes the first free + address to tx_application_define from _end, while C library conventions + use end. */ + + PROVIDE(end = .); + PROVIDE(_end = .); + + /* The module carries the status base as a constant and platform.h names it + as S32Z_MODULE_STATUS_BASE. Neither can see this script, so the agreement + is pinned here; the manager checks the same thing again at run time + against the symbol, so a build that skipped this file still says so. */ + + ASSERT(__module_status_start__ == 0x317F0000, + "the module status area is not at S32Z_MODULE_STATUS_BASE") + + /* And its size: the manager grants one region per granule from that base and + the module addresses them by index, so an area that is not exactly + S32Z_MODULE_STATUS_GRANULES granules long would leave a grant, or a module + write, outside it. */ + + ASSERT(__module_status_end__ - __module_status_start__ == 0x180, + "the module status area is not S32Z_MODULE_STATUS_GRANULES granules long") +} diff --git a/ports_module/cortex_r52/gnu/example_build/s32z280_evb/module_blob.S b/ports_module/cortex_r52/gnu/example_build/s32z280_evb/module_blob.S new file mode 100644 index 000000000..bd4045422 --- /dev/null +++ b/ports_module/cortex_r52/gnu/example_build/s32z280_evb/module_blob.S @@ -0,0 +1,65 @@ +@/*************************************************************************** +@ * 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. +@ * +@ * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +@ * The AI-generated portions may be considered public domain (CC0-1.0) +@ * and not subject to the project's licence. The human contributor has +@ * reviewed and verified that the code is correct. +@ * +@ * SPDX-License-Identifier: MIT and CC0-1.0 +@ **************************************************************************/ +@ +@/**************************************************************************/ +@/* */ +@/* MODULE MANAGER RELEASE */ +@/* */ +@/* module_blob.S Cortex-R52/GNU */ +@/* 6.5.2 */ +@/* AUTHOR */ +@/* */ +@/* Frédéric Desbiens, Eclipse Foundation */ +@/* */ +@/* DESCRIPTION */ +@/* */ +@/* Carries the demonstration module into the manager image as data. */ +@/* */ +@/* The module is built as its own link unit and objcopied to a raw */ +@/* binary, which is included here verbatim. It has to be a separate */ +@/* link: the module library defines shims named after the ThreadX API */ +@/* entry points the kernel also defines, and in one link the shims win */ +@/* -- objects beat archive members -- so the manager's own service calls */ +@/* end up trapping into the module. */ +@/* */ +@/* Included as bytes rather than linked as objects, so the module's */ +@/* symbols never enter the manager's link at all. Nothing here is */ +@/* called: the manager finds the preamble at the start of the image and */ +@/* reaches everything else through that. */ +@/* */ +@/**************************************************************************/ + + .section .module_blob, "a" + +@ 64-byte aligned, the PMSAv8-R granule, so the image starts where a region +@ can start. The linker script places this section at the module area base, +@ which is the address the module itself was linked for. + + .align 6 + + .global __demo_module_image + .global __demo_module_image_end + +__demo_module_image: + +@ demo_module.bin is produced by the s32z280_demo_module.elf target. The +@ assembler finds it through an include path pointing at the build directory, +@ set in CMakeLists.txt -- .incbin searches the -I paths, not the source tree. + + .incbin "demo_module.bin" + +__demo_module_image_end: + + .align 6 diff --git a/ports_module/cortex_r52/gnu/example_build/s32z280_evb/sample_threadx_module.c b/ports_module/cortex_r52/gnu/example_build/s32z280_evb/sample_threadx_module.c new file mode 100644 index 000000000..dbf0c8a82 --- /dev/null +++ b/ports_module/cortex_r52/gnu/example_build/s32z280_evb/sample_threadx_module.c @@ -0,0 +1,319 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* SAMPLE MODULE RELEASE */ +/* */ +/* sample_threadx_module.c Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frédéric Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* A module that exercises the protection boundary rather than */ +/* demonstrating features, for the NXP S32Z280-594EVB. */ +/* */ +/* The FVP copy of this file is the same module for the same port; what */ +/* differs is the two addresses at the bottom and the board named here, */ +/* so `diff` is the tool for telling whether the two have drifted. */ +/* */ +/* Four steps: */ +/* */ +/* 1. Writes and reads its own data, which must succeed. */ +/* 2. Makes a kernel call, which must succeed -- proving a module in */ +/* User mode can reach the kernel through the supervisor call */ +/* boundary and come back. */ +/* 3. Violates its protection in one of three ways the manager */ +/* selects, which must fault. */ +/* 4. Never reaches step 4, because step 3 terminates it. */ +/* */ +/* THE THREE VIOLATIONS. Two of them are the two aborts the hardware */ +/* distinguishes: reading the kernel's data is a DATA abort reported */ +/* through DFSR and DFAR, branching out of the code region is a */ +/* PREFETCH abort reported through IFSR and IFAR. The third writes a */ +/* granule of the SHARED area that the manager deliberately did not */ +/* grant, after writing and reading back every granule it did -- so it */ +/* is the shared-region machinery under test rather than the kernel's */ +/* own memory, and a grant that covered one granule too many is what it */ +/* is looking for. */ +/* */ +/* Steps 1 and 2 passing without step 3 faulting would mean the module */ +/* is running unprotected, which is the failure this example exists to */ +/* detect. A module that only ever touched its own memory would pass */ +/* identically with the MPU switched off. */ +/* */ +/* HOW PROGRESS GETS OUT. A module cannot print: the console belongs */ +/* to the board support package, outside every region a module owns, so */ +/* reaching it would fault as surely as step 3 does. So progress is */ +/* recorded twice -- in the module's own data, and in the first granule */ +/* of the shared area the manager granted it. */ +/* */ +/* Which of the two can be read depends on the board. On silicon a GDB */ +/* harness reads the module's own copy out of the data area the manager */ +/* allocated for it; the FVP has no such seam -- it exposes an Iris */ +/* server and no GDB stub -- so there only the shared copy is readable */ +/* and everything the run reports has to be reported by the image */ +/* itself. Both writes are kept on both boards deliberately: if the */ +/* shared write were the only one, a module that could not reach its own */ +/* data would still report progress. */ +/* */ +/* The shared address is a literal on this side. The module has no */ +/* loader to tell it anything and the manager deliberately knows no */ +/* symbol of the module, so the two agree by convention -- and the */ +/* manager checks that they do, against the linker's own symbol, rather */ +/* than trusting them to. */ +/* */ +/**************************************************************************/ + +#include "txm_module.h" + +/* Progress, recorded in two places. See the header: the shared copy is what + the manager reads, and the module's own copy is what proves it could write + its own data at all. */ + +#define MODULE_PROGRESS_OWN_DATA 0x00000001UL +#define MODULE_PROGRESS_KERNEL_CALL 0x00000002UL +#define MODULE_PROGRESS_ATTEMPTED_STEAL 0x00000004UL +#define MODULE_PROGRESS_SURVIVED_STEAL 0x00000008UL +#define MODULE_PROGRESS_ATTEMPTED_JUMP 0x00000010UL +#define MODULE_PROGRESS_SURVIVED_JUMP 0x00000020UL +#define MODULE_PROGRESS_SHARED_WROTE 0x00000040UL +#define MODULE_PROGRESS_ATTEMPTED_GAP 0x00000080UL +#define MODULE_PROGRESS_SURVIVED_GAP 0x00000100UL + +/* Which violation to commit, taken from the low byte of the module ID the + manager passes to the start thread. The rest of that word is left alone: the + preamble ships it as 0x52520001, so a manager that sets nothing still gets a + working data-abort test rather than a module that does nothing. */ + +#define MODULE_TEST_MASK 0x000000FFUL +#define MODULE_TEST_DATA_ABORT 0x00000001UL +#define MODULE_TEST_PREFETCH_ABORT 0x00000002UL +#define MODULE_TEST_SHARED_ABORT 0x00000003UL + +/* The shared status word, at the base of the module area. + + A literal address rather than anything reached through the GOT, because it is + not the module's own memory: it is memory the manager granted, and the module + has no channel through which to be told where it is. The same number is + S32Z_MODULE_STATUS_BASE in platform.h and ORIGIN(MODULE) in link_module.lds; + the manager checks all three agree before it starts this module, so a + disagreement is a reported failure rather than a fault at the first write. + + MISRA C:2012 Rule 11.6 (conversion between an integer and a pointer to void) + is deliberately violated: an address agreed between two separately linked + images can only be written as a literal, and there is no conforming way to + express it. */ + +#define MODULE_STATUS_ADDRESS 0x317F0000UL + +#define MODULE_STATUS (*((volatile ULONG *) MODULE_STATUS_ADDRESS)) + +/* And the rest of the shared area, which exists to exercise the shared-region + machinery rather than to report anything. + + The manager may grant a module TXM_MODULE_MPU_SHARED_ENTRIES regions and one + grant only ever proves the first entry works, so the area holds one granule + per entry -- five granted, and a sixth that the manager never grants. The + ungranted one is index 2, which puts a granted granule on either side of it: + a limit register masked the wrong way, or a base off by a granule, leaks into + that gap from below or from above, and either way a module that can write it + was given more than was asked for. + + The mark for each granule goes at WORD 1, because word 0 of granule 0 is the + progress word above. Uniform across all six so the address the gap write + faults on is one expression on both sides of the agreement. */ + +#define MODULE_STATUS_GRANULE 0x40UL +#define MODULE_STATUS_GRANULES 6UL +#define MODULE_STATUS_UNGRANTED 2UL +#define MODULE_STATUS_MARK_OFFSET 4UL + +#define MODULE_SHARED_SIGNATURE 0x5A5A0000UL + +#define MODULE_SHARED_MARK(index) \ + (*((volatile ULONG *) (MODULE_STATUS_ADDRESS \ + + ((index) * MODULE_STATUS_GRANULE) \ + + MODULE_STATUS_MARK_OFFSET))) + +volatile ULONG module_progress; +volatile ULONG module_scratch[16]; + +/* An address the module has no business touching, used by step 3. + + The base of DRAM0, where the manager's own data and stacks live on this + board: that region is EL1 read/write and execute-never, so a User-mode read + of it is a permission fault and a User-mode instruction fetch from it is one + too. Both are what step 3 needs, and both prove the KERNEL'S memory is what + a module cannot reach -- which is the property being demonstrated, rather + than the absence of a mapping. + + Held in initialised data rather than written as a literal, deliberately and + unlike the status address above. The module reads it through its rebased + GOT, so the value arriving in DFAR or IFAR also proves the GOT was rewritten + and .data was copied. The manager knows the same number and checks it. */ + +volatile ULONG module_forbidden_address = 0x31780000UL; + + +/* Declared as well as defined because the only caller is assembly: + txm_module_preamble.S names it with .extern and stores its offset in the + START entry-point word. An assembly caller supplies no prototype, so + without this the definition has external linkage and no visible + declaration -- prohibited by MISRA C:2012 Rule 8.4 and reported by + -Wmissing-prototypes. Same reason the board support has board.h. */ + +void demo_module_start(ULONG id); + + +void demo_module_start(ULONG id) +{ + ULONG i; + ULONG sum = 0UL; + ULONG shared_ok = 1UL; + + /* 1. The module's own data. If this faults, the data region is wrong and + nothing else in this file will be reached. */ + + for (i = 0UL; i < 16UL; i++) + { + module_scratch[i] = i * 3UL; + } + + for (i = 0UL; i < 16UL; i++) + { + sum += module_scratch[i]; + } + + if (sum == 360UL) /* 3 * (0 + 1 + ... + 15) */ + { + module_progress |= MODULE_PROGRESS_OWN_DATA; + MODULE_STATUS |= MODULE_PROGRESS_OWN_DATA; + } + + /* 2. A kernel call, which leaves User mode through the supervisor call + boundary and must come back. A sleep is used because it is the + simplest service with an observable effect and it yields, so the + scheduler runs a module thread and reloads its regions on the way + back -- exercising the region switch as well as the call. */ + + if (tx_thread_sleep(2UL) == TX_SUCCESS) + { + module_progress |= MODULE_PROGRESS_KERNEL_CALL; + MODULE_STATUS |= MODULE_PROGRESS_KERNEL_CALL; + } + + /* 3. The violation, and 4. the flag that says it was tolerated. Each is + marked before the access rather than after, because after is not + reached if the port is working. The SURVIVED flags are what the + manager fails on: they can only appear if the hardware allowed an + access it was configured to refuse. */ + + if ((id & MODULE_TEST_MASK) == MODULE_TEST_SHARED_ABORT) + { + /* Write every granule the manager granted, read all of them back, and + then write the one it did not grant. + + The readback matters as much as the write. A shared entry programmed + with the wrong base still accepts a store -- it just lands somewhere + else -- so a write that is never read back proves only that the core + did not object. Reading each granule's own mark out of its own + granule is what says the five entries describe five distinct + extents. */ + + for (i = 0UL; i < MODULE_STATUS_GRANULES; i++) + { + if (i != MODULE_STATUS_UNGRANTED) + { + MODULE_SHARED_MARK(i) = MODULE_SHARED_SIGNATURE | i; + } + } + + for (i = 0UL; i < MODULE_STATUS_GRANULES; i++) + { + if ((i != MODULE_STATUS_UNGRANTED) && + (MODULE_SHARED_MARK(i) != (MODULE_SHARED_SIGNATURE | i))) + { + shared_ok = 0UL; + } + } + + if (shared_ok != 0UL) + { + module_progress |= MODULE_PROGRESS_SHARED_WROTE; + MODULE_STATUS |= MODULE_PROGRESS_SHARED_WROTE; + } + + /* The gap. A WRITE rather than a read, so DFSR reports WnR set and the + fault cannot be confused with the read the data-abort passes do. It + lies between two granules this module was granted, so surviving it + means a grant covered a granule nobody asked for -- which is the + whole reason this pass exists. */ + + module_progress |= MODULE_PROGRESS_ATTEMPTED_GAP; + MODULE_STATUS |= MODULE_PROGRESS_ATTEMPTED_GAP; + + MODULE_SHARED_MARK(MODULE_STATUS_UNGRANTED) = + MODULE_SHARED_SIGNATURE | MODULE_STATUS_UNGRANTED; + + module_progress |= MODULE_PROGRESS_SURVIVED_GAP; + MODULE_STATUS |= MODULE_PROGRESS_SURVIVED_GAP; + } + else if ((id & MODULE_TEST_MASK) == MODULE_TEST_PREFETCH_ABORT) + { + /* Branch outside the code region: a prefetch abort, reported through + IFSR and IFAR. Nothing is executed at the target -- the fault is on + the fetch itself, so the thread never arrives. */ + + module_progress |= MODULE_PROGRESS_ATTEMPTED_JUMP; + MODULE_STATUS |= MODULE_PROGRESS_ATTEMPTED_JUMP; + + /* MISRA C:2012 Rule 11.1 (no conversion between a pointer to a function + and any other type) is deliberately violated here, and Rule 11.6 + (no conversion between an integer and a pointer to void) with it. + Provoking a fetch from an address that holds no function is the entire + purpose of these three lines; there is no conforming way to write it. */ + + ((void (*)(void)) module_forbidden_address)(); + + module_progress |= MODULE_PROGRESS_SURVIVED_JUMP; + MODULE_STATUS |= MODULE_PROGRESS_SURVIVED_JUMP; + } + else + { + /* Read outside the data region: a data abort, reported through DFSR and + DFAR. */ + + module_progress |= MODULE_PROGRESS_ATTEMPTED_STEAL; + MODULE_STATUS |= MODULE_PROGRESS_ATTEMPTED_STEAL; + + sum += *((volatile ULONG *) module_forbidden_address); + + module_progress |= MODULE_PROGRESS_SURVIVED_STEAL; + MODULE_STATUS |= MODULE_PROGRESS_SURVIVED_STEAL; + } + + /* Keep the compiler from discarding the read above. */ + + module_scratch[0] = sum; + + while (1) + { + (void) tx_thread_sleep(100UL); + } +} diff --git a/ports_module/cortex_r52/gnu/example_build/s32z280_evb/sample_threadx_module_manager.c b/ports_module/cortex_r52/gnu/example_build/s32z280_evb/sample_threadx_module_manager.c new file mode 100644 index 000000000..7b7d822e4 --- /dev/null +++ b/ports_module/cortex_r52/gnu/example_build/s32z280_evb/sample_threadx_module_manager.c @@ -0,0 +1,1736 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* MODULE MANAGER SAMPLE RELEASE */ +/* */ +/* sample_threadx_module_manager.c Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frédéric Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Loads the sample module four times, lets it misbehave every time, */ +/* and reports what the hardware did about it. */ +/* */ +/* The result this example exists to produce is the fault. A module */ +/* that starts and runs proves the loader works; a module that is */ +/* stopped by the memory protection unit when it reaches outside its */ +/* own memory proves the port works. So the fault notification is not */ +/* an error path here, it is the expected outcome, and its absence is */ +/* the failure. */ +/* */ +/* TWO passes, because one proves nothing about relocation. The module */ +/* is position independent: it is linked against nominal addresses it */ +/* never runs at, and _gcc_setup rewrites its global offset table to */ +/* wherever the manager actually put it. A single run at the linked */ +/* address would exercise a rebase whose input and output are the same */ +/* number, and would look identical if the rebase did nothing at all. */ +/* */ +/* So pass 1 loads the blob where the linker placed it and pass 2 loads */ +/* a byte-for-byte copy of it from the staging area, with pass 1 still */ +/* holding its pool memory so that pass 2's data lands somewhere else */ +/* too. Both the code base and the data base therefore differ between */ +/* the passes, which is what makes the comparison at the end mean */ +/* something: */ +/* */ +/* * the same instruction faults in both passes -- equal offsets from */ +/* each pass's own code base, at two different absolute addresses. */ +/* The module ran relocated. */ +/* * DFAR is the forbidden address in both passes. The module got */ +/* that value by reading one of its own initialised globals through */ +/* the rebased GOT, so this single register proves the GOT was */ +/* rewritten and .data was copied. */ +/* * SPSR says User mode in both passes. The boundary held. */ +/* */ +/* All of which is checked on the console, with no help from a debugger */ +/* and without the manager needing to know one symbol of the module. */ +/* */ +/* THEN A THIRD PASS, which faults the other way. The two passes above */ +/* make the module read an address it does not own: a data abort, */ +/* reported through DFSR and DFAR. A module can equally leave its code */ +/* region, which is a prefetch abort reported through IFSR and IFAR and */ +/* arrives at the handler by a different vector. Both halves of the */ +/* port's fault path are therefore exercised, and neither is inferred */ +/* from the other. */ +/* */ +/* Which violation a pass commits is chosen here, not in the module: the */ +/* manager writes the application-defined module ID in the instance */ +/* after loading it, and the manager passes that word to the module's */ +/* start thread. So one blob covers both cases and the manager needs no */ +/* symbol of the module to select between them. */ +/* */ +/* The third pass runs after the first two have been unloaded, which is */ +/* the other half of what this file demonstrates: a module fault must */ +/* leave the manager able to load and run the next module. A fault that */ +/* kills the manager is not isolation, and a fault that leaves the MPU */ +/* in a state where the next load misbehaves is not either. */ +/* */ +/* AND THE NOTIFICATION IS CHECKED, not merely printed. The manager */ +/* registers a fault-notify callback, and every pass must see it run */ +/* exactly once with the faulting thread and the right module instance. */ +/* That path used to be dead on this port -- the shared fault handler */ +/* terminates the thread before calling the hook, which only returns if */ +/* the port's abort vector tells the kernel it is inside an exception, */ +/* and this port's did not. It does now, so the hook is a result rather */ +/* than a known defect. */ +/* */ +/* AND A FOURTH PASS FOR THE SHARED REGIONS. The three above are each */ +/* granted one shared region -- the status granule they report their */ +/* progress through -- which exercises the first of the five shared */ +/* entries the port provides and says nothing about the other four. */ +/* The fourth pass is granted all five, one 64-byte granule each, and */ +/* is NOT granted the granule that sits between two of them. It writes */ +/* every granule it was given, reads every one of them back, and then */ +/* writes the gap, which must fault. */ +/* */ +/* That shape is chosen against a specific defect. A limit register */ +/* masked the wrong way, or a base off by one granule, extends a region */ +/* past what was asked for -- and with the gap sandwiched between two */ +/* granted granules it is reachable from either side if that happens. */ +/* The readback matters as much as the write: a region programmed with */ +/* the wrong base accepts a store and puts it elsewhere, so five marks */ +/* read out of five granules is what says five distinct extents were */ +/* programmed rather than one of them five times. */ +/* */ +/* The same pass probes the two ways the manager refuses a grant, which */ +/* nothing had ever called: an unaligned address must come back */ +/* TXM_MODULE_ALIGNMENT_ERROR, and one grant past the entry count must */ +/* come back TX_NO_MEMORY. Both are checked by name. The order is not */ +/* free -- the entry-count check runs before the alignment check, so the */ +/* unaligned probe has to happen while entries remain. */ +/* */ +/* A SECOND READING OF THE PROGRESS WORD comes with those granules. The */ +/* module records what it managed twice: in its own data, which the GDB */ +/* harness reads, and in the first shared granule, which this file now */ +/* reads on the target. The two are independent readings of the same */ +/* event, so the console judges progress without a debugger and the */ +/* harness still cross-checks it against the module's own copy. */ +/* */ +/* What the module image is and where it comes from: it is linked into */ +/* this application as a separate section and loaded in place, so */ +/* nothing is copied and no filesystem or download path is needed. */ +/* The manager still maps it with its own MPU regions, which is what */ +/* matters -- loading in place changes where the code lives, not */ +/* whether it is protected. */ +/* */ +/**************************************************************************/ + +#include "tx_api.h" +#include "txm_module.h" +#include "linflexd.h" +#include "platform.h" +#include "thread_mpu.h" +#include "cache.h" + +/* For bsp_main, which entry.S calls and therefore never declares. Every + other example in the board support package includes this header for the + same reason; MISRA C:2012 Rule 8.4 wants the declaration visible at the + definition, and -Wmissing-prototypes reports it when it is not. */ + +#include "board.h" + +/* The fault information the abort vector captured. Declared here because the + module manager expands it into the port's fault handler through the + TXM_MODULE_MANAGER_FAULT_INFO macro rather than declaring it in a header, so an + application that wants to read it has to say so itself. */ + +extern TXM_MODULE_MANAGER_MEMORY_FAULT_INFO _txm_module_manager_memory_fault_info; + +/* Where the module image sits. Provided by the linker script, which places the + module's preamble first so this address is also the preamble address. */ + +extern unsigned char __module_image_start__; +extern unsigned char __module_image_end__; + +/* The second address the same blob is loaded from, so relocation can be shown + rather than assumed. Reserved by the linker script and left empty by it -- + see .module_stage in link_module.lds for why it is not pre-filled. */ + +extern unsigned char __module_stage_start__; +extern unsigned char __module_stage_end__; + +/* The shared granules the module reports its progress through, and the one it + is not allowed to reach. See S32Z_MODULE_STATUS_BASE in platform.h. */ + +extern unsigned char __module_status_start__; +extern unsigned char __module_status_end__; + +/* The address the module is going to reach for and must not be allowed to have. + Declared here only so the console check can name it; the value lives in the + module's own initialised data, which is the point -- the module reads it + through its rebased GOT, so seeing it arrive in DFAR proves the rebase and + the .data copy both worked. Kept in step with sample_threadx_module.c by + hand, and checked at run time rather than trusted: if the two ever disagree + the relocation verdict says so instead of quietly passing. */ + +#define MODULE_FORBIDDEN_ADDRESS 0x31780000UL + +/* The shared area. The same numbers are S32Z_MODULE_STATUS_* in platform.h, + ORIGIN(MODULE) in link_module.lds and MODULE_STATUS_ADDRESS in the module; + the ASSERTs in the link script pin three of them together at link time and + the manager checks the linker's symbol at run time rather than trusting it. + + MODULE_STATUS_LENGTH is one granule and also the length of one grant. The + area is MODULE_STATUS_GRANULES of them: five the shared pass is granted, one + entry each, and MODULE_STATUS_UNGRANTED -- index 2, so a granted granule sits + on either side of it -- which is never granted to anything. Each granule's + mark goes at word 1, because word 0 of granule 0 is the progress word. + + MISRA C:2012 Rule 11.6 is deliberately violated by the accessors: an address + agreed between two separately linked images can only be written as a literal + and there is no conforming way to express it. */ + +#define MODULE_STATUS_ADDRESS S32Z_MODULE_STATUS_BASE +#define MODULE_STATUS_LENGTH S32Z_MODULE_STATUS_SIZE +#define MODULE_STATUS_GRANULES S32Z_MODULE_STATUS_GRANULES +#define MODULE_STATUS_UNGRANTED S32Z_MODULE_STATUS_UNGRANTED +#define MODULE_STATUS_AREA_LENGTH (MODULE_STATUS_GRANULES * MODULE_STATUS_LENGTH) +#define MODULE_STATUS_MARK_OFFSET 4UL + +#define MODULE_SHARED_SIGNATURE 0x5A5A0000UL + +/* How many grants the shared pass makes, which is every entry the port + provides -- granting fewer would leave an entry unexercised, and that the + other four work at all is what the pass exists to establish. */ + +#define MODULE_SHARED_GRANTS (MODULE_STATUS_GRANULES - 1UL) + +/* The two grants that must be refused on size, and the one that must not be. + + The top granule is the boundary case of the overflow guard: its inclusive end + is exactly 0xFFFFFFFF, so a guard written as (address + length) < address, or + one that tested the end against the top with the wrong comparison, would + refuse a perfectly legal grant. The wrapping grant starts at the same place + and asks for twice the room that is left. + + Neither address is ever programmed into the MPU: the guard probes run on an + instance that is loaded and unloaded without being started, so the accepted + grant is recorded in the instance and nothing more. That matters more here + than on the model -- the top of the address space on this part is peripheral + space the boot regions already cover, and two enabled regions over one + address is a translation fault waiting for whoever reads it. */ + +#define MODULE_TOP_GRANULE_ADDRESS (0xFFFFFFFFUL - (TXM_MODULE_MPU_ALIGNMENT - 1UL)) +#define MODULE_TOP_GRANULE_LENGTH TXM_MODULE_MPU_ALIGNMENT +#define MODULE_WRAP_LENGTH (2UL * TXM_MODULE_MPU_ALIGNMENT) + +#define MODULE_GRANULE_ADDRESS(index) \ + (MODULE_STATUS_ADDRESS + ((index) * MODULE_STATUS_LENGTH)) + +#define MODULE_SHARED_MARK(index) \ + (*((volatile ULONG *) (MODULE_GRANULE_ADDRESS(index) \ + + MODULE_STATUS_MARK_OFFSET))) + +/* The progress bits the module sets, mirrored from sample_threadx_module.c. + The three SURVIVED flags can only ever be set if the hardware allowed an + access it was configured to refuse, so they are checked for by name. */ + +#define MODULE_PROGRESS_OWN_DATA 0x00000001UL +#define MODULE_PROGRESS_KERNEL_CALL 0x00000002UL +#define MODULE_PROGRESS_ATTEMPTED_STEAL 0x00000004UL +#define MODULE_PROGRESS_SURVIVED_STEAL 0x00000008UL +#define MODULE_PROGRESS_ATTEMPTED_JUMP 0x00000010UL +#define MODULE_PROGRESS_SURVIVED_JUMP 0x00000020UL +#define MODULE_PROGRESS_SHARED_WROTE 0x00000040UL +#define MODULE_PROGRESS_ATTEMPTED_GAP 0x00000080UL +#define MODULE_PROGRESS_SURVIVED_GAP 0x00000100UL + +#define MODULE_PROGRESS_SURVIVED (MODULE_PROGRESS_SURVIVED_STEAL | \ + MODULE_PROGRESS_SURVIVED_JUMP | \ + MODULE_PROGRESS_SURVIVED_GAP) + +/* Which violation a pass tells the module to commit. Written into the module + instance's application-defined ID after the load and before the start, because + that word is what the manager hands the module's start thread. The high half + is the fingerprint the preamble ships; only the low byte selects the test, so a + module started without this still runs the data-abort case. */ + +#define MODULE_ID_BASE 0x52520000UL +#define MODULE_TEST_DATA_ABORT 0x00000001UL +#define MODULE_TEST_PREFETCH_ABORT 0x00000002UL +#define MODULE_TEST_SHARED_ABORT 0x00000003UL + +/* Memory the manager hands out to modules: object memory, and the data region a + module's own variables live in. It has to be outside every region a module is + given, or a module could reach another module's data. */ + +#ifndef MODULE_POOL_SIZE +#define MODULE_POOL_SIZE (16U * 1024U) +#endif + +/* In the module area, not in .bss. The manager carves a module's data out of + this pool, and that data is handed to the module as an MPU region -- so if the + pool lived in .bss it would sit inside the kernel's data region and the two + would overlap, which PMSAv8-R does not allow. Keeping the pool in the module + area is what makes a module's data disjoint from every kernel region. */ + +static unsigned char module_pool[MODULE_POOL_SIZE] + __attribute__((aligned(64), section(".module_pool"))); + +/* The object pool, which is a separate allocation from the module pool above and + is not optional here. A module that runs in User mode needs a kernel stack + for the privileged side of each system call, and the manager allocates that + from this pool -- txm_module_manager_initialize deliberately leaves the pool + uncreated, so without this a User-mode module fails to start with + TX_NOT_AVAILABLE from deep inside the thread create, which is not an obvious + way to be told that a pool is missing. */ + +#ifndef MODULE_OBJECT_POOL_SIZE +#define MODULE_OBJECT_POOL_SIZE (8U * 1024U) +#endif + +static unsigned char module_object_pool[MODULE_OBJECT_POOL_SIZE] + __attribute__((aligned(64))); + +/* One instance per pass. Passes 1 and 2 are loaded at once for part of the run: + pass 1 is stopped but still holds its data allocation while pass 2 loads, which + is what pushes pass 2's data base somewhere different. Pass 3 runs after both + have been unloaded, which is deliberate -- see the header. */ + +#define MODULE_PASSES 4U +#define MODULE_RELOCATION_PASSES 2U + +static TXM_MODULE_INSTANCE demo_module[MODULE_PASSES]; + +/* What each pass produced. Recorded rather than printed as it happens, because + the comparison between the two passes is the actual result and it cannot be + made until both have run. */ + +typedef struct PASS_RESULT_STRUCT +{ + CHAR *pass_name; + ULONG pass_test; /* MODULE_TEST_*: which abort is expected */ + ULONG pass_load_status; + ULONG pass_share_status; + ULONG pass_start_status; + ULONG pass_stop_status; + ULONG pass_code_start; + ULONG pass_code_end; + ULONG pass_data_start; + ULONG pass_data_end; + ULONG pass_data_base; + ULONG pass_faults; + ULONG pass_captured; + ULONG pass_fault_r9; + ULONG pass_dfsr; + ULONG pass_dfar; + ULONG pass_ifsr; + ULONG pass_ifar; + ULONG pass_spsr; + ULONG pass_code_location; + + /* What the module reported through the shared granules. Read on the target + rather than only by the debug harness: the harness reads the module's own + copy of the same word out of its data area, so the two are independent + readings of the same event and a disagreement is worth seeing. */ + + ULONG pass_progress; + ULONG pass_expect_progress; + + /* The shared-region results. Only the shared pass fills these in, so they + are judged only for that pass -- zero is TX_SUCCESS, and a pass that never + probed would otherwise read as one that probed and was refused nothing. */ + + ULONG pass_shared_grants; /* grants that succeeded */ + ULONG pass_shared_count; /* entries the instance holds after */ + ULONG pass_align_status; /* refusing an unaligned grant */ + ULONG pass_exhaust_status; /* refusing one grant too many */ + ULONG pass_marks[S32Z_MODULE_STATUS_GRANULES]; + + /* The address this pass must fault on. Per pass rather than one constant, + because the shared pass faults on the granule it was not granted and the + other three fault on the kernel's data. */ + + ULONG pass_expect_fault; + + /* What the notify callback was told, against what it should have been told. + Recorded as plain words rather than pointers so the console can print them + and a mismatch names both values. */ + + ULONG pass_notify_thread; + ULONG pass_notify_instance; + ULONG pass_expect_thread; + ULONG pass_expect_instance; +} PASS_RESULT; + +static PASS_RESULT pass_results[MODULE_PASSES]; + +/* The shared-grant size guards, which are about the manager and not about the + module. They need a LOADED instance and nothing else, so they get their own + -- loaded after the four passes are done with the pool, never started, and + unloaded again. Not folded into the shared pass because that pass grants + every entry the port has and has none to spare for a grant that is meant to + succeed, and not folded into one of the other three because a grant they + accepted would be programmed into the MPU when their module ran. + + The byte pool reuses a freed block, so this instance's data lands on top of + an earlier pass's. Harmless: it never runs, and every pass has been read + back at its own pass_done() long before this loads. */ + +typedef struct GUARD_RESULT_STRUCT +{ + ULONG guard_load_status; + ULONG guard_count_start; /* entries held before any probe */ + ULONG guard_zero_status; /* refusing a zero-length grant */ + ULONG guard_count_zero; /* entries held after it */ + ULONG guard_wrap_status; /* refusing a grant that runs off 4 GB */ + ULONG guard_count_wrap; + ULONG guard_top_status; /* accepting one that ends exactly at it */ + ULONG guard_count_top; + ULONG guard_unload_status; +} GUARD_RESULT; + +static TXM_MODULE_INSTANCE guard_module; +static GUARD_RESULT guard_result; + +/* What the fault handler saw. Read by the reporting thread after the module has + been terminated. */ + +static volatile ULONG fault_count; +static volatile ULONG fault_dfsr; +static volatile ULONG fault_dfar; +static volatile ULONG fault_ifsr; +static volatile ULONG fault_ifar; +static volatile ULONG fault_spsr; +static volatile ULONG fault_code_location; +static volatile ULONG fault_notify_thread; +static volatile ULONG fault_notify_instance; + +static TX_THREAD report_thread; +static unsigned char report_stack[2048] __attribute__((aligned(8))); + +/* The two symbols the debug harness stops on, declared here because they have + external linkage and are called before they are defined -- MISRA C:2012 Rule + 8.4 wants a visible declaration either way. Both are defined below; see each + for why it exists rather than a line number in a loop. */ + +void manager_done(void); +void pass_done(void); + + +/**************************************************************************/ +/* Fault notification. */ +/* */ +/* Called by the module manager after it has terminated the offending */ +/* thread. Records rather than prints, for two reasons: this runs in the */ +/* fault path, where the console is a polled driver that spins waiting */ +/* for a transmit to complete -- and it runs in Abort mode on the Abort */ +/* stack, which is a kilobyte on this board and already carries the */ +/* terminate underneath this frame. A callback that printed would work */ +/* and would still be the wrong shape to copy. */ +/* */ +/* Its two arguments are the point of the hook, so they are recorded and */ +/* checked rather than discarded: an application is being told WHICH */ +/* thread and WHICH module faulted, and a callback that fires with the */ +/* wrong pair is no more use than one that never fires. */ +/**************************************************************************/ + +static void module_fault_notify(TX_THREAD *thread_ptr, TXM_MODULE_INSTANCE *module_instance) +{ + fault_count++; + fault_notify_thread = (ULONG) thread_ptr; + fault_notify_instance = (ULONG) module_instance; + fault_dfsr = _txm_module_manager_memory_fault_info.txm_module_manager_memory_fault_info_dfsr; + fault_dfar = _txm_module_manager_memory_fault_info.txm_module_manager_memory_fault_info_dfar; + fault_ifsr = _txm_module_manager_memory_fault_info.txm_module_manager_memory_fault_info_ifsr; + fault_ifar = _txm_module_manager_memory_fault_info.txm_module_manager_memory_fault_info_ifar; + fault_spsr = _txm_module_manager_memory_fault_info.txm_module_manager_memory_fault_info_spsr; + fault_code_location = (ULONG) _txm_module_manager_memory_fault_info.txm_module_manager_memory_fault_info_code_location; +} + + +static void put_hex(unsigned long value) +{ + linflexd_put_hex32((unsigned int) value); +} + + +static void put_field(const char *label, unsigned long value) +{ + linflexd_puts(label); + put_hex(value); + linflexd_puts("\n"); +} + + +/**************************************************************************/ +/* A byte copy, written out rather than called for. */ +/* */ +/* The manager links -nostdlib, and reaching for memcpy would pull in a */ +/* libc whose presence this example does not otherwise depend on. The */ +/* blob is under two kilobytes and this runs once. */ +/**************************************************************************/ + +static void copy_bytes(unsigned char *destination, const unsigned char *source, + unsigned long length) +{ + unsigned long i; + + for (i = 0UL; i < length; i++) + { + destination[i] = source[i]; + } +} + + +/**************************************************************************/ +/* The shared granules, reached through the manager's load window. */ +/* */ +/* No kernel region covers the module area; region 16 does, and the */ +/* scheduler enables it for every thread that owns no module. This */ +/* thread owns none, so the window is open on it and these functions */ +/* need no bracketing of their own -- which is the whole reason the */ +/* window is owned by the scheduler rather than by whoever calls. */ +/**************************************************************************/ + +static void module_status_clear(void) +{ + ULONG granule; + + /* The WHOLE area, not just the progress word. The gap granule has to start + at a known zero, because "the module never wrote it" is one of the results + and a leftover mark from the previous pass would read as a module that + reached memory it was never granted -- or hide one that did. */ + + for (granule = 0UL; granule < MODULE_STATUS_GRANULES; granule++) + { + *((volatile ULONG *) MODULE_GRANULE_ADDRESS(granule)) = 0UL; + MODULE_SHARED_MARK(granule) = 0UL; + } +} + + +static ULONG module_status_read(void) +{ + return *((volatile ULONG *) MODULE_STATUS_ADDRESS); +} + + +/**************************************************************************/ +/* The shared grants a pass gets, and the two ways a grant is refused. */ +/* */ +/* Every pass is granted the first granule, which is the progress word it */ +/* reports through. The shared pass is granted one granule per shared */ +/* entry the port provides, skipping the gap, because a single grant only */ +/* ever exercises the first of the five and this port had never run the */ +/* other four. */ +/* */ +/* It also probes the two ways a grant is refused, which can only be done */ +/* on a LOADED instance. ORDER MATTERS: the manager checks the entry */ +/* count BEFORE it checks alignment, so the unaligned probe has to happen */ +/* while entries remain -- after five grants it would come back */ +/* TX_NO_MEMORY and say nothing about alignment at all. */ +/* */ +/* Returns the first grant status that was not TX_SUCCESS, or TX_SUCCESS. */ +/**************************************************************************/ + +static UINT grant_shared_regions(TXM_MODULE_INSTANCE *instance, PASS_RESULT *result) +{ + UINT status; + UINT first_failure = TX_SUCCESS; + ULONG granule; + + if (result -> pass_test != MODULE_TEST_SHARED_ABORT) + { + /* The progress word, and nothing else. */ + + return txm_module_manager_external_memory_enable(instance, + (VOID *) &__module_status_start__, + MODULE_STATUS_LENGTH, + TXM_MODULE_ATTRIBUTE_READ_WRITE); + } + + /* Refused for alignment. One word into the first granule: an address + inside the area, so what is being tested is the 64-byte granule rule and + not the range. It must also consume no entry, which the five grants + below prove by all succeeding. */ + + result -> pass_align_status = + (ULONG) txm_module_manager_external_memory_enable( + instance, + (VOID *) (&__module_status_start__ + MODULE_STATUS_MARK_OFFSET), + MODULE_STATUS_LENGTH, + TXM_MODULE_ATTRIBUTE_READ_WRITE); + + /* One region per granule, every entry the port has, and never the gap. */ + + for (granule = 0UL; granule < MODULE_STATUS_GRANULES; granule++) + { + if (granule != MODULE_STATUS_UNGRANTED) + { + status = txm_module_manager_external_memory_enable( + instance, + (VOID *) (&__module_status_start__ + (granule * MODULE_STATUS_LENGTH)), + MODULE_STATUS_LENGTH, + TXM_MODULE_ATTRIBUTE_READ_WRITE); + + if (status == TX_SUCCESS) + { + result -> pass_shared_grants++; + } + else if (first_failure == TX_SUCCESS) + { + first_failure = status; + } + else + { + /* Already recorded; the first failure is the informative one. */ + } + } + } + + /* And one grant too many, which must be refused. Not cosmetic: the entry + written is TXM_MODULE_MPU_SHARED_INDEX plus the count, so a sixth grant + that got past the check would write one past the end of the region table + and into the instance fields that follow it. + + Aimed at the GAP, deliberately. It overlaps nothing, so a refusal costs + nothing -- and if the check ever failed, the gap would become a granted + region and the module would go on to survive writing it. The same defect + would then be reported twice, once as this status and once by name as + MODULE_PROGRESS_SURVIVED_GAP, rather than only as a status nobody reads. */ + + result -> pass_exhaust_status = + (ULONG) txm_module_manager_external_memory_enable( + instance, + (VOID *) (&__module_status_start__ + + (MODULE_STATUS_UNGRANTED * MODULE_STATUS_LENGTH)), + MODULE_STATUS_LENGTH, + TXM_MODULE_ATTRIBUTE_READ_WRITE); + + result -> pass_shared_count = instance -> txm_module_instance_shared_memory_count; + + return first_failure; +} + + +/**************************************************************************/ +/* The size guards on a shared grant. */ +/* */ +/* A grant of no bytes and a grant whose inclusive end wraps past the top */ +/* of the address space both used to compute a limit BELOW the base, */ +/* program it, return TX_SUCCESS and spend one of the five entries on a */ +/* region the hardware cannot honour. Both must now be refused as */ +/* TX_SIZE_ERROR, and -- the half that a status code alone does not say -- */ +/* must leave the entry count exactly where they found it, because an */ +/* entry spent on a refused grant is one the caller can never get back. */ +/* */ +/* The third probe is the one that must SUCCEED: a grant ending exactly */ +/* at 0xFFFFFFFF is legal, and a guard that refused it would be a new bug */ +/* in place of the old one. It is checked last so that the count it does */ +/* move is unambiguous. */ +/* */ +/* Loaded here and unloaded below without ever being started, so nothing */ +/* these probes accept is programmed into an MPU region. See the comment */ +/* on MODULE_TOP_GRANULE_ADDRESS for why that matters on this part. */ +/* */ +/* Nothing here needs the debugger: every value it produces is a manager */ +/* return code or a field of the manager's own instance, so the console */ +/* carries the whole result and there is no pass_done() for it. */ +/**************************************************************************/ + +static void run_guard_probes(VOID *location) +{ + GUARD_RESULT *result = &guard_result; + TXM_MODULE_INSTANCE *instance = &guard_module; + + result -> guard_load_status = (ULONG) txm_module_manager_in_place_load(instance, + "shared-grant guards", + location); + + if (result -> guard_load_status != (ULONG) TX_SUCCESS) + { + return; + } + + result -> guard_count_start = instance -> txm_module_instance_shared_memory_count; + + /* No bytes at all, at an address that is otherwise perfectly grantable -- + the progress granule every other pass is given. So what is refused is + the length and nothing else. */ + + result -> guard_zero_status = + (ULONG) txm_module_manager_external_memory_enable( + instance, + (VOID *) &__module_status_start__, + 0UL, + TXM_MODULE_ATTRIBUTE_READ_WRITE); + + result -> guard_count_zero = instance -> txm_module_instance_shared_memory_count; + + /* Twice the room left above the base, so the inclusive end wraps to a low + address. Aligned, so again it is the length that is being refused. */ + + result -> guard_wrap_status = + (ULONG) txm_module_manager_external_memory_enable( + instance, + (VOID *) MODULE_TOP_GRANULE_ADDRESS, + MODULE_WRAP_LENGTH, + TXM_MODULE_ATTRIBUTE_READ_WRITE); + + result -> guard_count_wrap = instance -> txm_module_instance_shared_memory_count; + + /* And the boundary: the same base, asking for exactly the room there is. */ + + result -> guard_top_status = + (ULONG) txm_module_manager_external_memory_enable( + instance, + (VOID *) MODULE_TOP_GRANULE_ADDRESS, + MODULE_TOP_GRANULE_LENGTH, + TXM_MODULE_ATTRIBUTE_READ_WRITE); + + result -> guard_count_top = instance -> txm_module_instance_shared_memory_count; + + /* Unloaded, not stopped: it was never started. Recorded rather than + discarded, because a module that will not unload holds the pool. */ + + result -> guard_unload_status = (ULONG) txm_module_manager_unload(instance); +} + + +/**************************************************************************/ +/* One pass: load the blob from a given address, grant it the shared */ +/* granules it is entitled to, start it, wait for the fault it is written */ +/* to provoke, and stop it. */ +/* */ +/* The module is left loaded. Its data allocation is what moves the next */ +/* pass's data base, and releasing it here would defeat half the test. */ +/* Unloading happens after both passes have run. */ +/**************************************************************************/ + +/* name is CHAR * and not const CHAR *, because txm_module_manager_in_place_load + takes it that way -- the manager stores the pointer in the instance and the API + has never promised not to write through it. */ + +static void run_one_pass(UINT index, CHAR *name, VOID *location, ULONG test) +{ + PASS_RESULT *result = &pass_results[index]; + TXM_MODULE_INSTANCE *instance = &demo_module[index]; + unsigned int waited; + ULONG granule; + + result -> pass_name = name; + result -> pass_test = test; + + /* What the module should manage before the hardware stops it: its own data, + a kernel call, and the attempt -- plus, for the shared pass, the five + granules it wrote and read back on the way. Never a SURVIVED bit; that + one is the failure. + + The address it must fault on goes with it, because the three tests do not + share one. Two of them reach into the kernel's data; the shared pass + writes the mark word of the granule it was not granted, and that address + is computed here exactly as the module computes it. */ + + if (test == MODULE_TEST_SHARED_ABORT) + { + result -> pass_expect_progress = MODULE_PROGRESS_OWN_DATA + | MODULE_PROGRESS_KERNEL_CALL + | MODULE_PROGRESS_SHARED_WROTE + | MODULE_PROGRESS_ATTEMPTED_GAP; + + result -> pass_expect_fault = MODULE_GRANULE_ADDRESS(MODULE_STATUS_UNGRANTED) + + MODULE_STATUS_MARK_OFFSET; + } + else if (test == MODULE_TEST_PREFETCH_ABORT) + { + result -> pass_expect_progress = MODULE_PROGRESS_OWN_DATA + | MODULE_PROGRESS_KERNEL_CALL + | MODULE_PROGRESS_ATTEMPTED_JUMP; + + result -> pass_expect_fault = MODULE_FORBIDDEN_ADDRESS; + } + else + { + result -> pass_expect_progress = MODULE_PROGRESS_OWN_DATA + | MODULE_PROGRESS_KERNEL_CALL + | MODULE_PROGRESS_ATTEMPTED_STEAL; + + result -> pass_expect_fault = MODULE_FORBIDDEN_ADDRESS; + } + + /* Cleared before the module starts, so a fault or a progress bit counted + here belongs to this pass and not the previous one. */ + + fault_count = 0UL; + fault_notify_thread = 0UL; + fault_notify_instance = 0UL; + module_status_clear(); + + result -> pass_load_status = (ULONG) txm_module_manager_in_place_load(instance, name, location); + + if (result -> pass_load_status != (ULONG) TX_SUCCESS) + { + return; + } + + /* Read from the instance rather than computed here. Where the code ended up + is what the manager decided, and the whole point of the comparison at the + end is to check the module against the manager's own numbers. + + Recorded HERE, immediately after the load and before anything that can + fail, because the load is what decided them. Taken any later, a pass that + failed to be granted its shared regions would carry zeros into the overlap + comparison at the end of the run -- and zero against zero overlaps, so a + grant failure would be reported a second time as "its code and data + regions overlap", which is not true and points at the wrong thing. */ + + result -> pass_code_start = (ULONG) instance -> txm_module_instance_code_start; + result -> pass_code_end = (ULONG) instance -> txm_module_instance_code_end; + result -> pass_data_start = (ULONG) instance -> txm_module_instance_data_start; + result -> pass_data_end = (ULONG) instance -> txm_module_instance_data_end; + result -> pass_data_base = (ULONG) instance -> txm_module_instance_module_data_base_address; + + /* The shared granules the module reports through, and for the shared pass + every other entry as well. Granted while the module is LOADED and before + it is STARTED, which is the only window the manager accepts, and granted + per pass because each pass is its own instance with its own region table + -- an instance is memset by the load, so nothing carries over. */ + + result -> pass_share_status = (ULONG) grant_shared_regions(instance, result); + + if (result -> pass_share_status != (ULONG) TX_SUCCESS) + { + return; + } + + /* Which violation this pass provokes. Written after the load, which is what + filled the field in from the preamble, and before the start, which is what + hands it to the module's start thread. */ + + instance -> txm_module_instance_application_module_id = MODULE_ID_BASE | test; + + /* What the notify callback must be told, recorded before the module runs so + the comparison afterwards is against an expectation and not against + whatever the callback happened to write. */ + + result -> pass_expect_thread = (ULONG) &(instance -> txm_module_instance_start_stop_thread); + result -> pass_expect_instance = (ULONG) instance; + + result -> pass_start_status = (ULONG) txm_module_manager_start(instance); + + if (result -> pass_start_status != (ULONG) TX_SUCCESS) + { + return; + } + + /* Wait for the abort vector to capture a fault belonging to THIS pass. + + The captured fault info is waited on rather than the notify callback, even + though the callback now works. The capture happens in the abort vector + before anything else runs, so it is the earliest and most direct evidence + that a fault occurred; the callback is a later consequence of the same + event, and this file checks it separately. Waiting on the earlier of the + two means a regression in the callback path shows up as "notified 0" next + to a captured fault, rather than as "no fault occurred" -- which is the + opposite of the truth and is exactly what an earlier version of this file + reported. + + Attribution is by thread pointer: each pass has its own module instance and + therefore its own start thread, so a captured fault naming this pass's + thread cannot be a leftover from the previous pass. */ + + waited = 0U; + while ((_txm_module_manager_memory_fault_info.txm_module_manager_memory_fault_info_thread_ptr + != &(instance -> txm_module_instance_start_stop_thread)) && + (waited < 50U)) + { + tx_thread_sleep(2UL); + waited++; + } + + if (_txm_module_manager_memory_fault_info.txm_module_manager_memory_fault_info_thread_ptr + == &(instance -> txm_module_instance_start_stop_thread)) + { + result -> pass_captured = 1UL; + result -> pass_dfsr = _txm_module_manager_memory_fault_info.txm_module_manager_memory_fault_info_dfsr; + result -> pass_dfar = _txm_module_manager_memory_fault_info.txm_module_manager_memory_fault_info_dfar; + result -> pass_ifsr = _txm_module_manager_memory_fault_info.txm_module_manager_memory_fault_info_ifsr; + result -> pass_ifar = _txm_module_manager_memory_fault_info.txm_module_manager_memory_fault_info_ifar; + result -> pass_spsr = _txm_module_manager_memory_fault_info.txm_module_manager_memory_fault_info_spsr; + result -> pass_fault_r9 = _txm_module_manager_memory_fault_info.txm_module_manager_memory_fault_info_r9; + result -> pass_code_location = (ULONG) _txm_module_manager_memory_fault_info.txm_module_manager_memory_fault_info_code_location; + } + + /* What the module reached, and what the notify callback saw. Both read + after the wait above, so what ran is recorded and what did not shows as + zero. The status word is read while THIS pass is still the last thing to + have written it -- the same discipline pass_done() exists for on the + module's own copy, for the same reason. */ + + result -> pass_progress = module_status_read(); + result -> pass_faults = fault_count; + result -> pass_notify_thread = fault_notify_thread; + result -> pass_notify_instance = fault_notify_instance; + + /* Every granule's mark, granted or not. The granted ones say the module + wrote and read back the granule it meant to, which is what proves five + distinct entries were programmed rather than one entry five times; the + gap's says whether it stayed untouched. */ + + for (granule = 0UL; granule < MODULE_STATUS_GRANULES; granule++) + { + result -> pass_marks[granule] = MODULE_SHARED_MARK(granule); + } + + /* Stopped, not unloaded. The fault terminated the module's start thread but + left the module STARTED, and unload refuses anything that is not LOADED or + STOPPED -- so this is required, not tidiness. */ + + result -> pass_stop_status = (ULONG) txm_module_manager_stop(instance); + + /* Still loaded, so the module's own memory is still where this pass's data + base says it is. See pass_done. */ + + pass_done(); +} + + +static void report_one_pass(const PASS_RESULT *result) +{ + linflexd_puts("\n--- "); + linflexd_puts(result -> pass_name); + linflexd_puts(" ---\n"); + + linflexd_puts(" expected abort = "); + if (result -> pass_test == MODULE_TEST_PREFETCH_ABORT) + { + linflexd_puts("prefetch (IFSR/IFAR)\n"); + } + else if (result -> pass_test == MODULE_TEST_SHARED_ABORT) + { + linflexd_puts("data (DFSR/DFAR), writing an ungranted shared granule\n"); + } + else + { + linflexd_puts("data (DFSR/DFAR)\n"); + } + + put_field(" load status = ", result -> pass_load_status); + put_field(" share status = ", result -> pass_share_status); + put_field(" start status = ", result -> pass_start_status); + put_field(" stop status = ", result -> pass_stop_status); + put_field(" code region = ", result -> pass_code_start); + put_field(" .. to = ", result -> pass_code_end); + put_field(" data region = ", result -> pass_data_start); + put_field(" .. to = ", result -> pass_data_end); + put_field(" data base (r9) = ", result -> pass_data_base); + put_field(" fault captured = ", result -> pass_captured); + put_field(" module progress = ", result -> pass_progress); + put_field(" should be = ", result -> pass_expect_progress); + put_field(" fault address = ", result -> pass_expect_fault); + put_field(" notify callbacks = ", result -> pass_faults); + put_field(" notified thread = ", result -> pass_notify_thread); + put_field(" should be = ", result -> pass_expect_thread); + put_field(" notified module = ", result -> pass_notify_instance); + put_field(" should be = ", result -> pass_expect_instance); + put_field(" r9 at the fault = ", result -> pass_fault_r9); + put_field(" DFSR = ", result -> pass_dfsr); + put_field(" DFAR = ", result -> pass_dfar); + put_field(" IFSR = ", result -> pass_ifsr); + put_field(" IFAR = ", result -> pass_ifar); + put_field(" SPSR = ", result -> pass_spsr); + put_field(" faulting pc = ", result -> pass_code_location); + + /* Meaningful for a data abort, where the module faulted inside its own code. + A prefetch abort faults ON the address it branched to, so the faulting pc + is outside the module and the difference is not an offset into it. */ + + if (result -> pass_test != MODULE_TEST_PREFETCH_ABORT) + { + put_field(" pc - code base = ", result -> pass_code_location - result -> pass_code_start); + } + + /* The shared-region half, reported only by the pass that produces it. */ + + if (result -> pass_test == MODULE_TEST_SHARED_ABORT) + { + ULONG granule; + + put_field(" shared grants = ", result -> pass_shared_grants); + put_field(" should be = ", (unsigned long) MODULE_SHARED_GRANTS); + put_field(" entries held = ", result -> pass_shared_count); + put_field(" unaligned grant = ", result -> pass_align_status); + put_field(" should be = ", (unsigned long) TXM_MODULE_ALIGNMENT_ERROR); + put_field(" one grant too many = ", result -> pass_exhaust_status); + put_field(" should be = ", (unsigned long) TX_NO_MEMORY); + + for (granule = 0UL; granule < MODULE_STATUS_GRANULES; granule++) + { + if (granule == MODULE_STATUS_UNGRANTED) + { + put_field(" gap granule mark = ", result -> pass_marks[granule]); + put_field(" should be = ", 0UL); + } + else + { + put_field(" granule mark = ", result -> pass_marks[granule]); + put_field(" should be = ", MODULE_SHARED_SIGNATURE | granule); + } + } + } +} + + +/**************************************************************************/ +/* The shared-region verdict. Returns the number of failures it found, */ +/* and zero for any pass that does not exercise the shared regions. */ +/**************************************************************************/ + +static UINT judge_shared_regions(const PASS_RESULT *result) +{ + ULONG granule; + + if (result -> pass_test != MODULE_TEST_SHARED_ABORT) + { + return 0U; + } + + /* Every entry the port provides, granted. Fewer means an entry past the + first is not usable, which is the state this port was in before this pass + existed. */ + + if (result -> pass_shared_grants != (ULONG) MODULE_SHARED_GRANTS) + { + linflexd_puts("FAIL "); + linflexd_puts(result -> pass_name); + linflexd_puts(": not every shared entry could be granted\n"); + return 1U; + } + + if (result -> pass_shared_count != (ULONG) TXM_MODULE_MPU_SHARED_ENTRIES) + { + linflexd_puts("FAIL "); + linflexd_puts(result -> pass_name); + linflexd_puts(": the instance does not hold the entries it granted\n"); + return 1U; + } + + /* An unaligned grant must be refused BY NAME. Accepting it would not + fault: the low six bits of PRBAR are the shareability, permission and + execute-never fields, so an under-aligned base silently changes what the + region permits instead of where it is. */ + + if (result -> pass_align_status != (ULONG) TXM_MODULE_ALIGNMENT_ERROR) + { + linflexd_puts("FAIL "); + linflexd_puts(result -> pass_name); + linflexd_puts(": an unaligned shared grant was not refused as such\n"); + return 1U; + } + + if (result -> pass_exhaust_status != (ULONG) TX_NO_MEMORY) + { + linflexd_puts("FAIL "); + linflexd_puts(result -> pass_name); + linflexd_puts(": one grant too many was not refused\n"); + return 1U; + } + + /* And what the module actually managed to write where. Each granted + granule must hold its own mark -- a region programmed with the wrong base + accepts the store and puts it somewhere else -- and the gap must still + hold the zero the manager left in it. */ + + for (granule = 0UL; granule < MODULE_STATUS_GRANULES; granule++) + { + if (granule == MODULE_STATUS_UNGRANTED) + { + if (result -> pass_marks[granule] != 0UL) + { + linflexd_puts("FAIL "); + linflexd_puts(result -> pass_name); + linflexd_puts(": the ungranted granule was written -- a grant covered too much\n"); + return 1U; + } + } + else if (result -> pass_marks[granule] != (MODULE_SHARED_SIGNATURE | granule)) + { + linflexd_puts("FAIL "); + linflexd_puts(result -> pass_name); + linflexd_puts(": a granted granule does not hold its own mark\n"); + return 1U; + } + else + { + /* This granule is as it should be. */ + } + } + + return 0U; +} + + +/**************************************************************************/ +/* Where the debugger stops. */ +/* */ +/* A symbol and not a line number in the report loop. The harness used */ +/* to break on sample_threadx_module_manager.c:259, and every edit to */ +/* this file moved that line -- after which the run stops somewhere */ +/* arbitrary and reports whatever memory happens to hold, which looks */ +/* like a result rather than a mistake. This does not move. */ +/* */ +/* Not static, and noinline, so it survives to the symbol table with an */ +/* address a breakpoint can be set on. */ +/**************************************************************************/ + +__attribute__((noinline)) void manager_done(void) +{ + __asm__ volatile("nop"); +} + + +/**************************************************************************/ +/* Where the debugger stops after each pass. */ +/* */ +/* A module's data is read back by the harness, not by the manager: the */ +/* manager deliberately knows no symbol of the module, so it cannot find */ +/* module_progress, while a debugger can compute its offset from the */ +/* module's ELF and add it to the data base this pass recorded. */ +/* */ +/* But it has to read it WHILE THIS PASS STILL HOLDS THAT MEMORY. The */ +/* byte pool reuses a freed block, so once a later pass has loaded, an */ +/* earlier pass's data base points at the later pass's data -- and reading */ +/* every pass at the end of the run reports the last writer's progress for */ +/* all of them. That is not a hypothetical: pass 3 loads after passes 1 */ +/* and 2 are unloaded and lands exactly where pass 1 was. */ +/* */ +/* So this exists to be broken on, once per pass, after the pass has */ +/* faulted and been stopped and before anything is unloaded. */ +/**************************************************************************/ + +__attribute__((noinline)) void pass_done(void) +{ + __asm__ volatile("nop"); +} + + +/**************************************************************************/ +/* The size guards, reported and judged. Returns failures found. */ +/**************************************************************************/ + +static UINT report_and_judge_guards(void) +{ + const GUARD_RESULT *result = &guard_result; + + linflexd_puts("\n--- shared-grant size guards ---\n"); + + put_field(" load status = ", result -> guard_load_status); + put_field(" entries at start = ", result -> guard_count_start); + put_field(" zero length = ", result -> guard_zero_status); + put_field(" should be = ", (unsigned long) TX_SIZE_ERROR); + put_field(" entries after = ", result -> guard_count_zero); + put_field(" wrapping end = ", result -> guard_wrap_status); + put_field(" should be = ", (unsigned long) TX_SIZE_ERROR); + put_field(" entries after = ", result -> guard_count_wrap); + put_field(" ends at 0xFFFFFFFF = ", result -> guard_top_status); + put_field(" should be = ", (unsigned long) TX_SUCCESS); + put_field(" entries after = ", result -> guard_count_top); + put_field(" unload status = ", result -> guard_unload_status); + + if (result -> guard_load_status != (ULONG) TX_SUCCESS) + { + linflexd_puts("FAIL shared-grant guards: the probe module did not load\n"); + return 1U; + } + + if (result -> guard_count_start != 0UL) + { + linflexd_puts("FAIL shared-grant guards: a fresh instance already held entries\n"); + return 1U; + } + + if (result -> guard_zero_status != (ULONG) TX_SIZE_ERROR) + { + linflexd_puts("FAIL shared-grant guards: a zero-length grant was not refused as a size error\n"); + return 1U; + } + + if (result -> guard_wrap_status != (ULONG) TX_SIZE_ERROR) + { + linflexd_puts("FAIL shared-grant guards: a grant running off the top of memory was not refused\n"); + return 1U; + } + + /* The half a status code does not say. A refused grant that still spent an + entry would report exactly the same two codes above and quietly cost the + caller one of the five, with nothing to show for it. */ + + if ((result -> guard_count_zero != 0UL) || (result -> guard_count_wrap != 0UL)) + { + linflexd_puts("FAIL shared-grant guards: a refused grant consumed an entry\n"); + return 1U; + } + + /* And the boundary the guard must not overreach into. */ + + if (result -> guard_top_status != (ULONG) TX_SUCCESS) + { + linflexd_puts("FAIL shared-grant guards: a grant ending at 0xFFFFFFFF was refused\n"); + return 1U; + } + + if (result -> guard_count_top != 1UL) + { + linflexd_puts("FAIL shared-grant guards: the accepted grant did not consume exactly one entry\n"); + return 1U; + } + + if (result -> guard_unload_status != (ULONG) TX_SUCCESS) + { + linflexd_puts("FAIL shared-grant guards: the probe module did not unload\n"); + return 1U; + } + + linflexd_puts("PASS shared-grant guards: empty and wrapping grants refused, the boundary grant accepted\n"); + + return 0U; +} + + +/**************************************************************************/ +/* Reporting. */ +/**************************************************************************/ + +static void manager_entry(ULONG input) +{ + UINT status; + UINT i; + unsigned long blob_size; + ULONG offset_0; + ULONG offset_1; + UINT failures = 0U; + + (void) input; + + /* Every manager call happens here, in a thread, and not in + tx_application_define. Loading a module takes the manager's mutex, and a + service that can block cannot be called before the scheduler runs: the + first version of this drove the manager from tx_application_define, + printed its way as far as the load, and stopped there for ever. The + Armv8-M sample does all of this from a thread for the same reason. */ + + /* The spellings of the shared status base, checked rather than trusted. + It is a constant agreed between two separately linked images, and a + disagreement would present as a module faulting somewhere unexpected -- + which is exactly what the pass verdicts are trying to distinguish. */ + + if ((unsigned long) &__module_status_start__ != MODULE_STATUS_ADDRESS) + { + linflexd_puts("FAIL the linker put the status area somewhere the module will not look\n"); + failures++; + } + + if ((unsigned long) (&__module_status_end__ - &__module_status_start__) + < MODULE_STATUS_AREA_LENGTH) + { + linflexd_puts("FAIL the status area is smaller than the granules granted over it\n"); + failures++; + } + + linflexd_puts("M1 initialize\n"); + status = txm_module_manager_initialize((VOID *) module_pool, MODULE_POOL_SIZE); + + linflexd_puts("initialize = "); + put_hex(status); + linflexd_puts(" ready = "); + put_hex((ULONG) _txm_module_manager_ready); + linflexd_puts("\n"); + + /* The pool the module's kernel stacks come from. See module_object_pool. */ + + status = txm_module_manager_object_pool_create((VOID *) module_object_pool, + MODULE_OBJECT_POOL_SIZE); + + linflexd_puts("object pool create = "); + put_hex(status); + linflexd_puts("\n"); + + /* Registered before anything is loaded, so there is no window in which a + module could fault with nobody listening. */ + + linflexd_puts("M2 fault notify\n"); + txm_module_manager_memory_fault_notify(module_fault_notify); + + /* The copy that makes pass 2 a relocation test. The staging area is left + empty by the linker on purpose: if the blob were already there, a failure + to copy would be invisible because the right bytes would be present + anyway. */ + + blob_size = (unsigned long) (&__module_image_end__ - &__module_image_start__); + + linflexd_puts("M3 staging the blob\n"); + put_field(" blob size = ", blob_size); + put_field(" from = ", (unsigned long) &__module_image_start__); + put_field(" to = ", (unsigned long) &__module_stage_start__); + + if (blob_size > (unsigned long) (&__module_stage_end__ - &__module_stage_start__)) + { + /* Reported rather than allowed to overrun. The staging area is a fixed + size in the linker script and the module is free to grow. */ + + linflexd_puts("FAIL the module image does not fit the staging area\n"); + failures++; + } + else + { + copy_bytes(&__module_stage_start__, &__module_image_start__, blob_size); + + /* Those were data writes to memory that is about to be fetched as + instructions, and the module area is mapped Normal write-back + (MAIR attribute 0 is 0xFF). So the copied bytes may sit in dirty D + cache lines while the instruction side, which is not coherent with + the D cache on this core, fetches whatever main memory still holds. + Clean first so memory is correct, then invalidate the I cache so no + stale line from a previous image can be served. + + This is not a precaution the passing run justifies. It ran correctly + before this was added, which is exactly the problem: a cold I cache + over a never-executed address happens to work, and it keeps happening + to work until the staging area is reused or an eviction lands + differently. Any loader that copies code owes this pair of + operations, and by-range variants would be tighter than these + all-cache sweeps -- fine here, where it runs once at startup. */ + + cache_clean_all(); + cache_invalidate_icache_all(); + + /* Nothing to bracket for the MPU here. No kernel region covers the + module area, but the window that reaches it is owned by the scheduler, + which enables it for every thread that does not own a module and + disables it for every thread that does -- so it is already open on + this thread and cannot be open while a module's own regions are. */ + + linflexd_puts("M4 pass 1, at the linked address\n"); + run_one_pass(0U, "linked address, data abort", (VOID *) &__module_image_start__, + MODULE_TEST_DATA_ABORT); + + linflexd_puts("M5 pass 2, relocated\n"); + run_one_pass(1U, "relocated, data abort", (VOID *) &__module_stage_start__, + MODULE_TEST_DATA_ABORT); + + /* Both relocation passes are done with their memory now. Unloaded here + rather than at the end, so that the pass below is a load that follows + two faults and two unloads -- which is the state a manager is in after + a module has misbehaved, and the state the next load has to work in. */ + + for (i = 0U; i < MODULE_RELOCATION_PASSES; i++) + { + (void) txm_module_manager_unload(&demo_module[i]); + } + + /* The other abort type, from the staging area so that it is also a + relocated module: the address arriving in IFAR came out of the module's + own initialised data through its rebased GOT, exactly as DFAR does + above. */ + + linflexd_puts("M6 pass 3, prefetch abort\n"); + run_one_pass(2U, "relocated, prefetch abort", (VOID *) &__module_stage_start__, + MODULE_TEST_PREFETCH_ABORT); + + (void) txm_module_manager_unload(&demo_module[2]); + + /* The shared-region pass. Granted every entry the port provides, one + granule each, and never the granule between two of them -- which it + then writes. This is the only pass that exercises a shared entry + past the first, the granule-alignment refusal, and what happens when + the entries run out; the three passes above grant one region each and + would look identical if four of the five entries did not work. */ + + linflexd_puts("M7 pass 4, shared regions\n"); + run_one_pass(3U, "relocated, shared-region gap", (VOID *) &__module_stage_start__, + MODULE_TEST_SHARED_ABORT); + + (void) txm_module_manager_unload(&demo_module[3]); + + /* The size guards on a grant, which are the manager's business and not + the module's. Last, because it wants the pool to itself: every pass + above has released its data allocation by now. */ + + linflexd_puts("M8 shared-grant size guards\n"); + run_guard_probes((VOID *) &__module_image_start__); + } + + /* ------------------------------------------------------------------ + The verdict. + ------------------------------------------------------------------ */ + + linflexd_puts("\n=== ThreadX modules on S32Z280: relocation and protection ===\n"); + + for (i = 0U; i < MODULE_PASSES; i++) + { + report_one_pass(&pass_results[i]); + } + + failures += report_and_judge_guards(); + + linflexd_puts("\n"); + + /* Before anything else: a module's code and data regions are enabled at the + same time, and PMSAv8-R has no region priority -- an access that hits more + than one enabled region takes a translation fault (TRM 8.1), so an overlap + means aborts from addresses that look perfectly legal. Nothing in the + manager checks for it, so this example does. + + The risk is real here and not theoretical: pass 2 loads its code from the + staging area, which sits in the same 64 KB as the byte pool its data comes + out of. A module grown large enough, or a pool sized differently, and the + two would meet. */ + + for (i = 0U; i < MODULE_PASSES; i++) + { + const PASS_RESULT *result = &pass_results[i]; + + if (result -> pass_load_status != (ULONG) TX_SUCCESS) + { + continue; + } + + if ((result -> pass_code_start <= result -> pass_data_end) && + (result -> pass_data_start <= result -> pass_code_end)) + { + linflexd_puts("FAIL "); + linflexd_puts(result -> pass_name); + linflexd_puts(": its code and data regions overlap\n"); + failures++; + } + + /* The shared area is granted as regions too, and it sits in the same + 64 KB as the image, the pool and the staging area. A module grown + large enough, or a pool sized differently, and two of them would + meet. */ + + if ((result -> pass_code_start <= (MODULE_STATUS_ADDRESS + MODULE_STATUS_AREA_LENGTH - 1UL)) && + (MODULE_STATUS_ADDRESS <= result -> pass_code_end)) + { + linflexd_puts("FAIL "); + linflexd_puts(result -> pass_name); + linflexd_puts(": the shared status area overlaps its code\n"); + failures++; + } + + if ((result -> pass_data_start <= (MODULE_STATUS_ADDRESS + MODULE_STATUS_AREA_LENGTH - 1UL)) && + (MODULE_STATUS_ADDRESS <= result -> pass_data_end)) + { + linflexd_puts("FAIL "); + linflexd_puts(result -> pass_name); + linflexd_puts(": the shared status area overlaps its data\n"); + failures++; + } + + /* And what _txm_module_manager_alignment_adjust produced. It is called + by every load and has never been checked, because nothing it gets + wrong faults: it rounds a module's code and data sizes up to the + protection granule and declares the granule as their alignment, and + the loader allocates on that. Get it wrong and the region bases are + written into PRBAR with their low six bits landing on the shareability, + permission and execute-never fields -- so the module runs with + attributes nobody asked for rather than at the wrong address. + + The data region's end is checked as well as its base, because the data + region's length is the rounded size; the CODE region's end is not, it + is the true end of the image and is not rounded to anything. */ + + if (((result -> pass_code_start & (TXM_MODULE_MPU_ALIGNMENT - 1UL)) != 0UL) || + ((result -> pass_data_start & (TXM_MODULE_MPU_ALIGNMENT - 1UL)) != 0UL) || + (((result -> pass_data_end + 1UL) & (TXM_MODULE_MPU_ALIGNMENT - 1UL)) != 0UL)) + { + linflexd_puts("FAIL "); + linflexd_puts(result -> pass_name); + linflexd_puts(": its regions are not aligned to the protection granule\n"); + failures++; + } + } + + /* Each pass on its own: it has to have loaded, started, faulted once, and + faulted in User mode at the address it was told not to touch. */ + + for (i = 0U; i < MODULE_PASSES; i++) + { + const PASS_RESULT *result = &pass_results[i]; + + if ((result -> pass_load_status != (ULONG) TX_SUCCESS) || + (result -> pass_share_status != (ULONG) TX_SUCCESS) || + (result -> pass_start_status != (ULONG) TX_SUCCESS)) + { + linflexd_puts("FAIL "); + linflexd_puts(result -> pass_name); + linflexd_puts(": did not load, share and start\n"); + failures++; + } + else if ((result -> pass_progress & MODULE_PROGRESS_SURVIVED) != 0UL) + { + /* First, and named explicitly: the module must not have survived + what it was told to attempt. This is the one result that means + the protection did not hold, and it is checked before anything + else so that a run in which the MPU did nothing says so in those + words rather than through some downstream symptom. */ + + linflexd_puts("FAIL "); + linflexd_puts(result -> pass_name); + linflexd_puts(": the module SURVIVED its violation -- it is not protected\n"); + failures++; + } + else if (result -> pass_captured == 0UL) + { + linflexd_puts("FAIL "); + linflexd_puts(result -> pass_name); + linflexd_puts(": reached outside its memory and was not stopped\n"); + failures++; + } + else if (result -> pass_progress != result -> pass_expect_progress) + { + /* What it did manage, from the shared granule. A module that + faulted without having read its own data or made a kernel call + faulted for the wrong reason, and the fault alone would not have + said so. */ + + linflexd_puts("FAIL "); + linflexd_puts(result -> pass_name); + linflexd_puts(": did not reach the point it was supposed to fault at\n"); + failures++; + } + else if (result -> pass_fault_r9 != result -> pass_data_base) + { + /* r9 is the module's PIC base and the manager seeded it from the + thread entry info. If the value captured at the fault is not the + data base the manager handed out, the seeding is wrong and every + data reference the module made went somewhere unintended -- so + check it explicitly rather than inferring it from a symptom. */ + + linflexd_puts("FAIL "); + linflexd_puts(result -> pass_name); + linflexd_puts(": r9 was not the module's data base\n"); + failures++; + } + else if ((result -> pass_spsr & 0x1FUL) != 0x10UL) + { + /* A fault from anywhere but User mode is not this test passing: the + module runs unprivileged, so a privileged fault means the fault + came from the kernel and something else is wrong. */ + + linflexd_puts("FAIL "); + linflexd_puts(result -> pass_name); + linflexd_puts(": faulted, but not from User mode\n"); + failures++; + } + else if (((result -> pass_test == MODULE_TEST_PREFETCH_ABORT) ? + result -> pass_ifar : result -> pass_dfar) + != result -> pass_expect_fault) + { + /* The module got this address out of its own initialised data, + through its rebased GOT. Any other value means it faulted + somewhere unintended -- most likely on its own data, which is what + a bad rebase looks like. + + Which register carries it depends on the abort: a data abort + reports the address it tried to touch in DFAR, a prefetch abort + reports the address it tried to fetch in IFAR. Checking the wrong + one of the two passes for a stale value left by an earlier fault, + which is why this is selected on the expected type rather than on + whichever register happens to be non-zero. */ + + linflexd_puts("FAIL "); + linflexd_puts(result -> pass_name); + linflexd_puts(": faulted at the wrong address, so .data or the GOT is wrong\n"); + failures++; + } + else if (result -> pass_faults != 1UL) + { + /* The notify callback is a public API of the module manager, so it is + checked and not merely reported. Zero here with a captured fault + above means the fault path reached the hardware's evidence and + never reached the application: on this port that used to be the + case for every fault, because the shared fault handler terminates + the offending thread before calling the hook and the terminate only + returns if the abort vector has told the kernel it is inside an + exception. More than one means a single violation was reported + twice. */ + + linflexd_puts("FAIL "); + linflexd_puts(result -> pass_name); + linflexd_puts(": the fault-notify callback did not run exactly once\n"); + failures++; + } + else if ((result -> pass_notify_thread != result -> pass_expect_thread) || + (result -> pass_notify_instance != result -> pass_expect_instance)) + { + /* Being told that something faulted is not the service; being told + which thread and which module is. */ + + linflexd_puts("FAIL "); + linflexd_puts(result -> pass_name); + linflexd_puts(": notified about the wrong thread or module\n"); + failures++; + } + else if (judge_shared_regions(result) != 0U) + { + /* judge_shared_regions has already said which of the shared-region + results was wrong. */ + + failures++; + } + else + { + linflexd_puts("PASS "); + linflexd_puts(result -> pass_name); + linflexd_puts(": faulted in User mode at the forbidden address, and was reported\n"); + } + } + + /* And the first two passes against each other, which is the relocation + result. The third is not in this comparison: it faults on the address it + branched to rather than inside its own code, so its faulting pc is not an + offset into the module and there is nothing to compare. */ + + offset_0 = pass_results[0].pass_code_location - pass_results[0].pass_code_start; + offset_1 = pass_results[1].pass_code_location - pass_results[1].pass_code_start; + + if ((pass_results[0].pass_captured == 0UL) || (pass_results[1].pass_captured == 0UL)) + { + linflexd_puts("FAIL relocation: a pass did not fault, nothing to compare\n"); + failures++; + } + else if (pass_results[0].pass_code_start == pass_results[1].pass_code_start) + { + linflexd_puts("FAIL relocation: both passes ran from the same address\n"); + failures++; + } + else if (offset_0 != offset_1) + { + linflexd_puts("FAIL relocation: the two passes faulted at different offsets\n"); + failures++; + } + else + { + linflexd_puts("PASS relocation: the same blob ran correctly from two addresses\n"); + + if (pass_results[0].pass_data_base == pass_results[1].pass_data_base) + { + /* Not a failure -- the code rebase is still proven -- but worth + saying, because it means the data rebase produced the same + numbers twice and was not exercised as thoroughly. */ + + linflexd_puts("NOTE both passes shared a data base; the data rebase was not varied\n"); + } + } + + /* Both abort types, stated as its own line. Each pass above already checked + its own registers; this says that between them the two vectors were both + taken, which is the claim a reader of the log wants to be able to make + without working out what each pass did. */ + + if ((pass_results[0].pass_captured != 0UL) && (pass_results[0].pass_dfsr != 0UL) && + (pass_results[2].pass_captured != 0UL) && (pass_results[2].pass_ifsr != 0UL)) + { + linflexd_puts("PASS both abort types: data through DFSR/DFAR, prefetch through IFSR/IFAR\n"); + } + else + { + linflexd_puts("FAIL only one kind of abort was exercised\n"); + failures++; + } + + put_field("\nfailures = ", (unsigned long) failures); + + if (failures == 0U) + { + linflexd_puts("=== PASS ===\n"); + } + else + { + linflexd_puts("=== FAIL ===\n"); + } + + linflexd_puts("=== end ===\n"); + + /* Everything worth reading is in memory now. */ + + manager_done(); + + while (1) + { + tx_thread_sleep(100UL); + } +} + + +/**************************************************************************/ +/* Application definition. */ +/**************************************************************************/ + +/**************************************************************************/ +/* Board entry. */ +/* */ +/* entry.S calls this once the core is at EL1 with the MPU and caches */ +/* configured. Same shape as the other examples on this board: bring the */ +/* console up, say so, and enter the kernel. */ +/**************************************************************************/ + +void bsp_main(void) +{ + (void) linflexd_init(); + + linflexd_puts("\n=== ThreadX modules :: S32Z280-594EVB ===\n"); + linflexd_puts("entering kernel\n"); + + tx_kernel_enter(); + + /* Not reached. */ + + linflexd_puts("FAIL tx_kernel_enter returned\n"); + + for (;;) + { + __asm__ volatile("nop"); + } +} + + +void tx_application_define(void *first_unused_memory) +{ + UINT status; + + (void) first_unused_memory; + + linflexd_puts("\n=== module manager starting ===\n"); + + /* Nothing but the thread. See manager_entry for why the manager cannot be + driven from here. */ + + status = tx_thread_create(&report_thread, "module manager", manager_entry, 0UL, + report_stack, sizeof(report_stack), + 20U, 20U, TX_NO_TIME_SLICE, TX_AUTO_START); + + /* Reported rather than discarded. A thread that was never created and a + thread that was created but never scheduled produce exactly the same + silence on the console, and telling those two apart is most of the work + when the port itself is what is under test. */ + + if (status == TX_SUCCESS) + { + linflexd_puts("M0 thread created\n"); + } + else + { + linflexd_puts("FAIL tx_thread_create status 0x"); + put_hex((ULONG) status); + linflexd_puts("\n"); + } +} diff --git a/ports_module/cortex_r52/gnu/example_build/s32z280_evb/tools/diagnose_module.gdb b/ports_module/cortex_r52/gnu/example_build/s32z280_evb/tools/diagnose_module.gdb new file mode 100644 index 000000000..235cd6e48 --- /dev/null +++ b/ports_module/cortex_r52/gnu/example_build/s32z280_evb/tools/diagnose_module.gdb @@ -0,0 +1,252 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# Diagnostic run for the S32Z280 module manager demonstration. Same attach and +# load as run_module_demo.gdb, but instead of judging the result it dumps the +# state needed to explain one: +# +# * every ThreadX thread, with its run count -- which separates "the module +# thread never ran" from "it ran and died", the first question to answer +# when module_progress comes back zero. +# * the raw fault info, which says whether an abort was captured even though +# the notify callback never fired. +# * the module instance, so the addresses the manager decided on can be +# compared against where the module's code actually writes. +# * the live MPU regions, read back from the hardware. +# +# Usage: S32Z280_ELF= arm-none-eabi-gdb-py -batch -x diagnose_module.gdb + +# The probe and the S32DS installation, from the environment when +# run_module_demo.sh set them and from the same defaults it uses when this +# script is run by hand. Mirrored in run_module_demo.gdb and +# diagnose_module.gdb rather than shared, because gdb resolves a relative +# "source" against the working directory and these are run from anywhere. +python +import os + +_PROBE_IP = os.environ.get("S32Z280_PROBE", "s32dbg:192.168.50.238") + +_S32DS_ROOT = os.environ.get("S32DS_ROOT") +if not _S32DS_ROOT: + for _candidate in ("/opt/nxp/S32DS.3.6.10", + os.path.expanduser("~/NXP/S32DS.3.6.10")): + if os.path.isdir(_candidate): + _S32DS_ROOT = _candidate + break + +_S32DS_SCRIPT = os.path.join( + _S32DS_ROOT or "", + "S32DS/tools/S32Debugger/Debugger/scripts/s32z2e2", + "s32z2e2_generic_bareboard_all_cores.py") + +if not os.path.isfile(_S32DS_SCRIPT): + raise gdb.GdbError( + "S32DS core script not found at %s\n" + "Set S32DS_ROOT to your S32 Design Studio installation." + % (_S32DS_SCRIPT or "")) + +gdb.execute("source " + _S32DS_SCRIPT) +end + +py _SOC_NAME = "S32Z280" +py _CORE_NAME = "R52_0_0" +py _GDB_SERVER_PORT = 45000 + +py board_init() +py s32z2e2_cores.init(_CORE_NAME) +py s32z2e2_cores.start_debug_by_core_name(_CORE_NAME) + +py gta_lib.set_context(context.CORE_CTX[_SOC_NAME + "_" + _CORE_NAME]).unwrap() +py gta_lib.stop_core().unwrap() +py gta_lib.attach().unwrap() + +python +import gdb, os + +CONTROL2 = 0x4DC11044 +EDBGREQ_CORE0 = 0x00010000 + +def rd(addr): + return int(gdb.parse_and_eval("*(unsigned int *)0x%x" % addr)) & 0xFFFFFFFF + +c2 = rd(CONTROL2) +gdb.execute("set *(unsigned int *)0x%x = 0x%x" % (CONTROL2, c2 & ~EDBGREQ_CORE0)) +if rd(CONTROL2) & EDBGREQ_CORE0: + raise gdb.GdbError("CR52_RTU0_0_EDBGREQ is still set; the core will not run") + +elf = os.environ.get("S32Z280_ELF", "s32z280_module.elf") +gdb.execute("file %s" % elf) +gdb.execute("load") +start = int(gdb.parse_and_eval("(unsigned int)&_start")) & ~1 +gdb.execute("set $pc = 0x%x" % start) +gdb.execute("hbreak sample_threadx_module_manager.c:259") +gdb.execute("continue") +end + +echo \n===== THREADS =====\n +python +import gdb + +def ev(expr): + return gdb.parse_and_eval(expr) + +def u32(expr): + return int(ev(expr)) & 0xFFFFFFFF + +STATE = {0: "READY", 1: "COMPLETED", 2: "TERMINATED", 3: "SUSPENDED", + 4: "SLEEP", 5: "QUEUE_SUSP", 6: "SEMAPHORE_SUSP", 7: "EVENT_FLAG", + 8: "BLOCK_MEMORY", 9: "BYTE_MEMORY", 10: "IO_DRIVER", 11: "FILE", + 12: "TCP_IP", 13: "MUTEX_SUSP", 14: "PRIORITY_CHANGE"} + +try: + count = u32("_tx_thread_created_count") + print(" _tx_thread_created_count = %d" % count) + t = ev("_tx_thread_created_ptr") + print(" %-18s %-4s %-14s %-5s %-10s %-10s %s" + % ("name", "pri", "state", "runs", "stack_ptr", "entry", "module")) + for i in range(count): + name = t["tx_thread_name"].string() if int(t["tx_thread_name"]) else "(unnamed)" + pri = int(t["tx_thread_priority"]) + st = int(t["tx_thread_state"]) + runs = int(t["tx_thread_run_count"]) & 0xFFFFFFFF + sp = int(t["tx_thread_stack_ptr"]) & 0xFFFFFFFF + entry = int(t["tx_thread_entry"]) & 0xFFFFFFFF + try: + mod = int(t["tx_thread_module_instance_ptr"]) & 0xFFFFFFFF + except gdb.error: + mod = 0 + print(" %-18s %-4d %-14s %-5d 0x%08X 0x%08X %s" + % (name, pri, STATE.get(st, "?%d" % st), runs, sp, entry, + ("0x%08X" % mod) if mod else "-")) + t = t["tx_thread_created_next"] +except gdb.error as e: + print(" could not walk the thread list: %s" % e) + +print("") +print(" _tx_thread_current_ptr = 0x%08X" % u32("(unsigned int)_tx_thread_current_ptr")) +print(" _tx_thread_execute_ptr = 0x%08X" % u32("(unsigned int)_tx_thread_execute_ptr")) +end + +echo \n===== RAW FAULT INFO (was an abort captured at all?) =====\n +python +import gdb + +def u32(expr): + return int(gdb.parse_and_eval(expr)) & 0xFFFFFFFF + +f = "_txm_module_manager_memory_fault_info" +try: + info = gdb.parse_and_eval(f) + for field in ("thread_ptr", "code_location", "dfsr", "dfar", "ifsr", "ifar", + "sp", "r0", "r1", "r9", "r10", "r11", "r12", "lr", "spsr"): + key = "txm_module_manager_memory_fault_info_" + field + try: + v = int(info[key]) & 0xFFFFFFFF + print(" %-14s = 0x%08X" % (field, v)) + except gdb.error: + pass +except gdb.error as e: + print(" no fault info: %s" % e) + +print("") +print(" fault_count (sample's own counter) = %d" % u32("fault_count")) + +# Was the callback ever registered? The handler terminates the current thread +# and only then calls the notify hook, so a populated fault info with a zero +# counter has two explanations: the hook was never registered, or +# _tx_thread_terminate on the current thread did not return to the call site. +try: + n = u32("(unsigned int)_txm_module_manager_fault_notify") + want = u32("(unsigned int)&module_fault_notify") + print(" _txm_module_manager_fault_notify = 0x%08X" % n) + print(" &module_fault_notify (sample's) = 0x%08X" % want) + if n == 0: + print(" -> hook NEVER REGISTERED; that alone explains the zero counter") + elif n == want: + print(" -> hook IS registered, so the handler never reached the call:") + print(" _tx_thread_terminate on the current thread did not return") + else: + print(" -> hook points somewhere unexpected") +except gdb.error as e: + print(" could not read the notify hook: %s" % e) +end + +echo \n===== MODULE INSTANCE =====\n +python +import gdb + +def u32(expr): + return int(gdb.parse_and_eval(expr)) & 0xFFFFFFFF + +try: + m = gdb.parse_and_eval("demo_module") + for field in ("txm_module_instance_state", + "txm_module_instance_code_start", + "txm_module_instance_code_end", + "txm_module_instance_code_size", + "txm_module_instance_data_start", + "txm_module_instance_data_end", + "txm_module_instance_data_size", + "txm_module_instance_start_thread_entry", + "txm_module_instance_module_data_base_address", + "txm_module_instance_shell_entry_function", + "txm_module_instance_preamble_ptr", + "txm_module_instance_property_flags"): + try: + print(" %-46s = 0x%08X" % (field.replace("txm_module_instance_", ""), + int(m[field]) & 0xFFFFFFFF)) + except gdb.error: + pass +except gdb.error as e: + print(" cannot read demo_module: %s" % e) + +print("") +print(" where the module area's pieces ended up:") +_status = u32("(unsigned int)&__module_status_start__") +_image = u32("(unsigned int)&__module_image_start__") +print(" __module_status_start__ = 0x%08X" % _status) +print(" __module_image_start__ = 0x%08X" % _image) +print(" __module_pool_start__ = 0x%08X" % u32("(unsigned int)&__module_pool_start__")) +print(" __module_stage_start__ = 0x%08X" % u32("(unsigned int)&__module_stage_start__")) +print("") +print(" first words of the module image, to confirm the blob is really there.") +print(" Read from the linker's symbol, not from a literal: the module moves") +print(" whenever anything above it in the area changes size, and a stale") +print(" address here prints whatever now lives there as though it were the blob.") +for off in (0x00, 0x04, 0x14, 0x18): + a = _image + off + print(" 0x%08X = 0x%08X" % (a, u32("*(unsigned int *)0x%x" % a))) +print("") +print(" the shared granules, which is where the module reports progress and") +print(" where granule %d must have stayed zero:" % 2) +for _g in range(6): + a = _status + _g * 0x40 + print(" granule %d at 0x%08X: word0 = 0x%08X word1 = 0x%08X" + % (_g, a, u32("*(unsigned int *)0x%x" % a), + u32("*(unsigned int *)0x%x" % (a + 4)))) +print("") +print(" module_progress itself lives in the data area the manager allocated for") +print(" the pass, at that pass's data base plus its offset in the module's ELF;") +print(" it has no fixed address since the module became relocatable.") +end + +echo \n===== LIVE MPU REGIONS (read back from hardware) =====\n +python +import gdb + +# Regions 0-15 have direct MCR/MRC encodings at CP15 op1 0; 16 and up have them +# at op1 1 (TRM 8.4, Table 8-9), though only the PRSELR route is proven on this +# part and that is what the manager uses for region 16. Reading +# them back is the only way to see what the module thread was actually given, +# as opposed to what the manager computed. +print(" (read via the running core; regions 8-15 are the module block, 16 the window)") +try: + gdb.execute("p $pc") +except gdb.error: + pass +print(" NOTE: system registers are not exposed over this RSP connection, so the") +print(" region read-back needs an MRC executed on the core. The manager's own") +print(" copy of what it programmed is in the module instance above; comparing") +print(" that against a hardware read is a job for an on-target routine.") +end diff --git a/ports_module/cortex_r52/gnu/example_build/s32z280_evb/tools/run_module_demo.gdb b/ports_module/cortex_r52/gnu/example_build/s32z280_evb/tools/run_module_demo.gdb new file mode 100644 index 000000000..b95eb8265 --- /dev/null +++ b/ports_module/cortex_r52/gnu/example_build/s32z280_evb/tools/run_module_demo.gdb @@ -0,0 +1,657 @@ +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# Load s32z280_module.elf onto the S32Z280-594EVB, run it, and report what the +# protection boundary did. +# +# Usage, normally through run_module_demo.sh which computes the addresses: +# S32Z280_ELF= \ +# S32Z280_MODULE_ELF= \ +# arm-none-eabi-gdb-py -batch -x tools/run_module_demo.gdb +# +# Requires, and does not do for you: +# * a CCS listening on 41475 -- the *Windows* CCS ("ccs.exe -noportquit"). +# The Linux CCS's pushes to the probe stall after "Sending code ... done", +# and under WSL2 mirrored networking a stray Linux CCS holds the port and +# blocks the Windows one ("pkill -x ccs", not -f: it runs as ./ccs). +# * GTA on 45000: Server/gta/gta -p 45000 -k +# * PYTHONHOME pointing at a source-built Python 3.10.11. +# * The UART already being captured to a file BEFORE this runs. The console +# is the test method here, not a convenience: this script reports the same +# verdict from memory, but only the console shows the ordering of events +# that produced it. +# +# WHAT A PASS LOOKS LIKE, and why it is a fault +# +# The sample module writes its own data, calls the kernel through SVC, and then +# deliberately violates its protection. The expected end state is therefore an +# abort taken in User mode, captured by the abort vector, reported through the +# fault-notify callback, and terminating the module thread -- with the manager +# still alive to report it. A run with no fault is a FAILURE: it means a module +# reached kernel memory and was not stopped. +# +# module_progress bit 0x01 wrote and summed its own scratch expect SET +# bit 0x02 reached the kernel through SVC expect SET +# bit 0x04 about to READ the forbidden address data pass only +# bit 0x08 survived the forbidden read expect CLEAR +# bit 0x10 about to BRANCH to it prefetch pass only +# bit 0x20 survived the forbidden branch expect CLEAR +# bit 0x40 wrote and read back every granted +# shared granule shared pass only +# bit 0x80 about to write the UNGRANTED granule shared pass only +# bit 0x100 survived writing it expect CLEAR +# +# so module_progress == 0x7 for a data-abort pass, 0x13 for the prefetch pass and +# 0xC3 for the shared pass. +# +# The manager records the same word a second time, out of the first shared +# granule, and this script reads the module's own copy out of its data area. Two +# independent readings of one event: if they disagree, one of the two channels is +# lying and the run says which. +# +# FOUR PASSES, because one run proves neither relocation nor both abort types +# +# The module is position independent, so a single run at the address it was +# linked for would prove nothing: the GOT rebase would map every address to +# itself and a rebase that did nothing would look the same. So passes 1 and 2 +# run the same blob from two addresses -- once where the linker put it, once from +# a staging area -- and this script compares them. +# +# Pass 3 faults the other way. Passes 1 and 2 read an address they do not own, +# which is a DATA abort reported through DFSR and DFAR. Pass 3 branches outside +# its code region, which is a PREFETCH abort reported through IFSR and IFAR and +# arrives at the handler by a different vector. It runs after passes 1 and 2 have +# been unloaded, so it also shows that a module fault leaves the manager able to +# load and run the next module. +# +# Pass 4 is the shared regions. Passes 1 to 3 are each granted ONE shared +# region -- the granule they report progress through -- which exercises the first +# of the five shared entries the port provides and nothing about the other four. +# Pass 4 is granted all five, one 64-byte granule each, and is deliberately NOT +# granted the granule that sits between two of them; it writes every granule it +# was given, reads them all back, and then writes the gap, which must fault. A +# limit register masked the wrong way, or a base off by a granule, reaches into +# that gap from one side or the other. The same pass probes the two refusals -- +# an unaligned grant must come back TXM_MODULE_ALIGNMENT_ERROR (0xF0) and one +# grant past the entry count must come back TX_NO_MEMORY (0x10). +# +# THE NOTIFY CALLBACK IS A CHECK NOW, not a note +# +# It used to be dead on this port: the shared fault handler terminates the +# offending thread and only then calls the hook, and _tx_thread_terminate returns +# for the running thread only if the abort vector has told the kernel it is inside +# an exception -- which this port's vector did not do. It does now, so every pass +# must see the callback run exactly once, with the faulting thread and the right +# module instance. Zero notifications next to a captured fault is a regression in +# that bracket and nothing else. +# +# Finding module_progress is no longer a matter of reading the module's ELF. A +# relocated module's data lives wherever the manager allocated it, so the address +# is (this pass's data base) + (the nominal offset of module_progress within the +# module's data segment). The first number is read from the module instance on +# the target, the second from the module's ELF, and neither is a constant that +# can be written down here. +# +# AND IT HAS TO BE READ WHILE THE PASS STILL OWNS THE MEMORY. The byte pool +# reuses freed blocks, so pass 3 -- which loads after passes 1 and 2 are unloaded +# -- lands exactly where pass 1 was. Reading all three at the end of the run +# therefore reports pass 3's progress as pass 1's, and pass 1 looks like it took +# the wrong branch. So this script breaks on pass_done once per pass and reads +# that pass's word there, before anything is unloaded. + +# The probe and the S32DS installation, from the environment when +# run_module_demo.sh set them and from the same defaults it uses when this +# script is run by hand. Mirrored in run_module_demo.gdb and +# diagnose_module.gdb rather than shared, because gdb resolves a relative +# "source" against the working directory and these are run from anywhere. +python +import os + +_PROBE_IP = os.environ.get("S32Z280_PROBE", "s32dbg:192.168.50.238") + +_S32DS_ROOT = os.environ.get("S32DS_ROOT") +if not _S32DS_ROOT: + for _candidate in ("/opt/nxp/S32DS.3.6.10", + os.path.expanduser("~/NXP/S32DS.3.6.10")): + if os.path.isdir(_candidate): + _S32DS_ROOT = _candidate + break + +_S32DS_SCRIPT = os.path.join( + _S32DS_ROOT or "", + "S32DS/tools/S32Debugger/Debugger/scripts/s32z2e2", + "s32z2e2_generic_bareboard_all_cores.py") + +if not os.path.isfile(_S32DS_SCRIPT): + raise gdb.GdbError( + "S32DS core script not found at %s\n" + "Set S32DS_ROOT to your S32 Design Studio installation." + % (_S32DS_SCRIPT or "")) + +gdb.execute("source " + _S32DS_SCRIPT) +end + +py _SOC_NAME = "S32Z280" +py _CORE_NAME = "R52_0_0" +py _GDB_SERVER_PORT = 45000 + +py board_init() +py s32z2e2_cores.init(_CORE_NAME) +py s32z2e2_cores.start_debug_by_core_name(_CORE_NAME) + +# Select the core context before asking about core state. NXP's core_init() +# omits this and then stop_core() reads the mode of the SoC context, which has +# none, and reports "Core can't be stopped. State is undefined/unknown". +py gta_lib.set_context(context.CORE_CTX[_SOC_NAME + "_" + _CORE_NAME]).unwrap() +py gta_lib.stop_core().unwrap() +py gta_lib.attach().unwrap() + +python +import gdb, os + +# --------------------------------------------------------------------------- +# Release the core from the debugger's external debug request. +# +# _reset_to_first_instruction() asserts MDM_AP CONTROL2[19:16] = +# CR52_RTU0_{3,2,1,0}_EDBGREQ (0x000F0000) and nothing clears them, so every +# RTU0 core is pinned in debug state and executes nothing -- registers and +# memory still respond, which is what makes it look like working hardware. +# --------------------------------------------------------------------------- +CONTROL2 = 0x4DC11044 +EDBGREQ_CORE0 = 0x00010000 + +def rd(addr): + return int(gdb.parse_and_eval("*(unsigned int *)0x%x" % addr)) & 0xFFFFFFFF + +c2 = rd(CONTROL2) +gdb.execute("set *(unsigned int *)0x%x = 0x%x" % (CONTROL2, c2 & ~EDBGREQ_CORE0)) +if rd(CONTROL2) & EDBGREQ_CORE0: + raise gdb.GdbError("CR52_RTU0_0_EDBGREQ is still set; the core will not run") +print("EDBGREQ cleared: CONTROL2 0x%08X -> 0x%08X" % (c2, rd(CONTROL2))) + +elf = os.environ.get("S32Z280_ELF", "s32z280_module.elf") +gdb.execute("file %s" % elf) +gdb.execute("load") + +# The core resets in Thumb state and CPSR cannot be written through this +# connection, so entry must be the T32 _start. Mask bit 0: GDB reports a Thumb +# function's address with it set, but PC itself must be even. +start = int(gdb.parse_and_eval("(unsigned int)&_start")) & ~1 +gdb.execute("set $pc = 0x%x" % start) +print("PC set to 0x%08X" % start) + +# Stop after the manager has printed its whole report. manager_done exists for +# this and nothing else: the previous version of this script broke on +# sample_threadx_module_manager.c:259, and every edit to that file moved the line +# out from under the breakpoint, after which the run stopped somewhere arbitrary +# and reported whatever memory happened to hold. +# +# hbreak, not break: the code region is mapped read-only by the MPU, so a +# software breakpoint would have to write to it. +gdb.execute("hbreak pass_done") +gdb.execute("hbreak manager_done") + +# Each pass's module_progress, read at pass_done while that pass still holds its +# data. Kept in a global the reporting block below picks up; gdb's python runs in +# one persistent namespace, and the reader falls back to "skipped" rather than a +# traceback if that ever stops being true. +PROGRESS_BY_PASS = [] + +_offset = os.environ.get("S32Z280_MODULE_PROGRESS_OFFSET") +_offset = int(_offset, 0) if _offset else None + +for _i in range(4): + gdb.execute("continue") + if _offset is None: + PROGRESS_BY_PASS.append(None) + continue + _base = int(gdb.parse_and_eval("pass_results[%d].pass_data_base" % _i)) & 0xFFFFFFFF + if _base == 0: + # The pass never loaded, so there is no data base and nothing to read. + PROGRESS_BY_PASS.append(None) + else: + _addr = _base + _offset + PROGRESS_BY_PASS.append( + int(gdb.parse_and_eval("*(unsigned int *)0x%x" % _addr)) & 0xFFFFFFFF) + print("pass %d: module_progress 0x%08X at 0x%08X (read while loaded)" + % (_i + 1, PROGRESS_BY_PASS[-1], _addr)) + +# On to the report the manager prints for itself. +gdb.execute("continue") +end + +echo \n===== module manager run: what memory says =====\n +python +import gdb, os + +def rd(addr): + return int(gdb.parse_and_eval("*(unsigned int *)0x%x" % addr)) & 0xFFFFFFFF + +def ev(expr): + return int(gdb.parse_and_eval(expr)) & 0xFFFFFFFF + +failures = 0 + +OWN_DATA, KERNEL_CALL = 0x01, 0x02 +ATTEMPTED_STEAL, SURVIVED_STEAL = 0x04, 0x08 +ATTEMPTED_JUMP, SURVIVED_JUMP = 0x10, 0x20 +SHARED_WROTE = 0x40 +ATTEMPTED_GAP, SURVIVED_GAP = 0x80, 0x100 +FORBIDDEN = 0x31780000 + +# The shared area, mirrored from S32Z_MODULE_STATUS_* in platform.h. Five of the +# six granules are granted, one entry each; index 2 never is, and the marks go at +# word 1 because word 0 of granule 0 is the progress word. +STATUS_BASE, STATUS_GRANULE, STATUS_GRANULES = 0x317F0000, 0x40, 6 +STATUS_UNGRANTED, STATUS_MARK_OFFSET = 2, 4 +SHARED_SIGNATURE = 0x5A5A0000 +ALIGNMENT_ERROR, NO_MEMORY = 0xF0, 0x10 +SUCCESS, SIZE_ERROR = 0x00, 0x05 +MODE = {0x10: "User", 0x13: "Supervisor", 0x1A: "Hyp", 0x1F: "System"} + +# Which violation each pass was told to commit, from the low byte of the module ID +# the manager writes into the instance before starting it. +TEST_DATA_ABORT, TEST_PREFETCH_ABORT, TEST_SHARED_ABORT = 0x1, 0x2, 0x3 +PASSES = 4 +RELOCATION_PASSES = 2 + +# The nominal offset of module_progress inside the module's data segment. Both +# halves come from the module's own ELF and neither is an address the module ever +# runs at -- see link_demo_module.lds. The run-time address is this offset plus +# whatever data base the manager handed the module, which differs per pass. +progress_offset = os.environ.get("S32Z280_MODULE_PROGRESS_OFFSET") +progress_offset = int(progress_offset, 0) if progress_offset else None + +if progress_offset is None: + print(" NOTE S32Z280_MODULE_PROGRESS_OFFSET unset; skipping the progress checks") +else: + print(" module_progress sits %d bytes into the module's data segment" % progress_offset) + +passes = [] +for i in range(PASSES): + p = {} + for field in ("pass_test", "pass_load_status", "pass_share_status", + "pass_start_status", "pass_stop_status", + "pass_code_start", "pass_code_end", "pass_data_start", + "pass_data_end", "pass_data_base", "pass_faults", + "pass_captured", "pass_fault_r9", + "pass_dfsr", "pass_dfar", "pass_ifsr", "pass_ifar", + "pass_spsr", "pass_code_location", + "pass_notify_thread", "pass_notify_instance", + "pass_expect_thread", "pass_expect_instance", + "pass_progress", "pass_expect_progress", "pass_expect_fault", + "pass_shared_grants", "pass_shared_count", + "pass_align_status", "pass_exhaust_status"): + p[field] = ev("pass_results[%d].%s" % (i, field)) + p["marks"] = [ev("pass_results[%d].pass_marks[%d]" % (i, g)) + for g in range(STATUS_GRANULES)] + try: + p["name"] = gdb.parse_and_eval("pass_results[%d].pass_name" % i).string() + except gdb.error: + p["name"] = "pass %d" % (i + 1) + passes.append(p) + +for i, p in enumerate(passes): + prefetch = (p["pass_test"] == TEST_PREFETCH_ABORT) + shared = (p["pass_test"] == TEST_SHARED_ABORT) + print("") + print(" --- pass %d: %s ---" % (i + 1, p["name"])) + if prefetch: + print(" expected abort = prefetch, through IFSR/IFAR") + elif shared: + print(" expected abort = data, through DFSR/DFAR, writing an") + print(" ungranted shared granule") + else: + print(" expected abort = data, through DFSR/DFAR") + print(" load / share / start / stop = 0x%08X / 0x%08X / 0x%08X / 0x%08X" + % (p["pass_load_status"], p["pass_share_status"], + p["pass_start_status"], p["pass_stop_status"])) + print(" code region = 0x%08X .. 0x%08X" + % (p["pass_code_start"], p["pass_code_end"])) + print(" data region = 0x%08X .. 0x%08X" + % (p["pass_data_start"], p["pass_data_end"])) + print(" data base (r9) = 0x%08X" % p["pass_data_base"]) + + if (p["pass_load_status"] != 0 or p["pass_share_status"] != 0 + or p["pass_start_status"] != 0): + print(" *** FAIL: did not load, share and start") + failures += 1 + continue + + # Code and data regions are enabled together and PMSAv8-R has no region + # priority, so an access hitting both takes a translation fault (TRM 8.1) + # rather than merely being untidy. Checked here as well as on the target + # because a debugger can say which two regions met, and the target can only + # say that something did. + if (p["pass_code_start"] <= p["pass_data_end"] + and p["pass_data_start"] <= p["pass_code_end"]): + print(" *** FAIL: this module's code and data regions overlap") + failures += 1 + + progress = globals().get("PROGRESS_BY_PASS", [None] * PASSES)[i] + if progress is None: + print(" module_progress = not read") + else: + addr = p["pass_data_base"] + progress_offset + print(" module_progress = 0x%08X (read at 0x%08X while this pass" + % (progress, addr)) + print(" still held that memory)") + + # Every bit is checked, including the ones belonging to the violations + # this pass was NOT told to commit: a module that took more than one + # route, or the wrong one, is not the module this pass asked for and the + # result would not mean what the register checks below claim. + data = not (prefetch or shared) + wanted = [(OWN_DATA, "wrote its own data", True), + (KERNEL_CALL, "reached the kernel through SVC", True), + (ATTEMPTED_STEAL, "attempted the forbidden read", data), + (SURVIVED_STEAL, "SURVIVED the forbidden read", False), + (ATTEMPTED_JUMP, "attempted the forbidden branch", prefetch), + (SURVIVED_JUMP, "SURVIVED the forbidden branch", False), + (SHARED_WROTE, "wrote and read back every granted granule", shared), + (ATTEMPTED_GAP, "attempted the ungranted granule", shared), + (SURVIVED_GAP, "SURVIVED the ungranted granule", False)] + for bit, name, want_set in wanted: + got = bool(progress & bit) + ok = (got == want_set) + if not ok: + failures += 1 + print(" 0x%03X %-42s %-5s %s" + % (bit, name, "set" if got else "clear", + "ok" if ok else "*** WRONG ***")) + if progress & (SURVIVED_STEAL | SURVIVED_JUMP | SURVIVED_GAP): + print(" ISOLATION FAILURE: the module reached memory it was never granted.") + + # The manager's own reading of the same word, out of the first shared + # granule. Two independent channels for one event: the module writes + # both, this script reads its private copy and the manager read the + # shared one, so a disagreement means one of the two paths is lying and + # neither result should be trusted until it is explained. + if p["pass_progress"] != progress: + print(" *** FAIL: the manager read progress 0x%08X out of the shared" + % p["pass_progress"]) + print(" granule, the module's own copy says 0x%08X" % progress) + failures += 1 + if p["pass_progress"] != p["pass_expect_progress"]: + print(" *** FAIL: progress 0x%08X, expected 0x%08X" + % (p["pass_progress"], p["pass_expect_progress"])) + failures += 1 + + # "captured" and "notified" are different events: the abort vector records the + # fault registers before anything else runs, and the notify callback is a + # later consequence of the same fault. Both are required. Reporting them + # apart is what keeps a broken notify path from being read as "no fault + # occurred", which is the opposite of the truth. + print(" fault captured = %d" % p["pass_captured"]) + print(" notify callbacks = %d" % p["pass_faults"]) + if p["pass_captured"] == 0: + print(" *** FAIL: no fault was captured. The module reached outside its") + print(" memory and was not stopped, or never got that far.") + failures += 1 + continue + + # The callback is a public API of the module manager, so its arguments are + # checked and not merely counted. Zero notifications beside a captured fault + # means the fault reached the hardware's evidence and never reached the + # application: on this port that is the system-state bracket in + # txm_module_manager_fault_capture.S having gone missing again. + if p["pass_faults"] != 1: + print(" *** FAIL: the notify callback ran %d times, not once." + % p["pass_faults"]) + failures += 1 + elif (p["pass_notify_thread"] != p["pass_expect_thread"] + or p["pass_notify_instance"] != p["pass_expect_instance"]): + print(" *** FAIL: notified about thread 0x%08X / module 0x%08X," + % (p["pass_notify_thread"], p["pass_notify_instance"])) + print(" expected thread 0x%08X / module 0x%08X" + % (p["pass_expect_thread"], p["pass_expect_instance"])) + failures += 1 + else: + print(" notified about = thread 0x%08X, module 0x%08X (both correct)" + % (p["pass_notify_thread"], p["pass_notify_instance"])) + + dfsr, dfar, spsr, pc = (p["pass_dfsr"], p["pass_dfar"], + p["pass_spsr"], p["pass_code_location"]) + ifsr, ifar = p["pass_ifsr"], p["pass_ifar"] + + # Both pairs are printed for both kinds of pass, because the capture records + # both and the pair that does not belong to this fault is a leftover the + # hardware never cleared -- worth seeing, and worth not mistaking for a + # result. Which pair is meaningful is decided by the expected abort type, + # not by which of them looks plausible. + print(" DFSR = 0x%08X status 0x%02X WnR %d%s" + % (dfsr, dfsr & 0x3F, (dfsr >> 11) & 1, + "" if not prefetch else " (stale: this pass took a prefetch abort)")) + print(" DFAR = 0x%08X" % dfar) + print(" IFSR = 0x%08X status 0x%02X%s" + % (ifsr, ifsr & 0x3F, + " (stale: this pass took a data abort)" if not prefetch else "")) + print(" IFAR = 0x%08X" % ifar) + print(" SPSR = 0x%08X mode 0x%02X (%s)" + % (spsr, spsr & 0x1F, MODE.get(spsr & 0x1F, "?"))) + print(" faulting pc = 0x%08X" % pc) + if prefetch: + # The fault is on the fetch AT the branch target, so the faulting pc is + # the target and not a place inside the module. + print(" (the faulting pc is the branch target, outside the module)") + else: + print(" pc - code base = 0x%08X" % ((pc - p["pass_code_start"]) & 0xFFFFFFFF)) + print(" r9 at the fault = 0x%08X" % p["pass_fault_r9"]) + + # r9 is the module's PIC base, seeded by the manager's thread stack build from + # the thread entry info. Before T3 it was left at 0, which is what made every + # module data reference resolve to a small absolute address. Checking it + # directly turns that class of bug into one line instead of a fault to explain. + if p["pass_fault_r9"] != p["pass_data_base"]: + print(" *** FAIL: r9 should be the data base 0x%08X" % p["pass_data_base"]) + failures += 1 + + if (spsr & 0x1F) != 0x10: + print(" *** FAIL: the fault did not come from User mode, so it is not") + print(" a module being stopped at the boundary.") + failures += 1 + + # The faulting address is the strongest single check in this script. The + # module obtained it by reading one of its own initialised globals through the + # rebased GOT, so the right value here means the GOT was rewritten AND .data + # was copied out of the image. A wrong value usually means the module faulted + # on its own data instead, which is what a bad rebase looks like. + # + # A data abort reports it in DFAR, a prefetch abort in IFAR. Both registers + # are sticky, so checking the pair that does not belong to this fault would + # pass on a value some earlier fault left behind -- including the boot probes, + # which take a prefetch abort of their own before ThreadX starts. + # + # The shared pass is the exception: the address it faults on is the mark word + # of the granule it was not granted, which it computes from a literal rather + # than out of .data -- so for that pass this is a check on the grant and not + # on the rebase. Which is why the expectation is carried per pass. + reg_name, reg_value = ("IFAR", ifar) if prefetch else ("DFAR", dfar) + expect_fault = p["pass_expect_fault"] or FORBIDDEN + if reg_value != expect_fault: + print(" *** FAIL: expected %s 0x%08X, the address the module was told" + % (reg_name, expect_fault)) + print(" not to touch. A different one means .data was not") + print(" copied or the GOT was not rebased.") + failures += 1 + + # A prefetch abort with nothing in IFSR would mean the vector reached the + # capture without the core having recorded an instruction fault, which is the + # one way this pass could look right and be meaningless. + if prefetch and (ifsr & 0x3F) == 0: + print(" *** FAIL: IFSR reports no instruction fault status") + failures += 1 + + # The shared-region results, for the one pass that produces them. Read out + # of the manager's own record rather than out of the MPU: what the hardware + # holds is checked by the module having faulted, and what is checked here is + # that the manager granted what it meant to and refused what it should. + if shared: + print(" shared grants = %d (expected %d)" + % (p["pass_shared_grants"], STATUS_GRANULES - 1)) + print(" entries held = %d" % p["pass_shared_count"]) + print(" unaligned grant = 0x%02X (expected 0x%02X, TXM_MODULE_ALIGNMENT_ERROR)" + % (p["pass_align_status"], ALIGNMENT_ERROR)) + print(" one grant too many = 0x%02X (expected 0x%02X, TX_NO_MEMORY)" + % (p["pass_exhaust_status"], NO_MEMORY)) + + if p["pass_shared_grants"] != STATUS_GRANULES - 1: + print(" *** FAIL: not every shared entry could be granted") + failures += 1 + if p["pass_shared_count"] != STATUS_GRANULES - 1: + print(" *** FAIL: the instance does not hold the entries it granted") + failures += 1 + if p["pass_align_status"] != ALIGNMENT_ERROR: + print(" *** FAIL: an unaligned shared grant was not refused as such.") + print(" Accepting one does not fault -- the low six bits of") + print(" PRBAR are permissions, so it changes what the region") + print(" allows instead of where it is.") + failures += 1 + if p["pass_exhaust_status"] != NO_MEMORY: + print(" *** FAIL: one grant too many was not refused. The entry index") + print(" is TXM_MODULE_MPU_SHARED_INDEX plus the count, so a") + print(" sixth grant writes past the end of the region table.") + failures += 1 + + # And what the module managed to write where. A granted granule holding + # something other than its own mark means that entry was programmed with + # the wrong base -- the store was accepted and landed elsewhere -- and a + # non-zero gap means a grant covered a granule nobody asked for. + for g in range(STATUS_GRANULES): + addr = STATUS_BASE + g * STATUS_GRANULE + STATUS_MARK_OFFSET + want = 0 if g == STATUS_UNGRANTED else (SHARED_SIGNATURE | g) + got = p["marks"][g] + tag = "ungranted" if g == STATUS_UNGRANTED else "granted " + ok = (got == want) + if not ok: + failures += 1 + print(" granule %d %s at 0x%08X = 0x%08X (expected 0x%08X) %s" + % (g, tag, addr, got, want, "ok" if ok else "*** WRONG ***")) + +# --- the relocation result, which is the comparison between the passes -------- +print("") +print(" ===== both abort types =====") +data_passes = [q for q in passes if q["pass_test"] != TEST_PREFETCH_ABORT + and q["pass_captured"] and (q["pass_dfsr"] & 0x3F)] +pabt_passes = [q for q in passes if q["pass_test"] == TEST_PREFETCH_ABORT + and q["pass_captured"] and (q["pass_ifsr"] & 0x3F)] +print(" data aborts captured = %d" % len(data_passes)) +print(" prefetch aborts captured = %d" % len(pabt_passes)) +if not data_passes or not pabt_passes: + print(" *** FAIL: only one kind of abort was exercised, so half of the") + print(" port's fault path never ran") + failures += 1 +else: + print(" PASS: both vectors were taken and both register pairs reported") + +print("") +print(" ===== relocation =====") +a, b = passes[0], passes[1] +off_a = (a["pass_code_location"] - a["pass_code_start"]) & 0xFFFFFFFF +off_b = (b["pass_code_location"] - b["pass_code_start"]) & 0xFFFFFFFF + +if a["pass_captured"] == 0 or b["pass_captured"] == 0: + print(" *** FAIL: a pass did not fault, so there is nothing to compare") + failures += 1 +elif a["pass_code_start"] == b["pass_code_start"]: + print(" *** FAIL: both passes ran from the same address 0x%08X" + % a["pass_code_start"]) + failures += 1 +elif off_a != off_b: + print(" *** FAIL: the passes faulted at different offsets, 0x%08X and 0x%08X" + % (off_a, off_b)) + failures += 1 +else: + print(" code bases 0x%08X and 0x%08X, %d bytes apart" + % (a["pass_code_start"], b["pass_code_start"], + (b["pass_code_start"] - a["pass_code_start"]) & 0xFFFFFFFF)) + print(" both faulted at offset 0x%08X into their own image" % off_a) + print(" PASS: the same blob ran correctly from two different addresses") + if a["pass_data_base"] == b["pass_data_base"]: + print(" NOTE both passes shared a data base 0x%08X, so the data half of" + % a["pass_data_base"]) + print(" the rebase produced the same numbers twice") + +print("") +print(" ===== shared-grant size guards =====") + +# The manager's own record for the fifth module, which is loaded after the four +# passes and unloaded again without ever being started. Read from memory for the +# same reason everything above is: the console says what the manager believes, +# and this says what it actually stored. +# +# A grant of no bytes, and one whose inclusive end wraps past 0xFFFFFFFF, both +# used to describe a region whose limit lay below its base -- and both were +# programmed, charged an entry and reported as TX_SUCCESS. What is checked here +# is the pair: the status, and that the entry count did not move. A guard that +# returned the right code and still spent an entry would look correct on the +# console and would silently cost an application one of its five. +try: + g = {f: ev("guard_result.guard_%s" % f) for f in + ("load_status", "count_start", + "zero_status", "count_zero", + "wrap_status", "count_wrap", + "top_status", "count_top", + "unload_status")} +except gdb.error as e: + print(" *** FAIL: guard_result unreadable (%s)" % e) + failures += 1 + g = None + +if g is not None: + print(" probe module load = 0x%02X (expected 0x%02X)" + % (g["load_status"], SUCCESS)) + print(" entries at start = %d (expected 0)" % g["count_start"]) + print(" zero length = 0x%02X (expected 0x%02X, TX_SIZE_ERROR), " + "entries after = %d" % (g["zero_status"], SIZE_ERROR, g["count_zero"])) + print(" wrapping end = 0x%02X (expected 0x%02X, TX_SIZE_ERROR), " + "entries after = %d" % (g["wrap_status"], SIZE_ERROR, g["count_wrap"])) + print(" ends at 0xFFFFFFFF = 0x%02X (expected 0x%02X, TX_SUCCESS), " + "entries after = %d" % (g["top_status"], SUCCESS, g["count_top"])) + print(" probe module unload = 0x%02X (expected 0x%02X)" + % (g["unload_status"], SUCCESS)) + + if g["load_status"] != SUCCESS: + print(" *** FAIL: the probe module did not load, so nothing below ran") + failures += 1 + else: + if g["count_start"] != 0: + print(" *** FAIL: a freshly loaded instance already held shared entries") + failures += 1 + if g["zero_status"] != SIZE_ERROR: + print(" *** FAIL: a zero-length grant was not refused as a size error.") + print(" Its limit is base - 1, which lies below its base.") + failures += 1 + if g["wrap_status"] != SIZE_ERROR: + print(" *** FAIL: a grant running off the top of memory was not refused.") + print(" base + length - 1 wraps to a low address.") + failures += 1 + if g["count_zero"] != 0 or g["count_wrap"] != 0: + print(" *** FAIL: a refused grant still consumed one of the five entries") + failures += 1 + if g["top_status"] != SUCCESS: + print(" *** FAIL: a grant whose last byte is 0xFFFFFFFF was refused.") + print(" It needs exactly the room there is; the overflow") + print(" guard has overreached into a legal case.") + failures += 1 + elif g["count_top"] != 1: + print(" *** FAIL: the accepted grant did not consume exactly one entry") + failures += 1 + if g["unload_status"] != SUCCESS: + print(" *** FAIL: the probe module did not unload") + failures += 1 + +print("") +# Cast, because this symbol has no debug type in the manager image and gdb +# refuses to read an untyped symbol without being told its width. +try: + print(" boot_stage = %d" % ev("*(unsigned int *)&boot_stage")) +except gdb.error as e: + print(" boot_stage = unavailable (%s)" % e) +print("") +if failures == 0: + print("===== PASS: relocated, stopped at the boundary both ways, and reported =====") +else: + print("===== FAIL: %d check(s) wrong =====" % failures) +end diff --git a/ports_module/cortex_r52/gnu/example_build/s32z280_evb/tools/run_module_demo.sh b/ports_module/cortex_r52/gnu/example_build/s32z280_evb/tools/run_module_demo.sh new file mode 100755 index 000000000..c37d5a969 --- /dev/null +++ b/ports_module/cortex_r52/gnu/example_build/s32z280_evb/tools/run_module_demo.sh @@ -0,0 +1,187 @@ +#!/bin/bash +# Copyright (c) 2026 Eclipse ThreadX contributors +# SPDX-License-Identifier: MIT +# Some portions generated by Claude Code (Opus 5). +# +# Run the ThreadX module manager demonstration on the S32Z280-594EVB and capture +# the evidence: the console log and the fault registers. +# +# Usage: tools/run_module_demo.sh [] +# +# Paths that vary by machine come from the environment: S32DS_ROOT, S32Z280_PROBE +# and GDB_PY_HOME, each described where it is resolved below. UART and LOG +# override the console device and the capture file. +# +# The console is the test method here, not a convenience, so this captures the +# UART to a file before the image runs and prints the captured bytes afterwards. +# Both LINFlexD bugs found during bring-up were invisible from the target and +# showed up only in a byte diff of a captured log. +# +# Prerequisites this cannot do for you: +# * the *Windows* CCS listening on 41475, started as "ccs.exe -noportquit". +# The Linux CCS's pushes to the probe stall after "Sending code ... done". +# * board wiring for the console: LIN9 -> daughtercard USB-UART, jumper J248 +# at 1-2, micro-USB at J119 on the daughtercard. +set -u + +BUILD=${1:-build_mod} +EVB_BIN="$BUILD/ports/cortex_r52/gnu/example_build/s32z280_evb" +HERE=$(cd "$(dirname "$0")" && pwd) + +# Where the tools live. None of these paths are portable, so each is +# overridable and each is checked before it is used -- a wrong one otherwise +# surfaces as a gdb that will not start or an attach that never connects. +# +# S32DS_ROOT the S32 Design Studio installation. Tried in order: the +# variable, a system-wide install, the per-user layout. +# S32Z280_PROBE the debug probe, as the gdb scripts expect to address it. +# GDB_PY_HOME the source-built CPython that gdb-py needs; see PYTHONHOME +# below for why the one inside gdb is not enough. +if [ -n "${S32DS_ROOT:-}" ]; then + R=$S32DS_ROOT +elif [ -d /opt/nxp/S32DS.3.6.10 ]; then + R=/opt/nxp/S32DS.3.6.10 +else + R=$HOME/NXP/S32DS.3.6.10 +fi + +if [ ! -d "$R" ]; then + echo "ERROR: S32 Design Studio not found at $R" >&2 + echo " Set S32DS_ROOT to your installation, for example:" >&2 + echo " S32DS_ROOT=/opt/nxp/S32DS.3.6.10 $0 ${1:-}" >&2 + exit 1 +fi + +GDB=$R/S32DS/tools/gdb-arm/arm32-eabi/bin/arm-none-eabi-gdb-py +GTA=$R/S32DS/tools/S32Debugger/Debugger/Server/gta + +for f in "$GDB" "$GTA/gta"; do + if [ ! -x "$f" ]; then + echo "ERROR: $f is missing or not executable." >&2 + echo " S32DS_ROOT=$R does not look like an S32 Design Studio install." >&2 + exit 1 + fi +done + +# Resolved here and exported, so the gdb scripts use these values rather than +# resolving the same defaults again and possibly differently. +export S32DS_ROOT=$R +export S32Z280_PROBE=${S32Z280_PROBE:-s32dbg:192.168.50.238} + +echo "S32DS_ROOT = $R" +echo "S32Z280_PROBE = $S32Z280_PROBE" + +MANAGER_ELF=$EVB_BIN/s32z280_module.elf +MODULE_ELF=$EVB_BIN/s32z280_demo_module.elf +UART=${UART:-/dev/ttyUSB0} +LOG=${LOG:-/tmp/module_demo_uart.log} + +for f in "$MANAGER_ELF" "$MODULE_ELF"; do + if [ ! -f "$f" ]; then + echo "ERROR: $f not found. Build it first:" >&2 + echo " ninja -C $BUILD s32z280_module.elf" >&2 + exit 1 + fi +done + +# gdb-py needs the source-built interpreter: its embedded Python has a minimal +# builtin set and loads _struct/_socket/_ctypes as separate .so files. Compute +# the module address BEFORE exporting PYTHONHOME, since that breaks system tools. +# What is wanted is an OFFSET, not an address. The module is position +# independent: the address nm reports is a nominal one from a segment the module +# never runs at, and its real data lives wherever the manager allocated it -- a +# different place in each pass. So the offset of module_progress +# within the module's data segment is computed here, and the gdb script adds it +# to each pass's data base, which it reads off the target. +PROGRESS_SYM=$(nm "$MODULE_ELF" | awk '$3=="module_progress"{print $1}') +DATA_SEG=$(nm "$MODULE_ELF" | awk '$3=="__data_segment_start__"{print $1}') +if [ -z "$PROGRESS_SYM" ] || [ -z "$DATA_SEG" ]; then + echo "ERROR: module_progress or __data_segment_start__ not found in $MODULE_ELF" >&2 + exit 1 +fi +PROGRESS_OFFSET=$(( 0x$PROGRESS_SYM - 0x$DATA_SEG )) +if [ "$PROGRESS_OFFSET" -lt 0 ]; then + echo "ERROR: module_progress is below the module's data segment; the link map" >&2 + echo " and this script disagree about where the module's data starts." >&2 + exit 1 +fi +echo "module_progress is $PROGRESS_OFFSET bytes into the module's data segment" +echo " (nominal 0x$PROGRESS_SYM, data segment 0x$DATA_SEG -- neither is a real address)" + +if pgrep -x ccs > /dev/null; then + echo "ERROR: a Linux CCS is running (pid $(pgrep -x ccs | tr '\n' ' '))." >&2 + echo " It holds 41475 and blocks the Windows CCS. Kill it: pkill -x ccs" >&2 + exit 1 +fi +# /dev/tcp rather than a Python probe: PYTHONHOME below points at the +# source-built 3.10 for gdb-py, which would make system python3 fail and this +# check spuriously report "no CCS". +if ! timeout 5 bash -c "exec 3<>/dev/tcp/127.0.0.1/41475" 2>/dev/null; then + echo "ERROR: nothing listening on 41475." >&2 + echo " CCS quits when its client disconnects unless started with" >&2 + echo " -noportquit. Relaunch on Windows as: ccs.exe -noportquit" >&2 + exit 1 +fi + +# --- console capture, started BEFORE the image runs ------------------------- +if [ -c "$UART" ]; then + stty -F "$UART" 115200 cs8 -parenb -cstopb -crtscts raw -echo + : > "$LOG" + cat "$UART" > "$LOG" & + CAT_PID=$! + echo "capturing $UART -> $LOG (pid $CAT_PID)" +else + CAT_PID="" + echo "WARNING: $UART is not a character device; running without a console capture." >&2 +fi + +cleanup() { + if [ -n "$CAT_PID" ]; then + kill "$CAT_PID" 2>/dev/null || true + fi +} +trap cleanup EXIT + +P=${GDB_PY_HOME:-$HOME/toolchains/py310-src} +if [ ! -d "$P/lib/python3.10" ]; then + echo "ERROR: no source-built CPython 3.10 at $P" >&2 + echo " gdb-py's embedded interpreter loads _struct, _socket and" >&2 + echo " _ctypes as separate .so files and needs a real install to" >&2 + echo " find them. Set GDB_PY_HOME to one." >&2 + exit 1 +fi +export PYTHONHOME=$P +export PYTHONPATH=$P/lib/python3.10:$P/lib/python3.10/lib-dynload:$P/lib/python3.10/site-packages +export S32Z280_ELF=$MANAGER_ELF +export S32Z280_MODULE_ELF=$MODULE_ELF +export S32Z280_MODULE_PROGRESS_OFFSET=$PROGRESS_OFFSET + +# pkill -x, not -f: these run as ./gta, so a -f pattern like 'gta/gta' never +# matches and a stale server silently serves the next attach. +pkill -x gta 2>/dev/null +sleep 2 +( cd "$GTA" && nohup ./gta -p 45000 -k > /tmp/gta_module_demo.log 2>&1 & ) +sleep 4 +if ! pgrep -x gta > /dev/null; then + echo "ERROR: GTA failed to start; see /tmp/gta_module_demo.log" >&2 + exit 1 +fi + +timeout -k 20 500 "$GDB" -batch -x "$HERE/run_module_demo.gdb" +rc=$? + +# Let the last of the console output arrive before the capture is torn down. +sleep 2 + +echo "" +echo "===== console, as captured from $UART =====" +if [ -s "$LOG" ]; then + cat "$LOG" +else + echo "(nothing arrived on the console)" + echo "Check: jumper J248 at 1-2, micro-USB at J119 on the daughtercard, and" + echo "LED J122 for board-to-host traffic." +fi +echo "===== end of console =====" +echo "=== gdb exit=$rc ===" +exit $rc diff --git a/ports_module/cortex_r52/gnu/example_build/s32z280_evb/txm_module_preamble.S b/ports_module/cortex_r52/gnu/example_build/s32z280_evb/txm_module_preamble.S new file mode 100644 index 000000000..19bd89318 --- /dev/null +++ b/ports_module/cortex_r52/gnu/example_build/s32z280_evb/txm_module_preamble.S @@ -0,0 +1,151 @@ +@/*************************************************************************** +@ * 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. +@ * +@ * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +@ * The AI-generated portions may be considered public domain (CC0-1.0) +@ * and not subject to the project's licence. The human contributor has +@ * reviewed and verified that the code is correct. +@ * +@ * SPDX-License-Identifier: MIT and CC0-1.0 +@ **************************************************************************/ +@ +@/**************************************************************************/ +@/* */ +@/* MODULE PREAMBLE RELEASE */ +@/* */ +@/* txm_module_preamble.S Cortex-R52/GNU */ +@/* 6.5.2 */ +@/* AUTHOR */ +@/* */ +@/* Frédéric Desbiens, Eclipse Foundation */ +@/* */ +@/* DESCRIPTION */ +@/* */ +@/* The header the module manager reads before it will load a module. */ +@/* */ +@/* It must be the first thing in the module image, which is what the */ +@/* linker script arranges, and every entry point in it is an offset */ +@/* from the start of the preamble rather than an address. A module is */ +@/* position independent: the manager decides where it lands, so the */ +@/* module cannot know its own addresses at link time. */ +@/* */ +@/* Code and data sizes come from the linker script rather than being */ +@/* written in by hand. The Cortex-R4 preamble carries literal numbers */ +@/* for them, which is a standing invitation to grow a module past its */ +@/* declared size and have the manager map less memory than it uses -- */ +@/* a fault in a module that did nothing wrong, whose cause is a */ +@/* constant in a file nobody thought to change. */ +@/* */ +@/**************************************************************************/ + + .syntax unified + .arm + + .global __txm_module_preamble + + .extern _txm_module_thread_shell_entry + .extern _txm_module_callback_request_thread_entry + .extern demo_module_start + +@ Supplied by the module's linker script. + + .extern __txm_module_code_size + .extern __txm_module_data_size + +@ Properties. The compiler field tells the manager which set of entry-point +@ adjustments to apply, and the option bits say what the module is asking for: +@ user mode and memory protection, which together are the point of this port. +@ +@ 0x02000000 TXM_MODULE_GNU_COMPILER +@ 0x00000001 TXM_MODULE_USER_MODE +@ 0x00000002 TXM_MODULE_MEMORY_PROTECTION +@ +@ Both option bits are REQUIRED here, unlike on every other module port, and a +@ preamble that carries either alone is refused by the loader with +@ TXM_MODULE_INVALID_PROPERTIES. On PMSAv8-R that is not a policy: the port +@ programs a module's regions only when both bits are set, the scheduler closes +@ the kernel's window over module memory before it dispatches a module thread, +@ and there is no background region to fall back on -- so a module that asked +@ for user mode without protection would have no mapping at all rather than a +@ weaker one. See TXM_MODULE_MANAGER_REQUIRED_OPTIONS in txm_module_port.h. +@ +@ 0x00000004 TXM_MODULE_SHARED_EXTERNAL_MEMORY_ACCESS +@ +@ is supported and optional. A module that does not ask for it simply never has +@ a shared region granted to it. + + .equ MODULE_PROPERTIES, 0x02000003 + + .section .txm_module_preamble, "a" + .align 6 + +__txm_module_preamble: + + .word 0x4D4F4455 @ Module ID, "MODU" + .word 0x6 @ Major version + .word 0x1 @ Minor version + .word 32 @ Preamble size, 32-bit words + .word 0x52520001 @ Application-defined ID + .word MODULE_PROPERTIES @ Properties, see above + +@ Entry points, as offsets from the preamble. + +@ Entry points are stored relative to the word that holds them, not to the +@ start of the preamble. That is what the manager expects: it recovers the +@ offset from the module base by adding the field's own byte offset back -- +@ TXM_MODULE_GNU_SHELL_ADJUST 24, START 28, STOP 32, CALLBACK 44, which are +@ exactly the offsets of the four words below. Storing these relative to +@ __txm_module_preamble instead counts that offset twice, and the module is +@ then entered that many bytes into its shell entry: past the prologue, with +@ the arguments never saved and the frame pointer never set up, so the first +@ dereference goes through a register the stack build had zeroed. On silicon +@ that read faulted at 0x1C, which is offset 0x1C from a null r3. +@ +@ Every other GNU module port writes these the same way; cortex_m33's +@ preamble, which this port was seeded from, spells it "symbol - . - 0". + + .word _txm_module_thread_shell_entry - . + .word demo_module_start - . + .word 0 @ No stop thread + .word 1 @ Start/stop thread priority + .word 1024 @ Start/stop thread stack size + .word _txm_module_callback_request_thread_entry - . + .word 1 @ Callback thread priority + .word 1024 @ Callback thread stack size + +@ Sizes, from the linker script. The manager rounds both up to the 64-byte MPU +@ granule and maps exactly this much; anything the module touches beyond it +@ faults, which is the intended behaviour and not a bug to work around by +@ inflating these numbers. + + .word __txm_module_code_size + .word __txm_module_data_size + + .word 0 @ Reserved 0 + .word 0 @ Reserved 1 + .word 0 @ Reserved 2 + .word 0 @ Reserved 3 + .word 0 @ Reserved 4 + .word 0 @ Reserved 5 + .word 0 @ Reserved 6 + .word 0 @ Reserved 7 + .word 0 @ Reserved 8 + .word 0 @ Reserved 9 + .word 0 @ Reserved 10 + .word 0 @ Reserved 11 + .word 0 @ Reserved 12 + .word 0 @ Reserved 13 + .word 0 @ Reserved 14 + .word 0 @ Reserved 15 + +@ The preamble declares its own length in its fourth word, and the manager +@ believes it. If the two ever disagree the manager reads entry points from the +@ wrong offsets, so the assembler checks rather than the reader. + + .if (. - __txm_module_preamble) != (32 * 4) + .error "txm_module_preamble is not the 32 words its size field declares" + .endif diff --git a/ports_module/cortex_r52/gnu/inc/tx_port.h b/ports_module/cortex_r52/gnu/inc/tx_port.h new file mode 100644 index 000000000..d3013b1f0 --- /dev/null +++ b/ports_module/cortex_r52/gnu/inc/tx_port.h @@ -0,0 +1,442 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * 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 + **************************************************************************/ +// Some portions generated by Claude Code (Opus 5). + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Port Specific */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* PORT SPECIFIC C INFORMATION RELEASE */ +/* */ +/* tx_port.h Cortex-R52/GNU */ +/* 6.5.2 */ +/* */ +/* AUTHOR */ +/* */ +/* Frédéric Desbiens, Eclipse Foundation */ +/* */ +/* Derived from the Cortex-R5/GNU port originally written by */ +/* William E. Lamie, Microsoft Corporation. */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file contains data type definitions that make the ThreadX */ +/* real-time kernel function identically on a variety of different */ +/* processor architectures. For example, the size or number of bits */ +/* in an "int" data type vary between microprocessor architectures and */ +/* even C compilers for the same microprocessor. ThreadX does not */ +/* directly use native C data types. Instead, ThreadX creates its */ +/* own special types that can be mapped to actual data types by this */ +/* file to guarantee consistency in the interface and functionality. */ +/* */ +/**************************************************************************/ + +#ifndef TX_PORT_H +#define TX_PORT_H + + +/* Determine if the optional ThreadX user define file should be used. */ + +#ifdef TX_INCLUDE_USER_DEFINE_FILE + + +/* Yes, include the user defines in tx_user.h. The defines in this file may + alternately be defined on the command line. */ + +#include "tx_user.h" +#endif + + +/* Define compiler library include files. */ + +#include +#include + + +/* Define ThreadX basic types for this port. */ + +#define VOID void +typedef char CHAR; +typedef unsigned char UCHAR; +typedef int INT; +typedef unsigned int UINT; +typedef long LONG; +typedef unsigned long ULONG; +typedef short SHORT; +typedef unsigned short USHORT; + + +/* Define the priority levels for ThreadX. Legal values range + from 32 to 1024 and MUST be evenly divisible by 32. */ + +#ifndef TX_MAX_PRIORITIES +#define TX_MAX_PRIORITIES 32 +#endif + + +/* Define the minimum stack for a ThreadX thread on this processor. If the size supplied during + thread creation is less than this value, the thread create call will return an error. */ + +#ifndef TX_MINIMUM_STACK +#define TX_MINIMUM_STACK 200 /* Minimum stack size for this port */ +#endif + + +/* Define the system timer thread's default stack size and priority. These are only applicable + if TX_TIMER_PROCESS_IN_ISR is not defined. */ + +#ifndef TX_TIMER_THREAD_STACK_SIZE +#define TX_TIMER_THREAD_STACK_SIZE 1024 /* Default timer thread stack size */ +#endif + +#ifndef TX_TIMER_THREAD_PRIORITY +#define TX_TIMER_THREAD_PRIORITY 0 /* Default timer thread priority */ +#endif + + +/* Define various constants for the ThreadX ARM port. */ + +#ifdef TX_ENABLE_FIQ_SUPPORT +#define TX_INT_DISABLE 0xC0 /* Disable IRQ & FIQ interrupts */ +#else +#define TX_INT_DISABLE 0x80 /* Disable IRQ interrupts */ +#endif +#define TX_INT_ENABLE 0x00 /* Enable IRQ interrupts */ + + +/* Define the clock source for trace event entry time stamp. The following two item are port specific. + For example, if the time source is at the address 0x0a800024 and is 16-bits in size, the clock + source constants would be: + +#define TX_TRACE_TIME_SOURCE *((ULONG *) 0x0a800024) +#define TX_TRACE_TIME_MASK 0x0000FFFFUL + +*/ + +#ifndef TX_TRACE_TIME_SOURCE +#define TX_TRACE_TIME_SOURCE ++_tx_trace_simulated_time +#endif +#ifndef TX_TRACE_TIME_MASK +#define TX_TRACE_TIME_MASK 0xFFFFFFFFUL +#endif + + +/* Define the port specific options for the _tx_build_options variable. This variable indicates + how the ThreadX library was built. */ + +#ifdef TX_ENABLE_FIQ_SUPPORT +#define TX_FIQ_ENABLED 1 +#else +#define TX_FIQ_ENABLED 0 +#endif + +#ifdef TX_ENABLE_IRQ_NESTING +#define TX_IRQ_NESTING_ENABLED 2 +#else +#define TX_IRQ_NESTING_ENABLED 0 +#endif + +#ifdef TX_ENABLE_FIQ_NESTING +#define TX_FIQ_NESTING_ENABLED 4 +#else +#define TX_FIQ_NESTING_ENABLED 0 +#endif + +#define TX_PORT_SPECIFIC_BUILD_OPTIONS TX_FIQ_ENABLED | TX_IRQ_NESTING_ENABLED | TX_FIQ_NESTING_ENABLED + + +/* Define the in-line initialization constant so that modules with in-line + initialization capabilities can prevent their initialization from being + a function call. */ + +#define TX_INLINE_INITIALIZATION + + +/* Determine whether or not stack checking is enabled. By default, ThreadX stack checking is + disabled. When the following is defined, ThreadX thread stack checking is enabled. If stack + checking is enabled (TX_ENABLE_STACK_CHECKING is defined), the TX_DISABLE_STACK_FILLING + define is negated, thereby forcing the stack fill which is necessary for the stack checking + logic. */ + +#ifdef TX_ENABLE_STACK_CHECKING +#undef TX_DISABLE_STACK_FILLING +#endif + + +/* Define the TX_THREAD control block extensions for this port. The main reason + for the multiple macros is so that backward compatibility can be maintained with + existing ThreadX kernel awareness modules. */ + +/* TX_THREAD_EXTENSION_2 carries the per-thread VFP enable flag used by the + lazy floating-point save and restore in tx_thread_schedule.S, + tx_thread_system_return.S and tx_thread_context_restore.S. + + It is defined UNCONDITIONALLY, not under TX_ENABLE_VFP_SUPPORT, and that is + deliberate: the assembly reaches this field through a hard-coded structure + offset, so making the field conditional would move every following member + between build configurations and leave the offset correct in only one of + them. Keeping it always present makes the layout independent of the + floating-point build options. The offset is checked at compile time in + tx_port_offset_check.c, which turns a wrong offset into a build failure + instead of silent corruption of an unrelated thread field. */ + +#define TX_THREAD_EXTENSION_0 +#define TX_THREAD_EXTENSION_1 +/* The module thread extension. A thread that belongs to a module carries a + pointer to its module instance, its entry information, the user-mode state to + restore when it is scheduled, and two stacks: the module's own stack for user + mode and a kernel stack for the privileged side of a system call. + + Two stacks rather than one is not an implementation detail that can be + simplified away. A module thread runs in user mode on memory the module owns; + the moment it enters the kernel through a system call, the kernel must not be + writing its own state onto memory the module can also write, or the module + could corrupt the kernel by scribbling on its own stack. */ + +/* tx_thread_vfp_enable comes first and is not optional here. The Cortex-R52 + port keeps the floating-point lazy-enable flag in this extension, and dropping + it while adding the module fields would leave VFP threads with nowhere to + record that they have used the unit -- the kind of breakage that shows up as + corrupted floating-point state in a module, a long way from its cause. */ + +#define TX_THREAD_EXTENSION_2 ULONG tx_thread_vfp_enable; \ + VOID *tx_thread_module_instance_ptr; \ + VOID *tx_thread_module_entry_info_ptr; \ + ULONG tx_thread_module_current_user_mode; \ + ULONG tx_thread_module_user_mode; \ + ULONG tx_thread_module_saved_lr; \ + VOID *tx_thread_module_kernel_stack_start; \ + VOID *tx_thread_module_kernel_stack_end; \ + ULONG tx_thread_module_kernel_stack_size; \ + VOID *tx_thread_module_stack_ptr; \ + VOID *tx_thread_module_stack_start; \ + VOID *tx_thread_module_stack_end; \ + ULONG tx_thread_module_stack_size; \ + VOID *tx_thread_module_reserved; +#define TX_THREAD_EXTENSION_3 + + +/* Define the port extensions of the remaining ThreadX objects. */ + +#define TX_BLOCK_POOL_EXTENSION +#define TX_BYTE_POOL_EXTENSION +/* The four object extensions below each carry the module instance that owns the + object, and the module manager needs them to answer a question it must answer + on every service call: is the object this module is asking about one it owns? + Without them a module could pass any address it liked as a queue or a semaphore + and the kernel would act on whatever was there. + + They are also why a module port cannot share the base port's ThreadX library. + They change the layout of TX_QUEUE, TX_SEMAPHORE, TX_EVENT_FLAGS_GROUP and + TX_TIMER, so a library compiled against the base port's tx_port.h and a manager + compiled against this one disagree about every kernel object -- and both + compile, so nothing says so. + + Block pool, byte pool and mutex stay empty, as they are in the Armv8-M module + port: the manager tracks ownership of those differently. */ + +#define TX_EVENT_FLAGS_GROUP_EXTENSION VOID *tx_event_flags_group_module_instance; \ + VOID (*tx_event_flags_group_set_module_notify)(struct TX_EVENT_FLAGS_GROUP_STRUCT *group_ptr); +#define TX_MUTEX_EXTENSION +#define TX_QUEUE_EXTENSION VOID *tx_queue_module_instance; \ + VOID (*tx_queue_send_module_notify)(struct TX_QUEUE_STRUCT *queue_ptr); +#define TX_SEMAPHORE_EXTENSION VOID *tx_semaphore_module_instance; \ + VOID (*tx_semaphore_put_module_notify)(struct TX_SEMAPHORE_STRUCT *semaphore_ptr); +#define TX_TIMER_EXTENSION VOID *tx_timer_module_instance; \ + VOID (*tx_timer_module_expiration_function)(ULONG id); + + +/* Define the user extension field of the thread control block. Nothing + additional is needed for this port so it is defined as white space. */ + +#ifndef TX_THREAD_USER_EXTENSION +#define TX_THREAD_USER_EXTENSION +#endif + + +/* Define the macros for processing extensions in tx_thread_create, tx_thread_delete, + tx_thread_shell_entry, and tx_thread_terminate. */ + + +#define TX_THREAD_CREATE_EXTENSION(thread_ptr) +#define TX_THREAD_DELETE_EXTENSION(thread_ptr) +#define TX_THREAD_COMPLETED_EXTENSION(thread_ptr) +#define TX_THREAD_TERMINATED_EXTENSION(thread_ptr) + + +/* Define the ThreadX object creation extensions for remaining objects. */ + +#define TX_BLOCK_POOL_CREATE_EXTENSION(pool_ptr) +#define TX_BYTE_POOL_CREATE_EXTENSION(pool_ptr) +#define TX_EVENT_FLAGS_GROUP_CREATE_EXTENSION(group_ptr) +#define TX_MUTEX_CREATE_EXTENSION(mutex_ptr) +#define TX_QUEUE_CREATE_EXTENSION(queue_ptr) +#define TX_SEMAPHORE_CREATE_EXTENSION(semaphore_ptr) +#define TX_TIMER_CREATE_EXTENSION(timer_ptr) + + +/* Define the ThreadX object deletion extensions for remaining objects. */ + +#define TX_BLOCK_POOL_DELETE_EXTENSION(pool_ptr) +#define TX_BYTE_POOL_DELETE_EXTENSION(pool_ptr) +#define TX_EVENT_FLAGS_GROUP_DELETE_EXTENSION(group_ptr) +#define TX_MUTEX_DELETE_EXTENSION(mutex_ptr) +#define TX_QUEUE_DELETE_EXTENSION(queue_ptr) +#define TX_SEMAPHORE_DELETE_EXTENSION(semaphore_ptr) +#define TX_TIMER_DELETE_EXTENSION(timer_ptr) + + +/* Determine whether this core has the CLZ instruction and this compiler will + admit to it, and if so replace the portable lowest-set-bit search with it. + + The guard is not upstream's. Upstream asks __TARGET_ARCH_ARM > 4, which is an + Arm Compiler 5 predefine. GCC does not define it -- it predefines the ACLE + macros __ARM_ARCH and __ARM_FEATURE_CLZ instead -- so under GCC the test reads + 0 > 4, this whole block is dropped and tx_thread.h's portable loop runs on a + core that has had the instruction since Armv5. Measured with + arm-none-eabi-gcc 14.3 on 20 Aug 2026: zero CLZ instructions in the built + scheduler objects. + + That was not a dormant path. Half the TX_LOWEST_SET_BIT_CALCULATE call sites + in tx_thread_suspend.c and tx_thread_system_suspend.c sit OUTSIDE the + TX_MAX_PRIORITIES > 32 guards, so the portable loop was running in the + scheduler's priority search in the default 32-priority configuration, which is + the one every R52 build uses. + + __ARM_FEATURE_CLZ is the ACLE answer to the question actually being asked, and + the compiler defines it exactly when the architecture has the instruction, so + a core without CLZ is excluded by construction rather than by an architecture + number. Arm Compiler 5's spelling is kept beside it, now wrapped in defined() + so the test no longer leans on an undefined identifier evaluating to zero -- + which is what -Wundef reports and how this was found. + + The __thumb__ guard stays, and it is load-bearing rather than inherited + caution: __ARM_FEATURE_CLZ describes the ARCHITECTURE, not the instruction + set. Checked on 20 Aug 2026 -- GCC defines it for -mthumb -march=armv5te, + where Thumb-1 has no CLZ at all and this asm would fail to assemble. A Thumb + build therefore keeps the portable loop on purpose. (On this core it is moot: + the R52 toolchain file builds -marm.) + + Two deliberate deviations, per AGENTS.md: + + - Rule 1.2, language extensions. Inline assembly is the entire point of the + macro; there is no conforming way to reach CLZ. Spelled __asm__ and not + asm, because the asm keyword is rejected under -std=c99 -- verified, it is + an "'asm' undeclared" error -- and AGENTS.md requires C99 compatibility. + + - Rule 10.1 / 10.3 on the isolation step, which is why it is respelled. + Upstream isolates the lowest set bit with (ULONG) (-((LONG) m)): that + converts an unsigned map to signed and negates it, which is undefined for + the one input whose top bit is set. (~(m)) + 1 is the same value in + well-defined unsigned arithmetic, and it is character-for-character what + tx_thread.h's portable version uses -- so the two implementations now + visibly compute the same thing instead of merely agreeing. + + Rule 20.7 is a straight fix rather than a deviation: upstream leaves m and b + unparenthesised in the expansion. + + PRECONDITION: m must be non-zero, and the two implementations DISAGREE when it + is not. CLZ(0) is 32, so this yields 31 - 32; the portable loop yields 0. + All twelve call sites in common/src reach the macro only on a map already + tested against zero -- every one checked on 20 Aug 2026 -- so the divergence is + unreachable today. It is written down because a new call site is exactly how + it would stop being unreachable, and demo_clz.c pins both answers so that + changing this has to be a decision. */ + +#if defined(__ARM_FEATURE_CLZ) || (defined(__TARGET_ARCH_ARM) && (__TARGET_ARCH_ARM > 4)) + +#ifndef __thumb__ + +#define TX_LOWEST_SET_BIT_CALCULATE(m, b) \ + (m) = (m) & ((~(m)) + ((ULONG) 1)); \ + __asm__ volatile (" CLZ %0,%1 " : "=r" (b) : "r" (m)); \ + (b) = 31 - (b); + +#endif +#endif + + +/* Define ThreadX interrupt lockout and restore macros for protection on + access of critical kernel information. The restore interrupt macro must + restore the interrupt posture of the running thread prior to the value + present prior to the disable macro. In most cases, the save area macro + is used to define a local function save area for the disable and restore + macros. */ + +/* Per-thread floating-point control. Implemented in tx_thread_schedule.S and + available only when the library is built with TX_ENABLE_VFP_SUPPORT. A + thread's floating-point context is saved and restored lazily: only threads + that have called tx_thread_vfp_enable() pay for it. */ + +#ifdef TX_ENABLE_VFP_SUPPORT +void tx_thread_vfp_enable(void); +void tx_thread_vfp_disable(void); +#endif + + +#ifdef __thumb__ + +unsigned int _tx_thread_interrupt_disable(void); +unsigned int _tx_thread_interrupt_restore(UINT old_posture); + + +#define TX_INTERRUPT_SAVE_AREA UINT interrupt_save; + +#define TX_DISABLE interrupt_save = _tx_thread_interrupt_disable(); +#define TX_RESTORE _tx_thread_interrupt_restore(interrupt_save); + +#else + +#define TX_INTERRUPT_SAVE_AREA UINT interrupt_save; + +#ifdef TX_ENABLE_FIQ_SUPPORT +#define TX_DISABLE asm volatile (" MRS %0,CPSR; CPSID if ": "=r" (interrupt_save) ); +#else +#define TX_DISABLE asm volatile (" MRS %0,CPSR; CPSID i ": "=r" (interrupt_save) ); +#endif + +#define TX_RESTORE asm volatile (" MSR CPSR_c,%0 "::"r" (interrupt_save) ); + +#endif + + +/* Define the interrupt lockout macros for each ThreadX object. */ + +#define TX_BLOCK_POOL_DISABLE TX_DISABLE +#define TX_BYTE_POOL_DISABLE TX_DISABLE +#define TX_EVENT_FLAGS_GROUP_DISABLE TX_DISABLE +#define TX_MUTEX_DISABLE TX_DISABLE +#define TX_QUEUE_DISABLE TX_DISABLE +#define TX_SEMAPHORE_DISABLE TX_DISABLE + + +/* Define the version ID of ThreadX. This may be used by the application.*/ + +#ifdef TX_THREAD_INIT +CHAR _tx_version_id[] = + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadXCortex-R52/GNU Version 6.5.1.202602a *"; +#else +extern CHAR _tx_version_id[]; +#endif + + +#endif + diff --git a/ports_module/cortex_r52/gnu/inc/txm_module_port.h b/ports_module/cortex_r52/gnu/inc/txm_module_port.h new file mode 100644 index 000000000..33a994d93 --- /dev/null +++ b/ports_module/cortex_r52/gnu/inc/txm_module_port.h @@ -0,0 +1,491 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + +// Some portions generated by Claude Code (Opus 5). + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Module */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + + +/**************************************************************************/ +/* */ +/* APPLICATION INTERFACE DEFINITION RELEASE */ +/* */ +/* txm_module_port.h Cortex-R52/GNU */ +/* 6.1.10 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This file defines the basic module constants, interface structures, */ +/* and function prototypes. */ +/* */ +/**************************************************************************/ + +#ifndef TXM_MODULE_PORT_H +#define TXM_MODULE_PORT_H + +/* Determine if the optional Modules user define file should be used. */ + +#ifdef TXM_MODULE_INCLUDE_USER_DEFINE_FILE + +/* Yes, include the user defines in txm_module_user.h. The defines in this file may + alternately be defined on the command line. */ + +#include "txm_module_user.h" +#endif + +/* It is assumed that the base ThreadX tx_port.h file has been modified to add the + following extensions to the ThreadX thread control block (this code should replace + the corresponding macro define in tx_port.h): + +#define TX_THREAD_EXTENSION_2 VOID *tx_thread_module_instance_ptr; \ + VOID *tx_thread_module_entry_info_ptr; \ + ULONG tx_thread_module_current_user_mode; \ + ULONG tx_thread_module_user_mode; \ + ULONG tx_thread_module_saved_lr; \ + VOID *tx_thread_module_kernel_stack_start; \ + VOID *tx_thread_module_kernel_stack_end; \ + ULONG tx_thread_module_kernel_stack_size; \ + VOID *tx_thread_module_stack_ptr; \ + VOID *tx_thread_module_stack_start; \ + VOID *tx_thread_module_stack_end; \ + ULONG tx_thread_module_stack_size; \ + VOID *tx_thread_module_reserved; + +The following extensions must also be defined in tx_port.h: + +#define TX_EVENT_FLAGS_GROUP_EXTENSION VOID *tx_event_flags_group_module_instance; \ + VOID (*tx_event_flags_group_set_module_notify)(struct TX_EVENT_FLAGS_GROUP_STRUCT *group_ptr); + +#define TX_QUEUE_EXTENSION VOID *tx_queue_module_instance; \ + VOID (*tx_queue_send_module_notify)(struct TX_QUEUE_STRUCT *queue_ptr); + +#define TX_SEMAPHORE_EXTENSION VOID *tx_semaphore_module_instance; \ + VOID (*tx_semaphore_put_module_notify)(struct TX_SEMAPHORE_STRUCT *semaphore_ptr); + +#define TX_TIMER_EXTENSION VOID *tx_timer_module_instance; \ + VOID (*tx_timer_module_expiration_function)(ULONG id); +*/ + +/* Define the kernel stack size for a module thread. */ +#ifndef TXM_MODULE_KERNEL_STACK_SIZE +#define TXM_MODULE_KERNEL_STACK_SIZE 768 +#endif + +/* Define constants specific to the tools the module can be built with for this particular modules port. */ + +#define TXM_MODULE_IAR_COMPILER 0x00000000 +#define TXM_MODULE_RVDS_COMPILER 0x01000000 +#define TXM_MODULE_GNU_COMPILER 0x02000000 +#define TXM_MODULE_COMPILER_MASK 0xFF000000 +#define TXM_MODULE_OPTIONS_MASK 0x000000FF + + +/* Define the properties for this particular module port. */ + +/* No port dispatch. It exists so a port can service kernel requests specific to + it, and this one has none: the only calls the Armv8-M port dispatches are its + secure-stack allocate and free, which belong to the security extension this core + does not have. Defining it would have the module manager call a + _txm_module_manager_port_dispatch that does not exist. The Cortex-R4 module + port leaves it undefined for the same reason. */ + +/* #define TXM_MODULE_PORT_DISPATCH */ + +#define TXM_MODULE_MEMORY_PROTECTION_ENABLED + +#ifdef TXM_MODULE_MEMORY_PROTECTION_ENABLED +#define TXM_MODULE_REQUIRE_ALLOCATED_OBJECT_MEMORY +#else +#define TXM_MODULE_REQUIRE_LOCAL_OBJECT_MEMORY +#endif + +#define TXM_MODULE_USER_MODE 0x00000001 +#define TXM_MODULE_MEMORY_PROTECTION 0x00000002 +#define TXM_MODULE_SHARED_EXTERNAL_MEMORY_ACCESS 0x00000004 + + +/* Define the supported options for this module. + + TXM_MODULE_SHARED_EXTERNAL_MEMORY_ACCESS is supported and optional: a module + that does not ask for it simply never has a shared region granted to it, and + everything else about it works. + + TXM_MODULE_USER_MODE and TXM_MODULE_MEMORY_PROTECTION are supported and + REQUIRED, together, which every other module port in the tree leaves at 0. + The divergence is a property of PMSAv8-R rather than a policy choice, and the + alternative is not a module that runs unprotected -- it is a module that + cannot run at all: + + - TXM_MODULE_MANAGER_MODULE_SETUP below programs the eight-entry region + table only when both bits are set, so for any other accepted combination + the table stays as the load memset it, all zeros. + + - tx_thread_schedule.S closes the kernel's window over the module area + before it dispatches a module thread, because PMSAv8-R has no region + priority and the window covers the same memory the module's own regions + do. A zeroed table therefore leaves nothing enabled over module memory. + + - There is no background region to fall back on. Per the Cortex-R52 TRM + section 8.2.1, the EL1-controlled background region is used only when the + MPU is disabled or when SCTLR.BR is set, and accesses from EL0 are + faulted whenever the MPU is enabled. Neither example board support + package sets SCTLR.BR, and a board that did would still not help a + User-mode module. + + So a module asking for user mode without protection, or for neither, is + accepted by the portable loader, started, and aborts on the fetch of its own + first instruction. Requiring both bits turns that into + TXM_MODULE_INVALID_PROPERTIES from txm_module_manager_in_place_load, at the + point where the property word can still be corrected. + + Supporting them for real -- a privileged module mapped through the kernel's + window, or an unprotected User-mode module -- needs a second mapping path in + the scheduler and its own tests. Until that exists this is the honest + contract rather than a restriction. */ + +#define TXM_MODULE_MANAGER_SUPPORTED_OPTIONS (TXM_MODULE_USER_MODE | TXM_MODULE_MEMORY_PROTECTION | TXM_MODULE_SHARED_EXTERNAL_MEMORY_ACCESS) +#define TXM_MODULE_MANAGER_REQUIRED_OPTIONS (TXM_MODULE_USER_MODE | TXM_MODULE_MEMORY_PROTECTION) + + +/* Define offset adjustments according to the compiler used to build the module. */ + +#define TXM_MODULE_IAR_SHELL_ADJUST 24 +#define TXM_MODULE_IAR_START_ADJUST 28 +#define TXM_MODULE_IAR_STOP_ADJUST 32 +#define TXM_MODULE_IAR_CALLBACK_ADJUST 44 + +#define TXM_MODULE_RVDS_SHELL_ADJUST 0 +#define TXM_MODULE_RVDS_START_ADJUST 0 +#define TXM_MODULE_RVDS_STOP_ADJUST 0 +#define TXM_MODULE_RVDS_CALLBACK_ADJUST 0 + +#define TXM_MODULE_GNU_SHELL_ADJUST 24 +#define TXM_MODULE_GNU_START_ADJUST 28 +#define TXM_MODULE_GNU_STOP_ADJUST 32 +#define TXM_MODULE_GNU_CALLBACK_ADJUST 44 + + +/* Define other module port-specific constants. */ + +/* Define INLINE_DECLARE to inline for ARM compiler. */ + +#define INLINE_DECLARE inline + +/* Define the number of MPU entries assigned to the code and data sections. + + PMSAv8-R gives this core many more regions than Armv8-M gives an M33, and that + changes the design rather than just the numbers. MPUIR on the S32Z280 reports + 20 EL1 regions, where an M33 has 8 in total and the kernel and a module must + therefore share them. Here the kernel's map can keep its own regions + permanently and the manager owns a separate block, so a module switch + reprograms only the module's regions and never rebuilds the kernel's. + + Eight entries are reserved, laid out as on the M33 -- one for the kernel entry + function, one for module code, one for module data, five for shared memory -- + starting at TXM_MODULE_MPU_FIRST_REGION. The indices below are relative to + that base. + + TXM_MODULE_MPU_FIRST_REGION is 8, and the choice is not arbitrary. The TRM + provides direct access to PRBAR0 through PRBAR15 and PRLAR0 through PRLAR15 + at CP15 op1 0, encoded CRn c6, CRm 0b1rrr where rrr is region_number[3:1], + opc2 0 and 1 for an even region and 4 and 5 for an odd one. Regions 16 + through 24 have direct encodings as well, at op1 1 with the same CRm and opc2 + rule (8.4, Table 8-9), so no region on this core is reachable only through + PRSELR. PRSELR remains the indirect route: it selects a region for the + unnumbered PRBAR and PRLAR view and needs an ISB before those can be written, + per region. + + The TRM contradicts itself on this and the disagreement is worth recording, + so that a reader who checks only one half does not correct it back. The + register descriptions at 3.3.85 and 3.3.86 say flatly "Direct access is + provided to PRBAR0 to PRBAR15" and give only the op1 0 form; 8.4 and Table + 8-9 give both forms. Table 8-9 is itself imprecise -- it prints opc2 0 for + the even limit registers where the prose of 8.4 says 1 -- so the op1 1 + encoding has to be proven on the part before anything relies on it. + + What 8 through 15 buys is that all eight regions sit in the op1 0 range, the + form already exercised on this part, and that they are contiguous, so a + module switch writes them as one unrolled block with a single barrier pair. + Measured on this part: programming one region through PRSELR costs 542 to 604 + cycles, and the same region written directly costs 434 to 470. Most of what + remains is the closing dsb and isb rather than the writes, so a block of + regions written directly with one barrier pair at the end is far cheaper than + the per-region figure suggests, while the PRSELR route pays an ISB every time. + + The board support package's map occupies 0 through 7. A board needing more + than eight kernel regions has to either shrink this block or move it, and + moving it past 15 changes the op1 the scheduler's MCR encodings carry. */ + +/* The kernel's window over the module area. tx_thread_schedule.S carries the + same number as a .equ, because the assembler cannot include this header, and + txm_module_manager_offset_check.c checks the two spellings against each + other. Moving it past 15 changes the op1 the scheduler's MCR encodings + carry, which is what the first assertion in that file is about. */ + +#define TXM_MODULE_MPU_WINDOW_REGION 16 + +#define TXM_MODULE_MPU_FIRST_REGION 8 +#define TXM_MODULE_MPU_TOTAL_ENTRIES 8 +#define TXM_MODULE_MPU_KERNEL_ENTRY_INDEX 0 +#define TXM_MODULE_MPU_CODE_INDEX 1 +#define TXM_MODULE_MPU_DATA_INDEX 2 + +#define TXM_MODULE_MPU_SHARED_INDEX 3 +#define TXM_MODULE_MPU_SHARED_ENTRIES 5 + +#define TXM_MODULE_ATTRIBUTE_NON_SHAREABLE 0x00 +#define TXM_MODULE_ATTRIBUTE_OUTER_SHAREABLE 0x10 +#define TXM_MODULE_ATTRIBUTE_INNER_SHAREABLE 0x18 +#define TXM_MODULE_ATTRIBUTE_READ_WRITE 0x02 +#define TXM_MODULE_ATTRIBUTE_READ_ONLY 0x06 +#define TXM_MODULE_ATTRIBUTE_EXECUTE_NEVER 0x01 +#define TXM_MODULE_ATTRIBUTE_REGION_ENABLE 0x01 +#define TXM_MODULE_ATTRIBUTE_MASK 0x1E +#define TXM_MODULE_ATTRIBUTE_INDEX 0x00 + +/* The attribute encodings above are the PMSAv8 field layout and are the same on + this core as on an M33: shareability in PRBAR[4:3], access permission in + PRBAR[2:1], execute-never in PRBAR[0], attribute index in PRLAR[3:1] and the + region enable in PRLAR[0]. What differs is the granule -- 64 bytes here + against 32 on Armv8-M, so the base and limit fields are [31:6] rather than + [31:5] -- and that the registers are reached through CP15, either by a + region's own direct encoding or through PRSELR, rather than being memory + mapped. */ + +/* MAIR_ATTR settings +Device-nGnRE : 0b [Outer]0000 [Inner]0100 +Code WT RA : 0b [Outer]1010 [Inner]1010 +DATA WBWA RA : 0b [Outer]1111 [Inner]1111 +*/ + +/* Data aligned to 8 bytes (stacks must be 8-byte aligned). */ +#define TXM_MODULE_DATA_ALIGNMENT 8 + +/* MPU regions must be 64-byte aligned on PMSAv8-R, where Armv8-M requires 32. + Getting this wrong is silent: the low bits of PRBAR and PRLAR hold attributes, + so an under-aligned base does not fault, it changes the shareability and + permissions of the region instead. + + Unsigned, and that is not decoration. Every use of this macro is a mask over + an address or a size -- both ULONG -- and the useful form is the complement, + ~(TXM_MODULE_MPU_ALIGNMENT - 1). Spelled as a plain 64 that complement is a + signed -64 converted to 0xFFFFFFC0 on the way into the expression, which is + what MISRA C:2012 Rule 7.2 requires a U suffix to prevent and what + -Wsign-conversion reports. The value is identical either way here; the + suffix is what keeps the essential type of the mask unsigned. */ +#define TXM_MODULE_MPU_ALIGNMENT 64UL + +/* Mask that keeps only the address bits of PRBAR and PRLAR. The low six bits + hold attributes on this core, so every base and limit written into the region + table must be masked with this and not with the Armv8-M 32-byte equivalent. */ + +#define TXM_MODULE_MPU_ADDRESS_MASK 0xFFFFFFC0 + +/* No secure-stack extension calls. Those are the Armv8-M security extension, + which this core does not have: privilege here is the ARM mode, EL1 against + EL0, and there is no secure world to allocate a second stack in. */ + +/* Two registers set up each MPU region: PRBAR and PRLAR, reached either by the + region's own direct encoding or through PRSELR. + Held per module so a switch is a sequence of register writes with nothing to + compute -- the cost measured on this part is dominated by the barriers, not + the writes, so a switch should program every region and issue one dsb and isb + at the end rather than a pair per region. */ +typedef struct TXM_MODULE_MPU_INFO_STRUCT +{ + ULONG txm_module_mpu_region_base_address; + ULONG txm_module_mpu_region_limit_address; +} TXM_MODULE_MPU_INFO; + +/* Define the port-extensions to the module manager instance structure. */ +#define TXM_MODULE_MANAGER_PORT_EXTENSION \ + TXM_MODULE_MPU_INFO txm_module_instance_mpu_registers[TXM_MODULE_MPU_TOTAL_ENTRIES]; \ + ULONG txm_module_instance_shared_memory_count; \ + ULONG txm_module_instance_shared_memory_address[TXM_MODULE_MPU_SHARED_ENTRIES]; \ + ULONG txm_module_instance_shared_memory_length[TXM_MODULE_MPU_SHARED_ENTRIES]; + + +/* Define the memory fault information structure that is populated when a memory fault occurs. */ + +typedef struct TXM_MODULE_MANAGER_MEMORY_FAULT_INFO_STRUCT +{ + TX_THREAD *txm_module_manager_memory_fault_info_thread_ptr; + VOID *txm_module_manager_memory_fault_info_code_location; + /* Fault status and address, read through CP15. Armv8-M reports a memory + fault in SHCSR, CFSR, MMFAR and BFAR; this core splits it by access type + instead -- DFSR and DFAR for a data abort, IFSR and IFAR for a prefetch + abort -- and both pairs are recorded because a module can fault either + way: writing outside its data region, or branching outside its code + region. */ + + ULONG txm_module_manager_memory_fault_info_dfsr; + ULONG txm_module_manager_memory_fault_info_dfar; + ULONG txm_module_manager_memory_fault_info_ifsr; + ULONG txm_module_manager_memory_fault_info_ifar; + ULONG txm_module_manager_memory_fault_info_sp; + ULONG txm_module_manager_memory_fault_info_r0; + ULONG txm_module_manager_memory_fault_info_r1; + ULONG txm_module_manager_memory_fault_info_r2; + ULONG txm_module_manager_memory_fault_info_r3; + ULONG txm_module_manager_memory_fault_info_r4; + ULONG txm_module_manager_memory_fault_info_r5; + ULONG txm_module_manager_memory_fault_info_r6; + ULONG txm_module_manager_memory_fault_info_r7; + ULONG txm_module_manager_memory_fault_info_r8; + ULONG txm_module_manager_memory_fault_info_r9; + ULONG txm_module_manager_memory_fault_info_r10; + ULONG txm_module_manager_memory_fault_info_r11; + ULONG txm_module_manager_memory_fault_info_r12; + ULONG txm_module_manager_memory_fault_info_lr; + /* SPSR rather than xPSR: the mode the faulting code was running in is what + says whether it was the module in user mode or the kernel. */ + + ULONG txm_module_manager_memory_fault_info_spsr; +} TXM_MODULE_MANAGER_MEMORY_FAULT_INFO; + + +#define TXM_MODULE_MANAGER_FAULT_INFO \ + TXM_MODULE_MANAGER_MEMORY_FAULT_INFO _txm_module_manager_memory_fault_info; + + +/* Define the macro to check the code alignment. */ + +#define TXM_MODULE_MANAGER_CHECK_CODE_ALIGNMENT(module_location, code_alignment) \ + { \ + ULONG temp; \ + temp = (ULONG) module_location; \ + temp = temp & (code_alignment - 1); \ + if (temp) \ + { \ + _tx_mutex_put(&_txm_module_manager_mutex); \ + return(TXM_MODULE_ALIGNMENT_ERROR); \ + } \ + } + + +/* Define the macro to adjust the alignment and size for code/data areas. */ + +#define TXM_MODULE_MANAGER_ALIGNMENT_ADJUST(module_preamble, code_size, code_alignment, data_size, data_alignment) _txm_module_manager_alignment_adjust(module_preamble, &code_size, &code_alignment, &data_size, &data_alignment); + + +/* Define the macro to adjust the symbols in the module preamble. */ + +#define TXM_MODULE_MANAGER_CALCULATE_ADJUSTMENTS(properties, shell_function_adjust, start_function_adjust, stop_function_adjust, callback_function_adjust) \ + if ((properties & TXM_MODULE_COMPILER_MASK) == TXM_MODULE_IAR_COMPILER) \ + { \ + shell_function_adjust = TXM_MODULE_IAR_SHELL_ADJUST; \ + start_function_adjust = TXM_MODULE_IAR_START_ADJUST; \ + stop_function_adjust = TXM_MODULE_IAR_STOP_ADJUST; \ + callback_function_adjust = TXM_MODULE_IAR_CALLBACK_ADJUST; \ + } \ + else if ((properties & TXM_MODULE_COMPILER_MASK) == TXM_MODULE_RVDS_COMPILER) \ + { \ + shell_function_adjust = TXM_MODULE_RVDS_SHELL_ADJUST; \ + start_function_adjust = TXM_MODULE_RVDS_START_ADJUST; \ + stop_function_adjust = TXM_MODULE_RVDS_STOP_ADJUST; \ + callback_function_adjust = TXM_MODULE_RVDS_CALLBACK_ADJUST; \ + } \ + else \ + { \ + shell_function_adjust = TXM_MODULE_GNU_SHELL_ADJUST; \ + start_function_adjust = TXM_MODULE_GNU_START_ADJUST; \ + stop_function_adjust = TXM_MODULE_GNU_STOP_ADJUST; \ + callback_function_adjust = TXM_MODULE_GNU_CALLBACK_ADJUST; \ + } + + +/* Define the macro to populate the thread control block with module port-specific information. + Check if the module is in user mode and set up txm_module_thread_entry_info_kernel_call_dispatcher accordingly. +*/ + +#define TXM_MODULE_MANAGER_THREAD_SETUP(thread_ptr, module_instance) \ + thread_ptr -> tx_thread_module_current_user_mode = module_instance -> txm_module_instance_property_flags & TXM_MODULE_USER_MODE; \ + thread_ptr -> tx_thread_module_user_mode = module_instance -> txm_module_instance_property_flags & TXM_MODULE_USER_MODE; \ + if (thread_ptr -> tx_thread_module_user_mode) \ + { \ + thread_entry_info -> txm_module_thread_entry_info_kernel_call_dispatcher = _txm_module_manager_user_mode_entry; \ + } \ + else \ + { \ + thread_entry_info -> txm_module_thread_entry_info_kernel_call_dispatcher = _txm_module_manager_kernel_dispatch; \ + } + + +/* Define the macro to populate the module control block with module port-specific information. + If memory protection is enabled, set up the MPU registers. + + TXM_MODULE_MANAGER_REQUIRED_OPTIONS makes both tests below true for every + module the loader accepts, so the nesting is redundant today. It is kept + because it is the only thing that decides whether the region table is + programmed: a future port that learned to map a privileged module would relax + REQUIRED_OPTIONS, and this macro is where the second path would go. +*/ +#define TXM_MODULE_MANAGER_MODULE_SETUP(module_instance) \ + if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_USER_MODE) \ + { \ + if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) \ + { \ + _txm_module_manager_mm_register_setup(module_instance); \ + } \ + } \ + else \ + { \ + /* Do nothing. */ \ + } + +/* Define the macro to perform port-specific functions when unloading the module. */ +/* Nothing needs to be done for this port. */ +#define TXM_MODULE_MANAGER_MODULE_UNLOAD(module_instance) + + +/* Define the macros to perform port-specific checks when passing pointers to the kernel. */ + +/* Define macro to make sure object is inside the module's data. */ +#define TXM_MODULE_MANAGER_CHECK_INSIDE_DATA(module_instance, obj_ptr, obj_size) \ + _txm_module_manager_inside_data_check(module_instance, obj_ptr, obj_size) + +/* Define some internal prototypes to this module port. */ + +#ifndef TX_SOURCE_CODE +#define txm_module_manager_memory_fault_notify _txm_module_manager_memory_fault_notify +#endif + + +#ifdef TX_SOURCE_CODE + +#endif + +#define TXM_MODULE_MANAGER_ADDITIONAL_PROTOTYPES \ +VOID _txm_module_manager_alignment_adjust(TXM_MODULE_PREAMBLE *module_preamble, ULONG *code_size, ULONG *code_alignment, ULONG *data_size, ULONG *data_alignment); \ +VOID _txm_module_manager_memory_fault_handler(VOID); \ +UINT _txm_module_manager_memory_fault_notify(VOID (*notify_function)(TX_THREAD *, TXM_MODULE_INSTANCE *)); \ +VOID _txm_module_manager_mm_register_setup(TXM_MODULE_INSTANCE *module_instance); \ +UINT _txm_module_manager_inside_data_check(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE obj_ptr, UINT obj_size); \ +ALIGN_TYPE _txm_module_manager_port_dispatch(TXM_MODULE_INSTANCE *module_instance, ULONG kernel_request, ALIGN_TYPE param_0, ALIGN_TYPE param_1, ALIGN_TYPE param_2); + + +#define TXM_MODULE_MANAGER_VERSION_ID \ +CHAR _txm_module_manager_version_id[] = \ + "Copyright (c) 2024 Microsoft Corporation. * ThreadX Module Cortex-R52/GNU Version 6.5.0.202601 *"; + +#endif diff --git a/ports_module/cortex_r52/gnu/module_lib/src/txm_module_gcc_setup.S b/ports_module/cortex_r52/gnu/module_lib/src/txm_module_gcc_setup.S new file mode 100644 index 000000000..8d2b64d1f --- /dev/null +++ b/ports_module/cortex_r52/gnu/module_lib/src/txm_module_gcc_setup.S @@ -0,0 +1,211 @@ +@/*************************************************************************** +@ * 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. +@ * +@ * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +@ * The AI-generated portions may be considered public domain (CC0-1.0) +@ * and not subject to the project's licence. The human contributor has +@ * reviewed and verified that the code is correct. +@ * +@ * SPDX-License-Identifier: MIT and CC0-1.0 +@ **************************************************************************/ +@ +@/**************************************************************************/ +@/* */ +@/* MODULE LIBRARY RELEASE */ +@/* */ +@/* txm_module_gcc_setup.S Cortex-R52/GNU */ +@/* 6.5.2 */ +@/* AUTHOR */ +@/* */ +@/* Frédéric Desbiens, Eclipse Foundation */ +@/* */ +@/* DESCRIPTION */ +@/* */ +@/* Where a position-independent module fixes up its own data */ +@/* references, before it has run a line of its own code. */ +@/* */ +@/* The module's shell entry calls this once, on the start thread only, */ +@/* passing the address the module's code was actually loaded at. Three */ +@/* things happen here, and the module cannot touch a single global */ +@/* until all three have: */ +@/* */ +@/* 1. The global offset table is copied out of the image into the */ +@/* module's own data, and every entry in it is rewritten from the */ +@/* nominal address the linker chose to the address the manager */ +@/* decided on. */ +@/* 2. .data is copied out of the image into the module's own data. */ +@/* 3. .bss is zeroed. */ +@/* */ +@/* Why any of this is needed: the module is built -fpic with */ +@/* -msingle-pic-base, so a reference to a global compiles to */ +@/* LDR rX, [r9, #offset] -- a load of a GOT entry, at a fixed offset */ +@/* from whatever r9 holds. The manager seeds r9 with the module's data */ +@/* base when it builds the thread's stack frame, so the offsets land in */ +@/* the right place; but the entries there are zero until this function */ +@/* writes them, because the manager memsets the data area and nothing */ +@/* else populates it. */ +@/* */ +@/* And .data has to be copied for the same reason. The manager does */ +@/* not copy it: _txm_module_manager_internal_load allocates a data area */ +@/* from its byte pool and zeroes it, so the module's linked .data -- */ +@/* wherever it sits -- is outside every region the module owns. A */ +@/* module reading an initialised global before this ran would fault, or */ +@/* read a zero, depending on where it looked. */ +@/* */ +@/* This function may not use a global itself, which is the constraint */ +@/* that shapes it: it is what makes the GOT usable, so it cannot use */ +@/* the GOT. Every address it needs comes from a literal pool load of a */ +@/* linker-supplied nominal address, rebased by hand. That is also why */ +@/* it is assembly and not C. */ +@/* */ +@/* INPUT */ +@/* */ +@/* r0 Address the module's code was actually loaded at */ +@/* r9 Address of the module's data area, already seeded by */ +@/* _txm_module_manager_thread_stack_build. Also the base the */ +@/* compiler measures every GOT offset from, so the GOT must go */ +@/* at exactly this address and nowhere else. */ +@/* */ +@/* OUTPUT */ +@/* */ +@/* None. r9 is unchanged, and must be: it is the module's PIC base for */ +@/* the rest of the thread's life. */ +@/* */ +@/* CALLED BY */ +@/* */ +@/* _txm_module_thread_shell_entry, on the start thread only */ +@/* */ +@/**************************************************************************/ + + .syntax unified + .arm + .text + .align 2 + + .global _gcc_setup + .type _gcc_setup, %function + +@ Supplied by the module's linker script. The two segment origins are nominal +@ addresses the module never runs at -- see link_demo_module.lds. + + .extern __code_segment_start__ + .extern __data_segment_start__ + .extern __got_load_start__ + .extern __new_got_start__ + .extern __new_got_end__ + .extern __data_load_start__ + .extern __data_start__ + .extern __data_end__ + .extern __bss_start__ + .extern __bss_end__ + +_gcc_setup: + + PUSH {r4-r7, lr} + +@ The two deltas every address below is corrected by. Everything the linker +@ emitted is expressed against the nominal origins; everything that exists at +@ run time is at the same offset from the real base. + + LDR r3, =__code_segment_start__ + SUB r4, r0, r3 @ r4 = code delta, real - nominal + LDR r3, =__data_segment_start__ + SUB r5, r9, r3 @ r5 = data delta, real - nominal + +@ --------------------------------------------------------------------------- +@ 1. The global offset table. +@ --------------------------------------------------------------------------- +@ +@ Read from the image, written to the module's data area, one entry at a time, +@ with each entry rebased according to which segment it points into. The test +@ is a single unsigned compare against the nominal data origin, which is what +@ the linker script's far-apart origins exist to make sound: everything below +@ it is code or read-only data and moves with the code, everything at or above +@ it is writable data and moves with the data area. +@ +@ A zero entry is left alone. The linker leaves an entry zero when it had +@ nothing to put there, and rebasing it would turn a recognisable null into a +@ plausible-looking pointer into the middle of the module. + + LDR r1, =__got_load_start__ + ADD r1, r1, r4 @ Source, in the image + LDR r2, =__new_got_start__ + ADD r2, r2, r5 @ Destination, in the data area + LDR r3, =__new_got_end__ + ADD r3, r3, r5 @ One past the last entry + LDR r7, =__data_segment_start__ @ The code / data dividing line + +got_loop: + CMP r2, r3 + BHS got_done + LDR r6, [r1], #4 @ Pickup the entry as linked + CMP r6, #0 + BEQ got_store @ Never filled in; leave it alone + CMP r6, r7 + ADDLO r6, r6, r4 @ Below the line: a code address + ADDHS r6, r6, r5 @ At or above: a data address +got_store: + STR r6, [r2], #4 + B got_loop +got_done: + +@ --------------------------------------------------------------------------- +@ 2. Initialised data. +@ --------------------------------------------------------------------------- +@ +@ Byte at a time. The run-time destination is the manager's data base plus a +@ linker offset, and while both happen to be word aligned today, a byte copy +@ does not have to care -- and this runs once per module start, where the cost +@ of not having to think about it is nothing. + + LDR r1, =__data_load_start__ + ADD r1, r1, r4 @ Source, in the image + LDR r2, =__data_start__ + ADD r2, r2, r5 @ Destination, in the data area + LDR r3, =__data_end__ + ADD r3, r3, r5 + +data_loop: + CMP r2, r3 + BHS data_done + LDRB r6, [r1], #1 + STRB r6, [r2], #1 + B data_loop +data_done: + +@ --------------------------------------------------------------------------- +@ 3. Zero-initialised data. +@ --------------------------------------------------------------------------- +@ +@ The manager has already zeroed the whole allocation, so this is redundant +@ with the loader this port ships. It is here because that is the loader's +@ behaviour and not the module's contract: a module that only works because +@ its loader happens to memset is a module that breaks on the next loader. + + LDR r1, =__bss_start__ + ADD r1, r1, r5 + LDR r2, =__bss_end__ + ADD r2, r2, r5 + MOV r6, #0 + +bss_loop: + CMP r1, r2 + BHS bss_done + STRB r6, [r1], #1 + B bss_loop +bss_done: + +@ The module's data is now readable and writable through r9, and the module +@ proper can run. A data barrier because the GOT and .data were just written +@ as data and are about to be read as the module's working set; no instruction +@ barrier, because nothing executable was modified. + + DSB + POP {r4-r7, lr} + BX lr + + .size _gcc_setup, . - _gcc_setup diff --git a/ports_module/cortex_r52/gnu/module_lib/src/txm_module_thread_shell_entry.c b/ports_module/cortex_r52/gnu/module_lib/src/txm_module_thread_shell_entry.c new file mode 100644 index 000000000..4f01b7a8c --- /dev/null +++ b/ports_module/cortex_r52/gnu/module_lib/src/txm_module_thread_shell_entry.c @@ -0,0 +1,168 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Module */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#ifndef TXM_MODULE +#define TXM_MODULE +#endif + +#ifndef TX_SOURCE_CODE +#define TX_SOURCE_CODE +#endif + + +/* Include necessary system files. */ + +#include "txm_module.h" +#include "tx_thread.h" + +/* Define the global module entry pointer from the start thread of the module. */ + +TXM_MODULE_THREAD_ENTRY_INFO *_txm_module_entry_info; + + +/* Define the dispatch function pointer used in the module implementation. */ + +ULONG (*_txm_module_kernel_call_dispatcher)(ULONG kernel_request, ULONG param_1, ULONG param_2, ULONG param3); + + +/* Define the GCC startup code that clears the uninitialized global data and sets up the + preset global variables. */ + +extern VOID _gcc_setup(TXM_MODULE_INSTANCE *); + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txm_module_thread_shell_entry Cortex-R52/GNU */ +/* 6.1.5 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function calls the specified entry function of the thread. It */ +/* also provides a place for the thread's entry function to return. */ +/* If the thread returns, this function places the thread in a */ +/* "COMPLETED" state. */ +/* */ +/* INPUT */ +/* */ +/* thread_ptr Pointer to current thread */ +/* thread_info Pointer to thread entry info */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _gcc_setup GNU global init function */ +/* thread_entry Thread's entry function */ +/* tx_thread_resume Resume the module callback thread */ +/* _txm_module_thread_system_suspend Module thread suspension routine */ +/* */ +/* CALLED BY */ +/* */ +/* Initial thread stack frame */ +/* */ +/**************************************************************************/ +VOID _txm_module_thread_shell_entry(TX_THREAD *thread_ptr, TXM_MODULE_THREAD_ENTRY_INFO *thread_info) +{ + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + VOID (*entry_exit_notify)(TX_THREAD *, UINT); +#endif + + + /* Determine if this is the start thread. If so, we must prepare the module for + execution. If not, simply skip the C startup code. */ + if (thread_info -> txm_module_thread_entry_info_start_thread) + { + /* Initialize the GNU C environment. */ + _gcc_setup(thread_info -> txm_module_thread_entry_info_code_base_address); + + /* Save the entry info pointer, for later use. */ + _txm_module_entry_info = thread_info; + + /* Save the kernel function dispatch address. This is used to make all resident calls from + the module. */ + _txm_module_kernel_call_dispatcher = thread_info -> txm_module_thread_entry_info_kernel_call_dispatcher; + + /* Ensure that we have a valid pointer. */ + while (!_txm_module_kernel_call_dispatcher) + { + /* Loop here, if an error is present getting the dispatch function pointer! + An error here typically indicates the resident portion of _tx_thread_schedule + is not supporting the trap to obtain the function pointer. */ + } + + /* Resume the module's callback thread, already created in the manager. */ + _txe_thread_resume(thread_info -> txm_module_thread_entry_info_callback_request_thread); + } + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Pickup the entry/exit application callback routine. */ + entry_exit_notify = thread_info -> txm_module_thread_entry_info_exit_notify; + + /* Determine if an application callback routine is specified. */ + if (entry_exit_notify != TX_NULL) + { + + /* Yes, notify application that this thread has been entered! */ + (entry_exit_notify)(thread_ptr, TX_THREAD_ENTRY); + } +#endif + + /* Call current thread's entry function. */ + (thread_info -> txm_module_thread_entry_info_entry) (thread_info -> txm_module_thread_entry_info_parameter); + + /* Suspend thread with a "completed" state. */ + + +#ifndef TX_DISABLE_NOTIFY_CALLBACKS + + /* Pickup the entry/exit application callback routine again. */ + entry_exit_notify = thread_info -> txm_module_thread_entry_info_exit_notify; + + /* Determine if an application callback routine is specified. */ + if (entry_exit_notify != TX_NULL) + { + + /* Yes, notify application that this thread has exited! */ + (entry_exit_notify)(thread_ptr, TX_THREAD_EXIT); + } +#endif + + /* Call actual thread suspension routine. */ + _txm_module_thread_system_suspend(thread_ptr); + +#ifdef TX_SAFETY_CRITICAL + + /* If we ever get here, raise safety critical exception. */ + TX_SAFETY_CRITICAL_EXCEPTION(__FILE__, __LINE__, 0); +#endif +} + diff --git a/ports_module/cortex_r52/gnu/module_manager/src/tx_thread_context_restore.S b/ports_module/cortex_r52/gnu/module_manager/src/tx_thread_context_restore.S new file mode 100644 index 000000000..90865906b --- /dev/null +++ b/ports_module/cortex_r52/gnu/module_manager/src/tx_thread_context_restore.S @@ -0,0 +1,264 @@ +@/*************************************************************************** +@ * Copyright (c) 2024 Microsoft Corporation +@ * 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 +@ **************************************************************************/ +@ Some portions generated by Claude Code (Opus 5). +@ +@ +@/**************************************************************************/ +@/**************************************************************************/ +@/** */ +@/** ThreadX Component */ +@/** */ +@/** Thread */ +@/** */ +@/**************************************************************************/ +@/**************************************************************************/ +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + + .arm + +@ Whole CPSR values, mode field and interrupt masks together -- which is what a +@ plain _MODE name means throughout this port. The bare mode field is spelled +@ _MODE_BITS instead; see tx_thread_stack_build.S. The base port's SVC_MODE is +@ absent because this port restores kernel threads into System mode, so nothing +@ here needs it and a name that is never used is a name waiting to be picked by +@ mistake. + +#ifdef TX_ENABLE_FIQ_SUPPORT +SYS_MODE = 0xDF @ Disable IRQ/FIQ, SYS mode +IRQ_MODE = 0xD2 @ Disable IRQ/FIQ, IRQ mode +#else +SYS_MODE = 0x9F @ Disable IRQ, SYS mode +IRQ_MODE = 0x92 @ Disable IRQ, IRQ mode +#endif +@ + .global _tx_thread_system_state + .global _tx_thread_current_ptr + .global _tx_thread_execute_ptr + .global _tx_timer_time_slice + .global _tx_thread_schedule + .global _tx_thread_preempt_disable + .global _tx_execution_isr_exit +@ +@ +@/* No 16-bit Thumb mode veneer code is needed for _tx_thread_context_restore +@ since it will never be called 16-bit mode. */ +@ + .arm + .text + .align 2 +@/**************************************************************************/ +@/* */ +@/* FUNCTION RELEASE */ +@/* */ +@/* _tx_thread_context_restore Cortex-R52/GNU */ +@/* 6.5.2 */ +@/* AUTHOR */ +@/* */ +@/* Frédéric Desbiens, Eclipse Foundation */ +@/* */ +@/* Derived from the Cortex-R5/GNU port originally written by */ +@/* William E. Lamie, Microsoft Corporation. */ +@/* */ +@/* DESCRIPTION */ +@/* */ +@/* This function restores the interrupt context if it is processing a */ +@/* nested interrupt. If not, it returns to the interrupt thread if no */ +@/* preemption is necessary. Otherwise, if preemption is necessary or */ +@/* if no thread was running, the function returns to the scheduler. */ +@/* */ +@/* INPUT */ +@/* */ +@/* None */ +@/* */ +@/* OUTPUT */ +@/* */ +@/* None */ +@/* */ +@/* CALLS */ +@/* */ +@/* _tx_thread_schedule Thread scheduling routine */ +@/* */ +@/* CALLED BY */ +@/* */ +@/* ISRs Interrupt Service Routines */ +@/* */ +@/**************************************************************************/ +@VOID _tx_thread_context_restore(VOID) +@{ + .global _tx_thread_context_restore + .type _tx_thread_context_restore,function +_tx_thread_context_restore: +@ +@ /* Lockout interrupts. */ +@ +#ifdef TX_ENABLE_FIQ_SUPPORT + CPSID if @ Disable IRQ and FIQ interrupts +#else + CPSID i @ Disable IRQ interrupts +#endif + +#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +@ +@ /* Call the ISR exit function to indicate an ISR is complete. */ +@ + BL _tx_execution_isr_exit @ Call the ISR exit function +#endif +@ +@ /* Determine if interrupts are nested. */ +@ if (--_tx_thread_system_state) +@ { +@ + LDR r3, =_tx_thread_system_state @ Pickup address of system state variable + LDR r2, [r3] @ Pickup system state + SUB r2, r2, #1 @ Decrement the counter + STR r2, [r3] @ Store the counter + CMP r2, #0 @ Was this the first interrupt? + BEQ __tx_thread_not_nested_restore @ If so, not a nested restore +@ +@ /* Interrupts are nested. */ +@ +@ /* Just recover the saved registers and return to the point of +@ interrupt. */ +@ + LDMIA sp!, {r0, r10, r12, lr} @ Recover SPSR, POI, and scratch regs + MSR SPSR_cxsf, r0 @ Put SPSR back + LDMIA sp!, {r0-r3} @ Recover r0-r3 + MOVS pc, lr @ Return to point of interrupt +@ +@ } +__tx_thread_not_nested_restore: +@ +@ /* Determine if a thread was interrupted and no preemption is required. */ +@ else if (((_tx_thread_current_ptr) && (_tx_thread_current_ptr == _tx_thread_execute_ptr)) +@ || (_tx_thread_preempt_disable)) +@ { +@ + LDR r1, =_tx_thread_current_ptr @ Pickup address of current thread ptr + LDR r0, [r1] @ Pickup actual current thread pointer + CMP r0, #0 @ Is it NULL? + BEQ __tx_thread_idle_system_restore @ Yes, idle system was interrupted +@ + LDR r3, =_tx_thread_preempt_disable @ Pickup preempt disable address + LDR r2, [r3] @ Pickup actual preempt disable flag + CMP r2, #0 @ Is it set? + BNE __tx_thread_no_preempt_restore @ Yes, don't preempt this thread + LDR r3, =_tx_thread_execute_ptr @ Pickup address of execute thread ptr + LDR r2, [r3] @ Pickup actual execute thread pointer + CMP r0, r2 @ Is the same thread highest priority? + BNE __tx_thread_preempt_restore @ No, preemption needs to happen +@ +@ +__tx_thread_no_preempt_restore: +@ +@ /* Restore interrupted thread or ISR. */ +@ +@ /* Pickup the saved stack pointer. */ +@ tmp_ptr = _tx_thread_current_ptr -> tx_thread_stack_ptr; +@ +@ /* Recover the saved context and return to the point of interrupt. */ +@ + LDMIA sp!, {r0, r10, r12, lr} @ Recover SPSR, POI, and scratch regs + MSR SPSR_cxsf, r0 @ Put SPSR back + LDMIA sp!, {r0-r3} @ Recover r0-r3 + MOVS pc, lr @ Return to point of interrupt +@ +@ } +@ else +@ { +__tx_thread_preempt_restore: +@ + LDMIA sp!, {r3, r10, r12, lr} @ Recover temporarily saved registers + MOV r1, lr @ Save lr (point of interrupt) +@ +@ /* SYS mode rather than SVC, and this is the substantive difference between +@ this file and the base port's. The interrupted thread's stack is the +@ banked sp that User and System mode share, whoever the thread belongs to: +@ a module thread was in User mode, and a kernel thread in this port starts +@ in System mode for exactly this reason. Entering SVC mode here would +@ push the interrupted context onto the supervisor call handler's stack +@ instead of the thread's, and the thread would resume with a corrupted +@ frame. */ +@ + MOV r2, #SYS_MODE @ Build SYS mode CPSR + MSR CPSR_c, r2 @ Enter SYS mode + STR r1, [sp, #-4]! @ Save point of interrupt + STMDB sp!, {r4-r12, lr} @ Save upper half of registers + MOV r4, r3 @ Save SPSR in r4 + MOV r2, #IRQ_MODE @ Build IRQ mode CPSR + MSR CPSR_c, r2 @ Enter IRQ mode + LDMIA sp!, {r0-r3} @ Recover r0-r3 + MOV r5, #SYS_MODE @ Build SYS mode CPSR + MSR CPSR_c, r5 @ Enter SYS mode + STMDB sp!, {r0-r3} @ Save r0-r3 on thread's stack +@ + LDR r1, =_tx_thread_current_ptr @ Pickup address of current thread ptr + LDR r0, [r1] @ Pickup current thread pointer +@ +#ifdef TX_ENABLE_VFP_SUPPORT + LDR r2, [r0, #144] @ Pickup the VFP enabled flag + CMP r2, #0 @ Is the VFP enabled? + BEQ _tx_skip_irq_vfp_save @ No, skip VFP IRQ save + VMRS r2, FPSCR @ Pickup the FPSCR + STR r2, [sp, #-4]! @ Save FPSCR + VSTMDB sp!, {D0-D15} @ Save D0-D15 +_tx_skip_irq_vfp_save: +#endif +@ + MOV r3, #1 @ Build interrupt stack type + STMDB sp!, {r3, r4} @ Save interrupt stack type and SPSR + STR sp, [r0, #8] @ Save stack pointer in thread control + @ block +@ +@ /* Save the remaining time-slice and disable it. */ +@ if (_tx_timer_time_slice) +@ { +@ + LDR r3, =_tx_timer_time_slice @ Pickup time-slice variable address + LDR r2, [r3] @ Pickup time-slice + CMP r2, #0 @ Is it active? + BEQ __tx_thread_dont_save_ts @ No, don't save it +@ +@ _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice; +@ _tx_timer_time_slice = 0; +@ + STR r2, [r0, #24] @ Save thread's time-slice + MOV r2, #0 @ Clear value + STR r2, [r3] @ Disable global time-slice flag +@ +@ } +__tx_thread_dont_save_ts: +@ +@ +@ /* Clear the current task pointer. */ +@ _tx_thread_current_ptr = TX_NULL; +@ + MOV r0, #0 @ NULL value + STR r0, [r1] @ Clear current thread pointer +@ +@ /* Return to the scheduler. */ +@ _tx_thread_schedule(); +@ + B _tx_thread_schedule @ Return to scheduler +@ } +@ +__tx_thread_idle_system_restore: +@ +@ /* Just return back to the scheduler! */ +@ + MOV r0, #SYS_MODE @ Build SYS mode CPSR + MSR CPSR_c, r0 @ Enter SYS mode + B _tx_thread_schedule @ Return to scheduler +@} + + + diff --git a/ports_module/cortex_r52/gnu/module_manager/src/tx_thread_context_save.S b/ports_module/cortex_r52/gnu/module_manager/src/tx_thread_context_save.S new file mode 100644 index 000000000..9b61077e4 --- /dev/null +++ b/ports_module/cortex_r52/gnu/module_manager/src/tx_thread_context_save.S @@ -0,0 +1,193 @@ +@/*************************************************************************** +@ * Copyright (c) 2024 Microsoft Corporation +@ * 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 +@ **************************************************************************/ +@ Some portions generated by Claude Code (Opus 5). +@ +@ +@/**************************************************************************/ +@/**************************************************************************/ +@/** */ +@/** ThreadX Component */ +@/** */ +@/** Thread */ +@/** */ +@/**************************************************************************/ +@/**************************************************************************/ +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + + .global _tx_thread_system_state + .global _tx_thread_current_ptr + .global _tx_irq_processing_return + .global _tx_execution_isr_enter +@ +@ +@/* No 16-bit Thumb mode veneer code is needed for _tx_thread_context_save +@ since it will never be called 16-bit mode. */ +@ + .arm + .text + .align 2 +@/**************************************************************************/ +@/* */ +@/* FUNCTION RELEASE */ +@/* */ +@/* _tx_thread_context_save Cortex-R52/GNU */ +@/* 6.5.2 */ +@/* AUTHOR */ +@/* */ +@/* Frédéric Desbiens, Eclipse Foundation */ +@/* */ +@/* Derived from the Cortex-R5/GNU port originally written by */ +@/* William E. Lamie, Microsoft Corporation. */ +@/* */ +@/* DESCRIPTION */ +@/* */ +@/* This function saves the context of an executing thread in the */ +@/* beginning of interrupt processing. The function also ensures that */ +@/* the system stack is used upon return to the calling ISR. */ +@/* */ +@/* INPUT */ +@/* */ +@/* None */ +@/* */ +@/* OUTPUT */ +@/* */ +@/* None */ +@/* */ +@/* CALLS */ +@/* */ +@/* None */ +@/* */ +@/* CALLED BY */ +@/* */ +@/* ISRs */ +@/* */ +@/**************************************************************************/ +@VOID _tx_thread_context_save(VOID) +@{ + .global _tx_thread_context_save + .type _tx_thread_context_save,function +_tx_thread_context_save: +@ +@ /* Upon entry to this routine, it is assumed that IRQ interrupts are locked +@ out, we are in IRQ mode, and all registers are intact. */ +@ +@ /* Check for a nested interrupt condition. */ +@ if (_tx_thread_system_state++) +@ { +@ + STMDB sp!, {r0-r3} @ Save some working registers +#ifdef TX_ENABLE_FIQ_SUPPORT + CPSID if @ Disable FIQ interrupts +#endif + LDR r3, =_tx_thread_system_state @ Pickup address of system state variable + LDR r2, [r3] @ Pickup system state + CMP r2, #0 @ Is this the first interrupt? + BEQ __tx_thread_not_nested_save @ Yes, not a nested context save +@ +@ /* Nested interrupt condition. */ +@ + ADD r2, r2, #1 @ Increment the interrupt counter + STR r2, [r3] @ Store it back in the variable +@ +@ /* Save the rest of the scratch registers on the stack and return to the +@ calling ISR. */ +@ + MRS r0, SPSR @ Pickup saved SPSR + SUB lr, lr, #4 @ Adjust point of interrupt + STMDB sp!, {r0, r10, r12, lr} @ Store other registers +@ +@ /* Return to the ISR. */ +@ + MOV r10, #0 @ Clear stack limit + +#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +@ +@ /* Call the ISR enter function to indicate an ISR is executing. */ +@ + PUSH {lr} @ Save ISR lr + BL _tx_execution_isr_enter @ Call the ISR enter function + POP {lr} @ Recover ISR lr +#endif + + B __tx_irq_processing_return @ Continue IRQ processing +@ +__tx_thread_not_nested_save: +@ } +@ +@ /* Otherwise, not nested, check to see if a thread was running. */ +@ else if (_tx_thread_current_ptr) +@ { +@ + ADD r2, r2, #1 @ Increment the interrupt counter + STR r2, [r3] @ Store it back in the variable + LDR r1, =_tx_thread_current_ptr @ Pickup address of current thread ptr + LDR r0, [r1] @ Pickup current thread pointer + CMP r0, #0 @ Is it NULL? + BEQ __tx_thread_idle_system_save @ If so, interrupt occurred in + @ scheduling loop - nothing needs saving! +@ +@ /* Save minimal context of interrupted thread. */ +@ + MRS r2, SPSR @ Pickup saved SPSR + SUB lr, lr, #4 @ Adjust point of interrupt + STMDB sp!, {r2, r10, r12, lr} @ Store other registers +@ +@ /* Save the current stack pointer in the thread's control block. */ +@ _tx_thread_current_ptr -> tx_thread_stack_ptr = sp; +@ +@ /* Switch to the system stack. */ +@ sp = _tx_thread_system_stack_ptr@ +@ + MOV r10, #0 @ Clear stack limit + +#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +@ +@ /* Call the ISR enter function to indicate an ISR is executing. */ +@ + PUSH {lr} @ Save ISR lr + BL _tx_execution_isr_enter @ Call the ISR enter function + POP {lr} @ Recover ISR lr +#endif + + B __tx_irq_processing_return @ Continue IRQ processing +@ +@ } +@ else +@ { +@ +__tx_thread_idle_system_save: +@ +@ /* Interrupt occurred in the scheduling loop. */ +@ +@ /* Not much to do here, just adjust the stack pointer, and return to IRQ +@ processing. */ +@ + MOV r10, #0 @ Clear stack limit + +#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +@ +@ /* Call the ISR enter function to indicate an ISR is executing. */ +@ + PUSH {lr} @ Save ISR lr + BL _tx_execution_isr_enter @ Call the ISR enter function + POP {lr} @ Recover ISR lr +#endif + + ADD sp, sp, #16 @ Recover saved registers + B __tx_irq_processing_return @ Continue IRQ processing +@ +@ } +@} + + + diff --git a/ports_module/cortex_r52/gnu/module_manager/src/tx_thread_schedule.S b/ports_module/cortex_r52/gnu/module_manager/src/tx_thread_schedule.S new file mode 100644 index 000000000..ad92ea7ed --- /dev/null +++ b/ports_module/cortex_r52/gnu/module_manager/src/tx_thread_schedule.S @@ -0,0 +1,504 @@ +@/*************************************************************************** +@ * Copyright (c) 2024 Microsoft Corporation +@ * 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 +@ **************************************************************************/ +@ Some portions generated by Claude Code (Opus 5). +@ +@ +@/**************************************************************************/ +@/**************************************************************************/ +@/** */ +@/** ThreadX Component */ +@/** */ +@/** Thread */ +@/** */ +@/**************************************************************************/ +@/**************************************************************************/ +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + +@ Offsets into TX_THREAD and TXM_MODULE_INSTANCE. Hard-coded offsets in port +@ assembly are a standing hazard -- see issue #577 -- so these are checked +@ against offsetof at compile time in txm_module_manager_offset_check.c, and a +@ mismatch is a build failure rather than a fault at run time. +@ +@ They are not the same as the Armv8-M port's: there the module instance pointer +@ sits at 0x90, and here it is 0x94 because the Cortex-R52 port keeps +@ tx_thread_vfp_enable ahead of the module fields in TX_THREAD_EXTENSION_2. + + .equ TXM_THREAD_MODULE_INSTANCE, 0x94 + .equ TXM_INSTANCE_PROPERTY_FLAGS, 0x0C + .equ TXM_INSTANCE_MPU_REGISTERS, 0x64 + +@ The property bits that say a module's region table was programmed: +@ TXM_MODULE_USER_MODE and TXM_MODULE_MEMORY_PROTECTION, which +@ TXM_MODULE_MANAGER_MODULE_SETUP requires together before it calls +@ _txm_module_manager_mm_register_setup. The instance carries the whole +@ preamble word, compiler field included, so the two bits are masked out rather +@ than compared against. + + .equ TXM_MODULE_PROTECTED_MASK, 0x03 + +@ Every thread in this port runs on the User-banked stack pointer: kernel threads +@ in System mode, module threads in User mode, and those two modes share SP_usr +@ and LR_usr. That shared bank is what lets one save and restore path reach any +@ thread's stack without first asking who owns it. +@ +@ So the scheduler has to run in System mode rather than SVC. It is already in +@ System mode when it is reached from the context restore, from the system return +@ and from the idle path, but it is in SVC mode on the very first dispatch out of +@ the kernel enter, so the mode is forced below instead of assumed. Getting this +@ wrong is silent rather than loud: writing sp in SVC mode sets SP_svc, the +@ exception return then switches to System mode, and the thread starts life on +@ whatever SP_usr happened to hold. +@ +@ The return itself needs a mode that has an SPSR, which System mode has not got, +@ so the frame is popped in System mode and only the final exception return +@ borrows SVC. + + .equ SVC_MODE_BITS, 0x13 + .equ SYS_MODE_BITS, 0x1F + +@ Offsets from the saved r0 word of an interrupt frame, which is where sp points +@ once the stack type, the saved CPSR and any VFP state have been popped. The +@ frame itself is built by tx_thread_stack_build.S and the context restore. + + .equ FRAME_PC_FROM_R0, 56 + +@ The kernel's window over the module area. Must match MPU_MODULE_LOAD_REGION +@ in mpu.h; the offset check asserts the two agree. + + .equ MPU_MODULE_WINDOW_REGION, 16 + + .global mpu_module_window_prbar + .global mpu_module_window_prlar + + .global _tx_thread_execute_ptr + .global _tx_thread_current_ptr + .global _tx_timer_time_slice + .global _tx_execution_thread_enter +@ +@ +@/* Define the 16-bit Thumb mode veneer for _tx_thread_schedule for +@ applications calling this function from to 16-bit Thumb mode. */ +@ + .text + .align 2 + .global $_tx_thread_schedule + .type $_tx_thread_schedule,function +$_tx_thread_schedule: + .thumb + BX pc @ Switch to 32-bit mode + NOP @ + .arm + STMFD sp!, {lr} @ Save return address + BL _tx_thread_schedule @ Call _tx_thread_schedule function + LDMFD sp!, {lr} @ Recover saved return address + BX lr @ Return to 16-bit caller +@ +@ + .text + .align 2 +@/**************************************************************************/ +@/* */ +@/* FUNCTION RELEASE */ +@/* */ +@/* _tx_thread_schedule Cortex-R52/GNU */ +@/* 6.5.2 */ +@/* AUTHOR */ +@/* */ +@/* Frédéric Desbiens, Eclipse Foundation */ +@/* */ +@/* Derived from the Cortex-R5/GNU port originally written by */ +@/* William E. Lamie, Microsoft Corporation. */ +@/* */ +@/* DESCRIPTION */ +@/* */ +@/* This function waits for a thread control block pointer to appear in */ +@/* the _tx_thread_execute_ptr variable. Once a thread pointer appears */ +@/* in the variable, the corresponding thread is resumed. */ +@/* */ +@/* INPUT */ +@/* */ +@/* None */ +@/* */ +@/* OUTPUT */ +@/* */ +@/* None */ +@/* */ +@/* CALLS */ +@/* */ +@/* None */ +@/* */ +@/* CALLED BY */ +@/* */ +@/* _tx_initialize_kernel_enter ThreadX entry function */ +@/* _tx_thread_system_return Return to system from thread */ +@/* _tx_thread_context_restore Restore thread's context */ +@/* */ +@/**************************************************************************/ +@VOID _tx_thread_schedule(VOID) +@{ + .global _tx_thread_schedule + .type _tx_thread_schedule,function +_tx_thread_schedule: +@ +@ /* Enable interrupts. */ +@ +#ifdef TX_ENABLE_FIQ_SUPPORT + CPSIE if @ Enable IRQ and FIQ interrupts +#else + CPSIE i @ Enable IRQ interrupts +#endif +@ +@ /* Wait for a thread to execute. */ +@ do +@ { + LDR r1, =_tx_thread_execute_ptr @ Address of thread execute ptr +@ +__tx_thread_schedule_loop: +@ + LDR r0, [r1] @ Pickup next thread to execute + CMP r0, #0 @ Is it NULL? + BEQ __tx_thread_schedule_loop @ If so, keep looking for a thread +@ +@ } +@ while(_tx_thread_execute_ptr == TX_NULL); +@ +@ /* Yes! We have a thread to execute. Lockout interrupts and +@ transfer control to it. */ +@ +#ifdef TX_ENABLE_FIQ_SUPPORT + CPSID if @ Disable IRQ and FIQ interrupts +#else + CPSID i @ Disable IRQ interrupts +#endif +@ +@ /* Setup the current thread pointer. */ +@ _tx_thread_current_ptr = _tx_thread_execute_ptr; +@ + LDR r1, =_tx_thread_current_ptr @ Pickup address of current thread + STR r0, [r1] @ Setup current thread pointer +@ +@ /* Increment the run count for this thread. */ +@ _tx_thread_current_ptr -> tx_thread_run_count++; +@ + LDR r2, [r0, #4] @ Pickup run counter + LDR r3, [r0, #24] @ Pickup time-slice for this thread + ADD r2, r2, #1 @ Increment thread run-counter + STR r2, [r0, #4] @ Store the new run counter +@ +@ /* Setup time-slice, if present. */ +@ _tx_timer_time_slice = _tx_thread_current_ptr -> tx_thread_time_slice; +@ + LDR r2, =_tx_timer_time_slice @ Pickup address of time-slice + @ variable +@ +@ /* Enter System mode before touching sp, so that the stack pointer written +@ below is the User-banked one every thread in this port actually runs on. +@ Nothing between here and the write uses the stack, which matters because +@ sp is undefined for this mode until it is set. */ +@ + CPS #SYS_MODE_BITS @ Threads run on SP_usr +@ + LDR sp, [r0, #8] @ Switch stack pointers + STR r3, [r2] @ Setup time-slice +@ +@ /* Load this thread's MPU regions, if it belongs to a module. */ +@ + LDR r1, [r0, #TXM_THREAD_MODULE_INSTANCE] @ Pickup module instance pointer + CMP r1, #0 @ Is this a module thread? + BEQ __tx_module_regions_off @ No, close the module regions +@ +@ /* Ask the PROPERTY FLAGS whether this module has a region table, not the +@ data start. The data start is set for every module the loader accepts, +@ protected or not, so testing it says only "a module was loaded" -- and +@ the branch not taken here is the branch that closes the kernel's window +@ over module memory. Programming a zeroed table and then closing the +@ window leaves an unprotected module with no mapping at all rather than +@ with a weaker one. +@ +@ TXM_MODULE_MANAGER_REQUIRED_OPTIONS makes this test redundant: the loader +@ refuses anything that does not have both bits. It is written anyway so +@ that the scheduler depends on a field it can see rather than on a loader +@ invariant it cannot, and so that relaxing REQUIRED_OPTIONS degrades to +@ "the module runs under the kernel's window" instead of to a fault on its +@ first instruction. */ +@ + LDR r2, [r1, #TXM_INSTANCE_PROPERTY_FLAGS] @ Pickup module property flags + AND r2, r2, #TXM_MODULE_PROTECTED_MASK @ Keep user mode and protection + CMP r2, #TXM_MODULE_PROTECTED_MASK @ Both asked for? + BNE __tx_module_regions_off @ No, close the module regions +@ +@ /* Eight regions, written directly rather than through PRSELR. CRm and opc2 +@ are encoded in the instruction, not held in a register, so this cannot be +@ a loop -- and unrolled is what we want anyway: sixteen writes with one +@ barrier pair at the end, where PRSELR would need an ISB per region. +@ +@ Regions 8 and 9 are CRm c12, 10 and 11 are c13, 12 and 13 are c14, 14 and +@ 15 are c15. Even regions use opc2 0 and 1, odd ones 4 and 5. +@ +@ ON THE ORDER, which is worth stating because it looks wrong. These eight +@ regions describe memory the kernel's window over the module area also +@ describes, and that window is not closed until after the last write below. +@ Between the two, the programmed map holds an overlap -- the thing the +@ whole design exists to avoid, and an access hitting two enabled regions +@ is an architected translation fault on this core (TRM 8.1), not something +@ left to the implementation. +@ +@ So the window has to be bounded exactly rather than waved at. It is not +@ shortened by the barriers: the ISB that PRSELR needs before the window's +@ PRLAR can be written comes first, so from that ISB to the closing ISB the +@ eight regions and the window are both architecturally in force. What +@ makes the overlap harmless is that no access inside it can hit both. +@ +@ - Every instruction fetched from the first MCR below to the closing ISB +@ comes from this function, which lives in the kernel's own code region +@ and not in the module area. +@ - The only data read is the region table walked by the LDMIAs, which +@ lives in the TXM_MODULE_INSTANCE the application supplied. +@ - The thread's stack is module memory, and nothing here touches it: sp +@ was loaded above, and the first access through it is the frame pop +@ after __tx_module_regions_done, past the closing ISB. +@ - IRQ, and FIQ where it is built in, have been masked since the CPSID +@ taken once a thread was picked, so no exception entry can insert an +@ access of its own. +@ +@ Speculation does not reopen it either: the MPU stops a speculative access +@ from reaching the bus but raises no translation or permission fault for +@ it (TRM 8.1). Only committed accesses fault, and the list above is all of +@ them. The barrier pair at the end is therefore placed for the transition +@ as a whole rather than to shorten this window. +@ +@ That does put one requirement on the application: a TXM_MODULE_INSTANCE +@ must not live inside the module area. Both examples keep theirs in .bss, +@ which is inside the kernel's data region and outside every region a +@ module is given. */ +@ + ADD r1, r1, #TXM_INSTANCE_MPU_REGISTERS @ Address of the region table +@ + LDMIA r1!, {r2, r3} @ Region 8: base, limit + MCR p15, 0, r2, c6, c12, 0 @ PRBAR8 + MCR p15, 0, r3, c6, c12, 1 @ PRLAR8 + LDMIA r1!, {r2, r3} @ Region 9 + MCR p15, 0, r2, c6, c12, 4 @ PRBAR9 + MCR p15, 0, r3, c6, c12, 5 @ PRLAR9 + LDMIA r1!, {r2, r3} @ Region 10 + MCR p15, 0, r2, c6, c13, 0 @ PRBAR10 + MCR p15, 0, r3, c6, c13, 1 @ PRLAR10 + LDMIA r1!, {r2, r3} @ Region 11 + MCR p15, 0, r2, c6, c13, 4 @ PRBAR11 + MCR p15, 0, r3, c6, c13, 5 @ PRLAR11 + LDMIA r1!, {r2, r3} @ Region 12 + MCR p15, 0, r2, c6, c14, 0 @ PRBAR12 + MCR p15, 0, r3, c6, c14, 1 @ PRLAR12 + LDMIA r1!, {r2, r3} @ Region 13 + MCR p15, 0, r2, c6, c14, 4 @ PRBAR13 + MCR p15, 0, r3, c6, c14, 5 @ PRLAR13 + LDMIA r1!, {r2, r3} @ Region 14 + MCR p15, 0, r2, c6, c15, 0 @ PRBAR14 + MCR p15, 0, r3, c6, c15, 1 @ PRLAR14 + LDMIA r1!, {r2, r3} @ Region 15 + MCR p15, 0, r2, c6, c15, 4 @ PRBAR15 + MCR p15, 0, r3, c6, c15, 5 @ PRLAR15 +@ +@ +@ /* Close the kernel's window over the module area. It covers the same +@ memory the regions just loaded do, and PMSAv8-R has no region priority: +@ an access hitting more than one enabled region takes a translation fault +@ (TRM 8.1). The abort seen on this part is that architected result, not a +@ part-specific resolution of unpredictable behaviour. A module thread +@ reaches its own memory through the regions above and needs nothing else. +@ +@ Region 16 is programmed through PRSELR here, and not because it has no +@ direct encoding: TRM 8.4 and Table 8-9 give PRBAR16 and PRLAR16 at CP15 +@ op1 1, CRm c8, opc2 0 and 1. The register descriptions at 3.3.85 and +@ 3.3.86 contradict that and say direct access stops at PRBAR15. The +@ selector sequence is the one proven on silicon, so it stays until the +@ op1 1 form has been measured on both targets; do not "correct" this back +@ to the 3.3.85 claim. Clearing PRLAR is what disables the region. */ +@ + MOV r2, #MPU_MODULE_WINDOW_REGION + MCR p15, 0, r2, c6, c2, 1 @ PRSELR + ISB + MOV r2, #0 + MCR p15, 0, r2, c6, c3, 1 @ PRLAR, region disabled +@ + DSB sy @ One barrier pair for the block + ISB + B __tx_module_regions_done +@ +__tx_module_regions_off: +@ +@ /* Not a module thread, or a module without protection. Close all eight +@ regions rather than leaving the previous module's windows open: a thread +@ that owns nothing must reach nothing, and the alternative is that whatever +@ ran last silently lends its memory to whatever runs next. +@ +@ Only PRLAR is written, because clearing its enable bit is what closes the +@ region; the base is irrelevant while it is disabled. */ +@ + MOV r2, #0 @ Region disabled + MCR p15, 0, r2, c6, c12, 1 @ PRLAR8 + MCR p15, 0, r2, c6, c12, 5 @ PRLAR9 + MCR p15, 0, r2, c6, c13, 1 @ PRLAR10 + MCR p15, 0, r2, c6, c13, 5 @ PRLAR11 + MCR p15, 0, r2, c6, c14, 1 @ PRLAR12 + MCR p15, 0, r2, c6, c14, 5 @ PRLAR13 + MCR p15, 0, r2, c6, c15, 1 @ PRLAR14 + MCR p15, 0, r2, c6, c15, 5 @ PRLAR15 +@ +@ /* Open the kernel's window over the module area, now that no module region +@ is enabled to overlap it. This is the only thing that lets privileged +@ code reach module memory: no boot region covers it, so without this the +@ manager cannot read a module's preamble to load it. +@ +@ Turning it on here, rather than leaving it on permanently, is what keeps +@ it and the module's own regions mutually exclusive without anyone having +@ to remember to bracket a call. A thread that owns no module gets the +@ window; a thread that owns one gets its regions instead. +@ +@ The two register words are computed once by mpu_module_window_init and +@ read from memory here, so this code holds no register layout. */ +@ + MOV r2, #MPU_MODULE_WINDOW_REGION + MCR p15, 0, r2, c6, c2, 1 @ PRSELR + ISB + LDR r2, =mpu_module_window_prbar + LDR r3, [r2] + MCR p15, 0, r3, c6, c3, 0 @ PRBAR + LDR r2, =mpu_module_window_prlar + LDR r3, [r2] + MCR p15, 0, r3, c6, c3, 1 @ PRLAR, region enabled +@ + DSB sy + ISB +@ +__tx_module_regions_done: +@ +@ /* Switch to the thread's stack. */ +@ sp = _tx_thread_execute_ptr -> tx_thread_stack_ptr; +@ +#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +@ +@ /* Call the thread entry function to indicate the thread is executing. */ +@ + BL _tx_execution_thread_enter @ Call the thread execution enter function +#endif +@ +@ /* Determine if an interrupt frame or a synchronous task suspension frame +@ is present. */ +@ + LDMIA sp!, {r4, r5} @ Pickup the stack type and saved CPSR + CMP r4, #0 @ Check for synchronous context switch + BEQ _tx_solicited_return +@ +@ /* r5 holds the thread's CPSR. It cannot go into SPSR yet: this is System +@ mode, which has no SPSR, so it is carried to the SVC borrow below. */ +@ +#ifdef TX_ENABLE_VFP_SUPPORT + LDR r1, [r0, #144] @ Pickup the VFP enabled flag + CMP r1, #0 @ Is the VFP enabled? + BEQ _tx_skip_interrupt_vfp_restore @ No, skip VFP interrupt restore + VLDMIA sp!, {D0-D15} @ Recover D0-D15 + LDR r4, [sp], #4 @ Pickup FPSCR + VMSR FPSCR, r4 @ Restore FPSCR +_tx_skip_interrupt_vfp_restore: +#endif +@ +@ /* sp now points at the saved r0, whether or not VFP state was in the way, +@ which is why the frame position is captured here rather than computed from +@ the thread's stack pointer. r1 survives the mode change: r0-r7 are common +@ to every mode. +@ +@ The two halves of the return have to be prepared in different modes. SVC +@ holds the SPSR and the return address; System mode holds the sp and lr the +@ thread itself will use. Preparing SVC first means the frame pop can end in +@ System mode with nothing left to do but the return. */ +@ + MOV r1, sp @ Frame position, at the saved r0 + CPS #SVC_MODE_BITS @ Borrow a mode that has an SPSR + MSR SPSR_cxsf, r5 @ Thread's CPSR, applied by the return + LDR lr, [r1, #FRAME_PC_FROM_R0] @ Thread's resume address + CPS #SYS_MODE_BITS @ Back to the thread's own bank +@ + LDMIA sp!, {r0-r12, lr} @ Restore, LR_usr included + ADD sp, sp, #4 @ Step over the saved pc +@ +@ /* SP_usr and LR_usr are now the thread's. Only the exception return is left, +@ and it must happen in the mode holding the SPSR -- switching back does not +@ disturb either, because SVC banks its own sp and lr. */ +@ + CPS #SVC_MODE_BITS @ Mode holding SPSR and the address + MOVS pc, lr @ Return to point of thread interrupt +@ +_tx_solicited_return: +#ifdef TX_ENABLE_VFP_SUPPORT + LDR r1, [r0, #144] @ Pickup the VFP enabled flag + CMP r1, #0 @ Is the VFP enabled? + BEQ _tx_skip_solicited_vfp_restore @ No, skip VFP solicited restore + VLDMIA sp!, {D8-D15} @ Recover D8-D15 + LDR r4, [sp], #4 @ Pickup FPSCR + VMSR FPSCR, r4 @ Restore FPSCR +_tx_skip_solicited_vfp_restore: +#endif + MOV r0, r5 @ Move CPSR to scratch register + LDMIA sp!, {r4-r11, lr} @ Return to thread synchronously + MSR CPSR_cxsf, r0 @ Recover CPSR +@ +#ifdef __THUMB_INTERWORK + BX lr @ Return to caller +#else + MOV pc, lr @ Return to caller +#endif +@ +@} +@ +@ +#ifdef TX_ENABLE_VFP_SUPPORT + .global tx_thread_vfp_enable + .type tx_thread_vfp_enable,function +tx_thread_vfp_enable: + MRS r2, CPSR @ Pickup the CPSR +#ifdef TX_ENABLE_FIQ_SUPPORT + CPSID if @ Disable IRQ and FIQ interrupts +#else + CPSID i @ Disable IRQ interrupts +#endif + LDR r0, =_tx_thread_current_ptr @ Build current thread pointer address + LDR r1, [r0] @ Pickup current thread pointer + CMP r1, #0 @ Check for NULL thread pointer + BEQ __tx_no_thread_to_enable @ If NULL, skip VFP enable + MOV r0, #1 @ Build enable value + STR r0, [r1, #144] @ Set the VFP enable flag (tx_thread_vfp_enable field in TX_THREAD) +__tx_no_thread_to_enable: + MSR CPSR_cxsf, r2 @ Recover CPSR + BX LR @ Return to caller +@ + .global tx_thread_vfp_disable + .type tx_thread_vfp_disable,function +tx_thread_vfp_disable: + MRS r2, CPSR @ Pickup the CPSR +#ifdef TX_ENABLE_FIQ_SUPPORT + CPSID if @ Disable IRQ and FIQ interrupts +#else + CPSID i @ Disable IRQ interrupts +#endif + LDR r0, =_tx_thread_current_ptr @ Build current thread pointer address + LDR r1, [r0] @ Pickup current thread pointer + CMP r1, #0 @ Check for NULL thread pointer + BEQ __tx_no_thread_to_disable @ If NULL, skip VFP disable + MOV r0, #0 @ Build disable value + STR r0, [r1, #144] @ Clear the VFP enable flag (tx_thread_vfp_enable field in TX_THREAD) +__tx_no_thread_to_disable: + MSR CPSR_cxsf, r2 @ Recover CPSR + BX LR @ Return to caller +#endif + diff --git a/ports_module/cortex_r52/gnu/module_manager/src/tx_thread_stack_build.S b/ports_module/cortex_r52/gnu/module_manager/src/tx_thread_stack_build.S new file mode 100644 index 000000000..935b321ad --- /dev/null +++ b/ports_module/cortex_r52/gnu/module_manager/src/tx_thread_stack_build.S @@ -0,0 +1,191 @@ +@/*************************************************************************** +@ * Copyright (c) 2024 Microsoft Corporation +@ * 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 +@ **************************************************************************/ +@ Some portions generated by Claude Code (Opus 5). +@ +@ +@/**************************************************************************/ +@/**************************************************************************/ +@/** */ +@/** ThreadX Component */ +@/** */ +@/** Thread */ +@/** */ +@/**************************************************************************/ +@/**************************************************************************/ +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + + .arm + +@ Bare CPSR mode field, spelled _MODE_BITS as the base port does in +@ tx_thread_irq_nesting_start.S and tx_thread_fiq_context_restore.S. In this +@ port a plain _MODE name means a whole CPSR value with the interrupt masks +@ already in it -- tx_thread_context_restore.S defines SYS_MODE as 0xDF or 0x9F +@ -- so the two must not share a name. The base port's SVC_MODE = 0x13 here was +@ the frame's mode before this port moved kernel threads to System mode; nothing +@ uses it now, so it is gone rather than left to be picked up by mistake. + +SYS_MODE_BITS = 0x1F @ SYS mode, privileged +#ifdef TX_ENABLE_FIQ_SUPPORT +CPSR_MASK = 0xDF @ Mask initial CPSR, IRQ & FIQ interrupts enabled +#else +CPSR_MASK = 0x9F @ Mask initial CPSR, IRQ interrupts enabled +#endif +@ +@ +@/* Define the 16-bit Thumb mode veneer for _tx_thread_stack_build for +@ applications calling this function from to 16-bit Thumb mode. */ +@ + .text + .align 2 + .thumb + .global $_tx_thread_stack_build + .type $_tx_thread_stack_build,function +$_tx_thread_stack_build: + BX pc @ Switch to 32-bit mode + NOP @ + .arm + STMFD sp!, {lr} @ Save return address + BL _tx_thread_stack_build @ Call _tx_thread_stack_build function + LDMFD sp!, {lr} @ Recover saved return address + BX lr @ Return to 16-bit caller +@ +@ + .text + .align 2 +@/**************************************************************************/ +@/* */ +@/* FUNCTION RELEASE */ +@/* */ +@/* _tx_thread_stack_build Cortex-R52/GNU */ +@/* 6.5.2 */ +@/* AUTHOR */ +@/* */ +@/* Frédéric Desbiens, Eclipse Foundation */ +@/* */ +@/* Derived from the Cortex-R5/GNU port originally written by */ +@/* William E. Lamie, Microsoft Corporation. */ +@/* */ +@/* DESCRIPTION */ +@/* */ +@/* This function builds a stack frame on the supplied thread's stack. */ +@/* The stack frame results in a fake interrupt return to the supplied */ +@/* function pointer. */ +@/* */ +@/* INPUT */ +@/* */ +@/* thread_ptr Pointer to thread control blk */ +@/* function_ptr Pointer to return function */ +@/* */ +@/* OUTPUT */ +@/* */ +@/* None */ +@/* */ +@/* CALLS */ +@/* */ +@/* None */ +@/* */ +@/* CALLED BY */ +@/* */ +@/* _tx_thread_create Create thread service */ +@/* */ +@/**************************************************************************/ +@VOID _tx_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID)) +@{ + .global _tx_thread_stack_build + .type _tx_thread_stack_build,function +_tx_thread_stack_build: +@ +@ +@ /* Build a fake interrupt frame. The form of the fake interrupt stack +@ on the ARM9 should look like the following after it is built: +@ +@ Stack Top: 1 Interrupt stack frame type +@ CPSR Initial value for CPSR +@ a1 (r0) Initial value for a1 +@ a2 (r1) Initial value for a2 +@ a3 (r2) Initial value for a3 +@ a4 (r3) Initial value for a4 +@ v1 (r4) Initial value for v1 +@ v2 (r5) Initial value for v2 +@ v3 (r6) Initial value for v3 +@ v4 (r7) Initial value for v4 +@ v5 (r8) Initial value for v5 +@ sb (r9) Initial value for sb +@ sl (r10) Initial value for sl +@ fp (r11) Initial value for fp +@ ip (r12) Initial value for ip +@ lr (r14) Initial value for lr +@ pc (r15) Initial value for pc +@ 0 For stack backtracing +@ +@ Stack Bottom: (higher memory address) */ +@ + LDR r2, [r0, #16] @ Pickup end of stack area + BIC r2, r2, #7 @ Ensure 8-byte alignment + SUB r2, r2, #76 @ Allocate space for the stack frame +@ +@ /* Actually build the stack frame. */ +@ + MOV r3, #1 @ Build interrupt stack type + STR r3, [r2, #0] @ Store stack type + MOV r3, #0 @ Build initial register value + STR r3, [r2, #8] @ Store initial r0 + STR r3, [r2, #12] @ Store initial r1 + STR r3, [r2, #16] @ Store initial r2 + STR r3, [r2, #20] @ Store initial r3 + STR r3, [r2, #24] @ Store initial r4 + STR r3, [r2, #28] @ Store initial r5 + STR r3, [r2, #32] @ Store initial r6 + STR r3, [r2, #36] @ Store initial r7 + STR r3, [r2, #40] @ Store initial r8 + STR r3, [r2, #44] @ Store initial r9 + LDR r3, [r0, #12] @ Pickup stack starting address + STR r3, [r2, #48] @ Store initial r10 (sl) + LDR r3,=_tx_thread_schedule @ Pickup address of _tx_thread_schedule for GDB backtrace + STR r3, [r2, #60] @ Store initial r14 (lr) + MOV r3, #0 @ Build initial register value + STR r3, [r2, #52] @ Store initial r11 + STR r3, [r2, #56] @ Store initial r12 + STR r1, [r2, #64] @ Store initial pc + STR r3, [r2, #68] @ 0 for back-trace + MRS r1, CPSR @ Pickup CPSR + BIC r1, r1, #CPSR_MASK @ Mask mode bits of CPSR +@ +@ /* SYS mode, not SVC. In a module port no thread runs in SVC mode: SVC is +@ reserved for the supervisor call handler, which is how a module reaches +@ the kernel, and a thread sitting in SVC mode would be using the handler's +@ banked stack pointer as its own. Kernel threads therefore start in SYS +@ mode, which is privileged and shares User mode's banked sp -- the same sp +@ a module thread uses -- so the context save and restore paths can reach a +@ thread's stack the same way whoever it belongs to. +@ +@ This is the one line that differs from the base port's stack build, and +@ leaving it as SVC would have put kernel threads on the SVC stack while the +@ restore path looked for them on the SYS one. */ +@ + ORR r3, r1, #SYS_MODE_BITS @ Build CPSR, SYS mode, interrupts enabled + STR r3, [r2, #4] @ Store initial CPSR +@ +@ /* Setup stack pointer. */ +@ thread_ptr -> tx_thread_stack_ptr = r2; +@ + STR r2, [r0, #8] @ Save stack pointer in thread's + @ control block +#ifdef __THUMB_INTERWORK + BX lr @ Return to caller +#else + MOV pc, lr @ Return to caller +#endif +@} + + diff --git a/ports_module/cortex_r52/gnu/module_manager/src/tx_thread_system_return.S b/ports_module/cortex_r52/gnu/module_manager/src/tx_thread_system_return.S new file mode 100644 index 000000000..c0ab615b4 --- /dev/null +++ b/ports_module/cortex_r52/gnu/module_manager/src/tx_thread_system_return.S @@ -0,0 +1,169 @@ +@/*************************************************************************** +@ * Copyright (c) 2024 Microsoft Corporation +@ * 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 +@ **************************************************************************/ +@ Some portions generated by Claude Code (Opus 5). +@ +@ +@/**************************************************************************/ +@/**************************************************************************/ +@/** */ +@/** ThreadX Component */ +@/** */ +@/** Thread */ +@/** */ +@/**************************************************************************/ +@/**************************************************************************/ +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + + .arm +@ +@ + .global _tx_thread_current_ptr + .global _tx_timer_time_slice + .global _tx_thread_schedule + .global _tx_execution_thread_exit +@ +@ +@ +@/* Define the 16-bit Thumb mode veneer for _tx_thread_system_return for +@ applications calling this function from to 16-bit Thumb mode. */ +@ + .text + .align 2 + .global $_tx_thread_system_return + .type $_tx_thread_system_return,function +$_tx_thread_system_return: + .thumb + BX pc @ Switch to 32-bit mode + NOP @ + .arm + STMFD sp!, {lr} @ Save return address + BL _tx_thread_system_return @ Call _tx_thread_system_return function + LDMFD sp!, {lr} @ Recover saved return address + BX lr @ Return to 16-bit caller +@ +@ + .text + .align 2 +@/**************************************************************************/ +@/* */ +@/* FUNCTION RELEASE */ +@/* */ +@/* _tx_thread_system_return Cortex-R52/GNU */ +@/* 6.5.2 */ +@/* AUTHOR */ +@/* */ +@/* Frédéric Desbiens, Eclipse Foundation */ +@/* */ +@/* Derived from the Cortex-R5/GNU port originally written by */ +@/* William E. Lamie, Microsoft Corporation. */ +@/* */ +@/* DESCRIPTION */ +@/* */ +@/* This function is target processor specific. It is used to transfer */ +@/* control from a thread back to the ThreadX system. Only a */ +@/* minimal context is saved since the compiler assumes temp registers */ +@/* are going to get slicked by a function call anyway. */ +@/* */ +@/* INPUT */ +@/* */ +@/* None */ +@/* */ +@/* OUTPUT */ +@/* */ +@/* None */ +@/* */ +@/* CALLS */ +@/* */ +@/* _tx_thread_schedule Thread scheduling loop */ +@/* */ +@/* CALLED BY */ +@/* */ +@/* ThreadX components */ +@/* */ +@/**************************************************************************/ +@VOID _tx_thread_system_return(VOID) +@{ + .global _tx_thread_system_return + .type _tx_thread_system_return,function +_tx_thread_system_return: +@ +@ /* Lockout interrupts. */ +@ + MRS r1, CPSR @ Pickup the CPSR +#ifdef TX_ENABLE_FIQ_SUPPORT + CPSID if @ Disable IRQ and FIQ interrupts +#else + CPSID i @ Disable IRQ interrupts +#endif +@ /* Save minimal context on the stack. */ +@ + STMDB sp!, {r4-r11, lr} @ Save minimal context + LDR r5, =_tx_thread_current_ptr @ Pickup address of current ptr + LDR r6, [r5, #0] @ Pickup current thread pointer +@ +#ifdef TX_ENABLE_VFP_SUPPORT + LDR r0, [r6, #144] @ Pickup the VFP enabled flag + CMP r0, #0 @ Is the VFP enabled? + BEQ _tx_skip_solicited_vfp_save @ No, skip VFP solicited save + VMRS r4, FPSCR @ Pickup the FPSCR + STR r4, [sp, #-4]! @ Save FPSCR + VSTMDB sp!, {D8-D15} @ Save D8-D15 +_tx_skip_solicited_vfp_save: +#endif +@ + MOV r0, #0 @ Build a solicited stack type + STMDB sp!, {r0-r1} @ Save type and CPSR +@ +@ +#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +@ +@ /* Call the thread exit function to indicate the thread is no longer executing. */ +@ + BL _tx_execution_thread_exit @ Call the thread exit function +#endif +@ + LDR r2, =_tx_timer_time_slice @ Pickup address of time slice + LDR r1, [r2, #0] @ Pickup current time slice +@ +@ /* Save current stack and switch to system stack. */ +@ _tx_thread_current_ptr -> tx_thread_stack_ptr = sp; +@ sp = _tx_thread_system_stack_ptr; +@ + STR sp, [r6, #8] @ Save thread stack pointer +@ +@ /* Determine if the time-slice is active. */ +@ if (_tx_timer_time_slice) +@ { +@ + MOV r4, #0 @ Build clear value + CMP r1, #0 @ Is a time-slice active? + BEQ __tx_thread_dont_save_ts @ No, don't save the time-slice +@ +@ /* Save time-slice for the thread and clear the current time-slice. */ +@ _tx_thread_current_ptr -> tx_thread_time_slice = _tx_timer_time_slice; +@ _tx_timer_time_slice = 0; +@ + STR r4, [r2, #0] @ Clear time-slice + STR r1, [r6, #24] @ Save current time-slice +@ +@ } +__tx_thread_dont_save_ts: +@ +@ /* Clear the current thread pointer. */ +@ _tx_thread_current_ptr = TX_NULL; +@ + STR r4, [r5, #0] @ Clear current thread pointer + B _tx_thread_schedule @ Jump to scheduler! +@ +@} + diff --git a/ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_alignment_adjust.c b/ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_alignment_adjust.c new file mode 100644 index 000000000..6850fe558 --- /dev/null +++ b/ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_alignment_adjust.c @@ -0,0 +1,97 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + +// Some portions generated by Claude Code (Opus 5). + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Module Manager */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + +#include "tx_api.h" +#include "txm_module.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txm_module_manager_alignment_adjust Cortex-R52 */ +/* 6.1.8 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function adjusts the alignment and size of the code and data */ +/* section for a given module implementation. */ +/* */ +/* INPUT */ +/* */ +/* module_preamble Pointer to module preamble */ +/* code_size Size of the code area (updated) */ +/* code_alignment Code area alignment (updated) */ +/* data_size Size of data area (updated) */ +/* data_alignment Data area alignment (updated) */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Initial thread stack frame */ +/* */ +/**************************************************************************/ +VOID _txm_module_manager_alignment_adjust(TXM_MODULE_PREAMBLE *module_preamble, + ULONG *code_size, + ULONG *code_alignment, + ULONG *data_size, + ULONG *data_alignment) +{ + + /* The preamble is not read here, and the signature is not ours to change: + _txm_module_manager_internal_load calls this through a fixed prototype + shared by every port. Referenced and discarded so that the parameter is + used, which is what MISRA C:2012 Rule 2.7 asks for and what + -Wunused-parameter reports. A port that did have to grow or reposition a + module -- the Cortex-R4 one, below -- reads it. */ + + (VOID)module_preamble; + + /* Rounding to the granule is all this has to do, and that is a property of + PMSAv8-R rather than a shortcut. The Cortex-R4 port's equivalent runs to + 183 lines because PMSAv7 regions must be a power of two in size and + aligned to their own size, so a module's code and data have to be grown + and repositioned to fit the nearest legal region. Base and limit pairs + have no such constraint: any 64-byte-aligned extent is a legal region. */ + + /* Round code and data size UP to TXM_MODULE_MPU_ALIGNMENT bytes. */ + *code_size = (*code_size + TXM_MODULE_MPU_ALIGNMENT - 1) & ~(TXM_MODULE_MPU_ALIGNMENT - 1); + *data_size = (*data_size + TXM_MODULE_MPU_ALIGNMENT - 1) & ~(TXM_MODULE_MPU_ALIGNMENT - 1); + + /* Alignment for code and data is TXM_MODULE_MPU_ALIGNMENT bytes. */ + *code_alignment = TXM_MODULE_MPU_ALIGNMENT; + *data_alignment = TXM_MODULE_MPU_ALIGNMENT; +} diff --git a/ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_external_memory_enable.c b/ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_external_memory_enable.c new file mode 100644 index 000000000..c5b9adcf5 --- /dev/null +++ b/ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_external_memory_enable.c @@ -0,0 +1,228 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + +// Some portions generated by Claude Code (Opus 5). + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Module Manager */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + +#include "tx_api.h" +#include "tx_mutex.h" +#include "tx_queue.h" +#include "tx_thread.h" +#include "txm_module.h" + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txm_module_manager_external_memory_enable Cortex-R52 */ +/* 6.1.8 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function creates an entry in the MPU table for a shared */ +/* memory space. The start_address must be aligned to the PMSAv8-R */ +/* protection granule, which is 64 bytes on Cortex-R52 -- the comment */ +/* inherited from the Armv8-M port says 32, and TXM_MODULE_MPU_ALIGNMENT*/ +/* below is what is actually enforced. */ +/* */ +/* The length must describe at least one byte and must not run off the */ +/* top of the address space; either is TX_SIZE_ERROR. It need not be a */ +/* multiple of the granule, but the hardware grant is rounded up to */ +/* one -- see the limit-address comment below for what the caller is */ +/* therefore agreeing to hand over. */ +/* */ +/* INPUT */ +/* */ +/* module_instance Module instance pointer */ +/* start_address Start address of memory */ +/* length Length of external memory */ +/* attributes Memory attributes (r/w) */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* _tx_mutex_get Get protection mutex */ +/* _tx_mutex_put Release protection mutex */ +/* */ +/* CALLED BY */ +/* */ +/* Application code */ +/* */ +/**************************************************************************/ +UINT _txm_module_manager_external_memory_enable(TXM_MODULE_INSTANCE *module_instance, + VOID *start_address, + ULONG length, + UINT attributes) +{ + +ULONG address; +ULONG shared_index; + + /* Determine if the module manager has not been initialized yet. */ + if (_txm_module_manager_ready != TX_TRUE) + { + /* Module manager has not been initialized. */ + return(TX_NOT_AVAILABLE); + } + + /* Determine if the module is valid. */ + if (module_instance == TX_NULL) + { + /* Invalid module pointer. */ + return(TX_PTR_ERROR); + } + + /* Get module manager protection mutex. */ + _tx_mutex_get(&_txm_module_manager_mutex, TX_WAIT_FOREVER); + + /* Determine if the module instance is valid. */ + if (module_instance -> txm_module_instance_id != TXM_MODULE_ID) + { + /* Release the protection mutex. */ + _tx_mutex_put(&_txm_module_manager_mutex); + + /* Invalid module pointer. */ + return(TX_PTR_ERROR); + } + + /* Determine if the module instance is in the loaded state. */ + if (module_instance -> txm_module_instance_state != TXM_MODULE_LOADED) + { + /* Release the protection mutex. */ + _tx_mutex_put(&_txm_module_manager_mutex); + + /* Return error if the module is not ready. */ + return(TX_START_ERROR); + } + + /* Determine if there are shared memory entries available. */ + if(module_instance -> txm_module_instance_shared_memory_count >= TXM_MODULE_MPU_SHARED_ENTRIES) + { + /* Release the protection mutex. */ + _tx_mutex_put(&_txm_module_manager_mutex); + + /* No more entries available. */ + return(TX_NO_MEMORY); + } + + /* Start address must adhere to Cortex-R52 MPU alignment. */ + address = (ULONG) start_address; + if(address != (address & ~(TXM_MODULE_MPU_ALIGNMENT - 1))) + { + /* Release the protection mutex. */ + _tx_mutex_put(&_txm_module_manager_mutex); + + /* Return alignment error. */ + return(TXM_MODULE_ALIGNMENT_ERROR); + } + + /* Reject a grant that describes no memory, and one whose inclusive end + address runs off the top of the address space. Both produce a limit + BELOW the base: a zero length computes address - 1 outright, and a + wrapping end computes some low address. Either would be programmed into + PRLAR, returned as TX_SUCCESS, and would consume one of the five shared + entries for a region the hardware cannot honour. + + Checked here rather than at the limit computation because a refused grant + must cost the caller nothing -- no register written and no entry spent -- + and the entry count is incremented further down. + + The wrap test is written against the room left above the base rather than + as (address + length) < address, which would have to commit the overflow + in order to detect it. length is known non-zero by then, so length - 1 is + the number of bytes above the base the grant needs, and a grant ending + exactly at the top of memory needs precisely the room there is and is + accepted. + + TX_SIZE_ERROR for both: the portable API already defines it as the size + fault, so neither case needs a new return code for callers to handle. */ + + if ((length == 0UL) || ((length - 1UL) > (((ULONG) ~0UL) - address))) + { + /* Release the protection mutex. */ + _tx_mutex_put(&_txm_module_manager_mutex); + + /* Return size error. */ + return(TX_SIZE_ERROR); + } + + /* At this point, we have a valid address and length. Set up MPU registers. */ + + /* Pick up index into shared memory entries. */ + shared_index = TXM_MODULE_MPU_SHARED_INDEX + module_instance -> txm_module_instance_shared_memory_count; + + /* Set base address register with start address, sanitized attributes and execute never. */ + module_instance -> txm_module_instance_mpu_registers[shared_index].txm_module_mpu_region_base_address = address | (attributes & TXM_MODULE_ATTRIBUTE_MASK) | TXM_MODULE_ATTRIBUTE_EXECUTE_NEVER; + + /* Set the limit address (data start + length-1), attribute index, and enable bit. + + The limit is MASKED to the protection granule before the attributes are + ORed in, exactly as txm_module_manager_mm_register_setup.c does for the + code and data regions, and this is not cosmetic. PRLAR holds LIMIT[31:6] + with the low six bits carrying RES0[5:4], AttrIndx[3:1] and EN[0], and the + hardware reads the limit back as LIMIT concatenated with 0x3F -- so the + masked value describes exactly the same inclusive end address. Without + the mask, a granule-sized region ends in 0x3F and those bits land on top + of the attributes: AttrIndx comes out 7 instead of 0, which selects an + unwritten MAIR byte and gives the shared region Device memory type, and + the two RES0 bits are set as well. The region still works well enough to + pass a functional test, which is why this was worth writing down. + + What the mask does NOT do is round the grant down. PRLAR describes an + inclusive end of LIMIT:0x3F, so the smallest region the hardware can + express is one 64-byte granule and the effective grant is the requested + range rounded UP to the next granule boundary: a one-byte grant hands the + module 64 bytes, a 65-byte grant hands it 128. The caller owns every byte + of that rounded range and must intend the module to have it -- there is no + length this function can accept that gives the module less. + + The length recorded below, and therefore the length + _txm_module_manager_inside_data_check() validates kernel-call pointers + against, is the UNROUNDED one the caller asked for. So a module can reach + the surplus bytes directly while a kernel call carrying a pointer into + them is refused. That asymmetry is deliberate and inherited: every other + module port computes the same rounded-up grant, and one that did not would + reject code moved from an Armv8-M part. Pass a granule multiple and the + two lengths agree. */ + module_instance -> txm_module_instance_mpu_registers[shared_index].txm_module_mpu_region_limit_address = ((address + length - 1) & TXM_MODULE_MPU_ADDRESS_MASK) | TXM_MODULE_ATTRIBUTE_INDEX | TXM_MODULE_ATTRIBUTE_REGION_ENABLE; + + /* Keep track of shared memory address and length in module instance. */ + module_instance -> txm_module_instance_shared_memory_address[module_instance -> txm_module_instance_shared_memory_count] = address; + module_instance -> txm_module_instance_shared_memory_length[module_instance -> txm_module_instance_shared_memory_count] = length; + + /* Increment counter. */ + module_instance -> txm_module_instance_shared_memory_count++; + + /* Release the protection mutex. */ + _tx_mutex_put(&_txm_module_manager_mutex); + + /* Return success. */ + return(TX_SUCCESS); +} diff --git a/ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_fault_capture.S b/ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_fault_capture.S new file mode 100644 index 000000000..48090ff33 --- /dev/null +++ b/ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_fault_capture.S @@ -0,0 +1,285 @@ +@/*************************************************************************** +@ * 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. +@ * +@ * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +@ * The AI-generated portions may be considered public domain (CC0-1.0) +@ * and not subject to the project's licence. The human contributor has +@ * reviewed and verified that the code is correct. +@ * +@ * SPDX-License-Identifier: MIT and CC0-1.0 +@ **************************************************************************/ +@ +@/**************************************************************************/ +@/* */ +@/* MODULE MANAGER RELEASE */ +@/* */ +@/* txm_module_manager_fault_capture.S Cortex-R52/GNU */ +@/* 6.5.2 */ +@/* AUTHOR */ +@/* */ +@/* Frédéric Desbiens, Eclipse Foundation */ +@/* */ +@/* DESCRIPTION */ +@/* */ +@/* Records why a memory protection fault happened, then hands over to */ +@/* the C handler which terminates the offending thread. */ +@/* */ +@/* A board's abort vectors branch here. Two entry points, because this */ +@/* core reports the two kinds of violation in different registers: a */ +@/* module writing outside its data region raises a data abort and */ +@/* reports through DFSR and DFAR, while a module branching outside its */ +@/* code region raises a prefetch abort and reports through IFSR and */ +@/* IFAR. Both are recorded either way, so a reader of the fault info */ +@/* can tell which pair is meaningful, and both entry points converge. */ +@/* */ +@/* This has to be assembly, and it has to run first. The fault */ +@/* registers hold only the most recent fault, so anything that runs */ +@/* before the capture and faults itself destroys the evidence. The */ +@/* abort is also taken in Abort mode, with its own banked sp and lr, so */ +@/* C cannot be entered until a stack is known good. */ +@/* */ +@/* THE CONTRACT WITH THE SHARED C HANDLER */ +@/* */ +@/* _txm_module_manager_memory_fault_handler is common to every module */ +@/* port and it terminates the faulting thread and then calls the */ +@/* application's fault-notify callback. For the second half of that to */ +@/* happen, _tx_thread_terminate has to RETURN -- and terminating the */ +@/* running thread only returns if the kernel believes it is inside an */ +@/* exception. _tx_thread_terminate ends in */ +@/* _tx_thread_system_preempt_check, which calls */ +@/* _tx_thread_system_return whenever _tx_thread_system_state and */ +@/* _tx_thread_preempt_disable are both zero; on this architecture that */ +@/* switches context immediately and never comes back. */ +@/* */ +@/* So this routine owes the handler three things, exactly as the */ +@/* Cortex-A7 module port's abort vector does: */ +@/* */ +@/* 1. _tx_thread_system_state incremented across the call, so the */ +@/* terminate returns instead of scheduling from Abort mode. */ +@/* 2. _tx_thread_current_ptr cleared afterwards -- the thread it */ +@/* names is terminated and the scheduler must not save into it. */ +@/* 3. an exception return into _tx_thread_schedule in System mode, */ +@/* which is where the next thread is chosen. */ +@/* */ +@/* Without step 1 the notify callback is unreachable, and the */ +@/* _tx_thread_system_return that runs in its place saves a solicited */ +@/* frame on the ABORT stack and writes that Abort-mode sp into the */ +@/* dead thread's stack pointer. It looks like it works, because the */ +@/* thread is never resumed -- but nothing gives the Abort stack back, */ +@/* so each module fault costs it about 56 bytes for the life of the */ +@/* run. The Cortex-M ports do not need step 1: there */ +@/* _tx_thread_system_return only pends PendSV and returns. */ +@/* */ +@/**************************************************************************/ + + .arm + .text + .align 2 + + .global _txm_module_manager_data_abort + .global _txm_module_manager_prefetch_abort + .extern _txm_module_manager_memory_fault_info + .extern _txm_module_manager_memory_fault_handler + .extern _tx_thread_current_ptr + .extern _tx_thread_system_state + .extern _tx_thread_schedule + +@ Offsets into TXM_MODULE_MANAGER_MEMORY_FAULT_INFO. Checked against offsetof at +@ compile time in txm_module_manager_offset_check.c. + + .equ FAULT_THREAD_PTR, 0x00 + .equ FAULT_CODE_LOCATION, 0x04 + .equ FAULT_DFSR, 0x08 + .equ FAULT_DFAR, 0x0C + .equ FAULT_IFSR, 0x10 + .equ FAULT_IFAR, 0x14 + .equ FAULT_SP, 0x18 + .equ FAULT_R0, 0x1C + .equ FAULT_LR, 0x50 + .equ FAULT_SPSR, 0x54 + +@ Processor mode and state bits. System mode is used for the return because +@ every kernel thread in this port runs in it, and it is the mode +@ _tx_thread_schedule expects to choose the next thread from. + + .equ MODE_MASK, 0x1F + .equ SYS_MODE_BITS, 0x1F + .equ THUMB_BIT, 0x20 + +@ Bytes pushed on the Abort stack by the capture below, so it can be given back. + + .equ CAPTURE_FRAME_SIZE, 20 + + +@/**************************************************************************/ +@/* Data abort: a module wrote or read outside a region it owns. */ +@/**************************************************************************/ + + .type _txm_module_manager_data_abort, %function +_txm_module_manager_data_abort: + +@ lr on data abort entry is the faulting address plus 8. Recorded as the +@ faulting instruction rather than the return address, because the value that +@ helps is where the module went wrong. + + SUB lr, lr, #8 + B _txm_module_manager_fault_common + + +@/**************************************************************************/ +@/* Prefetch abort: a module tried to execute outside its code region. */ +@/**************************************************************************/ + + .type _txm_module_manager_prefetch_abort, %function +_txm_module_manager_prefetch_abort: + +@ lr on prefetch abort entry is the faulting address plus 4. + + SUB lr, lr, #4 + + +@/**************************************************************************/ +@/* Common path. */ +@/**************************************************************************/ + +_txm_module_manager_fault_common: + +@ Save the registers this routine is about to use, on the Abort mode stack, so +@ the values recorded below are the module's and not ours. + + STMDB sp!, {r0-r3, r12} + +@ Tell the kernel it is inside an exception, before any kernel service runs. +@ This is what makes _tx_thread_terminate return to the C handler rather than +@ scheduling from Abort mode; see THE CONTRACT WITH THE SHARED C HANDLER above. + + LDR r0, =_tx_thread_system_state + LDR r1, [r0] + ADD r1, r1, #1 + STR r1, [r0] + + LDR r0, =_txm_module_manager_memory_fault_info + +@ Which thread was running, and where it was. + + LDR r1, =_tx_thread_current_ptr + LDR r1, [r1] + STR r1, [r0, #FAULT_THREAD_PTR] + STR lr, [r0, #FAULT_CODE_LOCATION] + +@ Both fault register pairs. Read before anything else can fault over them. + + MRC p15, 0, r1, c5, c0, 0 @ DFSR + STR r1, [r0, #FAULT_DFSR] + MRC p15, 0, r1, c6, c0, 0 @ DFAR + STR r1, [r0, #FAULT_DFAR] + MRC p15, 0, r1, c5, c0, 1 @ IFSR + STR r1, [r0, #FAULT_IFSR] + MRC p15, 0, r1, c6, c0, 2 @ IFAR + STR r1, [r0, #FAULT_IFAR] + +@ The mode the faulting code was in, which is what says whether this was the +@ module in user mode or the kernel itself. + + MRS r1, SPSR + STR r1, [r0, #FAULT_SPSR] + +@ The faulting context's own sp and lr, read from its mode rather than Abort's. +@ Without the mode switch these would be Abort mode's banked copies, which say +@ nothing about the module. +@ +@ System mode is used because it shares User mode's banked sp and lr, and a +@ module faults in User mode. That is exactly right for the case this exists +@ to report and wrong for one it does not: a fault taken in a privileged mode +@ gets System's sp and lr, which are not that mode's. SPSR says which happened, +@ so a reader can tell when these two fields do not apply. + + MRS r2, CPSR + BIC r3, r2, #0x1F @ Clear the mode field first: + ORR r3, r3, #0x1F @ ORR alone would only give + MSR CPSR_c, r3 @ System mode by luck, and + @ only from Abort mode. + @ System shares User's + @ banked sp and lr. + MOV r1, sp + MOV r12, lr + MSR CPSR_c, r2 @ Back to Abort mode + STR r1, [r0, #FAULT_SP] + STR r12, [r0, #FAULT_LR] + +@ The module's r0 through r3 and r12, from where they were pushed above, then +@ r4 through r11 which the fault did not disturb. + +@ Five words were pushed, r0 through r3 and r12, and they are copied one at a +@ time. Loading them as a group and then building the destination address in +@ the same registers destroys the values on the way past, which is what the +@ first version of this did. + + LDR r1, [sp, #0] @ Module r0 + STR r1, [r0, #FAULT_R0] + LDR r1, [sp, #4] @ Module r1 + STR r1, [r0, #(FAULT_R0 + 4)] + LDR r1, [sp, #8] @ Module r2 + STR r1, [r0, #(FAULT_R0 + 8)] + LDR r1, [sp, #12] @ Module r3 + STR r1, [r0, #(FAULT_R0 + 12)] + LDR r1, [sp, #16] @ Module r12 + STR r1, [r0, #(FAULT_R0 + 0x30)] @ r12 sits after r11 + +@ r4 through r11 were never disturbed, so they can go straight out. + + ADD r1, r0, #(FAULT_R0 + 16) + STMIA r1, {r4-r11} + +@ Give the Abort stack back. The five words above were read out of it rather +@ than popped, because the copies needed them in place; nothing needs them now. +@ This routine does not return to the faulting code, so an unbalanced sp here +@ would never be corrected and every module fault would cost the Abort stack +@ twenty bytes until it ran out. + + ADD sp, sp, #CAPTURE_FRAME_SIZE + +@ Hand over. The handler terminates the offending thread and then calls the +@ application's fault-notify callback, and it DOES return here -- the +@ incremented system state above is what makes that true. + + BL _txm_module_manager_memory_fault_handler + +@ Out of the exception. Balanced against the increment above. + + LDR r0, =_tx_thread_system_state + LDR r1, [r0] + SUB r1, r1, #1 + STR r1, [r0] + +@ The current thread is terminated, so there is no context to save into it and +@ the scheduler must not try. Clearing the pointer is how this port says "no +@ thread is running", the same state _tx_thread_system_return leaves behind. + + MOV r1, #0 + LDR r0, =_tx_thread_current_ptr + STR r1, [r0] + +@ Return into the scheduler rather than to the faulting instruction, which +@ would fault again immediately and for ever. An exception return, not a +@ branch: it leaves Abort mode properly and restores the interrupt mask the +@ faulting context had, where a branch would run the scheduler in Abort mode +@ on the Abort stack. +@ +@ SPSR is rewritten for the mode this port's kernel threads run in, with the +@ Thumb bit cleared because _tx_thread_schedule is A32. The value recorded in +@ the fault info was stored before this, so what an application reads is still +@ the mode the module faulted in. + + MRS r0, SPSR + BIC r0, r0, #MODE_MASK + ORR r0, r0, #SYS_MODE_BITS + BIC r0, r0, #THUMB_BIT + MSR SPSR_cxsf, r0 + + LDR lr, =_tx_thread_schedule + SUBS pc, lr, #0 diff --git a/ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_memory_fault_handler.c b/ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_memory_fault_handler.c new file mode 100644 index 000000000..cac30d2fb --- /dev/null +++ b/ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_memory_fault_handler.c @@ -0,0 +1,139 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Module Manager */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +// Some portions generated by Claude Code (Opus 5). + +#define TX_SOURCE_CODE + +#include "tx_api.h" +#include "tx_thread.h" +#include "txm_module.h" + + +/* This handler is architecture-neutral: it terminates the faulting thread and + calls the notification callback. The fault registers are captured before it + runs, in the abort vector, because DFSR, DFAR, IFSR and IFAR must be read + before anything else can fault and overwrite them -- and on this core the + abort is taken in Abort mode with its own banked lr and sp, so the capture has + to happen there rather than here. + + Data aborts and prefetch aborts both arrive here. A module can violate its + protection either way: writing outside its data region, or branching outside + its code region. Which pair of registers is meaningful depends on which it + was, and the fault info structure carries both. + + THIS FUNCTION RETURNS, AND THAT IS A REQUIREMENT ON THE ABORT VECTOR. + + It terminates the faulting thread and then calls the application's notify + callback. The second of those is only reached if _tx_thread_terminate returns, + and terminating the RUNNING thread returns only when the kernel believes it is + inside an exception: _tx_thread_terminate ends in + _tx_thread_system_preempt_check, which calls _tx_thread_system_return whenever + _tx_thread_system_state and _tx_thread_preempt_disable are both zero. On this + architecture _tx_thread_system_return switches context immediately and never + comes back, so the callback would be unreachable. + + The body below is therefore left exactly as the cortex_m33, cortex_a7 and + cortex_m7 ports have it, and the requirement is met where it belongs -- in + txm_module_manager_fault_capture.S, which increments _tx_thread_system_state + around this call, clears _tx_thread_current_ptr afterwards and returns into + the scheduler. The Cortex-M ports need no such bracket because their + _tx_thread_system_return only pends PendSV and returns. Anyone tempted to + reorder the two statements below to "fix" a notify callback that does not fire + should look at the abort vector first: the ordering here is upstream's and it + is not the defect. */ + +/* Define the user's fault notification callback function pointer. This is + setup via the txm_module_manager_memory_fault_notify API. */ + +VOID (*_txm_module_manager_fault_notify)(TX_THREAD *, TXM_MODULE_INSTANCE *); + + +/* Define a macro that can be used to allocate global variables useful to + store information about the last fault. This macro is defined in + txm_module_port.h and is usually populated in the assembly language + fault handling prior to the code calling _txm_module_manager_memory_fault_handler. */ + +TXM_MODULE_MANAGER_FAULT_INFO + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txm_module_manager_memory_fault_handler Cortex-R52 */ +/* 6.1.8 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function handles a fault associated with a memory protected */ +/* module. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_terminate Terminate thread */ +/* */ +/* CALLED BY */ +/* */ +/* Fault handler */ +/* */ +/**************************************************************************/ +VOID _txm_module_manager_memory_fault_handler(VOID) +{ + +TXM_MODULE_INSTANCE *module_instance_ptr; +TX_THREAD *thread_ptr; + + /* Pickup the current thread. */ + thread_ptr = _tx_thread_current_ptr; + + /* Initialize the module instance pointer to NULL. */ + module_instance_ptr = TX_NULL; + + /* Is there a thread? */ + if (thread_ptr) + { + /* Pickup the module instance. */ + module_instance_ptr = thread_ptr -> tx_thread_module_instance_ptr; + + /* Terminate the current thread. */ + _tx_thread_terminate(_tx_thread_current_ptr); + } + + /* Determine if there is a user memory fault notification callback. */ + if (_txm_module_manager_fault_notify) + { + /* Yes, call the user's notification memory fault callback. */ + (_txm_module_manager_fault_notify)(thread_ptr, module_instance_ptr); + } +} diff --git a/ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_memory_fault_notify.c b/ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_memory_fault_notify.c new file mode 100644 index 000000000..a86196876 --- /dev/null +++ b/ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_memory_fault_notify.c @@ -0,0 +1,78 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Module Manager */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + +#include "tx_api.h" +#include "tx_thread.h" +#include "txm_module.h" + + +/* Define the external user's fault notification callback function pointer. This is + setup via the txm_module_manager_memory_fault_notify API. */ + +extern VOID (*_txm_module_manager_fault_notify)(TX_THREAD *, TXM_MODULE_INSTANCE *); + + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txm_module_manager_memory_fault_notify Cortex-R52 */ +/* 6.1.8 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function registers an application callback when/if a memory */ +/* fault occurs. The supplied thread is automatically terminated, but */ +/* any other threads in the same module may still execute. */ +/* */ +/* INPUT */ +/* */ +/* notify_function Memory fault notification */ +/* function, NULL disables. */ +/* */ +/* OUTPUT */ +/* */ +/* status Completion status */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Application Code */ +/* */ +/**************************************************************************/ +UINT _txm_module_manager_memory_fault_notify(VOID (*notify_function)(TX_THREAD *, TXM_MODULE_INSTANCE *)) +{ + /* Setup notification function. */ + _txm_module_manager_fault_notify = notify_function; + + /* Return success. */ + return(TX_SUCCESS); +} diff --git a/ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_mm_register_setup.c b/ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_mm_register_setup.c new file mode 100644 index 000000000..2a3fe6791 --- /dev/null +++ b/ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_mm_register_setup.c @@ -0,0 +1,219 @@ +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * Copyright (c) 2026-present 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 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Module Manager */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + +#include "tx_api.h" +#include "txm_module.h" + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txm_module_manager_mm_register_setup Cortex-R52 */ +/* 6.1.6 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function sets up the Cortex-R52 MPU register definitions based */ +/* on the module's memory characteristics. */ +/* */ +/* INPUT */ +/* */ +/* module_instance Pointer to module instance */ +/* */ +/* OUTPUT */ +/* */ +/* MPU settings for the module in module_instance */ +/* */ +/* CALLS */ +/* */ +/* none */ +/* */ +/* CALLED BY */ +/* */ +/* _txm_module_manager_thread_create */ +/* */ +/**************************************************************************/ +/* Two departures from the Armv8-M version this was derived from, both + deliberate. + + The address mask is 64-byte, not 32-byte. PRBAR and PRLAR hold attributes in + the bits below the granule, so masking to the wrong boundary does not fault -- + it silently writes address bits into the shareability and permission fields + and the region comes up with attributes nobody asked for. + + Regions are non-shareable rather than inner-shareable. The M33 port marks + module memory inner-shareable; the RTU here is a single Cortex-R52 and every + region in the board support package's map is non-shareable, so matching it + keeps one memory model across the kernel and its modules. A multi-core RTU + configuration would need to revisit this, and would need to revisit far more + than this. */ + +/* Marks the end of the user-mode entry function, so the kernel entry region can + be sized to it. */ + +extern VOID _txm_module_manager_user_mode_entry_end(VOID); + +VOID _txm_module_manager_mm_register_setup(TXM_MODULE_INSTANCE *module_instance) +{ + +ULONG data_size; +ULONG start_stop_stack_size; +ULONG callback_stack_size; + + /* Setup MPU region for kernel mode entry. */ + /* Set base address register to user mode entry function address, which is guaranteed to be at least 32-byte aligned. + Mask address to proper range, inner shareable, read only. */ + module_instance -> txm_module_instance_mpu_registers[TXM_MODULE_MPU_KERNEL_ENTRY_INDEX].txm_module_mpu_region_base_address = ((ULONG) _txm_module_manager_user_mode_entry & TXM_MODULE_MPU_ADDRESS_MASK) | TXM_MODULE_ATTRIBUTE_NON_SHAREABLE | TXM_MODULE_ATTRIBUTE_READ_ONLY; + /* Set the limit address, attribute index, and enable bit. */ + /* Limit taken from the end of the function rather than from its base. The + whole privileged surface a module can execute is 24 bytes, so one granule + covers it today and the base would have done -- but if the entry ever grows + past 64 bytes, sizing from the base would silently leave the tail of it + outside the region and the module would fault on a call it is entitled to + make. */ + + module_instance -> txm_module_instance_mpu_registers[TXM_MODULE_MPU_KERNEL_ENTRY_INDEX].txm_module_mpu_region_limit_address = (((ULONG) _txm_module_manager_user_mode_entry_end - 1) & TXM_MODULE_MPU_ADDRESS_MASK) | TXM_MODULE_ATTRIBUTE_INDEX | TXM_MODULE_ATTRIBUTE_REGION_ENABLE; + /* End of kernel mode entry setup. */ + + + /* Setup MPU region for module code protection. */ + /* Set base address register to module code address, which should be at least 32-byte aligned. + Mask address to proper range, inner shareable, read only. */ + module_instance -> txm_module_instance_mpu_registers[TXM_MODULE_MPU_CODE_INDEX].txm_module_mpu_region_base_address = ((ULONG) module_instance -> txm_module_instance_code_start & TXM_MODULE_MPU_ADDRESS_MASK) | TXM_MODULE_ATTRIBUTE_NON_SHAREABLE | TXM_MODULE_ATTRIBUTE_READ_ONLY; + /* Set the limit address (code start + code size-1), attribute index, and enable bit. */ + module_instance -> txm_module_instance_mpu_registers[TXM_MODULE_MPU_CODE_INDEX].txm_module_mpu_region_limit_address = (((ULONG) module_instance -> txm_module_instance_code_start + module_instance -> txm_module_instance_preamble_ptr -> txm_module_preamble_code_size - 1) & TXM_MODULE_MPU_ADDRESS_MASK) | TXM_MODULE_ATTRIBUTE_INDEX | TXM_MODULE_ATTRIBUTE_REGION_ENABLE; + /* End of module code protection. */ + + + /* Setup MPU region for module data protection. */ + /* Set base address register to module data address, which should be at least 32-byte aligned. + Mask address to proper range, inner shareable, read write, execute never. */ + module_instance -> txm_module_instance_mpu_registers[TXM_MODULE_MPU_DATA_INDEX].txm_module_mpu_region_base_address = ((ULONG) module_instance -> txm_module_instance_data_start & TXM_MODULE_MPU_ADDRESS_MASK) | TXM_MODULE_ATTRIBUTE_NON_SHAREABLE | TXM_MODULE_ATTRIBUTE_READ_WRITE | TXM_MODULE_ATTRIBUTE_EXECUTE_NEVER; + + /* Adjust the size of the module elements to be aligned to the default alignment. We do this + so that when we partition the allocated memory, we can simply place these regions right beside + each other without having to align their pointers. Note this only works when they all have + the same alignment. */ + + data_size = module_instance -> txm_module_instance_preamble_ptr -> txm_module_preamble_data_size; + start_stop_stack_size = module_instance -> txm_module_instance_preamble_ptr -> txm_module_preamble_start_stop_stack_size; + callback_stack_size = module_instance -> txm_module_instance_preamble_ptr -> txm_module_preamble_callback_stack_size; + + data_size = ((data_size + TXM_MODULE_DATA_ALIGNMENT - 1)/TXM_MODULE_DATA_ALIGNMENT) * TXM_MODULE_DATA_ALIGNMENT; + start_stop_stack_size = ((start_stop_stack_size + TXM_MODULE_DATA_ALIGNMENT - 1)/TXM_MODULE_DATA_ALIGNMENT) * TXM_MODULE_DATA_ALIGNMENT; + callback_stack_size = ((callback_stack_size + TXM_MODULE_DATA_ALIGNMENT - 1)/TXM_MODULE_DATA_ALIGNMENT) * TXM_MODULE_DATA_ALIGNMENT; + + /* Update the data size to include thread stacks. */ + data_size = data_size + start_stop_stack_size + callback_stack_size; + + /* Set the limit address (data start + data size-1), attribute index, and enable bit. */ + module_instance -> txm_module_instance_mpu_registers[TXM_MODULE_MPU_DATA_INDEX].txm_module_mpu_region_limit_address = (((ULONG) module_instance -> txm_module_instance_data_start + data_size - 1) & TXM_MODULE_MPU_ADDRESS_MASK) | TXM_MODULE_ATTRIBUTE_INDEX | TXM_MODULE_ATTRIBUTE_REGION_ENABLE; + /* End of module data protection. */ + + /* Remaining MPU entries are disabled for now and can be used for shared memory. */ +} + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txm_module_manager_inside_data_check Cortex-R52 */ +/* 6.1.6 */ +/* AUTHOR */ +/* */ +/* Scott Larson, Microsoft Corporation */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function checks if the specified object is inside shared */ +/* memory. */ +/* */ +/* INPUT */ +/* */ +/* module_instance Pointer to module instance */ +/* obj_ptr Pointer to the object */ +/* obj_size Size of the object */ +/* */ +/* OUTPUT */ +/* */ +/* Whether the object is inside the shared memory region. */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* Module dispatch check functions */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 12-31-2020 Scott Larson Initial Version 6.1.3 */ +/* 04-02-2021 Scott Larson Modified comments, */ +/* resulting in version 6.1.6 */ +/* */ +/**************************************************************************/ +UINT _txm_module_manager_inside_data_check(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE obj_ptr, UINT obj_size) +{ + +UINT shared_memory_index; +UINT num_shared_memory_mpu_entries; +ALIGN_TYPE shared_memory_address_start; +ALIGN_TYPE shared_memory_address_end; + + /* Check for overflow. */ + if ((obj_ptr) > ((obj_ptr) + (obj_size))) + { + return(TX_FALSE); + } + + /* Check if the object is inside the module data. */ + if ((obj_ptr >= (ALIGN_TYPE) module_instance -> txm_module_instance_data_start) && + ((obj_ptr + obj_size) <= ((ALIGN_TYPE) module_instance -> txm_module_instance_data_end + 1))) + { + return(TX_TRUE); + } + + /* Check if the object is inside the shared memory. */ + num_shared_memory_mpu_entries = module_instance -> txm_module_instance_shared_memory_count; + for (shared_memory_index = 0; shared_memory_index < num_shared_memory_mpu_entries; shared_memory_index++) + { + + shared_memory_address_start = (ALIGN_TYPE) module_instance -> txm_module_instance_shared_memory_address[shared_memory_index]; + shared_memory_address_end = shared_memory_address_start + module_instance -> txm_module_instance_shared_memory_length[shared_memory_index]; + + if ((obj_ptr >= (ALIGN_TYPE) shared_memory_address_start) && + ((obj_ptr + obj_size) <= (ALIGN_TYPE) shared_memory_address_end)) + { + return(TX_TRUE); + } + } + + return(TX_FALSE); +} diff --git a/ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_offset_check.c b/ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_offset_check.c new file mode 100644 index 000000000..09ba7420c --- /dev/null +++ b/ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_offset_check.c @@ -0,0 +1,261 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/**************************************************************************/ +/* */ +/* MODULE MANAGER RELEASE */ +/* */ +/* txm_module_manager_offset_check.c Cortex-R52/GNU */ +/* 6.5.2 */ +/* AUTHOR */ +/* */ +/* Frédéric Desbiens, Eclipse Foundation */ +/* */ +/* DESCRIPTION */ +/* */ +/* Compile-time verification of the structure offsets that this port's */ +/* assembly hard-codes. */ +/* */ +/* tx_thread_schedule.S reaches into TX_THREAD and TXM_MODULE_INSTANCE */ +/* with numeric offsets, because assembly has no other way to do it. */ +/* Nothing in the toolchain connects those numbers to the structures */ +/* they describe, so adding a field, reordering an extension or */ +/* building with a different set of ThreadX options silently moves the */ +/* target and the scheduler reads the wrong word. The failure is a */ +/* corrupted region table or a fault in a thread that did nothing wrong, */ +/* a long way from the change that caused it. */ +/* */ +/* This file exists so that becomes a build error instead. It emits no */ +/* code. */ +/* */ +/* The offsets here are not the same as the Armv8-M module port's, and */ +/* that is the concrete case in point: there the module instance pointer */ +/* sits at 0x90, and here it is 0x94, because the Cortex-R52 port keeps */ +/* tx_thread_vfp_enable ahead of the module fields in */ +/* TX_THREAD_EXTENSION_2. Copying the Armv8-M numbers would have built */ +/* cleanly and misbehaved on the board. */ +/* */ +/* See eclipse-threadx/threadx issue #577, which proposes this check for */ +/* every port rather than only this one. */ +/* */ +/**************************************************************************/ + +#include +#include "tx_api.h" +#include "txm_module.h" + +/* The board's MPU header is not on the include path when this file is compiled + as a port source, and it must not have to be: the region number this file + asserts on is the port's, spelled in txm_module_port.h. Where a board header + is present the two are still checked against each other below, so a board + support package cannot quietly disagree with the scheduler. */ +#if defined(__has_include) +# if __has_include("mpu.h") +# include "mpu.h" +# define TXM_R52_BOARD_MPU_H_PRESENT +# endif +#endif + +/* These must match the .equ values at the top of tx_thread_schedule.S. */ + +#define TXM_THREAD_MODULE_INSTANCE 0x94 +#define TXM_INSTANCE_PROPERTY_FLAGS 0x0C +#define TXM_INSTANCE_MPU_REGISTERS 0x64 + +/* The offset the scheduler no longer reads, kept as its own constant because the + assert below still pins it. */ + +#define TXM_INSTANCE_DATA_START 0x2C + +_Static_assert(offsetof(TX_THREAD, tx_thread_module_instance_ptr) + == TXM_THREAD_MODULE_INSTANCE, + "tx_thread_schedule.S TXM_THREAD_MODULE_INSTANCE no longer matches " + "TX_THREAD; the scheduler would read the wrong word"); + +/* The field the scheduler decides protection on. Reading a word that happens to + have both low bits set would program a region table for a module that has + none; reading one that does not would send a protected module down the path + that closes the kernel's window and enables nothing in its place. Neither + shows up as a wrong number anywhere -- one is a fault in a module that asked + correctly, the other is the silent absence of one. */ + +_Static_assert(offsetof(TXM_MODULE_INSTANCE, txm_module_instance_property_flags) + == TXM_INSTANCE_PROPERTY_FLAGS, + "tx_thread_schedule.S TXM_INSTANCE_PROPERTY_FLAGS no longer matches " + "TXM_MODULE_INSTANCE; the protection check would test the wrong field"); + +/* The data start, which the assembly stopped reading when the protection check + moved to the property flags. Kept, because the two offsets pin opposite ends + of the same region of TXM_MODULE_INSTANCE -- property flags is its fourth word + and data start its twelfth -- and a reordering that moved either without + moving the other is exactly what this file exists to catch. It costs no + code. */ + +_Static_assert(offsetof(TXM_MODULE_INSTANCE, txm_module_instance_data_start) + == TXM_INSTANCE_DATA_START, + "TXM_MODULE_INSTANCE has been reordered around " + "txm_module_instance_data_start; check every offset in this file " + "against tx_thread_schedule.S"); + +_Static_assert(offsetof(TXM_MODULE_INSTANCE, txm_module_instance_mpu_registers) + == TXM_INSTANCE_MPU_REGISTERS, + "tx_thread_schedule.S TXM_INSTANCE_MPU_REGISTERS no longer matches " + "TXM_MODULE_INSTANCE; the scheduler would load regions from the " + "wrong address"); + +/* Offset the module thread stack build hard-codes. This one decides the mode a + module thread starts in, so a wrong value starts it privileged when it asked + not to be -- protection that is absent from the first instruction and looks + present everywhere else. The Cortex-R4 module port reads 0x9C here, which in + this port is a different field. */ + +_Static_assert(offsetof(TX_THREAD, tx_thread_module_user_mode) == 0xA0, + "txm_module_manager_thread_stack_build.S THREAD_MODULE_USER_MODE " + "no longer matches TX_THREAD; module threads could start in the " + "wrong privilege mode"); + +_Static_assert(offsetof(TX_THREAD, tx_thread_module_user_mode) + != offsetof(TX_THREAD, tx_thread_module_current_user_mode), + "the requested and current user-mode fields have collapsed onto " + "one offset; the stack build and the SVC handler would be reading " + "each other's field"); + +/* Offsets the supervisor call handler hard-codes, from + txm_module_manager_svc_handler.S. This is the privilege boundary, so a wrong + offset here does not merely misbehave: writing the user-mode flag to the wrong + word would leave a thread believing it is privileged when it is not, or the + reverse, and swapping to a stack pointer read from the wrong field would put + the kernel on memory the module can write. */ + +#define THREAD_STACK_PTR 0x08 +#define THREAD_STACK_START 0x0C +#define THREAD_STACK_END 0x10 +#define THREAD_STACK_SIZE 0x14 +#define THREAD_CUR_USER_MODE 0x9C +#define THREAD_KSTACK_START 0xA8 +#define THREAD_KSTACK_END 0xAC +#define THREAD_KSTACK_SIZE 0xB0 +#define THREAD_MSTACK_PTR 0xB4 +#define THREAD_MSTACK_START 0xB8 +#define THREAD_MSTACK_END 0xBC +#define THREAD_MSTACK_SIZE 0xC0 + +#define T_OFF(f) offsetof(TX_THREAD, f) + +_Static_assert(T_OFF(tx_thread_stack_ptr) == THREAD_STACK_PTR, "svc handler: stack_ptr moved"); +_Static_assert(T_OFF(tx_thread_stack_start) == THREAD_STACK_START, "svc handler: stack_start moved"); +_Static_assert(T_OFF(tx_thread_stack_end) == THREAD_STACK_END, "svc handler: stack_end moved"); +_Static_assert(T_OFF(tx_thread_stack_size) == THREAD_STACK_SIZE, "svc handler: stack_size moved"); + +_Static_assert(T_OFF(tx_thread_module_current_user_mode) == THREAD_CUR_USER_MODE, + "svc handler: the user-mode flag moved; a thread could be left " + "believing it is privileged when it is not"); + +_Static_assert(T_OFF(tx_thread_module_kernel_stack_start) == THREAD_KSTACK_START, "svc handler: kernel_stack_start moved"); +_Static_assert(T_OFF(tx_thread_module_kernel_stack_end) == THREAD_KSTACK_END, + "svc handler: kernel_stack_end moved; the kernel would run on a " + "stack read from the wrong field"); +_Static_assert(T_OFF(tx_thread_module_kernel_stack_size) == THREAD_KSTACK_SIZE, "svc handler: kernel_stack_size moved"); +_Static_assert(T_OFF(tx_thread_module_stack_ptr) == THREAD_MSTACK_PTR, "svc handler: module stack_ptr moved"); +_Static_assert(T_OFF(tx_thread_module_stack_start) == THREAD_MSTACK_START, "svc handler: module stack_start moved"); +_Static_assert(T_OFF(tx_thread_module_stack_end) == THREAD_MSTACK_END, "svc handler: module stack_end moved"); +_Static_assert(T_OFF(tx_thread_module_stack_size) == THREAD_MSTACK_SIZE, "svc handler: module stack_size moved"); + +/* Offsets the fault capture hard-codes, from + txm_module_manager_fault_capture.S. Same hazard as the scheduler's: the + capture runs in Abort mode with a fault in progress, and a wrong offset there + writes the evidence into the wrong field of a structure the application is + about to read. */ + +#define FAULT_THREAD_PTR 0x00 +#define FAULT_CODE_LOCATION 0x04 +#define FAULT_DFSR 0x08 +#define FAULT_DFAR 0x0C +#define FAULT_IFSR 0x10 +#define FAULT_IFAR 0x14 +#define FAULT_SP 0x18 +#define FAULT_R0 0x1C +#define FAULT_LR 0x50 +#define FAULT_SPSR 0x54 + +#define FAULT_OFF(f) offsetof(TXM_MODULE_MANAGER_MEMORY_FAULT_INFO, \ + txm_module_manager_memory_fault_info_##f) + +_Static_assert(FAULT_OFF(thread_ptr) == FAULT_THREAD_PTR, "fault capture: thread_ptr offset moved"); +_Static_assert(FAULT_OFF(code_location) == FAULT_CODE_LOCATION, "fault capture: code_location offset moved"); +_Static_assert(FAULT_OFF(dfsr) == FAULT_DFSR, "fault capture: dfsr offset moved"); +_Static_assert(FAULT_OFF(dfar) == FAULT_DFAR, "fault capture: dfar offset moved"); +_Static_assert(FAULT_OFF(ifsr) == FAULT_IFSR, "fault capture: ifsr offset moved"); +_Static_assert(FAULT_OFF(ifar) == FAULT_IFAR, "fault capture: ifar offset moved"); +_Static_assert(FAULT_OFF(sp) == FAULT_SP, "fault capture: sp offset moved"); +_Static_assert(FAULT_OFF(r0) == FAULT_R0, "fault capture: r0 offset moved"); +_Static_assert(FAULT_OFF(lr) == FAULT_LR, "fault capture: lr offset moved"); +_Static_assert(FAULT_OFF(spsr) == FAULT_SPSR, "fault capture: spsr offset moved"); + +/* The capture writes r4 through r11 as one block starting sixteen bytes past r0, + and r12 thirty-two bytes past that, which assumes the registers are laid out + in order with no padding. */ + +_Static_assert(FAULT_OFF(r4) == (FAULT_R0 + 16), "fault capture: r4 is not four words past r0"); +_Static_assert(FAULT_OFF(r12) == (FAULT_R0 + 0x30), "fault capture: r12 is not where the block store expects"); + +/* The scheduler loads exactly eight regions as sixteen consecutive words, with + LDMIA walking the table two words at a time. If the entry stops being two + words, or the table stops holding eight of them, the unrolled sequence walks + off the end of it. */ + +_Static_assert(sizeof(TXM_MODULE_MPU_INFO) == (2U * sizeof(ULONG)), + "TXM_MODULE_MPU_INFO is no longer two words; the unrolled LDMIA " + "sequence in tx_thread_schedule.S would misread the region table"); + +_Static_assert(TXM_MODULE_MPU_TOTAL_ENTRIES == 8, + "tx_thread_schedule.S has an unrolled sequence for exactly eight " + "regions; change both together"); + +/* The block has to sit inside the CP15 op1 0 direct-access range. Regions 16 + and above are directly addressable too, but at op1 1 (TRM 8.4, Table 8-9); + the scheduler emits op1 0 encodings for all eight, so a block crossing 15 + would be programming the wrong registers rather than merely being out of + reach. */ + +_Static_assert((TXM_MODULE_MPU_FIRST_REGION + TXM_MODULE_MPU_TOTAL_ENTRIES) <= 16, + "the module region block extends past region 15; the unrolled " + "sequence in tx_thread_schedule.S emits CP15 op1 0 encodings, " + "which do not address regions 16 and above"); + +/* The kernel's window over the module area. tx_thread_schedule.S hard-codes the + region number in an MCR to PRSELR, because the assembler cannot include this + header, so the two spellings are checked against each other here. + + It also has to sit clear of the module's own block: the scheduler enables the + window for a thread that owns no module and the block for a thread that does, + and if the two ever named the same region one would silently be the other. */ + +_Static_assert(TXM_MODULE_MPU_WINDOW_REGION == 16, + "tx_thread_schedule.S writes region 16 as the module window; " + "change MPU_MODULE_WINDOW_REGION there to match"); + +_Static_assert(TXM_MODULE_MPU_WINDOW_REGION >= (TXM_MODULE_MPU_FIRST_REGION + + TXM_MODULE_MPU_TOTAL_ENTRIES), + "the module window overlaps the regions handed to a module; the " + "scheduler would enable one believing it was the other"); + +/* A board support package naming a different region than the scheduler uses + would program its window somewhere the scheduler never enables. */ +#ifdef TXM_R52_BOARD_MPU_H_PRESENT +_Static_assert(MPU_MODULE_LOAD_REGION == TXM_MODULE_MPU_WINDOW_REGION, + "the board's MPU_MODULE_LOAD_REGION disagrees with the port's " + "TXM_MODULE_MPU_WINDOW_REGION"); +#endif diff --git a/ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_svc_handler.S b/ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_svc_handler.S new file mode 100644 index 000000000..0689ffbaa --- /dev/null +++ b/ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_svc_handler.S @@ -0,0 +1,233 @@ +@/*************************************************************************** +@ * 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. +@ * +@ * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +@ * The AI-generated portions may be considered public domain (CC0-1.0) +@ * and not subject to the project's licence. The human contributor has +@ * reviewed and verified that the code is correct. +@ * +@ * SPDX-License-Identifier: MIT and CC0-1.0 +@ **************************************************************************/ +@ +@/**************************************************************************/ +@/* */ +@/* MODULE MANAGER RELEASE */ +@/* */ +@/* txm_module_manager_svc_handler.S Cortex-R52/GNU */ +@/* 6.5.2 */ +@/* AUTHOR */ +@/* */ +@/* Frédéric Desbiens, Eclipse Foundation */ +@/* */ +@/* DESCRIPTION */ +@/* */ +@/* The privilege boundary. A board's supervisor call vector branches */ +@/* here. */ +@/* */ +@/* SVC 1 raises a module thread out of User mode and onto its kernel */ +@/* stack; SVC 2 puts it back. Both are only reachable from the two */ +@/* exact instructions inside _txm_module_manager_user_mode_entry, and */ +@/* that check is what makes the boundary a boundary. Without it a */ +@/* module could execute SVC 1 from anywhere in its own code and come */ +@/* back privileged, which is every protection in this port gone at */ +@/* once. */ +@/* */ +@/* The two stacks are the other half of it. A module's own stack is in */ +@/* memory the module can write, so the kernel must not run on it: a */ +@/* module could otherwise corrupt kernel state by scribbling on what it */ +@/* believes is its own stack. SVC 1 therefore switches to a kernel */ +@/* stack the module cannot reach, and SVC 2 switches back. */ +@/* */ +@/* Any other SVC number stops. This core's base port does not use SVC */ +@/* at all -- its vector treats one as a fault -- so there is no third */ +@/* caller to accommodate and nothing legitimate to fall through to. */ +@/* */ +@/**************************************************************************/ + +@ Unified syntax, declared rather than assumed. In divided syntax the condition +@ precedes the size -- LDRNEH -- and in unified it follows -- LDRHNE. The +@ assembler's default rejected the unified form, and a file that hand-writes +@ exception entry is the last place to leave that to chance. + + .syntax unified + .arm + .text + .align 2 + + .global __tx_module_svc_interrupt + .extern _tx_thread_current_ptr + .extern _txm_system_mode_enter + .extern _txm_system_mode_exit + +@ Processor mode encodings and the CPSR mode field. + + .equ MODE_MASK, 0x1F + .equ USR_MODE_BITS, 0x10 + .equ SVC_MODE_BITS, 0x13 + .equ SYS_MODE_BITS, 0x1F + .equ THUMB_MASK, 0x20 + +@ Offsets into TX_THREAD. Checked against offsetof at compile time in +@ txm_module_manager_offset_check.c. They are not the Cortex-R4 module port's +@ values: tx_thread_vfp_enable sits ahead of the module fields in this port, so +@ everything after it moves by a word. + + .equ THREAD_STACK_PTR, 0x08 + .equ THREAD_STACK_START, 0x0C + .equ THREAD_STACK_END, 0x10 + .equ THREAD_STACK_SIZE, 0x14 + .equ THREAD_CUR_USER_MODE, 0x9C + .equ THREAD_KSTACK_START, 0xA8 + .equ THREAD_KSTACK_END, 0xAC + .equ THREAD_KSTACK_SIZE, 0xB0 + .equ THREAD_MSTACK_PTR, 0xB4 + .equ THREAD_MSTACK_START, 0xB8 + .equ THREAD_MSTACK_END, 0xBC + .equ THREAD_MSTACK_SIZE, 0xC0 + + +@/**************************************************************************/ +@/* Vector entry. */ +@/**************************************************************************/ + + .type __tx_module_svc_interrupt, %function +__tx_module_svc_interrupt: + + STMFD sp!, {r0-r3, r12, lr} @ Preserve the caller's registers + MRS r0, spsr + STMFD sp!, {r0, r3} @ SPSR, plus one more to keep the + @ stack eight-byte aligned + +@ Recover the SVC number from the instruction that caused this. The encoding +@ differs between states, so the saved SPSR decides where to read it from. + + TST r0, #THUMB_MASK + LDRHNE r0, [lr, #-2] @ Thumb: halfword, low 8 bits + BICNE r0, r0, #0xFF00 + LDREQ r0, [lr, #-4] @ ARM: word, low 24 bits + BICEQ r0, r0, #0xFF000000 + + CMP r0, #1 + BEQ _tx_module_svc_enter + CMP r0, #2 + BEQ _tx_module_svc_exit + + +@/**************************************************************************/ +@/* Anything else. */ +@/**************************************************************************/ + + .weak _tx_module_svc_unrecognized +_tx_module_svc_unrecognized: + +@ Stop rather than return. Returning would resume the caller as though the +@ call had succeeded, and for an unrecognised number that means resuming with +@ the privilege state undefined. + +_tx_module_svc_unrecognized_loop: + B _tx_module_svc_unrecognized_loop + + +@/**************************************************************************/ +@/* SVC 1: leave User mode. */ +@/**************************************************************************/ + +_tx_module_svc_enter: + +@ Only the SVC inside the user mode entry function may do this. lr points one +@ instruction past the call, so the call site is lr minus four. A module that +@ executes SVC 1 from its own code fails here and stops. + + LDR r2, =_txm_system_mode_enter + SUB r1, lr, #4 + CMP r1, r2 + BNE _tx_module_svc_unrecognized + + LDR r1, =_tx_thread_current_ptr + LDR r2, [r1] @ The running thread + +@ Record that it is no longer in User mode, so a nested service call and the +@ scheduler both see the truth. + + MOV r1, #0 + STR r1, [r2, #THREAD_CUR_USER_MODE] + +@ Return into System mode rather than User mode. + + LDMFD sp!, {r0, r3} @ SPSR back off the stack + BIC r0, r0, #MODE_MASK + ORR r0, r0, #SYS_MODE_BITS + MSR SPSR_cxsf, r0 + +@ Swap stacks. The module's sp is saved so SVC 2 can restore it, and sp is set +@ to the top of the kernel stack, which the module's regions do not cover. +@ System mode shares User mode's banked sp, which is why the swap happens there. + + LDR r1, [r2, #THREAD_KSTACK_END] @ Top of the kernel stack + CPS #SYS_MODE_BITS + MOV r3, sp @ The module's own sp + MOV sp, r1 + CPS #SVC_MODE_BITS + STR r3, [r2, #THREAD_MSTACK_PTR] + +@ Point ThreadX's stack checking at the kernel stack while it is in use. +@ Without this a stack check would measure the kernel's sp against the module's +@ bounds and report an overflow that has not happened. + + LDR r3, [r2, #THREAD_KSTACK_START] + STR r3, [r2, #THREAD_STACK_START] + LDR r3, [r2, #THREAD_KSTACK_END] + STR r3, [r2, #THREAD_STACK_END] + LDR r3, [r2, #THREAD_KSTACK_SIZE] + STR r3, [r2, #THREAD_STACK_SIZE] + + LDMFD sp!, {r0-r3, r12, pc}^ @ Return, restoring CPSR from SPSR + + +@/**************************************************************************/ +@/* SVC 2: return to User mode. */ +@/**************************************************************************/ + +_tx_module_svc_exit: + +@ Same check, against the other call site. + + LDR r2, =_txm_system_mode_exit + SUB r1, lr, #4 + CMP r1, r2 + BNE _tx_module_svc_unrecognized + + LDR r1, =_tx_thread_current_ptr + LDR r2, [r1] + + MOV r1, #1 + STR r1, [r2, #THREAD_CUR_USER_MODE] + +@ Return into User mode. + + LDMFD sp!, {r0, r3} + BIC r0, r0, #MODE_MASK + ORR r0, r0, #USR_MODE_BITS + MSR SPSR_cxsf, r0 + +@ Put the module's own stack back. + + LDR r1, [r2, #THREAD_MSTACK_PTR] + CPS #SYS_MODE_BITS + MOV sp, r1 + CPS #SVC_MODE_BITS + +@ And its own bounds, for the same reason they were changed on the way in. + + LDR r3, [r2, #THREAD_MSTACK_START] + STR r3, [r2, #THREAD_STACK_START] + LDR r3, [r2, #THREAD_MSTACK_END] + STR r3, [r2, #THREAD_STACK_END] + LDR r3, [r2, #THREAD_MSTACK_SIZE] + STR r3, [r2, #THREAD_STACK_SIZE] + + LDMFD sp!, {r0-r3, r12, pc}^ diff --git a/ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_thread_stack_build.S b/ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_thread_stack_build.S new file mode 100644 index 000000000..69916ff08 --- /dev/null +++ b/ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_thread_stack_build.S @@ -0,0 +1,251 @@ +@/*************************************************************************** +@ * Copyright (c) 2024 Microsoft Corporation +@ * 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 +@ **************************************************************************/ +@ Some portions generated by Claude Code (Opus 5). +@ +@ +@/**************************************************************************/ +@/**************************************************************************/ +@/** */ +@/** ThreadX Component */ +@/** */ +@/** Thread */ +@/** */ +@/**************************************************************************/ +@/**************************************************************************/ +#ifdef TX_INCLUDE_USER_DEFINE_FILE +#include "tx_user.h" +#endif + + .syntax unified + .arm + +@ Bare CPSR mode field. See tx_thread_stack_build.S for why the _MODE_BITS +@ suffix is not optional in this port: a plain _MODE name is a whole CPSR value +@ with the interrupt masks in it. SVC is not among them -- no thread in a module +@ port runs in SVC mode, which is reserved for the supervisor call handler. + +USR_MODE_BITS = 0x10 @ User mode, unprivileged +SYS_MODE_BITS = 0x1F @ System mode, privileged +THUMB_MASK = 0x20 @ CPSR Thumb bit + +@ Offset of tx_thread_module_user_mode, checked against offsetof at compile time +@ in txm_module_manager_offset_check.c. + +THREAD_MODULE_USER_MODE = 0xA0 +#ifdef TX_ENABLE_FIQ_SUPPORT +CPSR_MASK = 0xDF @ Mask initial CPSR, IRQ & FIQ interrupts enabled +#else +CPSR_MASK = 0x9F @ Mask initial CPSR, IRQ interrupts enabled +#endif +@ +@ +@/* Define the 16-bit Thumb mode veneer for _txm_module_manager_thread_stack_build for +@ applications calling this function from to 16-bit Thumb mode. */ +@ + .text + .align 2 + .thumb + .global $_txm_module_manager_thread_stack_build + .type $_txm_module_manager_thread_stack_build,function +$_txm_module_manager_thread_stack_build: + BX pc @ Switch to 32-bit mode + NOP @ + .arm + STMFD sp!, {lr} @ Save return address + BL _txm_module_manager_thread_stack_build @ Call _txm_module_manager_thread_stack_build function + LDMFD sp!, {lr} @ Recover saved return address + BX lr @ Return to 16-bit caller +@ +@ + .text + .align 2 +@/**************************************************************************/ +@/* */ +@/* FUNCTION RELEASE */ +@/* */ +@/* _txm_module_manager_thread_stack_build Cortex-R52/GNU */ +@/* 6.5.2 */ +@/* AUTHOR */ +@/* */ +@/* Frédéric Desbiens, Eclipse Foundation */ +@/* */ +@/* Derived from the Cortex-R5/GNU port originally written by */ +@/* William E. Lamie, Microsoft Corporation. */ +@/* */ +@/* DESCRIPTION */ +@/* */ +@/* This function builds a stack frame on the supplied thread's stack. */ +@/* The stack frame results in a fake interrupt return to the supplied */ +@/* function pointer. */ +@/* */ +@/* INPUT */ +@/* */ +@/* thread_ptr Pointer to thread control blk */ +@/* function_ptr Pointer to return function */ +@/* */ +@/* OUTPUT */ +@/* */ +@/* None */ +@/* */ +@/* CALLS */ +@/* */ +@/* None */ +@/* */ +@/* CALLED BY */ +@/* */ +@/* _tx_thread_create Create thread service */ +@/* */ +@/**************************************************************************/ +@VOID _txm_module_manager_thread_stack_build(TX_THREAD *thread_ptr, VOID (*function_ptr)(VOID)) +@{ + .global _txm_module_manager_thread_stack_build + .type _txm_module_manager_thread_stack_build,function +_txm_module_manager_thread_stack_build: +@ +@ +@ /* Build a fake interrupt frame. The form of the fake interrupt stack +@ on the ARM9 should look like the following after it is built: +@ +@ Stack Top: 1 Interrupt stack frame type +@ CPSR Initial value for CPSR +@ a1 (r0) Initial value for a1 +@ a2 (r1) Initial value for a2 +@ a3 (r2) Initial value for a3 +@ a4 (r3) Initial value for a4 +@ v1 (r4) Initial value for v1 +@ v2 (r5) Initial value for v2 +@ v3 (r6) Initial value for v3 +@ v4 (r7) Initial value for v4 +@ v5 (r8) Initial value for v5 +@ sb (r9) Initial value for sb +@ sl (r10) Initial value for sl +@ fp (r11) Initial value for fp +@ ip (r12) Initial value for ip +@ lr (r14) Initial value for lr +@ pc (r15) Initial value for pc +@ 0 For stack backtracing +@ +@ Stack Bottom: (higher memory address) */ +@ +@ The thread entry information pointer, which _txm_module_manager_thread_create +@ parked in the stack pointer position of the control block for exactly this +@ purpose. It has to be read before the frame is built, because the initial +@ stack pointer is written over that same field further down. +@ +@ The module's shell entry takes two arguments -- the thread and this pointer -- +@ and everything the module needs to start is behind it: its own entry point, +@ its parameter, its data and code bases, and the callback queue. ThreadX's +@ thread shell passes only one argument, so the second one can only arrive as a +@ seeded register, which is what the two stores below are for. Left at zero, +@ as the base port's stack build leaves them, the shell entry dereferences NULL +@ on its first instruction and the module faults before it runs a line of its +@ own code. + + LDR r12, [r0, #8] @ Pickup thread entry info pointer +@ + LDR r2, [r0, #16] @ Pickup end of stack area + BIC r2, r2, #7 @ Ensure 8-byte alignment + SUB r2, r2, #76 @ Allocate space for the stack frame +@ +@ /* Actually build the stack frame. */ +@ + MOV r3, #1 @ Build interrupt stack type + STR r3, [r2, #0] @ Store stack type + STR r0, [r2, #8] @ Store initial r0, the thread pointer + STR r12, [r2, #12] @ Store initial r1, the entry info + MOV r3, #0 @ Build initial register value + STR r3, [r2, #16] @ Store initial r2 + STR r3, [r2, #20] @ Store initial r3 + STR r3, [r2, #24] @ Store initial r4 + STR r3, [r2, #28] @ Store initial r5 + STR r3, [r2, #32] @ Store initial r6 + STR r3, [r2, #36] @ Store initial r7 + STR r3, [r2, #40] @ Store initial r8 +@ +@ r9 is the module's PIC base, and seeding it is not optional for a module +@ built -fpic -msingle-pic-base. Every reference the module makes to one of +@ its own globals compiles to LDR rX, [r9, #offset] -- an offset into the +@ global offset table, measured from whatever r9 holds -- and -msingle-pic-base +@ is precisely the promise that nothing in the module will set r9 up, because +@ the caller already did. Here is the caller. +@ +@ The value is the module's data base, which is also where _gcc_setup puts the +@ GOT, because the compiler measures its offsets from the GOT origin and the +@ linker script puts the GOT first in the data segment for that reason. Offset +@ 8 in the thread entry info is txm_module_thread_entry_info_data_base_address, +@ whose declaration in txm_module.h carries the comment "Don't move this, +@ referenced in stack build to setup module data base register." This is the +@ reference it means. +@ +@ Left at zero, as the base port's stack build leaves it and as this port did +@ until now, every module data reference reads address 0 + a small offset. +@ Silicon showed exactly that: r9 was 0 in every fault captured on the S32Z280. +@ + LDR r3, [r12, #8] @ Pickup the module's data base + STR r3, [r2, #44] @ Store initial r9, the PIC base + LDR r3, [r0, #12] @ Pickup stack starting address + STR r3, [r2, #48] @ Store initial r10 (sl) + LDR r3,=_tx_thread_schedule @ Pickup address of _tx_thread_schedule for GDB backtrace + STR r3, [r2, #60] @ Store initial r14 (lr) + MOV r3, #0 @ Build initial register value + STR r3, [r2, #52] @ Store initial r11 + STR r3, [r2, #56] @ Store initial r12 + STR r1, [r2, #64] @ Store initial pc + STR r3, [r2, #68] @ 0 for back-trace +@ +@ /* The mode a module thread starts in is the whole point of this function +@ existing separately. A kernel thread starts in SVC mode; a module thread +@ starts in User mode when it asked for protection, and System mode when it +@ did not. Everything else about the frame is identical, which is why this +@ is derived from the port's own stack build rather than from another +@ architecture's module port. +@ +@ The flag is read from tx_thread_module_user_mode at 0xA0. The Cortex-R4 +@ module port reads it from 0x9C, which in this port is +@ tx_thread_module_current_user_mode -- a different field, holding whether +@ the thread is privileged right now rather than whether it should start +@ unprivileged. Copying that offset would have built cleanly and started +@ module threads in the wrong mode. */ +@ + MRS r3, CPSR @ Pickup CPSR + BIC r3, r3, #CPSR_MASK @ Mask mode bits of CPSR +@ +@ The state bit comes from bit 0 of the entry pointer, so the test has to +@ happen while r1 still holds it -- CPSR is staged in r3 and the user mode +@ flag is read into r1 afterwards, the same register allocation the +@ Cortex-R4 module port uses. The pointer stored as the initial PC above +@ is the unmasked one on purpose: on the A and R profiles the saved T bit +@ selects the state on exception return and the low bit of the restored PC +@ is ignored, so masking it would be pointless and clearing it would break +@ an interworking entry. +@ + TST r1, #1 @ Was a Thumb entry point requested? + ORRNE r3, r3, #THUMB_MASK @ Yes, start in Thumb state +@ + LDR r1, [r0, #THREAD_MODULE_USER_MODE] @ Pickup the requested user mode + TST r1, #1 + ORREQ r3, r3, #SYS_MODE_BITS @ Clear: privileged, System mode + ORRNE r3, r3, #USR_MODE_BITS @ Set: unprivileged, User mode + STR r3, [r2, #4] @ Store initial CPSR +@ +@ /* Setup stack pointer. */ +@ thread_ptr -> tx_thread_stack_ptr = r2; +@ + STR r2, [r0, #8] @ Save stack pointer in thread's + @ control block +#ifdef __THUMB_INTERWORK + BX lr @ Return to caller +#else + MOV pc, lr @ Return to caller +#endif +@} + + diff --git a/ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_user_mode_entry.S b/ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_user_mode_entry.S new file mode 100644 index 000000000..afc307b51 --- /dev/null +++ b/ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_user_mode_entry.S @@ -0,0 +1,133 @@ +@/*************************************************************************** +@ * 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. +@ * +@ * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +@ * The AI-generated portions may be considered public domain (CC0-1.0) +@ * and not subject to the project's licence. The human contributor has +@ * reviewed and verified that the code is correct. +@ * +@ * SPDX-License-Identifier: MIT and CC0-1.0 +@ **************************************************************************/ +@ +@/**************************************************************************/ +@/* */ +@/* MODULE MANAGER RELEASE */ +@/* */ +@/* txm_module_manager_user_mode_entry.S Cortex-R52/GNU */ +@/* 6.5.2 */ +@/* AUTHOR */ +@/* */ +@/* Frédéric Desbiens, Eclipse Foundation */ +@/* */ +@/* DESCRIPTION */ +@/* */ +@/* The only way a module reaches the kernel. */ +@/* */ +@/* A module runs in User mode and cannot execute kernel code or touch */ +@/* kernel memory. When it calls a ThreadX service, the call arrives */ +@/* here: SVC 1 raises privilege, the dispatch function performs the */ +@/* service, SVC 2 drops back to User mode, and the module continues. */ +@/* */ +@/* This function is the entire privileged surface a module can see. */ +@/* It gets an MPU region of its own -- the one at */ +@/* TXM_MODULE_MPU_KERNEL_ENTRY_INDEX -- because a module must be able */ +@/* to execute these few instructions and nothing else on that side of */ +@/* the boundary. Everything the module is allowed to ask for is */ +@/* decided inside _txm_module_manager_kernel_dispatch, in kernel */ +@/* memory the module cannot reach. */ +@/* */ +@/* SVC 1 and SVC 2 are handled by the port's supervisor call vector. */ +@/* */ +@/* CALLS */ +@/* */ +@/* SVC 1 Leave User mode */ +@/* _txm_module_manager_kernel_dispatch Perform the service */ +@/* SVC 2 Return to User mode */ +@/* */ +@/* CALLED BY */ +@/* */ +@/* Modules in User mode */ +@/* */ +@/**************************************************************************/ + + .arm + +@ Its own section, placed after __code_end__ by the linker script, so that this +@ function sits OUTSIDE the kernel's code region. +@ +@ It has to. A module runs in User mode and the kernel code region grants no +@ EL0 access, so the module needs a region of its own covering these +@ instructions -- and PMSAv8-R has no region priority, so that region must not +@ overlap the kernel's. An access that hits more than one enabled region takes +@ a translation fault (TRM 8.1); the abort is specified, not a part-specific +@ resolution of unpredictable behaviour. With this function still inside +@ .text, the first memory access after a module's regions were loaded took a +@ data abort in the scheduler. +@ +@ Nothing else may share the section, because whatever does becomes executable +@ by every module. + + .section .txm_user_entry, "ax", %progbits + +@ 64-byte aligned, which is the PMSAv8-R granule and all that is needed here. +@ +@ The Cortex-R4 module port aligns this to 4 KB, and has to: PMSAv7 regions must +@ be a power of two in size and aligned to their own size, so the smallest +@ region that can cover this function without also covering its neighbours is a +@ page. A base and limit pair has no such constraint, so the kernel entry +@ region can be sized to these instructions and stop. That matters for +@ isolation rather than for memory: on PMSAv7 whatever else shares the page is +@ inside the one region a module is allowed to execute. + + .align 6 + + .global _txm_module_manager_user_mode_entry + .global _txm_module_manager_user_mode_entry_end + +@ The supervisor call handler compares the faulting lr against these two, to +@ refuse an SVC 1 or SVC 2 raised from anywhere else. They have to be visible +@ outside this file for that check to link, which also means they are the two +@ addresses the whole privilege boundary rests on. + + .global _txm_system_mode_enter + .global _txm_system_mode_exit + .extern _txm_module_manager_kernel_dispatch + + .type _txm_module_manager_user_mode_entry, %function +_txm_module_manager_user_mode_entry: + +_txm_system_mode_enter: + +@ Leave User mode. The supervisor call vector recognises 1 and raises the +@ thread to privileged mode on its kernel stack. + + SVC 1 + +_txm_module_priv: + +@ Privileged now. r3 is pushed alongside lr only to keep the stack eight-byte +@ aligned, which the ABI requires at a public interface. + + PUSH {r3, lr} + BL _txm_module_manager_kernel_dispatch + POP {r3, lr} + +_txm_system_mode_exit: + +@ Back to User mode before returning to the module. If this were skipped the +@ module would resume privileged, which is the whole protection gone -- so it is +@ unconditional and sits between the dispatch and every return path. + + SVC 2 + + BX lr + +@ Marks the end of the region a module is allowed to execute, so the region can +@ be sized to this function rather than rounded up to something larger. + +_txm_module_manager_user_mode_entry_end: + NOP From b37cd4a81a1cb8c2ebefc438220ab7f009e13362 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Wed, 23 Sep 2026 16:52:44 -0400 Subject: [PATCH 150/181] Fixed RISC-V regression portability failures (#773) RISC-V regression builds ran only at -O0, leaving a timer callback counter that spins forever at -O2. The trace regression was excluded because it referenced a port-specific interrupt-save variable, and its adjacent pools could start misaligned on RV64. Made the timer counter volatile, gave the trace test aligned pool storage and a portable saved-interrupt value, and enabled it on RISC-V. Added an -O2 QEMU configuration to keep the optimized failure covered. CMake/Ninja/QEMU: RV64 default, optimized and trace suites passed 97/97 each; RV32 passed 96/96 each. Two ISR event tests passed 30 repeats each at -O2. The Linux/GCC 14 trace test passed. The reported timing resonance did not recur. Assisted-by: Codex (gpt-6-sol) --- test/tx/cmake/riscv/CMakeLists.txt | 11 ++++- test/tx/cmake/riscv/regression/CMakeLists.txt | 4 +- ...ad_multi_level_preemption_threshold_test.c | 4 +- test/tx/regression/threadx_trace_basic_test.c | 45 +++++++++++-------- 4 files changed, 40 insertions(+), 24 deletions(-) diff --git a/test/tx/cmake/riscv/CMakeLists.txt b/test/tx/cmake/riscv/CMakeLists.txt index a4f7e7e84..41b44949d 100644 --- a/test/tx/cmake/riscv/CMakeLists.txt +++ b/test/tx/cmake/riscv/CMakeLists.txt @@ -5,7 +5,7 @@ cmake_policy(SET CMP0057 NEW) project(threadx_riscv_test LANGUAGES C ASM) # Build configurations (same defines as Linux tests, minus coverage instrumentation) -set(BUILD_CONFIGURATIONS default_build disable_notify_callbacks_build +set(BUILD_CONFIGURATIONS default_build optimized_build disable_notify_callbacks_build stack_checking_build stack_checking_rand_fill_build trace_build) set(CMAKE_CONFIGURATION_TYPES ${BUILD_CONFIGURATIONS} @@ -26,14 +26,21 @@ message(STATUS "THREADX_ARCH: ${THREADX_ARCH}") # Per-configuration compile definitions set(default_build -DTX_QUEUE_MESSAGE_MAX_SIZE=32) +set(optimized_build -DTX_QUEUE_MESSAGE_MAX_SIZE=32) set(disable_notify_callbacks_build -DTX_QUEUE_MESSAGE_MAX_SIZE=32 -DTX_DISABLE_NOTIFY_CALLBACKS) set(stack_checking_build -DTX_QUEUE_MESSAGE_MAX_SIZE=32 -DTX_ENABLE_STACK_CHECKING) set(stack_checking_rand_fill_build -DTX_QUEUE_MESSAGE_MAX_SIZE=32 -DTX_ENABLE_STACK_CHECKING -DTX_ENABLE_RANDOM_NUMBER_STACK_FILLING) set(trace_build -DTX_QUEUE_MESSAGE_MAX_SIZE=32 -DTX_ENABLE_EVENT_TRACE) +if(CMAKE_BUILD_TYPE STREQUAL "optimized_build") + set(REGRESSION_OPTIMIZATION -O2) +else() + set(REGRESSION_OPTIMIZATION -O0) +endif() + add_compile_options( -std=c99 - -O0 + ${REGRESSION_OPTIMIZATION} -g3 -fdiagnostics-color -Werror diff --git a/test/tx/cmake/riscv/regression/CMakeLists.txt b/test/tx/cmake/riscv/regression/CMakeLists.txt index 3db2eeec5..b15247ffb 100644 --- a/test/tx/cmake/riscv/regression/CMakeLists.txt +++ b/test/tx/cmake/riscv/regression/CMakeLists.txt @@ -110,9 +110,7 @@ set(regression_test_cases ${SOURCE_DIR}/threadx_timer_multiple_accuracy_test.c ${SOURCE_DIR}/threadx_timer_multiple_test.c ${SOURCE_DIR}/threadx_timer_simple_test.c - # threadx_trace_basic_test.c excluded: references tx_saved_posture - # (the Linux port's interrupt save variable) which is named - # interrupt_save on RISC-V. + ${SOURCE_DIR}/threadx_trace_basic_test.c ) # Architecture specific tests living next to this file. The RV32 stack diff --git a/test/tx/regression/threadx_thread_multi_level_preemption_threshold_test.c b/test/tx/regression/threadx_thread_multi_level_preemption_threshold_test.c index 59ed4f4d4..f71593843 100644 --- a/test/tx/regression/threadx_thread_multi_level_preemption_threshold_test.c +++ b/test/tx/regression/threadx_thread_multi_level_preemption_threshold_test.c @@ -9,6 +9,8 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /* This test is designed to test multi-level preemption threshold. The protection placed by a thread must be preserved after higher-priority thread preemption that is above the threshold. */ @@ -74,7 +76,7 @@ static TX_TIMER timer_0; /* Define counters. */ -static unsigned long timer_0_counter = 0; +static volatile unsigned long timer_0_counter = 0; static unsigned long thread_1_0_counter = 0; static unsigned long thread_2_1_counter = 0; static unsigned long thread_3_2_counter = 0; diff --git a/test/tx/regression/threadx_trace_basic_test.c b/test/tx/regression/threadx_trace_basic_test.c index c40be8f18..19f6953be 100644 --- a/test/tx/regression/threadx_trace_basic_test.c +++ b/test/tx/regression/threadx_trace_basic_test.c @@ -9,6 +9,8 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /* This test is designed to test trace functionality in ThreadX. */ @@ -66,6 +68,16 @@ static unsigned long error = 0; static unsigned long full_buffer = 0; static void *save_pointer; +#define TRACE_BLOCK_POOL_SIZE ((ULONG) (((100U + sizeof(ALIGN_TYPE) - 1U) / sizeof(ALIGN_TYPE)) * sizeof(ALIGN_TYPE))) +#define TRACE_BYTE_POOL_SIZE ((ULONG) (((1000U + sizeof(ALIGN_TYPE) - 1U) / sizeof(ALIGN_TYPE)) * sizeof(ALIGN_TYPE))) + +/* Keep pool storage aligned for ports with pointer-wide metadata. */ +static struct +{ + ALIGN_TYPE alignment; + CHAR bytes[TRACE_BLOCK_POOL_SIZE + TRACE_BYTE_POOL_SIZE + 400U]; +} object_memory; + #if defined(TX_WIN32_MEMORY_SIZE) || defined(TX_LINUX_MEMORY_SIZE) static FILE *trace_dump_file; @@ -185,25 +197,21 @@ INT status; CHAR *pointer; - /* Setup a pointer. */ - pointer = (CHAR *) first_unused_memory; - - /* Adjust it forward just to make sure there is some space for the test below. */ - pointer = pointer + 200; + /* Setup aligned object storage. */ + pointer = object_memory.bytes; /* Create a bunch of objects before being enabled. */ /* Create a timer for the test. */ save_pointer = (void *) pointer; tx_timer_create(&timer_0, "timer 0", timer_entry, 0, 2, 2, TX_AUTO_ACTIVATE); - tx_block_pool_create(&block_pool_0, "block pool 0", 20, pointer, 100); - pointer = pointer + 100; - tx_byte_pool_create(&byte_pool_0, "byte pool 0", pointer, 1000); - pointer = pointer + 1000; + tx_block_pool_create(&block_pool_0, "block pool 0", 20, pointer, TRACE_BLOCK_POOL_SIZE); + pointer = pointer + TRACE_BLOCK_POOL_SIZE; + tx_byte_pool_create(&byte_pool_0, "byte pool 0", pointer, TRACE_BYTE_POOL_SIZE); + pointer = pointer + TRACE_BYTE_POOL_SIZE; tx_event_flags_create(&group_0, "event flags group 0"); tx_mutex_create(&mutex_0, "mutex 0", TX_NO_INHERIT); tx_queue_create(&queue_0, "queue 0", 16, pointer, 400); - pointer = pointer + 400; tx_semaphore_create(&semaphore_0, "semaphore 0", 1); /* Enable event tracing. */ @@ -230,6 +238,9 @@ CHAR *pointer; } #endif + pointer = (CHAR *) first_unused_memory; + pointer = pointer + 200; + /* Put system definition stuff in here, e.g. thread creates and other assorted create information. */ @@ -281,12 +292,11 @@ static void thread_0_entry(ULONG thread_input) UINT status; UINT old_interrupt; CHAR *pointer; -TX_INTERRUPT_SAVE_AREA ULONG object; /* Coverage for build without TraceX enabled. */ - tx_saved_posture = _tx_trace_interrupt_control(TX_INT_DISABLE); - _tx_trace_interrupt_control(tx_saved_posture); + old_interrupt = _tx_trace_interrupt_control(TX_INT_DISABLE); + _tx_trace_interrupt_control(old_interrupt); #ifndef TX_ENABLE_EVENT_TRACE _tx_trace_object_register(0, TX_NULL, TX_NULL, 0, 0); _tx_trace_object_register(1, TX_NULL, TX_NULL, 0, 0); @@ -354,14 +364,13 @@ ULONG object; /* Now, create them all again. */ pointer = (CHAR *) save_pointer; - tx_block_pool_create(&block_pool_0, "block pool 0", 20, pointer, 100); - pointer = pointer + 100; - tx_byte_pool_create(&byte_pool_0, "byte pool 0", pointer, 1000); - pointer = pointer + 1000; + tx_block_pool_create(&block_pool_0, "block pool 0", 20, pointer, TRACE_BLOCK_POOL_SIZE); + pointer = pointer + TRACE_BLOCK_POOL_SIZE; + tx_byte_pool_create(&byte_pool_0, "byte pool 0", pointer, TRACE_BYTE_POOL_SIZE); + pointer = pointer + TRACE_BYTE_POOL_SIZE; tx_event_flags_create(&group_0, "event flags group 0"); tx_mutex_create(&mutex_0, "mutex 0", TX_NO_INHERIT); tx_queue_create(&queue_0, "queue 0", 16, pointer, 400); - pointer = pointer + 400; tx_semaphore_create(&semaphore_0, "semaphore 0", 1); /* Attempt to enable event tracing again. */ From d55fe1ef2f9e512439c9b1147204683e7feeeafa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 28 Sep 2026 07:28:23 -0400 Subject: [PATCH 151/181] Stopped the release script adding a Co-authored-by trailer (#777) prepare_release.sh committed the version passes with a Co-authored-by trailer naming an AI. That trailer asserts authorship an AI cannot hold: the human contributor signs the ECA and is solely responsible for the contribution. It is already in the published history, on the 6.5.1.202602 and 6.5.1.202602a preparations. The commits now carry their subject alone. A version pass is mechanical sed output, so no agent produces it at run time; an agent that runs the script records its own Assisted-by trailer on that run instead. The script also gains the AI disclosure line it was missing. Ran the patched script against a scratch clone targeting 6.5.2.202603. Both commits come out with an empty trailer block, the version constants and 211 port version strings update as before, and check_ports.sh passes. Assisted-by: Claude Code (Opus 5) --- scripts/prepare_release.sh | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/scripts/prepare_release.sh b/scripts/prepare_release.sh index c6b1d93c4..0c4536670 100755 --- a/scripts/prepare_release.sh +++ b/scripts/prepare_release.sh @@ -15,6 +15,7 @@ # # Copyright (C) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT +# Portions of this file were generated with AI assistance. set -eu @@ -134,8 +135,6 @@ sed -i -E "s|(#define THREADX_HOTFIX_VERSION[[:space:]]+)'[^']*'|\1${HOTFIX_DEFI git -C "${REPO_ROOT}" add "${API_HEADER}" git -C "${REPO_ROOT}" commit -F - <<'COMMIT_EOF' Updated version number constants - -Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> COMMIT_EOF printf "Committed version constant updates.\n" @@ -175,8 +174,6 @@ EOF else git -C "${REPO_ROOT}" commit -F - <<'COMMIT_EOF' Updated port version strings - -Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> COMMIT_EOF printf "Committed port version string updates.\n" fi From 7495b0237459ca703ff86cc27a8a975c0f0292f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 28 Sep 2026 09:08:55 -0400 Subject: [PATCH 152/181] Merge commit from fork A memory-protected module names the kernel objects it wants operated on by address, and the Module Manager decided whether a privileged service could dereference that address by asking only whether it fell outside the module. The object pool is outside every module, so that test was satisfied by an address shifted into the interior of one of the module's own privileged allocations, which denotes no object at all. The bytes such an address presents as a control block are bytes the module put there through ordinary create and set services, so the control block ID at the front of them could be made to read as any type the module chose, and the _txe_ layer's ID test then agreed. A module could therefore have the kernel read and write fields of an object that does not exist, at an address it picked; the reported chain reaches a privileged memset across an attacker-chosen range that way. Authentication now answers the question the location test could not: is this the exact address of a live kernel object of the type this service expects. It is answered from the kernel's created list for the type, which the create and delete services maintain, so membership establishes at once that the address is an object start rather than an address inside an object, that the object is of this type, and that it has not been deleted. That list is also what makes an object the application created and shared with a module authenticable at all, since the manager allocated no such object and has no record of its own to consult, so sharing keeps working and needs no new registration API. Nothing a module can influence is used to establish a type. An earlier form of this fix accepted an address that was the exact start of one of the calling module's own allocations of the right size and then took the type from the control block ID, which is cheaper -- a module's allocation list is much shorter than the system's created list for a type. The tests here refused it: a byte pool, a mutex and a timer are all the same size on a 32-bit target, so an allocation created as one of them and presented as another passed both the address and the size test, leaving the ID as the only thing between the module and a type confusion. The ID is still checked, after the created list has settled the question, because it is the test the _txe_ services make and it is compiled away with them under TX_DISABLE_ERROR_CHECKING. An address a module named is not read at all until a kernel record says there is an object there. All 58 object-using dispatchers now pass the object type rather than a control block size, since a size cannot establish a type. Both scans are bounded by the counts the kernel and the manager maintain beside their lists, so the cost of one check is bounded and a list whose links have been damaged cannot make a scan run on, and both run with interrupts disabled, which is the protection those lists are maintained under and which adds no blocking point or priority inversion to a kernel request. The cost is a walk of the created list for the type, paid only by memory-protected modules; the size-based check is kept for dispatchers outside this repository and hardened to refuse object pool interiors, which is the part of the attack it can see without a type. Two further changes close paths the authentication alone would leave open. Thread reset now refuses a thread that carries no module instance: such a thread is authentic, can be found by name and satisfies reset's own state test, and reset reads the shell entry function out of that instance, so a null one was followed in privileged mode. Object deallocation now clears the control block ID as it gives memory back, so an object freed without being deleted first stops being vouched for at the moment the manager stops owning its memory, rather than returning to the pool still carrying a valid ID for the next allocation placed there to present. The 120 expectations in the new test offer every aligned interior offset of a legitimate object as a foreign type, with that type's own ID planted at the offset, and assert that none is accepted; they cover all eight object types against each other, uncreated allocations, deleted objects, freed addresses that have been handed out again, objects the application owns and memory that merely carries a plausible ID, objects another module allocated, and the bounds on both scans. Reverting the object checks to the permissive policy fails 89 of them; removing the thread reset guard makes the test die with SIGSEGV inside the reset path; removing the ID clearing in deallocation fails 2. All 99 tests pass in each of the five configurations the tree builds with GCC 14. Assisted-by: Claude Code (Opus 5) --- .../inc/txm_module_manager_dispatch.h | 118 +- .../inc/txm_module_manager_util.h | 30 +- .../txm_module_manager_object_deallocate.c | 23 + .../src/txm_module_manager_thread_reset.c | 16 + .../src/txm_module_manager_util.c | 814 +++++++++++- test/tx/cmake/module_manager/CMakeLists.txt | 25 + ...odule_manager_object_authentication_test.c | 1133 +++++++++++++++++ 7 files changed, 2098 insertions(+), 61 deletions(-) create mode 100644 test/tx/module_manager/threadx_module_manager_object_authentication_test.c diff --git a/common_modules/module_manager/inc/txm_module_manager_dispatch.h b/common_modules/module_manager/inc/txm_module_manager_dispatch.h index 3763d35db..9c0e5d212 100644 --- a/common_modules/module_manager/inc/txm_module_manager_dispatch.h +++ b/common_modules/module_manager/inc/txm_module_manager_dispatch.h @@ -10,6 +10,8 @@ **************************************************************************/ // Portions of this file were generated with AI assistance. +// Some portions generated by Claude Code (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -34,7 +36,7 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_BLOCK_POOL))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_BLOCK_POOL_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(VOID *))) @@ -102,7 +104,7 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_BLOCK_POOL))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_BLOCK_POOL_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); } @@ -136,7 +138,7 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_BLOCK_POOL))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_BLOCK_POOL_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(CHAR *))) @@ -189,7 +191,7 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_BLOCK_POOL))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_BLOCK_POOL_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(ULONG))) @@ -270,7 +272,7 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_BLOCK_POOL))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_BLOCK_POOL_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); } @@ -336,7 +338,7 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_BYTE_POOL))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_BYTE_POOL_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(VOID *))) @@ -406,7 +408,7 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_BYTE_POOL))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_BYTE_POOL_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); } @@ -440,7 +442,7 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_BYTE_POOL))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_BYTE_POOL_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(CHAR *))) @@ -496,7 +498,7 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_BYTE_POOL))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_BYTE_POOL_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(ULONG))) @@ -604,7 +606,7 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_BYTE_POOL))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_BYTE_POOL_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); } @@ -696,7 +698,7 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_EVENT_FLAGS_GROUP))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_EVENT_FLAGS_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); } @@ -728,7 +730,7 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_EVENT_FLAGS_GROUP))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_EVENT_FLAGS_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, extra_parameters[1], sizeof(ULONG))) @@ -765,7 +767,7 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_EVENT_FLAGS_GROUP))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_EVENT_FLAGS_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(CHAR *))) @@ -814,7 +816,7 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_EVENT_FLAGS_GROUP))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_EVENT_FLAGS_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(ULONG))) @@ -897,7 +899,7 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_EVENT_FLAGS_GROUP))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_EVENT_FLAGS_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); } @@ -924,7 +926,7 @@ VOID (*events_set_notify)(TX_EVENT_FLAGS_GROUP *); if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_EVENT_FLAGS_GROUP))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_EVENT_FLAGS_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); /* Since we need to write to the object, ensure it's valid. */ @@ -1001,7 +1003,7 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_MUTEX))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_MUTEX_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); } @@ -1030,7 +1032,7 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_MUTEX))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_MUTEX_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); } @@ -1059,7 +1061,7 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_MUTEX))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_MUTEX_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(CHAR *))) @@ -1114,7 +1116,7 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_MUTEX))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_MUTEX_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(ULONG))) @@ -1213,7 +1215,7 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_MUTEX))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_MUTEX_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); } @@ -1235,7 +1237,7 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_MUTEX))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_MUTEX_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); } @@ -1298,7 +1300,7 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_QUEUE))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_QUEUE_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); } @@ -1326,7 +1328,7 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_QUEUE))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_QUEUE_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); } @@ -1351,7 +1353,7 @@ TX_QUEUE *queue_ptr; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_QUEUE))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_QUEUE_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); /* We need to get the size of the message from the queue. */ @@ -1386,7 +1388,7 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_QUEUE))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_QUEUE_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(CHAR *))) @@ -1441,7 +1443,7 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_QUEUE))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_QUEUE_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(ULONG))) @@ -1540,7 +1542,7 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_QUEUE))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_QUEUE_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); } @@ -1565,7 +1567,7 @@ TX_QUEUE *queue_ptr; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_QUEUE))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_QUEUE_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); /* We need to get the max size of the buffer from the queue. */ @@ -1597,7 +1599,7 @@ TX_QUEUE *queue_ptr; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_QUEUE))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_QUEUE_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); /* We need to get the size of the message from the queue. */ @@ -1629,7 +1631,7 @@ VOID (*queue_send_notify)(TX_QUEUE *); if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_QUEUE))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_QUEUE_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); /* Since we need to write to the object, ensure it's valid. */ @@ -1673,7 +1675,7 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_SEMAPHORE))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_SEMAPHORE_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); } @@ -1730,7 +1732,7 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_SEMAPHORE))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_SEMAPHORE_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); } @@ -1759,7 +1761,7 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_SEMAPHORE))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_SEMAPHORE_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); } @@ -1787,7 +1789,7 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_SEMAPHORE))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_SEMAPHORE_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(CHAR *))) @@ -1836,7 +1838,7 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_SEMAPHORE))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_SEMAPHORE_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(ULONG))) @@ -1917,7 +1919,7 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_SEMAPHORE))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_SEMAPHORE_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); } @@ -1939,7 +1941,7 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_SEMAPHORE))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_SEMAPHORE_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); } @@ -1964,7 +1966,7 @@ VOID (*semaphore_put_notify)(TX_SEMAPHORE *); if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_SEMAPHORE))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_SEMAPHORE_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); /* Since we need to write to the object, ensure it's valid. */ @@ -2071,7 +2073,7 @@ ALIGN_TYPE stack_status; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_THREAD))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_THREAD_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); } @@ -2121,7 +2123,7 @@ VOID (*thread_entry_exit_notify)(TX_THREAD *, UINT); if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_THREAD))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_THREAD_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); /* Since we need to write to the object, ensure it's valid. */ @@ -2188,7 +2190,7 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_THREAD))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_THREAD_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(CHAR *))) @@ -2274,7 +2276,7 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_THREAD))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_THREAD_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(ULONG))) @@ -2421,7 +2423,7 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_THREAD))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_THREAD_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_2, sizeof(UINT))) @@ -2455,7 +2457,7 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_THREAD))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_THREAD_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_2, sizeof(UINT))) @@ -2492,7 +2494,7 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_THREAD))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_THREAD_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); } @@ -2514,7 +2516,7 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_THREAD))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_THREAD_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); } @@ -2571,7 +2573,7 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_THREAD))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_THREAD_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); } @@ -2600,7 +2602,7 @@ TX_THREAD *thread_ptr; { return(TXM_MODULE_INVALID_MEMORY); } - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_THREAD))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_THREAD_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); } @@ -2650,7 +2652,7 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_THREAD))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_THREAD_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); } @@ -2674,7 +2676,7 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_THREAD))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_THREAD_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_2, sizeof(ULONG))) @@ -2701,7 +2703,7 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_THREAD))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_THREAD_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); } @@ -2749,7 +2751,7 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_TIMER))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_TIMER_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); } @@ -2773,7 +2775,7 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_TIMER))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_TIMER_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); } @@ -2870,7 +2872,7 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_TIMER))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_TIMER_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); } @@ -2892,7 +2894,7 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_TIMER))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_TIMER_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); } @@ -2925,7 +2927,7 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_TIMER))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_TIMER_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(CHAR *))) @@ -2975,7 +2977,7 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, param_0, sizeof(TX_TIMER))) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_TIMER_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_1, sizeof(ULONG))) diff --git a/common_modules/module_manager/inc/txm_module_manager_util.h b/common_modules/module_manager/inc/txm_module_manager_util.h index 45c7f4098..77631beaa 100644 --- a/common_modules/module_manager/inc/txm_module_manager_util.h +++ b/common_modules/module_manager/inc/txm_module_manager_util.h @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Claude Code (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -89,10 +91,31 @@ ((TXM_MODULE_MANAGER_ENSURE_INSIDE_MODULE_DATA(module_instance, buffer_ptr, buffer_size)) || \ ((void *) (buffer_ptr) == TX_NULL)) -/* Kernel objects should be outside the module at the very least. */ +/* Kernel objects a module names must be authenticated before a privileged service is + allowed to dereference them. Being outside the module is necessary but nowhere near + sufficient: the manager's object pool is outside every module, so an address shifted + into the interior of one of the module's own privileged allocations satisfies that + test while denoting no object at all. Authentication answers the question the + location test cannot -- is this the exact address of a live kernel object of the type + this service expects -- and it answers it from manager and kernel bookkeeping rather + than from fields of the purported object, which a module can influence. + + TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE is the complete check and is what + the dispatch table uses. It is given the object type rather than a control block size + so that it can also establish the type, which a size cannot: distinct object types of + equal size exist. + + TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE is retained for dispatchers outside this + repository that pass a size. It authenticates addresses in the manager's object pool, + which is what the shifted-pointer attack needs, but without a type it can neither + establish the type nor authenticate an application-owned object, so in-repository code + should use the typed form. */ #define TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_USE(module_instance, obj_ptr, obj_size) \ (_txm_module_manager_param_check_object_for_use(module_instance, obj_ptr, obj_size)) +#define TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, obj_ptr, obj_type) \ + (_txm_module_manager_param_check_typed_object_for_use(module_instance, obj_ptr, obj_type)) + /* When creating an object, the object must be inside the object pool. */ #define TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_CREATION(module_instance, obj_ptr, obj_size) \ (_txm_module_manager_param_check_object_for_creation(module_instance, obj_ptr, obj_size)) @@ -122,6 +145,11 @@ UINT _txm_module_manager_object_name_compare(CHAR *object_name1, UINT object_ UCHAR _txm_module_manager_created_object_check(TXM_MODULE_INSTANCE *module_instance, void *object_ptr); UINT _txm_module_manager_param_check_object_for_creation(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE object_ptr, ULONG object_size); UINT _txm_module_manager_param_check_object_for_use(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE object_ptr, ULONG object_size); +UINT _txm_module_manager_param_check_typed_object_for_use(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE object_ptr, UINT object_type); +UINT _txm_module_manager_allocated_object_check(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE object_ptr, ULONG object_size); +UINT _txm_module_manager_object_type_size_get(UINT object_type, ULONG *object_size); +UINT _txm_module_manager_created_object_type_check(ALIGN_TYPE object_ptr, UINT object_type); +UINT _txm_module_manager_object_id_check(ALIGN_TYPE object_ptr, UINT object_type); UINT _txm_module_manager_util_code_allocation_size_and_alignment_get(TXM_MODULE_PREAMBLE *module_preamble, ULONG *code_alignment_dest, ULONG *code_allocation_size_dest); #endif diff --git a/common_modules/module_manager/src/txm_module_manager_object_deallocate.c b/common_modules/module_manager/src/txm_module_manager_object_deallocate.c index 95e28e4d6..c34a0005f 100644 --- a/common_modules/module_manager/src/txm_module_manager_object_deallocate.c +++ b/common_modules/module_manager/src/txm_module_manager_object_deallocate.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Claude Code (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -125,6 +127,27 @@ UINT return_value; } } + /* Clear the first word of the object being given back, which for every kernel + object is its control block ID. + + Object authentication reads that ID to establish the type of an object and + that it is still created, having first established that the address is the + exact start of an allocation. The kernel clears the ID when it deletes an + object, so the ordinary sequence of delete and then deallocate has already + cleared it. What has not is a deallocation of an object that was never + deleted: the memory returns to the pool still carrying a valid ID, and the + next allocation to be placed there is a raw allocation that presents one. + Clearing it here means the manager stops vouching for a control block at + the moment it stops owning the memory, whatever order the module chose. + + An allocation too small to hold an ID cannot be presenting one, and is + left alone rather than written past its end. */ + if (module_allocated_object_ptr -> txm_module_object_size >= ((ULONG) sizeof(ULONG))) + { + + *((ULONG *) object_ptr) = TX_CLEAR_ID; + } + /* Release the object memory. */ return_value = (ULONG) _txe_byte_release((VOID *) module_allocated_object_ptr); } diff --git a/common_modules/module_manager/src/txm_module_manager_thread_reset.c b/common_modules/module_manager/src/txm_module_manager_thread_reset.c index 75dd4a495..1a33964e4 100644 --- a/common_modules/module_manager/src/txm_module_manager_thread_reset.c +++ b/common_modules/module_manager/src/txm_module_manager_thread_reset.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Claude Code (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -106,6 +108,20 @@ TXM_MODULE_THREAD_ENTRY_INFO *thread_entry_info; status = TX_NOT_DONE; } } + + /* Resetting a thread means rebuilding its stack around a module's shell entry + function, so the thread has to be one a module manager created. A thread the + application created carries no module instance, and the fields this function + goes on to read from it -- the shell entry function it builds the new stack + frame around -- would be read through a null pointer in privileged mode. A + module can name such a thread: any thread the system created can be found by + name, and one that has run to completion satisfies the state test above. */ + if (thread_ptr -> tx_thread_module_instance_ptr == TX_NULL) + { + + /* Not a module thread, so there is nothing here to reset. */ + status = TX_NOT_DONE; + } } /* Is the request valid? */ diff --git a/common_modules/module_manager/src/txm_module_manager_util.c b/common_modules/module_manager/src/txm_module_manager_util.c index 78031b5fc..1b60f9000 100644 --- a/common_modules/module_manager/src/txm_module_manager_util.c +++ b/common_modules/module_manager/src/txm_module_manager_util.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Claude Code (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -25,6 +27,15 @@ #define TX_SOURCE_CODE +#include "tx_api.h" +#include "tx_thread.h" +#include "tx_timer.h" +#include "tx_queue.h" +#include "tx_event_flags.h" +#include "tx_semaphore.h" +#include "tx_mutex.h" +#include "tx_block_pool.h" +#include "tx_byte_pool.h" #include "txm_module.h" #include "txm_module_manager_util.h" @@ -461,14 +472,40 @@ UINT _txm_module_manager_param_check_object_for_use(TXM_MODULE_INSTANCE *modu return(TX_FALSE); } - /* Determine if the object pointer is inside the module object pool. */ + /* Determine if the object is outside the calling module. */ if (TXM_MODULE_MANAGER_ENSURE_OUTSIDE_MODULE(module_instance, object_ptr, object_size) == TX_FALSE) { - /* Object pointer is not inside the object pool, which is invalid. */ + /* Object pointer is not outside the module, which is invalid. */ return(TX_FALSE); } + /* Being outside the module does not make an address an object. The manager's + object pool is outside every module, so an address shifted into the interior of + one of this module's own privileged allocations satisfies the test above while + denoting no object at all, and the bytes the shifted address then presents as a + control block are bytes the module chose through ordinary create and set + services. An address in the object pool is therefore only usable if it is the + exact address the manager handed out for an allocation of this size. + + This function is given a size rather than a type, so it can go no further than + that: it cannot establish which type of object it is, and it cannot authenticate + an application-owned object outside the pool. Dispatchers in this repository use + _txm_module_manager_param_check_typed_object_for_use, which does both. */ + if ((_txm_module_manager_object_pool_created == TX_TRUE) && + (object_ptr >= (ALIGN_TYPE) _txm_module_manager_object_pool.tx_byte_pool_start) && + (object_ptr < (ALIGN_TYPE) (_txm_module_manager_object_pool.tx_byte_pool_start + _txm_module_manager_object_pool.tx_byte_pool_size))) + { + + if (_txm_module_manager_allocated_object_check(module_instance, object_ptr, object_size) == TX_FALSE) + { + + /* An address in the object pool that is not the exact start of one of this + module's allocations, which is invalid. */ + return(TX_FALSE); + } + } + /* Define application-specific object memory check. */ #ifdef TXM_MODULE_MANGER_APPLICATION_VALID_OBJECT_MEMORY_CHECK @@ -481,6 +518,779 @@ UINT _txm_module_manager_param_check_object_for_use(TXM_MODULE_INSTANCE *modu } +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txm_module_manager_object_type_size_get PORTABLE C */ +/* 6.4.3 */ +/* AUTHOR */ +/* */ +/* Eclipse ThreadX contributors */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns the size of the control block belonging to a */ +/* module object type. It is the size a service of that type is */ +/* entitled to dereference, and the size the manager recorded when it */ +/* allocated object memory for that type. */ +/* */ +/* INPUT */ +/* */ +/* object_type Module object type */ +/* object_size Destination for the control block */ +/* size of that type */ +/* */ +/* OUTPUT */ +/* */ +/* TX_TRUE Known object type */ +/* TX_FALSE Unknown object type */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _txm_module_manager_param_check_typed_object_for_use */ +/* Module object authentication */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-2026 Eclipse ThreadX Initial Version 6.4.3 */ +/* contributors */ +/* */ +/**************************************************************************/ +UINT _txm_module_manager_object_type_size_get(UINT object_type, ULONG *object_size) +{ + +UINT status; + + + /* Assume the type is one this manager knows. */ + status = TX_TRUE; + + switch (object_type) + { + + case TXM_BLOCK_POOL_OBJECT: + + *object_size = (ULONG) sizeof(TX_BLOCK_POOL); + break; + + case TXM_BYTE_POOL_OBJECT: + + *object_size = (ULONG) sizeof(TX_BYTE_POOL); + break; + + case TXM_EVENT_FLAGS_OBJECT: + + *object_size = (ULONG) sizeof(TX_EVENT_FLAGS_GROUP); + break; + + case TXM_MUTEX_OBJECT: + + *object_size = (ULONG) sizeof(TX_MUTEX); + break; + + case TXM_QUEUE_OBJECT: + + *object_size = (ULONG) sizeof(TX_QUEUE); + break; + + case TXM_SEMAPHORE_OBJECT: + + *object_size = (ULONG) sizeof(TX_SEMAPHORE); + break; + + case TXM_THREAD_OBJECT: + + *object_size = (ULONG) sizeof(TX_THREAD); + break; + + case TXM_TIMER_OBJECT: + + *object_size = (ULONG) sizeof(TX_TIMER); + break; + + default: + + /* Not a type the manager authenticates. Report it rather than guessing a + size, so that a caller cannot be given a range to validate that has no + relationship to the object the service will dereference. */ + *object_size = ((ULONG) 0); + status = TX_FALSE; + break; + } + + return(status); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txm_module_manager_allocated_object_check PORTABLE C */ +/* 6.4.3 */ +/* AUTHOR */ +/* */ +/* Eclipse ThreadX contributors */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function determines whether an address is the exact address */ +/* the manager handed the specified module for one of its object */ +/* allocations, and whether that allocation is the size the caller */ +/* expects. */ +/* */ +/* The allocation list is the manager's own record, built as it hands */ +/* object memory out. Comparing against it is what makes an address */ +/* inside the object pool distinguishable from the exact start of an */ +/* allocation. Reading a header in front of a candidate address cannot */ +/* make that distinction: the bytes in front of an address chosen */ +/* inside an allocation are part of the object, and a module can place */ +/* values there through ordinary create and set services. */ +/* */ +/* INPUT */ +/* */ +/* module_instance Requesting module instance pointer*/ +/* object_ptr Address of object memory area */ +/* object_size Expected size of the allocation */ +/* */ +/* OUTPUT */ +/* */ +/* TX_TRUE An exact allocation of that size */ +/* TX_FALSE Anything else */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _txm_module_manager_param_check_object_for_use */ +/* Module object authentication */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-2026 Eclipse ThreadX Initial Version 6.4.3 */ +/* contributors */ +/* */ +/**************************************************************************/ +UINT _txm_module_manager_allocated_object_check(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE object_ptr, ULONG object_size) +{ + +TX_INTERRUPT_SAVE_AREA + +TXM_MODULE_ALLOCATED_OBJECT *allocated_object_ptr; +ULONG objects_examined; +UINT status; + + + /* Assume the address is not one of this module's allocations. */ + status = TX_FALSE; + + /* Disable interrupts. The allocation list is maintained by threads holding the + manager protection mutex, so a scan that runs to completion with interrupts + disabled cannot observe it being changed, and unlike taking the mutex it adds + no blocking point and no priority inversion to a kernel request. */ + TX_DISABLE + + allocated_object_ptr = module_instance -> txm_module_instance_object_list_head; + objects_examined = ((ULONG) 0); + + /* Loop through the objects allocated to this module. The loop is bounded by the + count the manager maintains alongside the list, so the cost of one check is + bounded by the number of objects this module has allocated, and a list whose + links have been damaged cannot make the scan run on. */ + while ((objects_examined < module_instance -> txm_module_instance_object_list_count) && + (allocated_object_ptr != TX_NULL)) + { + + /* The address the module was given is the one immediately after the private + header, so that is the only address in this allocation that names it. */ + if (((ALIGN_TYPE) (allocated_object_ptr + 1)) == object_ptr) + { + + /* Is the allocation the size the caller expects? An allocation made for a + smaller object does not become a larger one because a service was asked + to treat it as one. */ + if (allocated_object_ptr -> txm_module_object_size == object_size) + { + + status = TX_TRUE; + } + + /* An address matches at most one allocation, so there is nothing further + to look at either way. */ + break; + } + + /* Move to the next allocated object. */ + objects_examined++; + allocated_object_ptr = allocated_object_ptr -> txm_module_allocated_object_next; + } + + /* Restore interrupts. */ + TX_RESTORE + + return(status); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txm_module_manager_param_check_typed_object_for_use */ +/* PORTABLE C */ +/* 6.4.3 */ +/* AUTHOR */ +/* */ +/* Eclipse ThreadX contributors */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function authenticates a kernel object a module has named, */ +/* before a privileged service is allowed to dereference it. It */ +/* establishes that the address is the exact address of a live kernel */ +/* object of the type the service expects. */ +/* */ +/* The address is accepted only if it is on the kernel's created list */ +/* for that type. That list is the record the create and delete */ +/* services maintain, so being on it establishes at once that the */ +/* address is an object start rather than an address inside an object, */ +/* that the object is of this type, and that it has not been deleted. */ +/* It is also how an object the application created and shared with a */ +/* module is authenticated, since the manager allocated no such object */ +/* and has no record of its own to consult. */ +/* */ +/* Nothing a module can influence is used to establish a type. In */ +/* particular the control block ID is not, on its own, evidence of */ +/* anything: a module can arrange for the value of an ID to appear */ +/* inside an object it legitimately owns, which is what lets a shifted */ +/* pointer pass an ID test, and distinct object types of equal size */ +/* exist, so an ID is not even a type at an address known to be an */ +/* object start. It is checked, after the created list has settled the */ +/* question, because it is the check the _txe_ services make and it is */ +/* compiled away with them under TX_DISABLE_ERROR_CHECKING. */ +/* */ +/* INPUT */ +/* */ +/* module_instance Requesting module instance pointer*/ +/* object_ptr Address of object memory area */ +/* object_type Module object type the service */ +/* expects */ +/* */ +/* OUTPUT */ +/* */ +/* TX_TRUE Authenticated object pointer */ +/* TX_FALSE Invalid object pointer */ +/* */ +/* CALLS */ +/* */ +/* _txm_module_manager_object_type_size_get */ +/* Get control block size */ +/* _txm_module_manager_created_object_type_check */ +/* Check kernel created list */ +/* _txm_module_manager_object_id_check Check control block ID */ +/* */ +/* CALLED BY */ +/* */ +/* txm_module_manager_* Module manager functions */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-2026 Eclipse ThreadX Initial Version 6.4.3 */ +/* contributors */ +/* */ +/**************************************************************************/ +UINT _txm_module_manager_param_check_typed_object_for_use(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE object_ptr, UINT object_type) +{ + +ULONG object_size; +UINT exact_object; + + + /* Determine if the object pointer is NULL. */ + if ((void *) object_ptr == TX_NULL) + { + + /* Object pointer is NULL, which is invalid. */ + return(TX_FALSE); + } + + /* Pickup the size of the control block this type of service dereferences. */ + if (_txm_module_manager_object_type_size_get(object_type, &object_size) == TX_FALSE) + { + + /* Not an object type this manager authenticates, so it cannot be used. */ + return(TX_FALSE); + } + + /* Determine if the object is outside the calling module. A kernel object inside + the module's own memory is one the module can write behind the kernel's back, + so it is rejected here as it always has been. This also rejects a size that + wraps when added to the address. */ + if (TXM_MODULE_MANAGER_ENSURE_OUTSIDE_MODULE(module_instance, object_ptr, object_size) == TX_FALSE) + { + + /* Object pointer is not outside the module, which is invalid. */ + return(TX_FALSE); + } + + /* Establish that the address is the exact address of a live object of this type, + from the kernel's created list for the type. That list is the record the create + and delete services maintain, so being on it establishes at once that the + address is an object start, that the object is of this type, and that it has not + been deleted. + + It is deliberately the only ground on which an address is accepted. The + manager's own allocation list would establish the address and the size of an + object a module allocated, and would do it by walking a shorter list, but it + records no type, and the type cannot then be taken from the control block + itself: distinct object types of equal size exist -- on a 32-bit target a byte + pool, a mutex and a timer are all the same size -- so a control block whose ID + has been made to read as one of them would be accepted as that type. Nothing a + module can influence is used to establish a type. + + The address is not dereferenced to reach this decision. An address a module + named is not read until a kernel record says there is an object there. */ + exact_object = _txm_module_manager_created_object_type_check(object_ptr, object_type); + + if (exact_object == TX_FALSE) + { + + /* The address is not the start of a live object of this type. */ + return(TX_FALSE); + } + + /* The address is a live object of the requested type. Confirm it against the + control block's own ID, which is the check the _txe_ services would make and + which is compiled away with them under TX_DISABLE_ERROR_CHECKING. */ + if (_txm_module_manager_object_id_check(object_ptr, object_type) == TX_FALSE) + { + + /* The created list and the control block disagree, so the object is not in a + state the manager is prepared to vouch for. */ + return(TX_FALSE); + } + + /* Define application-specific object memory check. */ +#ifdef TXM_MODULE_MANGER_APPLICATION_VALID_OBJECT_MEMORY_CHECK + + /* Bring in the application-spefic objeft memory check, defined by the user. */ + TXM_MODULE_MANGER_APPLICATION_VALID_OBJECT_MEMORY_CHECK +#endif /* TXM_MODULE_MANGER_APPLICATION_VALID_OBJECT_MEMORY_ENABLE */ + + /* Everything is okay with the object, return TX_TRUE. */ + return(TX_TRUE); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txm_module_manager_created_object_type_check PORTABLE C */ +/* 6.4.3 */ +/* AUTHOR */ +/* */ +/* Eclipse ThreadX contributors */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function determines whether an address is the exact address */ +/* of an object on the kernel's created list for a module object type. */ +/* */ +/* This is how an object the application created and shared with a */ +/* module is authenticated. Such an object is not in the manager's */ +/* object pool and the manager has no allocation record of it, so the */ +/* kernel's own created list is the only record of it that a module */ +/* cannot influence. Being on that list establishes at once that the */ +/* address is an object start, that the object is of this type, and */ +/* that it is created. */ +/* */ +/* INPUT */ +/* */ +/* object_ptr Address of object memory area */ +/* object_type Module object type */ +/* */ +/* OUTPUT */ +/* */ +/* TX_TRUE A created object of that type */ +/* TX_FALSE Anything else */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _txm_module_manager_param_check_typed_object_for_use */ +/* Module object authentication */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-2026 Eclipse ThreadX Initial Version 6.4.3 */ +/* contributors */ +/* */ +/**************************************************************************/ +UINT _txm_module_manager_created_object_type_check(ALIGN_TYPE object_ptr, UINT object_type) +{ + +TX_INTERRUPT_SAVE_AREA + +ULONG objects_examined; +ULONG objects_created; +ALIGN_TYPE candidate_ptr; +UINT status; +TX_BLOCK_POOL *block_pool_ptr; +TX_BYTE_POOL *byte_pool_ptr; +TX_EVENT_FLAGS_GROUP *event_flags_ptr; +TX_MUTEX *mutex_ptr; +TX_QUEUE *queue_ptr; +TX_SEMAPHORE *semaphore_ptr; +TX_THREAD *thread_ptr; +TX_TIMER *timer_ptr; + + + /* Assume the address is not on the created list for this type. */ + status = TX_FALSE; + + /* Disable interrupts. The created lists are maintained with interrupts disabled, + so a scan that runs to completion this way sees a consistent list, and it adds + no blocking point to a kernel request. The cost of one check is bounded by the + number of objects of this type the system has created, which is the price of + authenticating an object the manager did not allocate; a module using its own + allocated objects does not reach this function. */ + TX_DISABLE + + /* Start each list from its head and pick up the count that bounds the walk, so a + list whose links have been damaged cannot make the scan run on. */ + switch (object_type) + { + + case TXM_BLOCK_POOL_OBJECT: + + block_pool_ptr = _tx_block_pool_created_ptr; + objects_created = _tx_block_pool_created_count; + objects_examined = ((ULONG) 0); + + while ((objects_examined < objects_created) && (block_pool_ptr != TX_NULL)) + { + candidate_ptr = (ALIGN_TYPE) block_pool_ptr; + if (candidate_ptr == object_ptr) + { + status = TX_TRUE; + break; + } + objects_examined++; + block_pool_ptr = block_pool_ptr -> tx_block_pool_created_next; + } + break; + + case TXM_BYTE_POOL_OBJECT: + + byte_pool_ptr = _tx_byte_pool_created_ptr; + objects_created = _tx_byte_pool_created_count; + objects_examined = ((ULONG) 0); + + while ((objects_examined < objects_created) && (byte_pool_ptr != TX_NULL)) + { + candidate_ptr = (ALIGN_TYPE) byte_pool_ptr; + if (candidate_ptr == object_ptr) + { + status = TX_TRUE; + break; + } + objects_examined++; + byte_pool_ptr = byte_pool_ptr -> tx_byte_pool_created_next; + } + break; + + case TXM_EVENT_FLAGS_OBJECT: + + event_flags_ptr = _tx_event_flags_created_ptr; + objects_created = _tx_event_flags_created_count; + objects_examined = ((ULONG) 0); + + while ((objects_examined < objects_created) && (event_flags_ptr != TX_NULL)) + { + candidate_ptr = (ALIGN_TYPE) event_flags_ptr; + if (candidate_ptr == object_ptr) + { + status = TX_TRUE; + break; + } + objects_examined++; + event_flags_ptr = event_flags_ptr -> tx_event_flags_group_created_next; + } + break; + + case TXM_MUTEX_OBJECT: + + mutex_ptr = _tx_mutex_created_ptr; + objects_created = _tx_mutex_created_count; + objects_examined = ((ULONG) 0); + + while ((objects_examined < objects_created) && (mutex_ptr != TX_NULL)) + { + candidate_ptr = (ALIGN_TYPE) mutex_ptr; + if (candidate_ptr == object_ptr) + { + status = TX_TRUE; + break; + } + objects_examined++; + mutex_ptr = mutex_ptr -> tx_mutex_created_next; + } + break; + + case TXM_QUEUE_OBJECT: + + queue_ptr = _tx_queue_created_ptr; + objects_created = _tx_queue_created_count; + objects_examined = ((ULONG) 0); + + while ((objects_examined < objects_created) && (queue_ptr != TX_NULL)) + { + candidate_ptr = (ALIGN_TYPE) queue_ptr; + if (candidate_ptr == object_ptr) + { + status = TX_TRUE; + break; + } + objects_examined++; + queue_ptr = queue_ptr -> tx_queue_created_next; + } + break; + + case TXM_SEMAPHORE_OBJECT: + + semaphore_ptr = _tx_semaphore_created_ptr; + objects_created = _tx_semaphore_created_count; + objects_examined = ((ULONG) 0); + + while ((objects_examined < objects_created) && (semaphore_ptr != TX_NULL)) + { + candidate_ptr = (ALIGN_TYPE) semaphore_ptr; + if (candidate_ptr == object_ptr) + { + status = TX_TRUE; + break; + } + objects_examined++; + semaphore_ptr = semaphore_ptr -> tx_semaphore_created_next; + } + break; + + case TXM_THREAD_OBJECT: + + thread_ptr = _tx_thread_created_ptr; + objects_created = _tx_thread_created_count; + objects_examined = ((ULONG) 0); + + while ((objects_examined < objects_created) && (thread_ptr != TX_NULL)) + { + candidate_ptr = (ALIGN_TYPE) thread_ptr; + if (candidate_ptr == object_ptr) + { + status = TX_TRUE; + break; + } + objects_examined++; + thread_ptr = thread_ptr -> tx_thread_created_next; + } + break; + + case TXM_TIMER_OBJECT: + + timer_ptr = _tx_timer_created_ptr; + objects_created = _tx_timer_created_count; + objects_examined = ((ULONG) 0); + + while ((objects_examined < objects_created) && (timer_ptr != TX_NULL)) + { + candidate_ptr = (ALIGN_TYPE) timer_ptr; + if (candidate_ptr == object_ptr) + { + status = TX_TRUE; + break; + } + objects_examined++; + timer_ptr = timer_ptr -> tx_timer_created_next; + } + break; + + default: + + /* Not a type the manager authenticates. */ + break; + } + + /* Restore interrupts. */ + TX_RESTORE + + return(status); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txm_module_manager_object_id_check PORTABLE C */ +/* 6.4.3 */ +/* AUTHOR */ +/* */ +/* Eclipse ThreadX contributors */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function determines whether the control block at an object */ +/* start carries the ID of a module object type. The kernel writes */ +/* that ID when it creates an object and clears it when it deletes */ +/* one, so at an address already established to be an object start the */ +/* ID reports both the type and whether the object is still created. */ +/* */ +/* This check must not be used on its own to decide that an address is */ +/* an object. A module can place the value of an ID inside an object */ +/* it legitimately owns, so an ID found at an address the manager has */ +/* not otherwise authenticated proves nothing. */ +/* */ +/* The check matters most where the error checking layer is absent: */ +/* with TX_DISABLE_ERROR_CHECKING the _txe_ services that would */ +/* otherwise test the ID are compiled away, and this is then the only */ +/* ID test between a module and a privileged dereference. */ +/* */ +/* INPUT */ +/* */ +/* object_ptr Address of an object start */ +/* object_type Module object type */ +/* */ +/* OUTPUT */ +/* */ +/* TX_TRUE A created object of that type */ +/* TX_FALSE Anything else */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _txm_module_manager_param_check_typed_object_for_use */ +/* Module object authentication */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-2026 Eclipse ThreadX Initial Version 6.4.3 */ +/* contributors */ +/* */ +/**************************************************************************/ +UINT _txm_module_manager_object_id_check(ALIGN_TYPE object_ptr, UINT object_type) +{ + +TX_INTERRUPT_SAVE_AREA + +ULONG object_id; +ULONG expected_id; +UINT status; + + + /* Read the ID through a pointer to the type the caller named, so that the field + read is the one that type declares rather than an assumed offset. */ + TX_DISABLE + + switch (object_type) + { + + case TXM_BLOCK_POOL_OBJECT: + + object_id = ((TX_BLOCK_POOL *) object_ptr) -> tx_block_pool_id; + expected_id = TX_BLOCK_POOL_ID; + break; + + case TXM_BYTE_POOL_OBJECT: + + object_id = ((TX_BYTE_POOL *) object_ptr) -> tx_byte_pool_id; + expected_id = TX_BYTE_POOL_ID; + break; + + case TXM_EVENT_FLAGS_OBJECT: + + object_id = ((TX_EVENT_FLAGS_GROUP *) object_ptr) -> tx_event_flags_group_id; + expected_id = TX_EVENT_FLAGS_ID; + break; + + case TXM_MUTEX_OBJECT: + + object_id = ((TX_MUTEX *) object_ptr) -> tx_mutex_id; + expected_id = TX_MUTEX_ID; + break; + + case TXM_QUEUE_OBJECT: + + object_id = ((TX_QUEUE *) object_ptr) -> tx_queue_id; + expected_id = TX_QUEUE_ID; + break; + + case TXM_SEMAPHORE_OBJECT: + + object_id = ((TX_SEMAPHORE *) object_ptr) -> tx_semaphore_id; + expected_id = TX_SEMAPHORE_ID; + break; + + case TXM_THREAD_OBJECT: + + object_id = ((TX_THREAD *) object_ptr) -> tx_thread_id; + expected_id = TX_THREAD_ID; + break; + + case TXM_TIMER_OBJECT: + + object_id = ((TX_TIMER *) object_ptr) -> tx_timer_id; + expected_id = TX_TIMER_ID; + break; + + default: + + /* Not a type the manager authenticates. Choose values that cannot match. */ + object_id = TX_CLEAR_ID; + expected_id = ~((ULONG) TX_CLEAR_ID); + break; + } + + /* Restore interrupts. */ + TX_RESTORE + + if (object_id == expected_id) + { + + status = TX_TRUE; + } + else + { + + status = TX_FALSE; + } + + return(status); +} + + /**************************************************************************/ /* */ /* FUNCTION RELEASE */ diff --git a/test/tx/cmake/module_manager/CMakeLists.txt b/test/tx/cmake/module_manager/CMakeLists.txt index 38808a26e..35a6f8bb4 100644 --- a/test/tx/cmake/module_manager/CMakeLists.txt +++ b/test/tx/cmake/module_manager/CMakeLists.txt @@ -78,3 +78,28 @@ target_compile_options( add_test(${CMAKE_BUILD_TYPE}::threadx_module_manager_thread_kernel_stack_test threadx_module_manager_thread_kernel_stack_test) + +# This test drives the manager services directly rather than through a dispatcher, +# so it needs none of the dispatch table and no guard list. +add_executable( + threadx_module_manager_object_authentication_test + ${SOURCE_DIR}/threadx_module_manager_object_authentication_test.c + ${module_manager_dir}/src/txm_module_manager_util.c + ${module_manager_dir}/src/txm_module_manager_object_allocate.c + ${module_manager_dir}/src/txm_module_manager_object_deallocate.c + ${module_manager_dir}/src/txm_module_manager_thread_reset.c) + +target_include_directories( + threadx_module_manager_object_authentication_test + PRIVATE ${SOURCE_DIR} + ${REPO_ROOT}/common/inc + ${REPO_ROOT}/common_modules/inc + ${module_manager_dir}/inc + ${cortex_a7_module_dir}/inc) + +target_compile_options( + threadx_module_manager_object_authentication_test + PRIVATE -include ${SOURCE_DIR}/threadx_module_manager_host_test_port.h) + +add_test(${CMAKE_BUILD_TYPE}::threadx_module_manager_object_authentication_test + threadx_module_manager_object_authentication_test) diff --git a/test/tx/module_manager/threadx_module_manager_object_authentication_test.c b/test/tx/module_manager/threadx_module_manager_object_authentication_test.c new file mode 100644 index 000000000..ca583956f --- /dev/null +++ b/test/tx/module_manager/threadx_module_manager_object_authentication_test.c @@ -0,0 +1,1133 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Test */ +/** */ +/** Module Manager kernel object authentication */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +/* A memory-protected module names the kernel objects it wants operated on by + address, and the Module Manager decides whether a privileged service may + dereference that address. Deciding it by asking only whether the address lies + outside the module is not enough, and the reason is the object pool: the pool + is outside every module, so an address shifted into the interior of one of the + module's own privileged allocations passes that test while denoting no object. + The bytes the shifted address then presents as a control block are bytes the + module put there through ordinary create and set services, so the control block + ID at the front of them can be made to read as any type the module likes. + + This test drives the manager's authentication of such addresses on the host. + The object pool behind it is modelled rather than run -- a bump allocator that + reuses the block it most recently released, which is how the address of a freed + object comes back for the cases about stale addresses -- but the two records + authentication actually consults are built the way the system builds them: the + module allocation list is built by running the real + _txm_module_manager_object_allocate, and the kernel created lists are built the + way the create and delete services maintain them, by writing the control block + ID and linking the object in, and by clearing the ID and unlinking it. + + What the test asserts is that an address is accepted when, and only when, it is + the exact address of a live object of the type the service expects. Every + aligned interior offset of a legitimate object is rejected as a foreign type, + including the offsets where this test has planted that type's own ID, which is + the case the reported attack is built on. */ + +#include + +#include "threadx_module_manager_host_test_port.h" + +#include "tx_thread.h" +#include "tx_trace.h" +#include "tx_timer.h" +#include "tx_queue.h" +#include "tx_event_flags.h" +#include "tx_semaphore.h" +#include "tx_mutex.h" +#include "tx_block_pool.h" +#include "tx_byte_pool.h" +#include "txm_module.h" +#include "txm_module_manager_util.h" + + +/* Define the stand-in interrupt lock the port shim counts through. */ + +unsigned int test_interrupt_disable_depth; +unsigned int test_interrupt_disable_max_depth; +unsigned int test_interrupt_restore_underflows; + + +/* Define the modelled object pool. */ + +#define TEST_POOL_BYTES ((ULONG) 8192) +#define TEST_MODULE_MEMORY_BYTES 512U +#define TEST_MAX_BLOCKS 32U + +static union +{ + ALIGN_TYPE test_pool_alignment; + UCHAR test_pool_bytes[TEST_POOL_BYTES]; +} test_pool_arena; + +static ULONG test_pool_offset; + + +/* Define the memory that stands for the calling module's own code and data. A + kernel object here is one the module could write behind the kernel's back, so + authentication has to refuse it however genuine it looks. */ + +static union +{ + ALIGN_TYPE test_data_alignment; + UCHAR test_data_bytes[TEST_MODULE_MEMORY_BYTES]; +} test_module_data; + +static union +{ + ALIGN_TYPE test_code_alignment; + UCHAR test_code_bytes[TEST_MODULE_MEMORY_BYTES]; +} test_module_code; + + +/* Define the objects that stand for application-owned objects shared with a + module. These live outside the pool, so the manager has no allocation record of + them and the kernel created list is the only record of them there is. */ + +static TX_QUEUE test_host_queue; +static TX_THREAD test_host_thread; +static TX_MUTEX test_host_stranger; + + +/* Define the block the modelled pool most recently released, so that a later + allocation of the same size lands on the address a freed object had. */ + +static UCHAR *test_released_start; +static ULONG test_released_bytes; + + +/* Define the manager state the code under test reaches for. */ + +TX_BYTE_POOL _txm_module_manager_object_pool; +UINT _txm_module_manager_object_pool_created; +TX_MUTEX _txm_module_manager_mutex; +TX_THREAD *_tx_thread_current_ptr; + + +/* Define the kernel created lists authentication walks. */ + +TX_BLOCK_POOL *_tx_block_pool_created_ptr; +ULONG _tx_block_pool_created_count; +TX_BYTE_POOL *_tx_byte_pool_created_ptr; +ULONG _tx_byte_pool_created_count; +TX_EVENT_FLAGS_GROUP *_tx_event_flags_created_ptr; +ULONG _tx_event_flags_created_count; +TX_MUTEX *_tx_mutex_created_ptr; +ULONG _tx_mutex_created_count; +TX_QUEUE *_tx_queue_created_ptr; +ULONG _tx_queue_created_count; +TX_SEMAPHORE *_tx_semaphore_created_ptr; +ULONG _tx_semaphore_created_count; +TX_THREAD *_tx_thread_created_ptr; +ULONG _tx_thread_created_count; +TX_TIMER *_tx_timer_created_ptr; +ULONG _tx_timer_created_count; + + +#ifdef TX_ENABLE_EVENT_TRACE + +/* Define the trace state the reset path's trace insert refers to when the tree is + configured with event tracing. The insert does nothing while the buffer pointer + is null, which is the state a system that has not enabled tracing is in, so the + cases below run identically in every configuration this tree builds. */ + +TX_TRACE_HEADER *_tx_trace_header_ptr; +TX_TRACE_BUFFER_ENTRY *_tx_trace_buffer_start_ptr; +TX_TRACE_BUFFER_ENTRY *_tx_trace_buffer_end_ptr; +TX_TRACE_BUFFER_ENTRY *_tx_trace_buffer_current_ptr; +ULONG _tx_trace_event_enable_bits; +ULONG _tx_trace_simulated_time; +VOID (*_tx_trace_full_notify_function)(VOID *buffer); +volatile ULONG _tx_thread_system_state; + +#endif + + +static UINT test_failures; +static ULONG test_checks; +static ULONG test_stack_builds; + + +/* Record the outcome of one expectation. */ +static VOID test_expect(const char *description, ULONG actual, ULONG expected) +{ + test_checks++; + + if (actual != expected) + { + printf("FAIL: %s (expected %lu, got %lu)\n", description, (unsigned long) expected, (unsigned long) actual); + test_failures++; + } +} + + +/* Report every module object type this manager authenticates, and the name and + control block size of each, so that the cases below can be written once and run + against all of them. */ + +typedef struct TEST_OBJECT_KIND_STRUCT +{ + UINT test_kind_type; + const char *test_kind_name; + ULONG test_kind_size; + ULONG test_kind_id; +} TEST_OBJECT_KIND; + +static const TEST_OBJECT_KIND test_object_kinds[] = +{ + { TXM_BLOCK_POOL_OBJECT, "block pool", (ULONG) sizeof(TX_BLOCK_POOL), TX_BLOCK_POOL_ID }, + { TXM_BYTE_POOL_OBJECT, "byte pool", (ULONG) sizeof(TX_BYTE_POOL), TX_BYTE_POOL_ID }, + { TXM_EVENT_FLAGS_OBJECT, "event flags", (ULONG) sizeof(TX_EVENT_FLAGS_GROUP), TX_EVENT_FLAGS_ID }, + { TXM_MUTEX_OBJECT, "mutex", (ULONG) sizeof(TX_MUTEX), TX_MUTEX_ID }, + { TXM_QUEUE_OBJECT, "queue", (ULONG) sizeof(TX_QUEUE), TX_QUEUE_ID }, + { TXM_SEMAPHORE_OBJECT, "semaphore", (ULONG) sizeof(TX_SEMAPHORE), TX_SEMAPHORE_ID }, + { TXM_THREAD_OBJECT, "thread", (ULONG) sizeof(TX_THREAD), TX_THREAD_ID }, + { TXM_TIMER_OBJECT, "timer", (ULONG) sizeof(TX_TIMER), TX_TIMER_ID } +}; + +#define TEST_OBJECT_KIND_COUNT (sizeof(test_object_kinds) / sizeof(test_object_kinds[0])) + + +/* Round a request up the way _tx_byte_allocate does. */ +static ULONG test_round_up(ULONG memory_size) +{ + return((((memory_size + ((ULONG) sizeof(ALIGN_TYPE))) - ((ULONG) 1)) / ((ULONG) sizeof(ALIGN_TYPE))) * ((ULONG) sizeof(ALIGN_TYPE))); +} + + +/* Stand in for the byte pool the manager allocates object memory from. + + The two size bounds are the real ones. The placement is a bump allocator with + one refinement: a request that exactly fits the block most recently released is + given that block back. A first-fit byte pool reuses freed memory, and the cases + about an address that has been freed and allocated again need the address to + actually come back. */ +UINT _txe_byte_allocate(TX_BYTE_POOL *pool_ptr, VOID **memory_ptr, ULONG memory_size, ULONG wait_option) +{ + +ULONG rounded_size; +UCHAR *block_start; + + + (VOID) wait_option; + + if ((pool_ptr != &_txm_module_manager_object_pool) || (memory_ptr == TX_NULL)) + { + return(TX_POOL_ERROR); + } + + if (memory_size == ((ULONG) 0)) + { + return(TX_SIZE_ERROR); + } + + if (memory_size > pool_ptr -> tx_byte_pool_size) + { + return(TX_SIZE_ERROR); + } + + rounded_size = test_round_up(memory_size); + + if ((test_released_start != TX_NULL) && (test_released_bytes == rounded_size)) + { + block_start = test_released_start; + test_released_start = TX_NULL; + test_released_bytes = ((ULONG) 0); + } + else + { + if ((test_pool_offset + rounded_size) > TEST_POOL_BYTES) + { + return(TX_NO_MEMORY); + } + + block_start = &test_pool_arena.test_pool_bytes[test_pool_offset]; + test_pool_offset = test_pool_offset + rounded_size; + } + + pool_ptr -> tx_byte_pool_available = pool_ptr -> tx_byte_pool_available - rounded_size; + + *memory_ptr = (VOID *) block_start; + + return(TX_SUCCESS); +} + + +/* Stand in for the release side, remembering the block so it can come back. */ +UINT _txe_byte_release(VOID *memory_ptr) +{ + +UCHAR *block_start; + + + block_start = (UCHAR *) memory_ptr; + + if ((block_start < test_pool_arena.test_pool_bytes) || + (block_start >= &test_pool_arena.test_pool_bytes[TEST_POOL_BYTES])) + { + return(TX_PTR_ERROR); + } + + /* The model does not track block lengths, and the only released block a case + needs to come back is the one it just released, whose length it knows. The + length is recorded by the caller through test_release_size. */ + test_released_start = block_start; + + return(TX_SUCCESS); +} + + +/* Tell the model how long the block just released was. */ +static VOID test_release_size(ULONG object_size) +{ + test_released_bytes = test_round_up(object_size + ((ULONG) sizeof(TXM_MODULE_ALLOCATED_OBJECT))); +} + + +/* Stand in for the protection mutex. */ +UINT _txe_mutex_get(TX_MUTEX *mutex_ptr, ULONG wait_option) +{ + (VOID) mutex_ptr; + (VOID) wait_option; + + return(TX_SUCCESS); +} + + +UINT _txe_mutex_put(TX_MUTEX *mutex_ptr) +{ + (VOID) mutex_ptr; + + return(TX_SUCCESS); +} + + +/* Stand in for the module port's data range check, which the portable + outside-the-module test is built on. */ +UINT _txm_module_manager_inside_data_check(ULONG obj_ptr) +{ + +ULONG data_start; +ULONG data_end; + + + data_start = (ULONG) (ALIGN_TYPE) test_module_data.test_data_bytes; + data_end = data_start + ((ULONG) TEST_MODULE_MEMORY_BYTES); + + if ((obj_ptr >= data_start) && (obj_ptr < data_end)) + { + return(TX_TRUE); + } + + return(TX_FALSE); +} + + +/* Stand in for the port primitives the manager sources under test refer to but + that no case here exercises. */ +VOID _txm_module_manager_alignment_adjust(TXM_MODULE_PREAMBLE *module_preamble, ULONG *code_size, + ULONG *code_alignment, ULONG *data_size, ULONG *data_alignment) +{ + (VOID) module_preamble; + (VOID) code_size; + (VOID) code_alignment; + (VOID) data_size; + (VOID) data_alignment; +} + + +VOID _txm_module_manager_thread_stack_build(TX_THREAD *thread_ptr, VOID (*shell_function)(TX_THREAD *, TXM_MODULE_INSTANCE *)) +{ + (VOID) thread_ptr; + (VOID) shell_function; + + test_stack_builds++; +} + + +/* Do to an object what the kernel's create service does to it, as far as + authentication can see: write the control block ID, and link the object onto + the created list for its type. + + The chain each list is built as ends in a self-link on its oldest member rather + than closing back on the head, so that a walk bounded by the created count + visits every member and a walk that ignored the count would not run off the + end. What is being tested is the bound, not the model. */ +static VOID test_object_create(VOID *object_ptr, UINT object_type) +{ + switch (object_type) + { + + case TXM_BLOCK_POOL_OBJECT: + { + TX_BLOCK_POOL *block_pool_ptr = (TX_BLOCK_POOL *) object_ptr; + + block_pool_ptr -> tx_block_pool_id = TX_BLOCK_POOL_ID; + block_pool_ptr -> tx_block_pool_created_next = (_tx_block_pool_created_ptr == TX_NULL) ? block_pool_ptr : _tx_block_pool_created_ptr; + _tx_block_pool_created_ptr = block_pool_ptr; + _tx_block_pool_created_count++; + break; + } + + case TXM_BYTE_POOL_OBJECT: + { + TX_BYTE_POOL *byte_pool_ptr = (TX_BYTE_POOL *) object_ptr; + + byte_pool_ptr -> tx_byte_pool_id = TX_BYTE_POOL_ID; + byte_pool_ptr -> tx_byte_pool_created_next = (_tx_byte_pool_created_ptr == TX_NULL) ? byte_pool_ptr : _tx_byte_pool_created_ptr; + _tx_byte_pool_created_ptr = byte_pool_ptr; + _tx_byte_pool_created_count++; + break; + } + + case TXM_EVENT_FLAGS_OBJECT: + { + TX_EVENT_FLAGS_GROUP *event_flags_ptr = (TX_EVENT_FLAGS_GROUP *) object_ptr; + + event_flags_ptr -> tx_event_flags_group_id = TX_EVENT_FLAGS_ID; + event_flags_ptr -> tx_event_flags_group_created_next = (_tx_event_flags_created_ptr == TX_NULL) ? event_flags_ptr : _tx_event_flags_created_ptr; + _tx_event_flags_created_ptr = event_flags_ptr; + _tx_event_flags_created_count++; + break; + } + + case TXM_MUTEX_OBJECT: + { + TX_MUTEX *mutex_ptr = (TX_MUTEX *) object_ptr; + + mutex_ptr -> tx_mutex_id = TX_MUTEX_ID; + mutex_ptr -> tx_mutex_created_next = (_tx_mutex_created_ptr == TX_NULL) ? mutex_ptr : _tx_mutex_created_ptr; + _tx_mutex_created_ptr = mutex_ptr; + _tx_mutex_created_count++; + break; + } + + case TXM_QUEUE_OBJECT: + { + TX_QUEUE *queue_ptr = (TX_QUEUE *) object_ptr; + + queue_ptr -> tx_queue_id = TX_QUEUE_ID; + queue_ptr -> tx_queue_created_next = (_tx_queue_created_ptr == TX_NULL) ? queue_ptr : _tx_queue_created_ptr; + _tx_queue_created_ptr = queue_ptr; + _tx_queue_created_count++; + break; + } + + case TXM_SEMAPHORE_OBJECT: + { + TX_SEMAPHORE *semaphore_ptr = (TX_SEMAPHORE *) object_ptr; + + semaphore_ptr -> tx_semaphore_id = TX_SEMAPHORE_ID; + semaphore_ptr -> tx_semaphore_created_next = (_tx_semaphore_created_ptr == TX_NULL) ? semaphore_ptr : _tx_semaphore_created_ptr; + _tx_semaphore_created_ptr = semaphore_ptr; + _tx_semaphore_created_count++; + break; + } + + case TXM_THREAD_OBJECT: + { + TX_THREAD *thread_ptr = (TX_THREAD *) object_ptr; + + thread_ptr -> tx_thread_id = TX_THREAD_ID; + thread_ptr -> tx_thread_created_next = (_tx_thread_created_ptr == TX_NULL) ? thread_ptr : _tx_thread_created_ptr; + _tx_thread_created_ptr = thread_ptr; + _tx_thread_created_count++; + break; + } + + case TXM_TIMER_OBJECT: + default: + { + TX_TIMER *timer_ptr = (TX_TIMER *) object_ptr; + + timer_ptr -> tx_timer_id = TX_TIMER_ID; + timer_ptr -> tx_timer_created_next = (_tx_timer_created_ptr == TX_NULL) ? timer_ptr : _tx_timer_created_ptr; + _tx_timer_created_ptr = timer_ptr; + _tx_timer_created_count++; + break; + } + } +} + + +/* Do to an object what the kernel's delete service does: clear the control block + ID, and take the object off the created list for its type. + + Every case that deletes has one object of that type on the list, which is the + shape that matters here, so the model empties the list rather than unlinking a + member of a longer one. */ +static VOID test_object_delete(VOID *object_ptr, UINT object_type) +{ + switch (object_type) + { + + case TXM_BLOCK_POOL_OBJECT: + + ((TX_BLOCK_POOL *) object_ptr) -> tx_block_pool_id = TX_CLEAR_ID; + _tx_block_pool_created_ptr = TX_NULL; + _tx_block_pool_created_count = ((ULONG) 0); + break; + + case TXM_BYTE_POOL_OBJECT: + + ((TX_BYTE_POOL *) object_ptr) -> tx_byte_pool_id = TX_CLEAR_ID; + _tx_byte_pool_created_ptr = TX_NULL; + _tx_byte_pool_created_count = ((ULONG) 0); + break; + + case TXM_EVENT_FLAGS_OBJECT: + + ((TX_EVENT_FLAGS_GROUP *) object_ptr) -> tx_event_flags_group_id = TX_CLEAR_ID; + _tx_event_flags_created_ptr = TX_NULL; + _tx_event_flags_created_count = ((ULONG) 0); + break; + + case TXM_MUTEX_OBJECT: + + ((TX_MUTEX *) object_ptr) -> tx_mutex_id = TX_CLEAR_ID; + _tx_mutex_created_ptr = TX_NULL; + _tx_mutex_created_count = ((ULONG) 0); + break; + + case TXM_QUEUE_OBJECT: + + ((TX_QUEUE *) object_ptr) -> tx_queue_id = TX_CLEAR_ID; + _tx_queue_created_ptr = TX_NULL; + _tx_queue_created_count = ((ULONG) 0); + break; + + case TXM_SEMAPHORE_OBJECT: + + ((TX_SEMAPHORE *) object_ptr) -> tx_semaphore_id = TX_CLEAR_ID; + _tx_semaphore_created_ptr = TX_NULL; + _tx_semaphore_created_count = ((ULONG) 0); + break; + + case TXM_THREAD_OBJECT: + + ((TX_THREAD *) object_ptr) -> tx_thread_id = TX_CLEAR_ID; + _tx_thread_created_ptr = TX_NULL; + _tx_thread_created_count = ((ULONG) 0); + break; + + case TXM_TIMER_OBJECT: + default: + + ((TX_TIMER *) object_ptr) -> tx_timer_id = TX_CLEAR_ID; + _tx_timer_created_ptr = TX_NULL; + _tx_timer_created_count = ((ULONG) 0); + break; + } +} + + +/* Bring the pool, the created lists and the modules back to a known state. + + Everything is reset together deliberately. The allocation lists point into the + pool and the created lists point at objects in it, so a case that left either + behind would have the next case reading the wreckage of an earlier one rather + than what it was written to check. */ +static VOID test_reset(TXM_MODULE_INSTANCE *module_a, TXM_MODULE_INSTANCE *module_b) +{ + +UINT index; + + + for (index = 0U; index < (UINT) TEST_POOL_BYTES; index++) + { + test_pool_arena.test_pool_bytes[index] = (UCHAR) 0; + } + + for (index = 0U; index < TEST_MODULE_MEMORY_BYTES; index++) + { + test_module_data.test_data_bytes[index] = (UCHAR) 0; + test_module_code.test_code_bytes[index] = (UCHAR) 0; + } + + test_pool_offset = ((ULONG) 0); + test_released_start = TX_NULL; + test_released_bytes = ((ULONG) 0); + + _txm_module_manager_object_pool.tx_byte_pool_id = TX_BYTE_POOL_ID; + _txm_module_manager_object_pool.tx_byte_pool_start = test_pool_arena.test_pool_bytes; + _txm_module_manager_object_pool.tx_byte_pool_size = TEST_POOL_BYTES; + _txm_module_manager_object_pool.tx_byte_pool_available = TEST_POOL_BYTES; + _txm_module_manager_object_pool_created = TX_TRUE; + + _tx_block_pool_created_ptr = TX_NULL; + _tx_block_pool_created_count = ((ULONG) 0); + _tx_byte_pool_created_ptr = TX_NULL; + _tx_byte_pool_created_count = ((ULONG) 0); + _tx_event_flags_created_ptr = TX_NULL; + _tx_event_flags_created_count = ((ULONG) 0); + _tx_mutex_created_ptr = TX_NULL; + _tx_mutex_created_count = ((ULONG) 0); + _tx_queue_created_ptr = TX_NULL; + _tx_queue_created_count = ((ULONG) 0); + _tx_semaphore_created_ptr = TX_NULL; + _tx_semaphore_created_count = ((ULONG) 0); + _tx_thread_created_ptr = TX_NULL; + _tx_thread_created_count = ((ULONG) 0); + _tx_timer_created_ptr = TX_NULL; + _tx_timer_created_count = ((ULONG) 0); + + module_a -> txm_module_instance_object_list_count = ((ULONG) 0); + module_a -> txm_module_instance_object_list_head = TX_NULL; + module_b -> txm_module_instance_object_list_count = ((ULONG) 0); + module_b -> txm_module_instance_object_list_head = TX_NULL; +} + + +/* Allocate object memory for a module through the real manager path. */ +static VOID *test_allocate(TXM_MODULE_INSTANCE *module_instance, ULONG object_size) +{ + +VOID *object_ptr; +UINT status; + + + object_ptr = TX_NULL; + status = _txm_module_manager_object_allocate(&object_ptr, object_size, module_instance); + + if (status != TX_SUCCESS) + { + printf("FAIL: the modelled pool refused an allocation of %lu bytes (status %u)\n", + (unsigned long) object_size, status); + test_failures++; + + return(TX_NULL); + } + + return(object_ptr); +} + + +/* Allocate and create one object of a type, the way a module does. */ +static VOID *test_allocate_and_create(TXM_MODULE_INSTANCE *module_instance, const TEST_OBJECT_KIND *kind) +{ + +VOID *object_ptr; + + + object_ptr = test_allocate(module_instance, kind -> test_kind_size); + + if (object_ptr != TX_NULL) + { + test_object_create(object_ptr, kind -> test_kind_type); + } + + return(object_ptr); +} + + +/* Ask the manager to authenticate an address, and report what it said. */ +static ULONG test_authenticate(TXM_MODULE_INSTANCE *module_instance, VOID *object_ptr, UINT object_type) +{ + +ULONG accepted; + + + test_interrupt_disable_depth = 0U; + test_interrupt_disable_max_depth = 0U; + test_interrupt_restore_underflows = 0U; + + accepted = (ULONG) _txm_module_manager_param_check_typed_object_for_use(module_instance, + (ALIGN_TYPE) object_ptr, + object_type); + + /* Whatever it decided, it must have left the interrupt lock as it found it. */ + if ((test_interrupt_disable_depth != 0U) || (test_interrupt_restore_underflows != 0U)) + { + printf("FAIL: authentication left the interrupt lock unbalanced (depth %u, underflows %u)\n", + test_interrupt_disable_depth, test_interrupt_restore_underflows); + test_failures++; + } + + return(accepted); +} + + +/* Plant a value at an offset into an object, the way a module reaches interior + words of its own privileged allocations through ordinary create and set + services, and report what was there before. */ +static ULONG test_plant(VOID *object_ptr, ULONG offset, ULONG value) +{ + +ULONG *word_ptr; +ULONG previous; + + + word_ptr = (ULONG *) (VOID *) (((UCHAR *) object_ptr) + offset); + previous = *word_ptr; + *word_ptr = value; + + return(previous); +} + + +int main(void) +{ + +TXM_MODULE_INSTANCE module_a; +TXM_MODULE_INSTANCE module_b; +TXM_MODULE_INSTANCE *owner; +const TEST_OBJECT_KIND *kind; +const TEST_OBJECT_KIND *other_kind; +VOID *object; +VOID *other_object; +VOID *raw_object; +VOID *shifted; +UCHAR *shifted_bytes; +ULONG offset; +ULONG interior_offsets; +ULONG accepted_interiors; +ULONG index; +ULONG other_index; +ULONG saved; +UINT status; +char description[128]; + + + /* Report expectations before anything can crash, so that a case that brings + the process down is still preceded by everything that passed. */ + setvbuf(stdout, TX_NULL, _IONBF, 0); + + test_failures = 0U; + test_checks = ((ULONG) 0); + + /* Set up two memory-protected modules. Module A does the asking throughout; + module B is there to own objects A did not allocate. */ + module_a.txm_module_instance_property_flags = TXM_MODULE_MEMORY_PROTECTION; + module_a.txm_module_instance_code_start = (VOID *) test_module_code.test_code_bytes; + module_a.txm_module_instance_code_end = (VOID *) &test_module_code.test_code_bytes[TEST_MODULE_MEMORY_BYTES - 1U]; + module_a.txm_module_instance_data_start = (VOID *) test_module_data.test_data_bytes; + module_a.txm_module_instance_data_end = (VOID *) &test_module_data.test_data_bytes[TEST_MODULE_MEMORY_BYTES - 1U]; + + module_b = module_a; + + _tx_thread_current_ptr = TX_NULL; + + /**********************************************************************/ + /* The reported attack: an address shifted into a legitimate object. */ + /**********************************************************************/ + + /* A module allocates and creates a timer of its own, entirely legitimately, + and then presents addresses inside it as though they were a thread. The + word at each of those addresses is set to TX_THREAD_ID first, which is what + the reported chain arranges through ordinary create and set services, so + that every address offered is one that an ID test on its own would accept. */ + test_reset(&module_a, &module_b); + + kind = &test_object_kinds[6]; + object = test_allocate(&module_a, (ULONG) sizeof(TX_THREAD)); + test_object_create(object, TXM_TIMER_OBJECT); + + test_expect("a timer's own address is not accepted as a thread", + test_authenticate(&module_a, object, TXM_THREAD_OBJECT), (ULONG) TX_FALSE); + + interior_offsets = ((ULONG) 0); + accepted_interiors = ((ULONG) 0); + + for (offset = (ULONG) sizeof(ULONG); offset < (ULONG) sizeof(TX_THREAD); offset = offset + ((ULONG) sizeof(ULONG))) + { + shifted_bytes = ((UCHAR *) object) + offset; + shifted = (VOID *) shifted_bytes; + + saved = test_plant(object, offset, TX_THREAD_ID); + + interior_offsets++; + + if (test_authenticate(&module_a, shifted, TXM_THREAD_OBJECT) == (ULONG) TX_TRUE) + { + accepted_interiors++; + } + + (VOID) test_plant(object, offset, saved); + } + + test_expect("every aligned interior offset of a legitimate object was offered", + (ULONG) (interior_offsets > ((ULONG) 0)), (ULONG) TX_TRUE); + test_expect("no aligned interior address carrying a planted thread ID is accepted as a thread", + accepted_interiors, ((ULONG) 0)); + + /* The unaligned offsets the report names, and the address one past the end. */ + (VOID) test_plant(object, ((ULONG) 0), TX_THREAD_ID); + + shifted = (VOID *) (((UCHAR *) object) + 1); + test_expect("an address one byte into a legitimate object is not accepted", + test_authenticate(&module_a, shifted, TXM_THREAD_OBJECT), (ULONG) TX_FALSE); + + shifted = (VOID *) (((UCHAR *) object) + 4); + test_expect("an address four bytes into a legitimate object is not accepted", + test_authenticate(&module_a, shifted, TXM_THREAD_OBJECT), (ULONG) TX_FALSE); + + shifted = (VOID *) (((UCHAR *) object) + (ULONG) sizeof(TX_THREAD)); + test_expect("the address one past a legitimate object is not accepted", + test_authenticate(&module_a, shifted, TXM_THREAD_OBJECT), (ULONG) TX_FALSE); + + /**********************************************************************/ + /* Exact addresses of live objects, for every type the manager knows. */ + /**********************************************************************/ + + for (index = ((ULONG) 0); index < (ULONG) TEST_OBJECT_KIND_COUNT; index++) + { + kind = &test_object_kinds[index]; + + test_reset(&module_a, &module_b); + + object = test_allocate_and_create(&module_a, kind); + + (void) snprintf(description, sizeof(description), + "the exact address of a live %s is accepted as one", kind -> test_kind_name); + test_expect(description, test_authenticate(&module_a, object, kind -> test_kind_type), (ULONG) TX_TRUE); + + /* Every other type must refuse it, whatever its ID has been made to say. */ + for (other_index = ((ULONG) 0); other_index < (ULONG) TEST_OBJECT_KIND_COUNT; other_index++) + { + if (other_index == index) + { + continue; + } + + other_kind = &test_object_kinds[other_index]; + + saved = test_plant(object, ((ULONG) 0), other_kind -> test_kind_id); + + (void) snprintf(description, sizeof(description), + "a %s carrying a %s ID is not accepted as a %s", + kind -> test_kind_name, other_kind -> test_kind_name, other_kind -> test_kind_name); + test_expect(description, test_authenticate(&module_a, object, other_kind -> test_kind_type), (ULONG) TX_FALSE); + + (VOID) test_plant(object, ((ULONG) 0), saved); + } + + /* A raw allocation of exactly the right size, never created. */ + raw_object = test_allocate(&module_a, kind -> test_kind_size); + + (void) snprintf(description, sizeof(description), + "an uncreated allocation the size of a %s is not accepted as one", kind -> test_kind_name); + test_expect(description, test_authenticate(&module_a, raw_object, kind -> test_kind_type), (ULONG) TX_FALSE); + + /* Deleting the object takes it off the created list and clears its ID. */ + test_object_delete(object, kind -> test_kind_type); + + (void) snprintf(description, sizeof(description), + "a deleted %s is not accepted as one", kind -> test_kind_name); + test_expect(description, test_authenticate(&module_a, object, kind -> test_kind_type), (ULONG) TX_FALSE); + } + + /**********************************************************************/ + /* Addresses that have been freed, and addresses that have come back. */ + /**********************************************************************/ + + test_reset(&module_a, &module_b); + + kind = &test_object_kinds[4]; + object = test_allocate_and_create(&module_a, kind); + + test_expect("a live queue is accepted before anything is given back", + test_authenticate(&module_a, object, TXM_QUEUE_OBJECT), (ULONG) TX_TRUE); + + /* Give the memory back without deleting the object first. The manager stops + vouching for the control block at the moment it stops owning the memory, so + the address is refused even though the created list has not been told. */ + _tx_thread_current_ptr = (TX_THREAD *) test_allocate(&module_a, (ULONG) sizeof(TX_THREAD)); + _tx_thread_current_ptr -> tx_thread_module_instance_ptr = &module_a; + + test_release_size(kind -> test_kind_size); + status = _txm_module_manager_object_deallocate(object); + test_expect("the object memory is given back", (ULONG) status, (ULONG) TX_SUCCESS); + + test_expect("an address whose memory was given back without a delete is refused", + test_authenticate(&module_a, object, TXM_QUEUE_OBJECT), (ULONG) TX_FALSE); + + /* The same address now comes back as a fresh, raw allocation. It is once + again an exact allocation start of the right size, and it is still on the + created list, so nothing but the cleared ID stands between it and being + taken for the object that used to be there. */ + raw_object = test_allocate(&module_a, kind -> test_kind_size); + test_expect("the freed address is handed out again", + (ULONG) (raw_object == object), (ULONG) TX_TRUE); + test_expect("and is not accepted as the object that used to be there", + test_authenticate(&module_a, raw_object, TXM_QUEUE_OBJECT), (ULONG) TX_FALSE); + + _tx_thread_current_ptr = TX_NULL; + + /**********************************************************************/ + /* Objects the application owns, and objects nobody owns. */ + /**********************************************************************/ + + test_reset(&module_a, &module_b); + + /* An application-owned object lives outside the pool, so the manager has no + allocation record of it. The kernel created list is the record that stands + in its place, and it is what makes sharing such an object with a module + possible at all. */ + test_object_create(&test_host_queue, TXM_QUEUE_OBJECT); + test_object_create(&test_host_thread, TXM_THREAD_OBJECT); + + test_expect("an application-owned queue on the created list is accepted", + test_authenticate(&module_a, &test_host_queue, TXM_QUEUE_OBJECT), (ULONG) TX_TRUE); + test_expect("an application-owned thread on the created list is accepted", + test_authenticate(&module_a, &test_host_thread, TXM_THREAD_OBJECT), (ULONG) TX_TRUE); + test_expect("but not as the wrong type", + test_authenticate(&module_a, &test_host_queue, TXM_THREAD_OBJECT), (ULONG) TX_FALSE); + + /* Memory outside the pool that carries the right ID but is on no created + list. Without the created list this would be indistinguishable from a real + object, and every word of privileged memory that happened to hold an ID + would be usable as one. */ + test_host_stranger.tx_mutex_id = TX_MUTEX_ID; + test_expect("memory carrying a mutex ID but on no created list is refused", + test_authenticate(&module_a, &test_host_stranger, TXM_MUTEX_OBJECT), (ULONG) TX_FALSE); + + test_object_delete(&test_host_queue, TXM_QUEUE_OBJECT); + test_expect("a deleted application-owned queue is refused", + test_authenticate(&module_a, &test_host_queue, TXM_QUEUE_OBJECT), (ULONG) TX_FALSE); + + test_object_delete(&test_host_thread, TXM_THREAD_OBJECT); + + /**********************************************************************/ + /* Objects another module allocated. */ + /**********************************************************************/ + + test_reset(&module_a, &module_b); + + kind = &test_object_kinds[5]; + object = test_allocate_and_create(&module_b, kind); + + /* A created object belonging to another module is authentic, and is accepted + as such: it is the exact address of a live semaphore. Whether module A is + *authorised* to operate on module B's semaphore is a separate question + about ownership, which this check does not answer and does not claim to. */ + test_expect("another module's live semaphore is authentic", + test_authenticate(&module_a, object, TXM_SEMAPHORE_OBJECT), (ULONG) TX_TRUE); + + /* An allocation another module has not created is not an object at all, and + neither module can use it as one. */ + raw_object = test_allocate(&module_b, kind -> test_kind_size); + test_expect("another module's uncreated allocation is not an object", + test_authenticate(&module_a, raw_object, TXM_SEMAPHORE_OBJECT), (ULONG) TX_FALSE); + test_expect("nor is it one to the module that allocated it", + test_authenticate(&module_b, raw_object, TXM_SEMAPHORE_OBJECT), (ULONG) TX_FALSE); + + /* An interior address of another module's object is refused the same way an + interior address of the caller's own object is. */ + shifted = (VOID *) (((UCHAR *) object) + (ULONG) sizeof(ULONG)); + (VOID) test_plant(object, (ULONG) sizeof(ULONG), TX_SEMAPHORE_ID); + test_expect("an interior address of another module's object is refused", + test_authenticate(&module_a, shifted, TXM_SEMAPHORE_OBJECT), (ULONG) TX_FALSE); + + /**********************************************************************/ + /* Addresses and types that are not objects at all. */ + /**********************************************************************/ + + test_reset(&module_a, &module_b); + + object = test_allocate_and_create(&module_a, &test_object_kinds[6]); + + test_expect("a null address is refused", + test_authenticate(&module_a, TX_NULL, TXM_THREAD_OBJECT), (ULONG) TX_FALSE); + test_expect("an object type the manager does not know is refused", + test_authenticate(&module_a, object, 0U), (ULONG) TX_FALSE); + test_expect("and so is one past the types it does know", + test_authenticate(&module_a, object, TXM_TIMER_OBJECT + 1U), (ULONG) TX_FALSE); + + /* A control block inside the calling module's own memory is one the module can + write behind the kernel's back, so it is refused however genuine it looks. */ + owner = &module_a; + test_object_create(test_module_data.test_data_bytes, TXM_MUTEX_OBJECT); + test_expect("a mutex in the module's own data is refused", + test_authenticate(owner, test_module_data.test_data_bytes, TXM_MUTEX_OBJECT), (ULONG) TX_FALSE); + + test_object_create(test_module_code.test_code_bytes, TXM_SEMAPHORE_OBJECT); + test_expect("a semaphore in the module's own code is refused", + test_authenticate(owner, test_module_code.test_code_bytes, TXM_SEMAPHORE_OBJECT), (ULONG) TX_FALSE); + + /**********************************************************************/ + /* The bound on every scan. */ + /**********************************************************************/ + + test_reset(&module_a, &module_b); + + object = test_allocate_and_create(&module_a, &test_object_kinds[6]); + + /* A count that claims more objects than the list holds must not make either + scan walk past the end of it. The chain the model builds ends in a self + link, so a scan that ignored the count would spin rather than crash; the + count is what stops it. */ + module_a.txm_module_instance_object_list_count = ((ULONG) 64); + _tx_thread_created_count = ((ULONG) 64); + + test_expect("a live thread is still accepted when the counts overstate the lists", + test_authenticate(&module_a, object, TXM_THREAD_OBJECT), (ULONG) TX_TRUE); + + other_object = (VOID *) &test_host_stranger; + test_expect("and an address on neither list is still refused", + test_authenticate(&module_a, other_object, TXM_THREAD_OBJECT), (ULONG) TX_FALSE); + + /* An empty allocation list with a head that has not been cleared must not be + followed either. */ + module_a.txm_module_instance_object_list_count = ((ULONG) 0); + _tx_thread_created_count = ((ULONG) 1); + + test_expect("a live thread is accepted with an empty allocation list", + test_authenticate(&module_a, object, TXM_THREAD_OBJECT), (ULONG) TX_TRUE); + + _tx_thread_created_count = ((ULONG) 0); + test_expect("and refused once the created list is empty too", + test_authenticate(&module_a, object, TXM_THREAD_OBJECT), (ULONG) TX_FALSE); + + /**********************************************************************/ + /* The size-based check kept for dispatchers outside this repository. */ + /**********************************************************************/ + + test_reset(&module_a, &module_b); + + kind = &test_object_kinds[3]; + object = test_allocate_and_create(&module_a, kind); + + test_expect("the size-based check accepts an exact allocation of that size", + (ULONG) _txm_module_manager_param_check_object_for_use(&module_a, (ALIGN_TYPE) object, + kind -> test_kind_size), + (ULONG) TX_TRUE); + + test_expect("and refuses an allocation of a different size", + (ULONG) _txm_module_manager_param_check_object_for_use(&module_a, (ALIGN_TYPE) object, + kind -> test_kind_size + ((ULONG) 4)), + (ULONG) TX_FALSE); + + /* The interior address the reported attack is built on is what this check has + to refuse, and it does, which is what makes hardening it worthwhile even + though it cannot be given a type. */ + interior_offsets = ((ULONG) 0); + accepted_interiors = ((ULONG) 0); + + for (offset = (ULONG) sizeof(ULONG); offset < kind -> test_kind_size; offset = offset + ((ULONG) sizeof(ULONG))) + { + shifted = (VOID *) (((UCHAR *) object) + offset); + + saved = test_plant(object, offset, kind -> test_kind_id); + + interior_offsets++; + + if (_txm_module_manager_param_check_object_for_use(&module_a, (ALIGN_TYPE) shifted, + kind -> test_kind_size) == TX_TRUE) + { + accepted_interiors++; + } + + (VOID) test_plant(object, offset, saved); + } + + test_expect("the size-based check was offered every aligned interior offset", + (ULONG) (interior_offsets > ((ULONG) 0)), (ULONG) TX_TRUE); + test_expect("and accepted none of them", + accepted_interiors, ((ULONG) 0)); + + /**********************************************************************/ + /* The disclosed sink: resetting a thread that is not a module thread. */ + /**********************************************************************/ + + test_reset(&module_a, &module_b); + + /* A thread the application created carries no module instance. Reset reads + the shell entry function out of that instance to rebuild the thread's + stack, so a null one would be followed in privileged mode. Such a thread is + authentic and can be found by name, and one that has run to completion + passes reset's own state test, so refusing it has to be reset's own job. */ + _tx_thread_current_ptr = &test_host_thread; + + object = test_allocate(&module_a, (ULONG) sizeof(TX_THREAD)); + test_object_create(object, TXM_THREAD_OBJECT); + + ((TX_THREAD *) object) -> tx_thread_state = TX_COMPLETED; + ((TX_THREAD *) object) -> tx_thread_module_instance_ptr = TX_NULL; + + test_stack_builds = ((ULONG) 0); + status = _txm_module_manager_thread_reset((TX_THREAD *) object); + + test_expect("resetting a completed thread with no module instance is refused", + (ULONG) status, (ULONG) TX_NOT_DONE); + test_expect("...without building a stack frame", test_stack_builds, ((ULONG) 0)); + test_expect("...and without moving it out of the completed state", + (ULONG) ((TX_THREAD *) object) -> tx_thread_state, (ULONG) TX_COMPLETED); + + /* A module thread in the same state is reset, so the guard has not broken the + operation it protects. */ + ((TX_THREAD *) object) -> tx_thread_module_instance_ptr = &module_a; + module_a.txm_module_instance_shell_entry_function = TX_NULL; + + test_stack_builds = ((ULONG) 0); + status = _txm_module_manager_thread_reset((TX_THREAD *) object); + + test_expect("a completed module thread is reset", (ULONG) status, (ULONG) TX_SUCCESS); + test_expect("...building its stack frame once", test_stack_builds, ((ULONG) 1)); + test_expect("...and leaving it suspended", + (ULONG) ((TX_THREAD *) object) -> tx_thread_state, (ULONG) TX_SUSPENDED); + + _tx_thread_current_ptr = TX_NULL; + + /**********************************************************************/ + /* What the whole run has to have held. */ + /**********************************************************************/ + + /**********************************************************************/ + /* Why a size cannot stand in for a type. */ + /**********************************************************************/ + + /* Authentication establishes an object's type from the kernel's created list + for that type, rather than from the size of its control block, because a size + does not identify one. Distinct control blocks share a size: on a 32-bit + target a byte pool, a mutex and a timer are all the same size as each other, + and a block pool is the same size as an event flags group. + + This is asserted rather than left as a remark so that the reasoning is checked + against the structures rather than remembered. It holds while any two distinct + types collide, so adding a field to one of them does not make it fail; it + fails only if every type becomes distinguishable by size, which is when the + remark above would need revisiting. */ + test_expect("distinct object types share a control block size", + (ULONG) ((sizeof(TX_BYTE_POOL) == sizeof(TX_MUTEX)) || + (sizeof(TX_BYTE_POOL) == sizeof(TX_TIMER)) || + (sizeof(TX_MUTEX) == sizeof(TX_TIMER)) || + (sizeof(TX_BLOCK_POOL) == sizeof(TX_EVENT_FLAGS_GROUP))), + (ULONG) TX_TRUE); + + test_expect("every case ran", (ULONG) (test_checks > ((ULONG) 100)), (ULONG) TX_TRUE); + + if (test_failures == 0U) + { + printf("SUCCESS! %lu expectations\n", (unsigned long) test_checks); + return(0); + } + + printf("ERROR: %u expectation(s) failed of %lu\n", test_failures, (unsigned long) test_checks); + return(1); +} From 3276b0efd57d5e74f2edb1cec15add6e24085611 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 28 Sep 2026 09:23:49 -0400 Subject: [PATCH 153/181] Merge commit from fork A module reaches a kernel object's delete service through the Module Manager's dispatch layer, which asked one question about the pointer: does the object lie outside the module's own code and data. That is the policy for using an object, and using an object a module does not own is supported and intended -- txm_module_object_pointer_get_extended searches the system's created objects by name and hands back objects the application created and objects other modules created, so that a module can send to a shared queue, take a shared semaphore or get a shared mutex. Destroying one of those is not sharing it. A module could name any object it had a pointer to and have the privileged dispatcher delete it: a host service lost its queue, waiters were resumed with TX_DELETED, an owned mutex's priority inheritance was unwound, and an active timer stopped. Nothing in the manager intended that. The deallocation the delete path performs afterwards has always required the memory to belong to the calling module, so a delete of anything else could only ever end in TX_PTR_ERROR -- the ownership requirement was already there and was enforced one step too late, after the kernel object had been irreversibly destroyed and its waiters woken. An error returned at that point describes a cleanup failure and restores nothing. The eight delete dispatchers now ask the question before the delete rather than after it. A memory-protected module may delete an object only if the object is one it allocated from the manager's object pool, at the exact address the manager returned to it, for an allocation made for that type's control block size -- the same conditions the create dispatchers already apply, since deletion is the inverse of creation. Anything else returns TXM_MODULE_INVALID_MEMORY, which is what every other parameter rejection in the dispatch table returns, so no new value enters the module ABI and a module cannot use a delete request to tell "not yours" apart from "not a usable address". The object stays created, nothing waiting on it is resumed, and no created count moves, because the kernel was never asked. The ownership question is deliberately separate from whether an object is there at all and of the expected type. It establishes nothing about liveness or type, and it is composed with the checks that do rather than replacing them. _txm_module_manager_object_deallocate reached the manager's private header by subtracting from whatever address the caller supplied, and read it before deciding whether it was a header. All eight delete dispatchers call that function directly, so an object the module does not own arrived there as a matter of course rather than exceptionally: for an object the application allocated statically, or for any address outside the object pool, the words in front of it were unrelated memory read in privileged mode -- and acted on, since an address whose preceding words happened to name the calling module was unlinked from that module's allocation list and handed to the byte pool. It now finds the allocation by searching the module's own allocation list. The caller's address is compared and never dereferenced, so an address that names none of this module's allocations is refused without a privileged read of anything in front of it, and the search establishes what the header read could not: that the address is the exact start of an allocation rather than somewhere inside one. The search is bounded by the count the manager keeps beside the list and runs with interrupts disabled, so a damaged list cannot make it run on and it cannot observe the list being changed under it. The fix is in the deallocation itself rather than at a call site, so it covers all eight delete dispatchers, the deallocation request a module can make directly, protected and unprotected modules alike. txm_module_manager_stop needs no exemption and was not given one. It deletes the objects a module created by calling the internal _tx_*_delete services directly, and identifies them with _txm_module_manager_created_object_check rather than through a module request, so no caller-facing check stands in its way. The 209 expectations in the new test drive all eight object types through allocation, an ownership check by the owning module and by another, a check against a larger and a smaller expected size, and a deallocation that succeeds. They cover an object the application owns, deliberately preceded by a header naming the requesting module so that reading it can be seen to have happened; another module's object, checked and refused from both sides; every aligned interior offset of an allocation and the addresses of its header, its end, the pool's ends and one past the pool; a null pointer and an address with no room for a header in front of it; a request from no module at all; memory that has changed hands, where a stale pointer names an address that now belongs to another module; the bounds on the search, against a count smaller than the list and against a count larger than a list whose links are broken; releasing the head, the middle and the last of a list of three; and an object pool that was never created. Every call asserts that the interrupt lock came back balanced, and that the search ran with interrupts disabled exactly one deep. Restoring the previous deallocation fails four of them and then segmentation faults, on the null-pointer case, where the header in front of address zero is read; removing the ownership check fails 74. Line and branch coverage of the two new functions and of the changed _txm_module_manager_object_deallocate is 100%, with two branch outcomes excepted that are test scaffolding rather than product code: the host shim's stand-ins for TX_DISABLE and TX_RESTORE carry a maximum-depth test and an underflow guard, and the real ports' primitives are inline assembly with no branch at all. All 99 tests pass in each of the five configurations the tree builds with GCC 14. Nothing in the tree compiles the dispatch header, so the eight changed dispatchers were cross-compiled by hand: the two changed C files and a translation unit that includes the header build at -Werror with arm-none-eabi-gcc 13.2.1 for every GNU 32-bit module port -- Cortex-A7, M0+, M23, M3, M33, M4 and M7 -- and produce the same -Wall -Wextra warning counts as before the change, 117 on Cortex-A7 and 116 on each of the others. Cortex-R4 and RXv2 have no GNU module port, and the two AArch64 module ports have no toolchain available here; the new arithmetic is a comparison of two addresses of the same type, so a wider ALIGN_TYPE changes nothing about it. MISRA: all if bodies are braced, the address comparison goes through ALIGN_TYPE, no pointer the caller supplied is dereferenced, and no goto appears. No deviation is required. Assisted-by: Claude Code (Opus 5) --- .../inc/txm_module_manager_dispatch.h | 27 + .../inc/txm_module_manager_util.h | 12 + .../txm_module_manager_object_deallocate.c | 40 +- .../src/txm_module_manager_util.c | 171 ++- test/tx/cmake/module_manager/CMakeLists.txt | 24 + ...adx_module_manager_delete_ownership_test.c | 992 ++++++++++++++++++ 6 files changed, 1230 insertions(+), 36 deletions(-) create mode 100644 test/tx/module_manager/threadx_module_manager_delete_ownership_test.c diff --git a/common_modules/module_manager/inc/txm_module_manager_dispatch.h b/common_modules/module_manager/inc/txm_module_manager_dispatch.h index 9c0e5d212..6b75be7f8 100644 --- a/common_modules/module_manager/inc/txm_module_manager_dispatch.h +++ b/common_modules/module_manager/inc/txm_module_manager_dispatch.h @@ -1,6 +1,7 @@ /*************************************************************************** * Copyright (c) 2024 Microsoft Corporation * Copyright (c) 2025 Eclipse ThreadX Contributors + * 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 @@ -12,6 +13,8 @@ // Some portions generated by Claude Code (Opus 5). +// Some portions generated by Claude Code (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -106,6 +109,9 @@ ALIGN_TYPE return_value; { if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_BLOCK_POOL_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); + + if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_DELETION(module_instance, param_0, sizeof(TX_BLOCK_POOL))) + return(TXM_MODULE_INVALID_MEMORY); } return_value = (ALIGN_TYPE) _txe_block_pool_delete( @@ -410,6 +416,9 @@ ALIGN_TYPE return_value; { if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_BYTE_POOL_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); + + if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_DELETION(module_instance, param_0, sizeof(TX_BYTE_POOL))) + return(TXM_MODULE_INVALID_MEMORY); } return_value = (ALIGN_TYPE) _txe_byte_pool_delete( @@ -700,6 +709,9 @@ ALIGN_TYPE return_value; { if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_EVENT_FLAGS_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); + + if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_DELETION(module_instance, param_0, sizeof(TX_EVENT_FLAGS_GROUP))) + return(TXM_MODULE_INVALID_MEMORY); } return_value = (ALIGN_TYPE) _txe_event_flags_delete( @@ -1005,6 +1017,9 @@ ALIGN_TYPE return_value; { if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_MUTEX_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); + + if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_DELETION(module_instance, param_0, sizeof(TX_MUTEX))) + return(TXM_MODULE_INVALID_MEMORY); } return_value = (ALIGN_TYPE) _txe_mutex_delete( @@ -1302,6 +1317,9 @@ ALIGN_TYPE return_value; { if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_QUEUE_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); + + if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_DELETION(module_instance, param_0, sizeof(TX_QUEUE))) + return(TXM_MODULE_INVALID_MEMORY); } return_value = (ALIGN_TYPE) _txe_queue_delete( @@ -1734,6 +1752,9 @@ ALIGN_TYPE return_value; { if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_SEMAPHORE_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); + + if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_DELETION(module_instance, param_0, sizeof(TX_SEMAPHORE))) + return(TXM_MODULE_INVALID_MEMORY); } return_value = (ALIGN_TYPE) _txe_semaphore_delete( @@ -2075,6 +2096,9 @@ ALIGN_TYPE stack_status; { if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_THREAD_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); + + if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_DELETION(module_instance, param_0, sizeof(TX_THREAD))) + return(TXM_MODULE_INVALID_MEMORY); } return_value = (ALIGN_TYPE) _txe_thread_delete(thread_ptr); @@ -2896,6 +2920,9 @@ ALIGN_TYPE return_value; { if (!TXM_MODULE_MANAGER_PARAM_CHECK_TYPED_OBJECT_FOR_USE(module_instance, param_0, TXM_TIMER_OBJECT)) return(TXM_MODULE_INVALID_MEMORY); + + if (!TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_DELETION(module_instance, param_0, sizeof(TX_TIMER))) + return(TXM_MODULE_INVALID_MEMORY); } return_value = (ALIGN_TYPE) _txe_timer_delete( diff --git a/common_modules/module_manager/inc/txm_module_manager_util.h b/common_modules/module_manager/inc/txm_module_manager_util.h index 77631beaa..2630fe290 100644 --- a/common_modules/module_manager/inc/txm_module_manager_util.h +++ b/common_modules/module_manager/inc/txm_module_manager_util.h @@ -120,6 +120,16 @@ #define TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_CREATION(module_instance, obj_ptr, obj_size) \ (_txm_module_manager_param_check_object_for_creation(module_instance, obj_ptr, obj_size)) +/* When deleting an object, being allowed to use it is not enough. Deletion is the + inverse of creation, so it asks what creation asks: that the object is one this + module allocated from the manager's object pool, at the exact address the manager + gave it, for an object of this size. A module may hold a pointer to an object it + does not own -- the manager's object lookup service hands application-owned + objects to modules by name, and sharing an object is what that service is for -- + and this is what separates using such an object from destroying it. */ +#define TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_DELETION(module_instance, obj_ptr, obj_size) \ + (_txm_module_manager_allocated_object_check(module_instance, obj_ptr, obj_size)) + /* Strings we dereference can be in RW/RO/Shared areas. */ #define TXM_MODULE_MANAGER_PARAM_CHECK_DEREFERENCE_STRING(module_instance, string_ptr) \ ((TXM_MODULE_MANAGER_ENSURE_INSIDE_MODULE(module_instance, string_ptr, 1)) || \ @@ -147,6 +157,8 @@ UINT _txm_module_manager_param_check_object_for_creation(TXM_MODULE_INSTANCE UINT _txm_module_manager_param_check_object_for_use(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE object_ptr, ULONG object_size); UINT _txm_module_manager_param_check_typed_object_for_use(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE object_ptr, UINT object_type); UINT _txm_module_manager_allocated_object_check(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE object_ptr, ULONG object_size); +TXM_MODULE_ALLOCATED_OBJECT + *_txm_module_manager_allocated_object_find(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE object_ptr, ULONG *object_size_ptr); UINT _txm_module_manager_object_type_size_get(UINT object_type, ULONG *object_size); UINT _txm_module_manager_created_object_type_check(ALIGN_TYPE object_ptr, UINT object_type); UINT _txm_module_manager_object_id_check(ALIGN_TYPE object_ptr, UINT object_type); diff --git a/common_modules/module_manager/src/txm_module_manager_object_deallocate.c b/common_modules/module_manager/src/txm_module_manager_object_deallocate.c index c34a0005f..43d96f3c1 100644 --- a/common_modules/module_manager/src/txm_module_manager_object_deallocate.c +++ b/common_modules/module_manager/src/txm_module_manager_object_deallocate.c @@ -27,6 +27,7 @@ #include "tx_api.h" #include "tx_thread.h" #include "txm_module.h" +#include "txm_module_manager_util.h" /**************************************************************************/ /* */ @@ -52,6 +53,13 @@ /* tx_*_delete() service is sufficient; pool deallocation is handled */ /* automatically by the dispatch layer. */ /* */ +/* Only memory the calling module allocated from the object pool is */ +/* released, and the allocation is identified by searching the */ +/* module's own allocation list rather than by reading a private */ +/* header from in front of the address the caller supplied. An */ +/* address that names none of this module's allocations returns */ +/* TX_PTR_ERROR and is not dereferenced. */ +/* */ /* INPUT */ /* */ /* object_ptr Object pointer to deallocate */ @@ -64,6 +72,8 @@ /* */ /* _txe_mutex_get Get module instance mutex */ /* _txe_mutex_put Release module instance mutex */ +/* _txm_module_manager_allocated_object_find */ +/* Find the module's allocation */ /* _txe_byte_release Release object back to pool */ /* */ /* */ @@ -90,14 +100,32 @@ UINT return_value; /* Pickup module instance pointer. */ module_instance = _tx_thread_current_ptr -> tx_thread_module_instance_ptr; - /* Setup the memory pointer. */ - module_allocated_object_ptr = (TXM_MODULE_ALLOCATED_OBJECT *) object_ptr; - - /* Position the object pointer backwards to position back to the module manager information. */ - previous_object = module_allocated_object_ptr--; + /* Find the allocation this address names. + + The private header in front of an allocation is the manager's own + record of who the memory belongs to, but it is only a header when the + address is one the manager gave out. Reaching it by subtraction from + whatever address the caller supplied assumes the answer: for an object + the application allocated statically, or for any address outside the + object pool, the words in front of it are unrelated memory, and this + read them in privileged mode before deciding they were not a header. + Every delete dispatcher reaches this function with the address the + module named, so an object the module does not own arrived here as a + matter of course rather than exceptionally. + + Searching the module's own allocation list answers the same question + without that assumption. The address is compared against the + allocations the manager made for this module and is never + dereferenced, so an address that names none of them -- an object the + application owns, an object another module owns, or an address nowhere + near the object pool -- is refused without a privileged read. The + search also establishes what the header read could not: that the + address is the exact start of an allocation rather than somewhere + inside one. */ + module_allocated_object_ptr = _txm_module_manager_allocated_object_find(module_instance, (ALIGN_TYPE) object_ptr, TX_NULL); /* Make sure the object is valid. */ - if ((module_allocated_object_ptr == TX_NULL) || (module_allocated_object_ptr -> txm_module_allocated_object_module_instance != module_instance) || (module_instance -> txm_module_instance_object_list_count == 0)) + if (module_allocated_object_ptr == TX_NULL) { /* Set return value to invalid pointer. */ return_value = TX_PTR_ERROR; diff --git a/common_modules/module_manager/src/txm_module_manager_util.c b/common_modules/module_manager/src/txm_module_manager_util.c index 1b60f9000..ba7e5a291 100644 --- a/common_modules/module_manager/src/txm_module_manager_util.c +++ b/common_modules/module_manager/src/txm_module_manager_util.c @@ -633,7 +633,7 @@ UINT status; /* */ /* FUNCTION RELEASE */ /* */ -/* _txm_module_manager_allocated_object_check PORTABLE C */ +/* _txm_module_manager_allocated_object_find PORTABLE C */ /* 6.4.3 */ /* AUTHOR */ /* */ @@ -641,29 +641,42 @@ UINT status; /* */ /* DESCRIPTION */ /* */ -/* This function determines whether an address is the exact address */ -/* the manager handed the specified module for one of its object */ -/* allocations, and whether that allocation is the size the caller */ -/* expects. */ -/* */ -/* The allocation list is the manager's own record, built as it hands */ -/* object memory out. Comparing against it is what makes an address */ -/* inside the object pool distinguishable from the exact start of an */ -/* allocation. Reading a header in front of a candidate address cannot */ -/* make that distinction: the bytes in front of an address chosen */ -/* inside an allocation are part of the object, and a module can place */ -/* values there through ordinary create and set services. */ +/* This function returns the manager's private header for the object */ +/* allocation an address names, or TX_NULL when the address names */ +/* none of the specified module's allocations. The size the */ +/* allocation was made for is reported to callers that ask for it. */ +/* */ +/* The allocation list is the manager's own record, built as it hands */ +/* object memory out, and it is searched rather than reached through */ +/* a header taken from in front of the caller's address. That order */ +/* is what makes the answer both correct and safe. */ +/* */ +/* Correct, because the address immediately after a header is the */ +/* only address in an allocation that the manager ever gave out, so */ +/* an address chosen inside an allocation is distinguishable from the */ +/* start of one. Reading a header cannot make that distinction: the */ +/* bytes in front of an interior address are part of the object, and */ +/* a module places values there through ordinary services. */ +/* */ +/* Safe, because the caller's address is only ever compared, never */ +/* dereferenced. An address that belongs to no allocation of this */ +/* module -- an object the application owns, an object another module */ +/* owns, or an address nowhere near the object pool -- is rejected */ +/* without a privileged read of the words in front of it. */ /* */ /* INPUT */ /* */ /* module_instance Requesting module instance pointer*/ /* object_ptr Address of object memory area */ -/* object_size Expected size of the allocation */ +/* object_size_ptr Address to return the size the */ +/* allocation was made for, or */ +/* TX_NULL to not return it */ /* */ /* OUTPUT */ /* */ -/* TX_TRUE An exact allocation of that size */ -/* TX_FALSE Anything else */ +/* allocation The allocation's private header, */ +/* or TX_NULL when the address */ +/* names none of this module's */ /* */ /* CALLS */ /* */ @@ -671,8 +684,9 @@ UINT status; /* */ /* CALLED BY */ /* */ -/* _txm_module_manager_param_check_object_for_use */ -/* Module object authentication */ +/* _txm_module_manager_allocated_object_check */ +/* Module object ownership check */ +/* _txm_module_manager_object_deallocate Module object deallocation */ /* */ /* RELEASE HISTORY */ /* */ @@ -682,18 +696,27 @@ UINT status; /* contributors */ /* */ /**************************************************************************/ -UINT _txm_module_manager_allocated_object_check(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE object_ptr, ULONG object_size) +TXM_MODULE_ALLOCATED_OBJECT *_txm_module_manager_allocated_object_find(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE object_ptr, ULONG *object_size_ptr) { TX_INTERRUPT_SAVE_AREA TXM_MODULE_ALLOCATED_OBJECT *allocated_object_ptr; +TXM_MODULE_ALLOCATED_OBJECT *found_object_ptr; ULONG objects_examined; -UINT status; - /* Assume the address is not one of this module's allocations. */ - status = TX_FALSE; + /* Assume the address names none of this module's allocations. */ + found_object_ptr = TX_NULL; + + /* Determine if there is a module whose allocations can be searched. A request + that does not come from a module owns no allocation. */ + if (module_instance == TX_NULL) + { + + /* Nothing to search, and nothing to report. */ + return(TX_NULL); + } /* Disable interrupts. The allocation list is maintained by threads holding the manager protection mutex, so a scan that runs to completion with interrupts @@ -705,7 +728,7 @@ UINT status; objects_examined = ((ULONG) 0); /* Loop through the objects allocated to this module. The loop is bounded by the - count the manager maintains alongside the list, so the cost of one check is + count the manager maintains alongside the list, so the cost of one search is bounded by the number of objects this module has allocated, and a list whose links have been damaged cannot make the scan run on. */ while ((objects_examined < module_instance -> txm_module_instance_object_list_count) && @@ -717,17 +740,19 @@ UINT status; if (((ALIGN_TYPE) (allocated_object_ptr + 1)) == object_ptr) { - /* Is the allocation the size the caller expects? An allocation made for a - smaller object does not become a larger one because a service was asked - to treat it as one. */ - if (allocated_object_ptr -> txm_module_object_size == object_size) + /* Found it. An address matches at most one allocation, so there is + nothing further to look at. */ + found_object_ptr = allocated_object_ptr; + + /* Report the size this allocation was made for, if the caller asked for + it. It is read here, inside the scan, so that the answer cannot be + taken from a header that stopped being one after the search. */ + if (object_size_ptr != TX_NULL) { - status = TX_TRUE; + *object_size_ptr = allocated_object_ptr -> txm_module_object_size; } - /* An address matches at most one allocation, so there is nothing further - to look at either way. */ break; } @@ -739,6 +764,92 @@ UINT status; /* Restore interrupts. */ TX_RESTORE + return(found_object_ptr); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txm_module_manager_allocated_object_check PORTABLE C */ +/* 6.4.3 */ +/* AUTHOR */ +/* */ +/* Eclipse ThreadX contributors */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function determines whether an address is the exact address */ +/* the manager handed the specified module for one of its object */ +/* allocations, and whether that allocation is the size the caller */ +/* expects. */ +/* */ +/* This is the question of ownership, and it is deliberately a */ +/* separate question from whether an object is there at all. A */ +/* module may hold, and legitimately use, a pointer to an object it */ +/* does not own: the manager hands application-owned objects to */ +/* modules by name through its object lookup service, and sharing an */ +/* object is what that service is for. Destroying one is not sharing */ +/* it, so the delete services ask this question in addition to the */ +/* ones that establish that the address denotes a usable object. */ +/* */ +/* INPUT */ +/* */ +/* module_instance Requesting module instance pointer*/ +/* object_ptr Address of object memory area */ +/* object_size Expected size of the allocation */ +/* */ +/* OUTPUT */ +/* */ +/* TX_TRUE An exact allocation of that size */ +/* TX_FALSE Anything else */ +/* */ +/* CALLS */ +/* */ +/* _txm_module_manager_allocated_object_find */ +/* Find the module's allocation */ +/* */ +/* CALLED BY */ +/* */ +/* txm_module_manager_* Module manager functions */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-2026 Eclipse ThreadX Initial Version 6.4.3 */ +/* contributors */ +/* */ +/**************************************************************************/ +UINT _txm_module_manager_allocated_object_check(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE object_ptr, ULONG object_size) +{ + +ULONG allocated_size; +UINT status; + + + /* Assume the address is not one of this module's allocations. */ + status = TX_FALSE; + + /* Initialize the size, so that nothing is read if no allocation is found. */ + allocated_size = ((ULONG) 0); + + /* Determine if the address is the exact start of one of this module's + allocations. */ + if (_txm_module_manager_allocated_object_find(module_instance, object_ptr, &allocated_size) != TX_NULL) + { + + /* Is the allocation the size the caller expects? An allocation made for a + smaller object does not become a larger one because a service was asked + to treat it as one. */ + if (allocated_size == object_size) + { + + status = TX_TRUE; + } + } + return(status); } diff --git a/test/tx/cmake/module_manager/CMakeLists.txt b/test/tx/cmake/module_manager/CMakeLists.txt index 35a6f8bb4..695a1fe5a 100644 --- a/test/tx/cmake/module_manager/CMakeLists.txt +++ b/test/tx/cmake/module_manager/CMakeLists.txt @@ -103,3 +103,27 @@ target_compile_options( add_test(${CMAKE_BUILD_TYPE}::threadx_module_manager_object_authentication_test threadx_module_manager_object_authentication_test) + +# This test drives the manager services directly rather than through a dispatcher, +# so it needs none of the dispatch table and no guard list. +add_executable( + threadx_module_manager_delete_ownership_test + ${SOURCE_DIR}/threadx_module_manager_delete_ownership_test.c + ${module_manager_dir}/src/txm_module_manager_util.c + ${module_manager_dir}/src/txm_module_manager_object_allocate.c + ${module_manager_dir}/src/txm_module_manager_object_deallocate.c) + +target_include_directories( + threadx_module_manager_delete_ownership_test + PRIVATE ${SOURCE_DIR} + ${REPO_ROOT}/common/inc + ${REPO_ROOT}/common_modules/inc + ${module_manager_dir}/inc + ${cortex_a7_module_dir}/inc) + +target_compile_options( + threadx_module_manager_delete_ownership_test + PRIVATE -include ${SOURCE_DIR}/threadx_module_manager_host_test_port.h) + +add_test(${CMAKE_BUILD_TYPE}::threadx_module_manager_delete_ownership_test + threadx_module_manager_delete_ownership_test) diff --git a/test/tx/module_manager/threadx_module_manager_delete_ownership_test.c b/test/tx/module_manager/threadx_module_manager_delete_ownership_test.c new file mode 100644 index 000000000..a84772533 --- /dev/null +++ b/test/tx/module_manager/threadx_module_manager_delete_ownership_test.c @@ -0,0 +1,992 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Test */ +/** */ +/** Module Manager kernel object delete ownership */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +/* A module reaches a kernel object's delete service through the Module Manager's + dispatch layer, which ran one check on the pointer: that the object lies outside + the module's own code and data. That is the policy for using an object, and using + an object a module does not own is supported -- the manager hands application-owned + objects to modules by name through its object lookup service, and sharing is what + that service is for. Destroying one is not sharing it. + + Two things follow from the missing question, and this test covers both. + + The manager's private header sits immediately in front of each allocation it makes, + and records which module the allocation belongs to. The deallocation the delete path + performs afterwards reached that header by subtracting from whatever address the + caller supplied, and read it before deciding whether it was a header at all. For an + object the application allocated statically, or for any address outside the object + pool, the words in front of it are unrelated memory read in privileged mode -- and + acted on: an address whose preceding words happen to name the calling module was + unlinked from that module's allocation list and handed to the byte pool. + + The manager now finds the allocation by searching the module's own allocation list + instead. The caller's address is compared, never dereferenced, so an address that + names none of this module's allocations is refused without a privileged read of + anything in front of it -- and the search establishes what the header read could + not, that the address is the exact start of an allocation rather than somewhere + inside one. + + The same search is the ownership question the delete dispatchers now ask before the + delete rather than after it. It is a separate question from whether an object is + there and of the expected type, and it is composed with that one rather than + replacing it. + + This test drives the search and the deallocation on the host. The object pool behind + it is modelled -- a bump allocator that hands back the block it most recently + released, so that an address a module has given up can be seen to come back to + another module -- while the record the fix actually consults is built the way the + system builds it, by running the real _txm_module_manager_object_allocate. + + The object standing for one the application owns is deliberately preceded by a + header naming the requesting module. Out-of-bounds reads do not fault on a host, so + that is how this test makes one observable: on the unfixed manager those words are + read and believed, and the application's object memory is released; here they must + be neither read nor believed. */ + +#include +#include + +#include "threadx_module_manager_host_test_port.h" + +#include "tx_thread.h" +#include "tx_timer.h" +#include "tx_queue.h" +#include "tx_event_flags.h" +#include "tx_semaphore.h" +#include "tx_mutex.h" +#include "tx_block_pool.h" +#include "tx_byte_pool.h" +#include "txm_module.h" +#include "txm_module_manager_util.h" + + +/* Define the stand-in interrupt lock the port shim counts through. */ + +unsigned int test_interrupt_disable_depth; +unsigned int test_interrupt_disable_max_depth; +unsigned int test_interrupt_restore_underflows; + + +/* Define the modelled object pool. */ + +#define TEST_POOL_BYTES ((ULONG) 8192) +#define TEST_MODULE_MEMORY_BYTES 512U + +static union +{ + ALIGN_TYPE test_pool_alignment; + UCHAR test_pool_bytes[TEST_POOL_BYTES]; +} test_pool_arena; + +static ULONG test_pool_offset; + + +/* Define the memory that stands for the calling module's own code and data. */ + +static union +{ + ALIGN_TYPE test_data_alignment; + UCHAR test_data_bytes[TEST_MODULE_MEMORY_BYTES]; +} test_module_data; + +static union +{ + ALIGN_TYPE test_code_alignment; + UCHAR test_code_bytes[TEST_MODULE_MEMORY_BYTES]; +} test_module_code; + + +/* Define an object that stands for one the application owns and shared with a + module by name. It lives outside the object pool, so the manager holds no + allocation record of it, and it carries in front of it exactly what the manager + would have put there had it allocated it -- a header naming the module that does + the asking below. Nothing outside this test can arrange those words; they are + here so that reading them can be seen to have happened. */ + +static struct +{ + TXM_MODULE_ALLOCATED_OBJECT test_host_header; + TX_QUEUE test_host_object; +} test_host_area; + + +/* Define the thread that stands for the module thread making the request. The + manager takes the calling module from it. */ + +static TX_THREAD test_current_thread; + + +/* Define the block the modelled pool most recently released, so that a later + allocation of the same size lands on the address a released one had, and so that + a case can see whether anything was released at all. */ + +static UCHAR *test_released_start; +static ULONG test_released_bytes; +static ULONG test_releases; + + +/* Define the manager state the code under test reaches for. */ + +TX_BYTE_POOL _txm_module_manager_object_pool; +UINT _txm_module_manager_object_pool_created; +TX_MUTEX _txm_module_manager_mutex; +TX_THREAD *_tx_thread_current_ptr; + + +/* The kernel's created lists. A created object lives on the list for its type, and + the manager reads those lists, so a test that stands in for the kernel has to + provide them. All stay empty here, because this test creates no kernel object; + it exercises ownership of the manager's own allocations. */ + +TX_BLOCK_POOL *_tx_block_pool_created_ptr; +ULONG _tx_block_pool_created_count; +TX_BYTE_POOL *_tx_byte_pool_created_ptr; +ULONG _tx_byte_pool_created_count; +TX_EVENT_FLAGS_GROUP *_tx_event_flags_created_ptr; +ULONG _tx_event_flags_created_count; +TX_MUTEX *_tx_mutex_created_ptr; +ULONG _tx_mutex_created_count; +TX_QUEUE *_tx_queue_created_ptr; +ULONG _tx_queue_created_count; +TX_SEMAPHORE *_tx_semaphore_created_ptr; +ULONG _tx_semaphore_created_count; +TX_THREAD *_tx_thread_created_ptr; +ULONG _tx_thread_created_count; +TX_TIMER *_tx_timer_created_ptr; +ULONG _tx_timer_created_count; + + +static UINT test_failures; +static ULONG test_checks; + + +/* Record the outcome of one expectation. */ +static VOID test_expect(const char *description, ULONG actual, ULONG expected) +{ + test_checks++; + + if (actual != expected) + { + printf("FAIL: %s (expected %lu, got %lu)\n", description, (unsigned long) expected, (unsigned long) actual); + test_failures++; + } +} + + +/* Report every module object type the manager knows and the size of its control + block, so that the cases below can be written once and run against all of them. + The size is what a delete dispatcher passes, and the eight sizes are not all + distinct: on a 32-bit target a byte pool, a mutex and a timer are the same size, + which is why the check below is an ownership check and not a type check. */ + +typedef struct TEST_OBJECT_KIND_STRUCT +{ + const char *test_kind_name; + ULONG test_kind_size; +} TEST_OBJECT_KIND; + +static const TEST_OBJECT_KIND test_object_kinds[] = +{ + { "block pool", (ULONG) sizeof(TX_BLOCK_POOL) }, + { "byte pool", (ULONG) sizeof(TX_BYTE_POOL) }, + { "event flags", (ULONG) sizeof(TX_EVENT_FLAGS_GROUP) }, + { "mutex", (ULONG) sizeof(TX_MUTEX) }, + { "queue", (ULONG) sizeof(TX_QUEUE) }, + { "semaphore", (ULONG) sizeof(TX_SEMAPHORE) }, + { "thread", (ULONG) sizeof(TX_THREAD) }, + { "timer", (ULONG) sizeof(TX_TIMER) } +}; + +#define TEST_OBJECT_KIND_COUNT (sizeof(test_object_kinds) / sizeof(test_object_kinds[0])) + + +/* Round a request up the way _tx_byte_allocate does. */ +static ULONG test_round_up(ULONG memory_size) +{ + return((((memory_size + ((ULONG) sizeof(ALIGN_TYPE))) - ((ULONG) 1)) / ((ULONG) sizeof(ALIGN_TYPE))) * ((ULONG) sizeof(ALIGN_TYPE))); +} + + +/* Stand in for the byte pool the manager allocates object memory from. + + The two size bounds are the real ones. The placement is a bump allocator with one + refinement: a request that exactly fits the block most recently released is given + that block back. A first-fit byte pool reuses freed memory, and the cases about an + address that has changed hands need the address to actually come back. */ +UINT _txe_byte_allocate(TX_BYTE_POOL *pool_ptr, VOID **memory_ptr, ULONG memory_size, ULONG wait_option) +{ + +ULONG rounded_size; +UCHAR *block_start; + + + (VOID) wait_option; + + if ((pool_ptr != &_txm_module_manager_object_pool) || (memory_ptr == TX_NULL)) + { + return(TX_POOL_ERROR); + } + + if (memory_size == ((ULONG) 0)) + { + return(TX_SIZE_ERROR); + } + + if (memory_size > pool_ptr -> tx_byte_pool_size) + { + return(TX_SIZE_ERROR); + } + + rounded_size = test_round_up(memory_size); + + if ((test_released_start != TX_NULL) && (test_released_bytes == rounded_size)) + { + block_start = test_released_start; + test_released_start = TX_NULL; + test_released_bytes = ((ULONG) 0); + } + else + { + if ((test_pool_offset + rounded_size) > TEST_POOL_BYTES) + { + return(TX_NO_MEMORY); + } + + block_start = &test_pool_arena.test_pool_bytes[test_pool_offset]; + test_pool_offset = test_pool_offset + rounded_size; + } + + pool_ptr -> tx_byte_pool_available = pool_ptr -> tx_byte_pool_available - rounded_size; + + *memory_ptr = (VOID *) block_start; + + return(TX_SUCCESS); +} + + +/* Stand in for the release side, remembering the block so it can come back, and + counting releases so that a case can see whether one happened. + + The bounds test is the one thing the model must keep: releasing an address the + pool never owned is the corruption the fix exists to prevent, so it is reported + as a failure rather than silently absorbed. */ +UINT _txe_byte_release(VOID *memory_ptr) +{ + +UCHAR *block_start; + + + block_start = (UCHAR *) memory_ptr; + + if ((block_start < test_pool_arena.test_pool_bytes) || + (block_start >= &test_pool_arena.test_pool_bytes[TEST_POOL_BYTES])) + { + printf("FAIL: an address outside the object pool was released to it\n"); + test_failures++; + + return(TX_PTR_ERROR); + } + + test_releases++; + + /* The model does not track block lengths, and the only released block a case + needs to come back is the one it just released, whose length it knows. The + length is recorded by the caller through test_release_size. */ + test_released_start = block_start; + + return(TX_SUCCESS); +} + + +/* Tell the model how long the block just released was. */ +static VOID test_release_size(ULONG object_size) +{ + test_released_bytes = test_round_up(object_size + ((ULONG) sizeof(TXM_MODULE_ALLOCATED_OBJECT))); +} + + +/* Stand in for the protection mutex. */ +UINT _txe_mutex_get(TX_MUTEX *mutex_ptr, ULONG wait_option) +{ + (VOID) mutex_ptr; + (VOID) wait_option; + + return(TX_SUCCESS); +} + + +UINT _txe_mutex_put(TX_MUTEX *mutex_ptr) +{ + (VOID) mutex_ptr; + + return(TX_SUCCESS); +} + + +/* Stand in for the module port's data range check. */ +UINT _txm_module_manager_inside_data_check(ULONG obj_ptr) +{ + +ULONG data_start; +ULONG data_end; + + + data_start = (ULONG) (ALIGN_TYPE) test_module_data.test_data_bytes; + data_end = data_start + ((ULONG) TEST_MODULE_MEMORY_BYTES); + + if ((obj_ptr >= data_start) && (obj_ptr < data_end)) + { + return(TX_TRUE); + } + + return(TX_FALSE); +} + + +/* Stand in for the port primitive a manager source under test refers to but that + no case here exercises. */ +VOID _txm_module_manager_alignment_adjust(TXM_MODULE_PREAMBLE *module_preamble, ULONG *code_size, + ULONG *code_alignment, ULONG *data_size, ULONG *data_alignment) +{ + (VOID) module_preamble; + (VOID) code_size; + (VOID) code_alignment; + (VOID) data_size; + (VOID) data_alignment; +} + + +/* Bring the pool, the modules and the application's object back to a known state. + + Everything is reset together deliberately. The allocation lists point into the + pool, so a case that left one behind would have the next case reading the + wreckage of an earlier one rather than what it was written to check. */ +static VOID test_reset(TXM_MODULE_INSTANCE *module_a, TXM_MODULE_INSTANCE *module_b) +{ + +UINT index; + + + for (index = 0U; index < (UINT) TEST_POOL_BYTES; index++) + { + test_pool_arena.test_pool_bytes[index] = (UCHAR) 0; + } + + for (index = 0U; index < TEST_MODULE_MEMORY_BYTES; index++) + { + test_module_data.test_data_bytes[index] = (UCHAR) 0; + test_module_code.test_code_bytes[index] = (UCHAR) 0; + } + + test_pool_offset = ((ULONG) 0); + test_released_start = TX_NULL; + test_released_bytes = ((ULONG) 0); + test_releases = ((ULONG) 0); + + _txm_module_manager_object_pool.tx_byte_pool_id = TX_BYTE_POOL_ID; + _txm_module_manager_object_pool.tx_byte_pool_start = test_pool_arena.test_pool_bytes; + _txm_module_manager_object_pool.tx_byte_pool_size = TEST_POOL_BYTES; + _txm_module_manager_object_pool.tx_byte_pool_available = TEST_POOL_BYTES; + _txm_module_manager_object_pool_created = TX_TRUE; + + module_a -> txm_module_instance_object_list_count = ((ULONG) 0); + module_a -> txm_module_instance_object_list_head = TX_NULL; + module_b -> txm_module_instance_object_list_count = ((ULONG) 0); + module_b -> txm_module_instance_object_list_head = TX_NULL; + + /* The application's object, and the header in front of it naming module A. The + links are made to point at the header itself, which is what an allocation + list of one looks like, so that the unfixed manager would find nothing + unusual about it either. */ + (VOID) memset((VOID *) &test_host_area, 0, sizeof(test_host_area)); + test_host_area.test_host_header.txm_module_allocated_object_module_instance = module_a; + test_host_area.test_host_header.txm_module_allocated_object_next = &test_host_area.test_host_header; + test_host_area.test_host_header.txm_module_allocated_object_previous = &test_host_area.test_host_header; + test_host_area.test_host_header.txm_module_object_size = (ULONG) sizeof(TX_QUEUE); + test_host_area.test_host_object.tx_queue_id = TX_QUEUE_ID; + + /* The requesting thread belongs to module A throughout, except where a case + says otherwise. */ + test_current_thread.tx_thread_module_instance_ptr = module_a; + _tx_thread_current_ptr = &test_current_thread; +} + + +/* Zero the interrupt lock accounting before a call into the manager. */ +static VOID test_interrupts_clear(VOID) +{ + test_interrupt_disable_depth = 0U; + test_interrupt_disable_max_depth = 0U; + test_interrupt_restore_underflows = 0U; +} + + +/* Whatever the manager decided, it must have left the interrupt lock as it found + it. */ +static VOID test_interrupts_check(const char *what) +{ + if ((test_interrupt_disable_depth != 0U) || (test_interrupt_restore_underflows != 0U)) + { + printf("FAIL: %s left the interrupt lock unbalanced (depth %u, underflows %u)\n", + what, test_interrupt_disable_depth, test_interrupt_restore_underflows); + test_failures++; + } +} + + +/* Allocate object memory for a module through the real manager path. */ +static VOID *test_allocate(TXM_MODULE_INSTANCE *module_instance, ULONG object_size) +{ + +VOID *object_ptr; +UINT status; + + + object_ptr = TX_NULL; + status = _txm_module_manager_object_allocate(&object_ptr, object_size, module_instance); + + if (status != TX_SUCCESS) + { + printf("FAIL: the modelled pool refused an allocation of %lu bytes (status %u)\n", + (unsigned long) object_size, status); + test_failures++; + + return(TX_NULL); + } + + return(object_ptr); +} + + +/* Ask the question a delete dispatcher asks: may this module destroy the object at + this address? The macro is what the dispatchers use, so the macro is what is + called here. */ +static ULONG test_owner_check(TXM_MODULE_INSTANCE *module_instance, VOID *object_ptr, ULONG object_size) +{ + +ULONG status; + + + test_interrupts_clear(); + + status = (ULONG) TXM_MODULE_MANAGER_PARAM_CHECK_OBJECT_FOR_DELETION(module_instance, + (ALIGN_TYPE) object_ptr, object_size); + + test_interrupts_check("the ownership check"); + + return(status); +} + + +/* Ask the manager to give an address back, with the same accounting. */ +static ULONG test_deallocate(VOID *object_ptr) +{ + +ULONG status; + + + test_interrupts_clear(); + + status = (ULONG) _txm_module_manager_object_deallocate(object_ptr); + + test_interrupts_check("the deallocation"); + + return(status); +} + + +int main(void) +{ + +TXM_MODULE_INSTANCE module_a; +TXM_MODULE_INSTANCE module_b; +const TEST_OBJECT_KIND *kind; +VOID *object; +VOID *second_object; +VOID *third_object; +VOID *reused_object; +TXM_MODULE_ALLOCATED_OBJECT *header_ptr; +ALIGN_TYPE address; +ULONG index; +ULONG offset; +ULONG reported_size; +char description[160]; + + + /* Report expectations before anything can crash, so that a case that brings the + process down is still preceded by everything that passed. */ + setvbuf(stdout, TX_NULL, _IONBF, 0); + + test_failures = 0U; + test_checks = ((ULONG) 0); + + /* Set up two memory-protected modules. Module A does the asking throughout; + module B is there to own allocations A did not make. */ + module_a.txm_module_instance_property_flags = TXM_MODULE_MEMORY_PROTECTION; + module_a.txm_module_instance_code_start = (VOID *) test_module_code.test_code_bytes; + module_a.txm_module_instance_code_end = (VOID *) &test_module_code.test_code_bytes[TEST_MODULE_MEMORY_BYTES - 1U]; + module_a.txm_module_instance_data_start = (VOID *) test_module_data.test_data_bytes; + module_a.txm_module_instance_data_end = (VOID *) &test_module_data.test_data_bytes[TEST_MODULE_MEMORY_BYTES - 1U]; + + module_b = module_a; + + /**********************************************************************/ + /* Every object type, owned and not owned. */ + /**********************************************************************/ + + for (index = ((ULONG) 0); index < (ULONG) TEST_OBJECT_KIND_COUNT; index++) + { + kind = &test_object_kinds[index]; + + test_reset(&module_a, &module_b); + + object = test_allocate(&module_a, kind -> test_kind_size); + + (void) snprintf(description, sizeof(description), + "the module that allocated a %s may delete it", kind -> test_kind_name); + test_expect(description, test_owner_check(&module_a, object, kind -> test_kind_size), (ULONG) TX_TRUE); + + /* The search has to have run with interrupts disabled, which is what keeps + it from observing the allocation list being changed under it. */ + test_expect("...found with interrupts disabled, one deep", + (ULONG) test_interrupt_disable_max_depth, ((ULONG) 1)); + + (void) snprintf(description, sizeof(description), + "another module may not delete that %s", kind -> test_kind_name); + test_expect(description, test_owner_check(&module_b, object, kind -> test_kind_size), (ULONG) TX_FALSE); + + (void) snprintf(description, sizeof(description), + "...and the refusal also ran with interrupts disabled"); + test_expect(description, (ULONG) test_interrupt_disable_max_depth, ((ULONG) 1)); + + (void) snprintf(description, sizeof(description), + "a %s allocation is not accepted as a larger object", kind -> test_kind_name); + test_expect(description, + test_owner_check(&module_a, object, kind -> test_kind_size + ((ULONG) sizeof(ALIGN_TYPE))), + (ULONG) TX_FALSE); + + (void) snprintf(description, sizeof(description), + "a %s allocation is not accepted as a smaller object", kind -> test_kind_name); + test_expect(description, + test_owner_check(&module_a, object, kind -> test_kind_size - ((ULONG) sizeof(ALIGN_TYPE))), + (ULONG) TX_FALSE); + + /* The search returns the allocation's own header, which is the one the + deallocation goes on to unlink. */ + test_interrupts_clear(); + reported_size = ((ULONG) 0); + header_ptr = _txm_module_manager_allocated_object_find(&module_a, (ALIGN_TYPE) object, &reported_size); + test_interrupts_check("the search"); + + (void) snprintf(description, sizeof(description), + "the search finds the header in front of the %s", kind -> test_kind_name); + test_expect(description, + (ULONG) (header_ptr == (((TXM_MODULE_ALLOCATED_OBJECT *) object) - 1)), (ULONG) TX_TRUE); + + (void) snprintf(description, sizeof(description), + "...and reports the size the %s allocation was made for", kind -> test_kind_name); + test_expect(description, reported_size, kind -> test_kind_size); + + /* A caller that does not want the size gets the same answer. */ + test_interrupts_clear(); + header_ptr = _txm_module_manager_allocated_object_find(&module_a, (ALIGN_TYPE) object, TX_NULL); + test_interrupts_check("the search"); + + test_expect("a search that does not ask for the size finds the same allocation", + (ULONG) (header_ptr == (((TXM_MODULE_ALLOCATED_OBJECT *) object) - 1)), (ULONG) TX_TRUE); + + /* Another module asking for the same address is told there is nothing, and + is told it without a size being written anywhere. */ + test_interrupts_clear(); + reported_size = (ULONG) 0xA5A5A5A5UL; + header_ptr = _txm_module_manager_allocated_object_find(&module_b, (ALIGN_TYPE) object, &reported_size); + test_interrupts_check("the search"); + + test_expect("a search of another module's allocations finds nothing", + (ULONG) (header_ptr == TX_NULL), (ULONG) TX_TRUE); + test_expect("...and reports no size", + reported_size, (ULONG) 0xA5A5A5A5UL); + + /* The deallocation the delete dispatcher performs after a successful delete + still goes through for the module that owns the memory. */ + test_release_size(kind -> test_kind_size); + + (void) snprintf(description, sizeof(description), + "the owning module gets its %s memory back", kind -> test_kind_name); + test_expect(description, test_deallocate(object), (ULONG) TX_SUCCESS); + test_expect("...released exactly once", test_releases, ((ULONG) 1)); + test_expect("...leaving nothing on its allocation list", + module_a.txm_module_instance_object_list_count, ((ULONG) 0)); + } + + /**********************************************************************/ + /* The reported call: an object the application owns. */ + /**********************************************************************/ + + test_reset(&module_a, &module_b); + + object = test_allocate(&module_a, (ULONG) sizeof(TX_QUEUE)); + + /* What the fixture is: the words in front of the application's object name the + module that is about to ask, so a manager that reads them finds its own + header there. That is the read the fix removes. */ + test_expect("the words in front of the application's object name the asking module", + (ULONG) ((((TXM_MODULE_ALLOCATED_OBJECT *) &test_host_area.test_host_object) - 1) + -> txm_module_allocated_object_module_instance == &module_a), + (ULONG) TX_TRUE); + + test_expect("the application's object is outside the object pool", + (ULONG) (((UCHAR *) &test_host_area.test_host_object) < test_pool_arena.test_pool_bytes || + ((UCHAR *) &test_host_area.test_host_object) >= &test_pool_arena.test_pool_bytes[TEST_POOL_BYTES]), + (ULONG) TX_TRUE); + + test_expect("a module may not delete an object the application owns", + test_owner_check(&module_a, &test_host_area.test_host_object, (ULONG) sizeof(TX_QUEUE)), + (ULONG) TX_FALSE); + + test_expect("and the manager will not give its memory back either", + test_deallocate(&test_host_area.test_host_object), (ULONG) TX_PTR_ERROR); + + test_expect("...having released nothing", test_releases, ((ULONG) 0)); + + test_expect("...left the module's own allocation on its list", + module_a.txm_module_instance_object_list_count, ((ULONG) 1)); + + test_expect("...with the list head where it was", + (ULONG) (module_a.txm_module_instance_object_list_head == (((TXM_MODULE_ALLOCATED_OBJECT *) object) - 1)), + (ULONG) TX_TRUE); + + test_expect("...and the application's object untouched", + (ULONG) test_host_area.test_host_object.tx_queue_id, (ULONG) TX_QUEUE_ID); + + /* The module's own object is unaffected by the refusal, and still deletable. */ + test_release_size((ULONG) sizeof(TX_QUEUE)); + test_expect("the module can still delete its own object afterwards", + test_deallocate(object), (ULONG) TX_SUCCESS); + + /**********************************************************************/ + /* An object another module owns. */ + /**********************************************************************/ + + test_reset(&module_a, &module_b); + + object = test_allocate(&module_a, (ULONG) sizeof(TX_QUEUE)); + second_object = test_allocate(&module_b, (ULONG) sizeof(TX_QUEUE)); + + test_expect("module A may delete its own object", + test_owner_check(&module_a, object, (ULONG) sizeof(TX_QUEUE)), (ULONG) TX_TRUE); + test_expect("module A may not delete module B's object", + test_owner_check(&module_a, second_object, (ULONG) sizeof(TX_QUEUE)), (ULONG) TX_FALSE); + test_expect("module B may delete its own object", + test_owner_check(&module_b, second_object, (ULONG) sizeof(TX_QUEUE)), (ULONG) TX_TRUE); + test_expect("module B may not delete module A's object", + test_owner_check(&module_b, object, (ULONG) sizeof(TX_QUEUE)), (ULONG) TX_FALSE); + + /* And the deallocation refuses it too, so a module that reached it another way + is stopped there as well. */ + test_expect("module A cannot give back module B's memory", + test_deallocate(second_object), (ULONG) TX_PTR_ERROR); + test_expect("...having released nothing", test_releases, ((ULONG) 0)); + test_expect("...leaving module B's allocation on module B's list", + module_b.txm_module_instance_object_list_count, ((ULONG) 1)); + + /**********************************************************************/ + /* Addresses that are not the start of an allocation. */ + /**********************************************************************/ + + test_reset(&module_a, &module_b); + + object = test_allocate(&module_a, (ULONG) sizeof(TX_QUEUE)); + second_object = test_allocate(&module_a, (ULONG) sizeof(TX_QUEUE)); + + test_expect("the header in front of an allocation is not the allocation", + test_owner_check(&module_a, (VOID *) ((((TXM_MODULE_ALLOCATED_OBJECT *) object) - 1)), + (ULONG) sizeof(TX_QUEUE)), + (ULONG) TX_FALSE); + + /* Every aligned address inside the object, which is where a shifted pointer + lands. The bytes in front of one of these are the object's own, so a manager + that read a header there would be reading what the module put there. */ + for (offset = (ULONG) sizeof(ALIGN_TYPE); + offset < (ULONG) sizeof(TX_QUEUE); + offset = offset + (ULONG) sizeof(ALIGN_TYPE)) + { + address = ((ALIGN_TYPE) object) + (ALIGN_TYPE) offset; + + (void) snprintf(description, sizeof(description), + "an address %lu bytes into an allocation is not that allocation", (unsigned long) offset); + test_expect(description, test_owner_check(&module_a, (VOID *) address, (ULONG) sizeof(TX_QUEUE)), + (ULONG) TX_FALSE); + + (void) snprintf(description, sizeof(description), + "...and the manager will not give back %lu bytes in", (unsigned long) offset); + test_expect(description, test_deallocate((VOID *) address), (ULONG) TX_PTR_ERROR); + } + + test_expect("the address one past an allocation is not that allocation", + test_owner_check(&module_a, (VOID *) (((ALIGN_TYPE) object) + (ALIGN_TYPE) sizeof(TX_QUEUE)), + (ULONG) sizeof(TX_QUEUE)), + (ULONG) TX_FALSE); + + test_expect("nothing was released by any of that", test_releases, ((ULONG) 0)); + test_expect("...and both allocations are still on the list", + module_a.txm_module_instance_object_list_count, ((ULONG) 2)); + + /**********************************************************************/ + /* Addresses with nothing behind them at all. */ + /**********************************************************************/ + + test_reset(&module_a, &module_b); + + object = test_allocate(&module_a, (ULONG) sizeof(TX_QUEUE)); + + test_expect("a null pointer names no allocation", + test_owner_check(&module_a, TX_NULL, (ULONG) sizeof(TX_QUEUE)), (ULONG) TX_FALSE); + test_expect("...and is refused by the deallocation", + test_deallocate(TX_NULL), (ULONG) TX_PTR_ERROR); + + test_expect("an address with no room for a header in front of it names no allocation", + test_owner_check(&module_a, (VOID *) ((ALIGN_TYPE) sizeof(TXM_MODULE_ALLOCATED_OBJECT)), + (ULONG) sizeof(TX_QUEUE)), + (ULONG) TX_FALSE); + + test_expect("the start of the object pool names no allocation", + test_owner_check(&module_a, (VOID *) test_pool_arena.test_pool_bytes, (ULONG) sizeof(TX_QUEUE)), + (ULONG) TX_FALSE); + + test_expect("the last byte of the object pool names no allocation", + test_owner_check(&module_a, (VOID *) &test_pool_arena.test_pool_bytes[TEST_POOL_BYTES - 1U], + (ULONG) sizeof(TX_QUEUE)), + (ULONG) TX_FALSE); + + test_expect("the address one past the object pool names no allocation", + test_owner_check(&module_a, (VOID *) &test_pool_arena.test_pool_bytes[TEST_POOL_BYTES], + (ULONG) sizeof(TX_QUEUE)), + (ULONG) TX_FALSE); + + test_expect("an address inside the calling module's own data names no allocation", + test_owner_check(&module_a, (VOID *) test_module_data.test_data_bytes, (ULONG) sizeof(TX_QUEUE)), + (ULONG) TX_FALSE); + + test_expect("nothing was released by any of that", test_releases, ((ULONG) 0)); + + /**********************************************************************/ + /* A request that comes from no module. */ + /**********************************************************************/ + + test_reset(&module_a, &module_b); + + object = test_allocate(&module_a, (ULONG) sizeof(TX_QUEUE)); + + test_expect("no module owns anything", + test_owner_check(TX_NULL, object, (ULONG) sizeof(TX_QUEUE)), (ULONG) TX_FALSE); + + test_interrupts_clear(); + header_ptr = _txm_module_manager_allocated_object_find(TX_NULL, (ALIGN_TYPE) object, TX_NULL); + test_interrupts_check("the search"); + + test_expect("...and there is no list to search", + (ULONG) (header_ptr == TX_NULL), (ULONG) TX_TRUE); + test_expect("...reached without disabling interrupts at all", + (ULONG) test_interrupt_disable_max_depth, ((ULONG) 0)); + + /* The deallocation service is documented as callable by the application, and an + application thread carries no module instance. */ + test_current_thread.tx_thread_module_instance_ptr = TX_NULL; + + test_expect("a caller that is not a module cannot give a module's memory back", + test_deallocate(object), (ULONG) TX_PTR_ERROR); + test_expect("...having released nothing", test_releases, ((ULONG) 0)); + + test_current_thread.tx_thread_module_instance_ptr = &module_a; + + /**********************************************************************/ + /* Memory that has changed hands. */ + /**********************************************************************/ + + test_reset(&module_a, &module_b); + + object = test_allocate(&module_a, (ULONG) sizeof(TX_QUEUE)); + + test_release_size((ULONG) sizeof(TX_QUEUE)); + test_expect("module A gives its memory back", test_deallocate(object), (ULONG) TX_SUCCESS); + + test_expect("...and may not delete the object there any more", + test_owner_check(&module_a, object, (ULONG) sizeof(TX_QUEUE)), (ULONG) TX_FALSE); + + test_expect("...nor give the same address back a second time", + test_deallocate(object), (ULONG) TX_PTR_ERROR); + + /* The pool hands the same address to module B, and the stale pointer module A + still holds now names memory that belongs to someone else. */ + reused_object = test_allocate(&module_b, (ULONG) sizeof(TX_QUEUE)); + + test_expect("the pool handed the same address to module B", + (ULONG) (reused_object == object), (ULONG) TX_TRUE); + test_expect("module A's stale pointer does not let it delete module B's object", + test_owner_check(&module_a, reused_object, (ULONG) sizeof(TX_QUEUE)), (ULONG) TX_FALSE); + test_expect("module B may delete what it was given", + test_owner_check(&module_b, reused_object, (ULONG) sizeof(TX_QUEUE)), (ULONG) TX_TRUE); + test_expect("module A's stale pointer does not get the memory back either", + test_deallocate(reused_object), (ULONG) TX_PTR_ERROR); + test_expect("...leaving module B's allocation on module B's list", + module_b.txm_module_instance_object_list_count, ((ULONG) 1)); + + /**********************************************************************/ + /* What bounds the search. */ + /**********************************************************************/ + + test_reset(&module_a, &module_b); + + object = test_allocate(&module_a, (ULONG) sizeof(TX_QUEUE)); + second_object = test_allocate(&module_a, (ULONG) sizeof(TX_QUEUE)); + third_object = test_allocate(&module_a, (ULONG) sizeof(TX_QUEUE)); + + test_expect("three allocations are on the list", module_a.txm_module_instance_object_list_count, ((ULONG) 3)); + test_expect("each of the three is found", + test_owner_check(&module_a, object, (ULONG) sizeof(TX_QUEUE)) + + test_owner_check(&module_a, second_object, (ULONG) sizeof(TX_QUEUE)) + + test_owner_check(&module_a, third_object, (ULONG) sizeof(TX_QUEUE)), + ((ULONG) 3) * (ULONG) TX_TRUE); + + /* A count smaller than the list stops the search early. Only the allocations + the count covers are found, which is what keeps the cost of a check bounded + by what the manager itself recorded. */ + module_a.txm_module_instance_object_list_count = ((ULONG) 1); + + test_expect("a search bounded by a count of one reaches the head", + test_owner_check(&module_a, module_a.txm_module_instance_object_list_head + 1, + (ULONG) sizeof(TX_QUEUE)), + (ULONG) TX_TRUE); + test_expect("...and goes no further", + test_owner_check(&module_a, object, (ULONG) sizeof(TX_QUEUE)) + + test_owner_check(&module_a, second_object, (ULONG) sizeof(TX_QUEUE)) + + test_owner_check(&module_a, third_object, (ULONG) sizeof(TX_QUEUE)), + (ULONG) TX_TRUE); + + module_a.txm_module_instance_object_list_count = ((ULONG) 3); + + /* A count larger than the list, with the chain broken, stops the search at the + break rather than running on into whatever follows. */ + (((TXM_MODULE_ALLOCATED_OBJECT *) second_object) - 1) -> txm_module_allocated_object_next = TX_NULL; + module_a.txm_module_instance_object_list_count = ((ULONG) 64); + + test_expect("a search stops at a broken link rather than running on", + test_owner_check(&module_a, third_object, (ULONG) sizeof(TX_QUEUE)), (ULONG) TX_FALSE); + test_expect("...having still found what came before the break", + test_owner_check(&module_a, second_object, (ULONG) sizeof(TX_QUEUE)), (ULONG) TX_TRUE); + + /* An empty list, which is the state a module starts in and the state the + manager is left in by module stop. */ + module_a.txm_module_instance_object_list_count = ((ULONG) 0); + module_a.txm_module_instance_object_list_head = TX_NULL; + + test_expect("a module that has allocated nothing owns nothing", + test_owner_check(&module_a, object, (ULONG) sizeof(TX_QUEUE)), (ULONG) TX_FALSE); + test_expect("...and gets nothing back", + test_deallocate(object), (ULONG) TX_PTR_ERROR); + + /**********************************************************************/ + /* Giving memory back, in each of the shapes the list can be in. */ + /**********************************************************************/ + + test_reset(&module_a, &module_b); + + object = test_allocate(&module_a, (ULONG) sizeof(TX_QUEUE)); + second_object = test_allocate(&module_a, (ULONG) sizeof(TX_QUEUE)); + third_object = test_allocate(&module_a, (ULONG) sizeof(TX_QUEUE)); + + test_expect("the first allocation is the list head", + (ULONG) (module_a.txm_module_instance_object_list_head == (((TXM_MODULE_ALLOCATED_OBJECT *) object) - 1)), + (ULONG) TX_TRUE); + + /* Releasing one that is not the head links its neighbours together and leaves + the head alone. */ + test_release_size((ULONG) sizeof(TX_QUEUE)); + test_expect("releasing an allocation in the middle succeeds", + test_deallocate(second_object), (ULONG) TX_SUCCESS); + test_expect("...leaving two on the list", module_a.txm_module_instance_object_list_count, ((ULONG) 2)); + test_expect("...with the head where it was", + (ULONG) (module_a.txm_module_instance_object_list_head == (((TXM_MODULE_ALLOCATED_OBJECT *) object) - 1)), + (ULONG) TX_TRUE); + test_expect("...and the released one no longer owned", + test_owner_check(&module_a, second_object, (ULONG) sizeof(TX_QUEUE)), (ULONG) TX_FALSE); + + /* Releasing the head moves it on. */ + test_release_size((ULONG) sizeof(TX_QUEUE)); + test_expect("releasing the head allocation succeeds", + test_deallocate(object), (ULONG) TX_SUCCESS); + test_expect("...leaving one on the list", module_a.txm_module_instance_object_list_count, ((ULONG) 1)); + test_expect("...and the head moved on to it", + (ULONG) (module_a.txm_module_instance_object_list_head == (((TXM_MODULE_ALLOCATED_OBJECT *) third_object) - 1)), + (ULONG) TX_TRUE); + + /* Releasing the last empties the list. */ + test_release_size((ULONG) sizeof(TX_QUEUE)); + test_expect("releasing the last allocation succeeds", + test_deallocate(third_object), (ULONG) TX_SUCCESS); + test_expect("...emptying the list", module_a.txm_module_instance_object_list_count, ((ULONG) 0)); + test_expect("...and clearing its head", + (ULONG) (module_a.txm_module_instance_object_list_head == TX_NULL), (ULONG) TX_TRUE); + test_expect("three allocations were released and no more", test_releases, ((ULONG) 3)); + + /**********************************************************************/ + /* An object pool that was never created. */ + /**********************************************************************/ + + test_reset(&module_a, &module_b); + + object = test_allocate(&module_a, (ULONG) sizeof(TX_QUEUE)); + + _txm_module_manager_object_pool_created = TX_FALSE; + + test_expect("with no object pool the deallocation reports the feature is not available", + test_deallocate(object), (ULONG) TX_NOT_AVAILABLE); + test_expect("...having released nothing", test_releases, ((ULONG) 0)); + + /* The ownership question does not depend on the pool flag: it is answered from + the module's allocation list, which is where the manager recorded what it + handed out. */ + test_expect("...and the ownership question is still answered from the allocation list", + test_owner_check(&module_a, object, (ULONG) sizeof(TX_QUEUE)), (ULONG) TX_TRUE); + + _txm_module_manager_object_pool_created = TX_TRUE; + + /**********************************************************************/ + /* What the whole run has to have held. */ + /**********************************************************************/ + + test_expect("every case ran", (ULONG) (test_checks > ((ULONG) 100)), (ULONG) TX_TRUE); + + if (test_failures == 0U) + { + printf("SUCCESS! %lu expectations\n", (unsigned long) test_checks); + return(0); + } + + printf("ERROR: %u expectation(s) failed of %lu\n", test_failures, (unsigned long) test_checks); + return(1); +} From 2930618cfeb77af872c7b3e13bf584c85c2ac153 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 28 Sep 2026 10:13:22 -0400 Subject: [PATCH 154/181] Merge commit from fork * Refused to give back the memory of a live kernel object A module allocates the control blocks of its kernel objects from the Module Manager's object pool and can ask for that memory back by address. The manager released it whatever was in it, including a control block the kernel was still using. Deallocation is not deletion: the object stays on the created list for its type, a thread stays wherever it was on the ready or suspension lists and stays schedulable, and an active timer stays on the timer list. Nothing on those paths consults a control block ID, so nothing about the memory having been freed stops the kernel from using it -- a created list walk reads a name pointer out of it and follows that pointer, a create or delete of another object of the same type writes through the created links in it, the scheduler switches the stack pointer to the word at offset 8 of it and pops a saved processor state, and timer expiration calls the function pointer in it. Meanwhile the byte pool is free to hand those same bytes to the next allocation, so what the kernel goes on reading as a control block becomes whatever the next owner of the memory puts there, through ordinary create services. The manager now refuses to release memory that holds an object which is still created, and returns TX_DELETE_ERROR without touching the allocation, the object or the memory. Deleting the object first is what makes its memory releasable, which is the sequence the delete dispatchers already follow and the one module authors are told to follow. The question is answered from the kernel's created lists, not from the control block. A control block ID is not evidence that an object is there: an allocation that was never created can be carrying the value of an ID, and refusing on that would strand memory a module is entitled to have back. Deallocation is also given an address and nothing else, so unlike a typed service it cannot be told which list to search, and each of the eight lists is searched in turn. The search is not narrowed by the size of the allocation, because that would be sound only if every object had been created through a size-checked path, and a module running without memory protection creates objects through no such path -- a queue at the start of a thread-sized allocation is a case the tests here cover. Each list is searched in its own interrupts-disabled window, bounded by the count the kernel keeps beside it, so the longest window is the length of one type's list and a list whose links have been damaged cannot make the search run on. The whole search is one pass over the objects the system has created, paid once per object deallocation. Storage that is not an object is released exactly as before, which is what keeps cleanup after a create that failed or was abandoned working, and what makes the release each delete dispatcher performs after a successful delete go through. The address the request arrives with is now checked before the manager's private header in front of it is read, rather than partly after. The size of the allocation comes from that header, so there is nothing to validate a size against until the header has been read, and the previous order established only where the header started: a header that began inside the pool and ended past it had its size word read from outside the pool. That check has moved out of the dispatcher into _txm_module_manager_param_check_object_for_deallocation, alongside the other parameter checks the dispatch table uses and where a test can reach it, and it now also refuses a size that would carry the end of the allocation past the top of the address space instead of wrapping it, since a wrapped end compares as though the allocation were inside the pool. The 301 expectations in the new test drive all eight object types through allocate, create, a refused deallocation, delete, and a deallocation that succeeds, and assert after the refusal that nothing reached the pool, that the allocation is still on the module's list at the head of it, that the control block still carries its ID and that the object is still live. They cover storage that was never created, storage carrying nothing but a plausible ID for each of the eight types, an object at the start of an oversized allocation, every aligned interior offset of a live object with that object's own ID planted at it, an application-owned object outside the pool, another module's allocations both live and raw, releasing the head of a list of several and releasing the same address twice, a type that has no created list, the bounds on the search against a list longer than its count and against a count larger than its list for every type, the boundary addresses at both ends of the pool, a crafted size, and an object pool that was never created. Removing the refusal fails 43 of them; removing the size wrap guard fails one. Line and branch coverage of the three new functions and of the changed _txm_module_manager_object_deallocate is 100%, with one exception that is test scaffolding rather than product code: the host shim's stand-in for TX_RESTORE has an underflow guard, and the test asserts that branch is never taken. All 99 tests pass in each of the five configurations the tree builds with GCC 14. Assisted-by: Claude Code (Opus 5) * Removed the object deallocation bounds check superseded by the search _txm_module_manager_param_check_object_for_deallocation() bounded the private header in front of a caller's address before the deallocator read it. The deallocator no longer reads that header: it finds the allocation by searching the module's own allocation list, which never dereferences the address, so the bounds check now guards a read that does not happen. The function, its prototype, its macro and its one call site in the txm_module_object_deallocate dispatcher are removed, along with the twelve expectations that covered it and three declarations left unused by their removal. The search proves more than the check did: the bounds test established only that the header lay inside the object pool, while the search establishes that the address is the exact start of one of this module's allocations. The live object deallocation test holds 289 expectations and passes. Reverting the live-object guard still fails 51 of them, the same 51 as before the deletion, so nothing the removed expectations covered was load-bearing. The full suite passes 108/108 in default_build_coverage, with no warnings. Assisted-by: Claude Code (Opus 5) --- build-all.log | 442 ++++++ .../src/txm_module_object_deallocate.c | 19 +- .../inc/txm_module_manager_dispatch.h | 37 +- .../inc/txm_module_manager_util.h | 1 + .../txm_module_manager_object_deallocate.c | 41 +- .../src/txm_module_manager_util.c | 110 +- ctest-all.log | 220 +++ test/tx/cmake/module_manager/CMakeLists.txt | 26 + ...le_manager_live_object_deallocation_test.c | 1223 +++++++++++++++++ ...odule_manager_object_authentication_test.c | 29 +- 10 files changed, 2086 insertions(+), 62 deletions(-) create mode 100644 build-all.log create mode 100644 ctest-all.log create mode 100644 test/tx/module_manager/threadx_module_manager_live_object_deallocation_test.c diff --git a/build-all.log b/build-all.log new file mode 100644 index 000000000..dbdac9452 --- /dev/null +++ b/build-all.log @@ -0,0 +1,442 @@ +[1/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_block_pool_performance_info_get.c.o +[2/441] Building C object threadx/CMakeFiles/threadx.dir/ports/linux/gnu/src/tx_thread_context_save.c.o +[3/441] Building C object threadx/CMakeFiles/threadx.dir/ports/linux/gnu/src/tx_timer_interrupt.c.o +[4/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_block_pool_info_get.c.o +[5/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_reset.c.o +[6/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_block_pool_delete.c.o +[7/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_block_pool_cleanup.c.o +[8/441] Building C object threadx/CMakeFiles/threadx.dir/ports/linux/gnu/src/tx_thread_interrupt_control.c.o +[9/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_delete.c.o +[10/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_block_allocate.c.o +[11/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_block_pool_initialize.c.o +[12/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_block_pool_performance_system_info_get.c.o +[13/441] Building C object threadx/CMakeFiles/threadx.dir/ports/linux/gnu/src/tx_thread_context_restore.c.o +[14/441] Building C object threadx/CMakeFiles/threadx.dir/ports/linux/gnu/src/tx_thread_system_return.c.o +[15/441] Building C object threadx/CMakeFiles/threadx.dir/ports/linux/gnu/src/tx_thread_stack_build.c.o +[16/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_block_pool_create.c.o +[17/441] Building C object threadx/CMakeFiles/threadx.dir/ports/linux/gnu/src/tx_thread_schedule.c.o +[18/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_byte_pool_initialize.c.o +[19/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_block_pool_prioritize.c.o +[20/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_byte_pool_performance_system_info_get.c.o +[21/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_block_release.c.o +[22/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_byte_pool_create.c.o +[23/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_byte_pool_delete.c.o +[24/441] Building C object threadx/CMakeFiles/threadx.dir/ports/linux/gnu/src/tx_initialize_low_level.c.o +[25/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_byte_pool_info_get.c.o +[26/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_event_flags_cleanup.c.o +[27/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_byte_pool_cleanup.c.o +[28/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_event_flags_create.c.o +[29/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_byte_pool_prioritize.c.o +[30/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_byte_pool_search.c.o +[31/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_event_flags_delete.c.o +[32/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_byte_release.c.o +[33/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_byte_allocate.c.o +[34/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_byte_pool_performance_info_get.c.o +[35/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_event_flags_get.c.o +[36/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_event_flags_performance_info_get.c.o +[37/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_event_flags_info_get.c.o +[38/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_event_flags_initialize.c.o +[39/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_event_flags_performance_system_info_get.c.o +[40/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_initialize_high_level.c.o +[41/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_misra.c.o +[42/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_mutex_create.c.o +[43/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_event_flags_set.c.o +[44/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_initialize_kernel_setup.c.o +[45/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_initialize_kernel_enter.c.o +[46/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_mutex_cleanup.c.o +[47/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_mutex_initialize.c.o +[48/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_mutex_get.c.o +[49/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_event_flags_set_notify.c.o +[50/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_mutex_info_get.c.o +[51/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_mutex_performance_info_get.c.o +[52/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_mutex_performance_system_info_get.c.o +[53/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_mutex_delete.c.o +[54/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_mutex_priority_change.c.o +[55/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_mutex_prioritize.c.o +[56/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_queue_initialize.c.o +[57/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_queue_create.c.o +[58/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_queue_cleanup.c.o +[59/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_queue_delete.c.o +[60/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_queue_flush.c.o +[61/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_queue_front_send.c.o +[62/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_queue_performance_system_info_get.c.o +[63/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_queue_performance_info_get.c.o +[64/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_queue_prioritize.c.o +[65/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_semaphore_ceiling_put.c.o +[66/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_queue_send.c.o +[67/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_queue_info_get.c.o +[68/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_mutex_put.c.o +[69/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_semaphore_initialize.c.o +[70/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_semaphore_get.c.o +[71/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_semaphore_create.c.o +[72/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_semaphore_delete.c.o +[73/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_semaphore_info_get.c.o +[74/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_semaphore_performance_system_info_get.c.o +[75/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_queue_send_notify.c.o +[76/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_semaphore_cleanup.c.o +[77/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_queue_receive.c.o +[78/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_semaphore_performance_info_get.c.o +[79/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_semaphore_prioritize.c.o +[80/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_create.c.o +[81/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_semaphore_put.c.o +[82/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_semaphore_put_notify.c.o +[83/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_entry_exit_notify.c.o +[84/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_identify.c.o +[85/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_performance_info_get.c.o +[86/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_performance_system_info_get.c.o +[87/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_relinquish.c.o +[88/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_preemption_change.c.o +[89/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_priority_change.c.o +[90/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_resume.c.o +[91/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_shell_entry.c.o +[92/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_stack_error_handler.c.o +[93/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_sleep.c.o +[94/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_stack_analyze.c.o +[95/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_initialize.c.o +[96/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_info_get.c.o +[97/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_stack_error_notify.c.o +[98/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_time_slice.c.o +[99/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_time_get.c.o +[100/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_terminate.c.o +[101/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_timer_activate.c.o +[102/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_timeout.c.o +[103/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_system_resume.c.o +[104/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_suspend.c.o +[105/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_time_slice_change.c.o +[106/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_timer_create.c.o +[107/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_timer_delete.c.o +[108/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_timer_change.c.o +[109/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_timer_deactivate.c.o +[110/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_wait_abort.c.o +[111/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_system_preempt_check.c.o +[112/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_timer_info_get.c.o +[113/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_thread_system_suspend.c.o +[114/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_time_set.c.o +[115/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_timer_system_deactivate.c.o +[116/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_timer_initialize.c.o +[117/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_timer_performance_info_get.c.o +[118/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_timer_performance_system_info_get.c.o +[119/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_timer_expiration_process.c.o +[120/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_timer_system_activate.c.o +[121/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_trace_disable.c.o +[122/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_trace_enable.c.o +[123/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_trace_event_filter.c.o +[124/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_trace_interrupt_control.c.o +[125/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_trace_buffer_full_notify.c.o +[126/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_trace_initialize.c.o +[127/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_trace_isr_exit_insert.c.o +[128/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_timer_thread_entry.c.o +[129/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_trace_event_unfilter.c.o +[130/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_trace_isr_enter_insert.c.o +[131/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_trace_object_unregister.c.o +[132/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_block_pool_prioritize.c.o +[133/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_trace_object_register.c.o +[134/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_block_pool_delete.c.o +[135/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/tx_trace_user_event_insert.c.o +[136/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_block_pool_info_get.c.o +[137/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_block_allocate.c.o +[138/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_byte_allocate.c.o +[139/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_block_release.c.o +[140/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_block_pool_create.c.o +[141/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_byte_pool_create.c.o +[142/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_byte_pool_delete.c.o +[143/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_byte_pool_prioritize.c.o +[144/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_byte_pool_info_get.c.o +[145/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_byte_release.c.o +[146/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_event_flags_create.c.o +[147/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_event_flags_info_get.c.o +[148/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_event_flags_delete.c.o +[149/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_event_flags_get.c.o +[150/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_event_flags_set.c.o +[151/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_event_flags_set_notify.c.o +[152/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_mutex_info_get.c.o +[153/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_mutex_get.c.o +[154/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_mutex_delete.c.o +[155/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_mutex_prioritize.c.o +[156/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_mutex_put.c.o +[157/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_queue_delete.c.o +[158/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_queue_create.c.o +[159/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_queue_front_send.c.o +[160/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_queue_prioritize.c.o +[161/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_queue_receive.c.o +[162/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_mutex_create.c.o +[163/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_queue_flush.c.o +[164/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_queue_info_get.c.o +[165/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_queue_send.c.o +[166/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_queue_send_notify.c.o +[167/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_semaphore_delete.c.o +[168/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_semaphore_get.c.o +[169/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_semaphore_prioritize.c.o +[170/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_semaphore_info_get.c.o +[171/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_semaphore_put_notify.c.o +[172/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_semaphore_ceiling_put.c.o +[173/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_semaphore_put.c.o +[174/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_thread_entry_exit_notify.c.o +[175/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_semaphore_create.c.o +[176/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_thread_delete.c.o +[177/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_thread_info_get.c.o +[178/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_thread_preemption_change.c.o +[179/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_thread_priority_change.c.o +[180/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_thread_create.c.o +[181/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_thread_reset.c.o +[182/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_thread_relinquish.c.o +[183/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_thread_time_slice_change.c.o +[184/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_thread_suspend.c.o +[185/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_thread_wait_abort.c.o +[186/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_thread_resume.c.o +[187/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_timer_activate.c.o +[188/441] Building C object regression/CMakeFiles/test_weak_defaults.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/shared/regression/testcontrol_weak_defaults.c.o +[189/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_timer_change.c.o +[190/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_thread_terminate.c.o +[191/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_timer_delete.c.o +[192/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_timer_deactivate.c.o +[193/441] Building C object thread_transition/CMakeFiles/tx_tt_ni.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/tx_thread_shell_entry.c.o +[194/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_timer_create.c.o +[195/441] Building C object samples/CMakeFiles/sample_threadx.dir/fake.c.o +[196/441] Building C object regression/CMakeFiles/threadx_initialize_kernel_setup_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_initialize_kernel_setup_test.c.o +[197/441] Building C object samples/CMakeFiles/sample_threadx.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/ports/linux/gnu/example_build/sample_threadx.c.o +[198/441] Building C object thread_transition/CMakeFiles/tx_tt_ni.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/tx_thread_delete.c.o +[199/441] Building C object threadx/CMakeFiles/threadx.dir/common/src/txe_timer_info_get.c.o +[200/441] Building C object thread_transition/CMakeFiles/tx_tt_ni.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/txe_thread_delete.c.o +[201/441] Building C object thread_transition/CMakeFiles/tx_tt_ni.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/thread_transition/threadx_thread_transition_configuration_test.c.o +[202/441] Building C object thread_transition/CMakeFiles/tx_tt_ni.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/tx_thread_terminate.c.o +[203/441] Building C object thread_transition/CMakeFiles/tx_tt_ni.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/txe_thread_terminate.c.o +[204/441] Building C object thread_transition/CMakeFiles/tx_tt_ni.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/tx_thread_reset.c.o +[205/441] Building C object thread_transition/CMakeFiles/tx_tt_ni.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/tx_thread_initialize.c.o +[206/441] Building C object thread_transition/CMakeFiles/tx_tt_ni.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/txe_thread_reset.c.o +[207/441] Building C object thread_transition/CMakeFiles/tx_tt_ni_no_error_checking.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/tx_thread_shell_entry.c.o +[208/441] Building C object thread_transition/CMakeFiles/tx_tt_ni_no_error_checking.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/tx_thread_delete.c.o +[209/441] Building C object thread_transition/CMakeFiles/tx_tt_ni_no_error_checking.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/tx_thread_terminate.c.o +[210/441] Building C object thread_transition/CMakeFiles/tx_tt_ni_no_error_checking.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/tx_thread_reset.c.o +[211/441] Building C object thread_transition/CMakeFiles/tx_tt_ni_no_error_checking.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/thread_transition/threadx_thread_transition_configuration_test.c.o +[212/441] Building C object thread_transition/CMakeFiles/tx_tt_ni_no_error_checking.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/txe_thread_reset.c.o +[213/441] Building C object thread_transition/CMakeFiles/tx_tt_ni_no_error_checking.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/txe_thread_delete.c.o +[214/441] Building C object thread_transition/CMakeFiles/tx_tt_ni_no_notify.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/tx_thread_shell_entry.c.o +[215/441] Building C object thread_transition/CMakeFiles/tx_tt_ni_no_notify.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/tx_thread_terminate.c.o +[216/441] Building C object thread_transition/CMakeFiles/tx_tt_ni_no_error_checking.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/txe_thread_terminate.c.o +[217/441] Building C object thread_transition/CMakeFiles/tx_tt_ni_no_error_checking.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/tx_thread_initialize.c.o +[218/441] Building C object thread_transition/CMakeFiles/tx_tt_ni_no_notify.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/tx_thread_delete.c.o +[219/441] Building C object thread_transition/CMakeFiles/tx_tt_ni_no_notify.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/txe_thread_delete.c.o +[220/441] Building C object thread_transition/CMakeFiles/tx_tt_ni_no_notify.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/tx_thread_reset.c.o +[221/441] Building C object thread_transition/CMakeFiles/tx_tt_ni_no_notify.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/txe_thread_terminate.c.o +[222/441] Building C object thread_transition/CMakeFiles/tx_tt_ni_no_notify.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/txe_thread_reset.c.o +[223/441] Building C object thread_transition/CMakeFiles/tx_tt_ni_no_notify.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/thread_transition/threadx_thread_transition_configuration_test.c.o +[224/441] Building C object thread_transition/CMakeFiles/tx_tt_no_error_checking.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/tx_thread_shell_entry.c.o +[225/441] Building C object thread_transition/CMakeFiles/tx_tt_ni_no_notify.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/tx_thread_initialize.c.o +[226/441] Building C object thread_transition/CMakeFiles/tx_tt_no_error_checking.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/tx_thread_delete.c.o +[227/441] Building C object thread_transition/CMakeFiles/tx_tt_no_error_checking.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/tx_thread_terminate.c.o +[228/441] Building C object thread_transition/CMakeFiles/tx_tt_no_error_checking.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/txe_thread_reset.c.o +[229/441] Building C object thread_transition/CMakeFiles/tx_tt_no_error_checking.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/thread_transition/threadx_thread_transition_configuration_test.c.o +[230/441] Building C object thread_transition/CMakeFiles/tx_tt_no_error_checking.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/txe_thread_terminate.c.o +[231/441] Building C object thread_transition/CMakeFiles/tx_tt_no_error_checking.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/tx_thread_reset.c.o +[232/441] Building C object thread_transition/CMakeFiles/tx_tt_no_error_checking.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/tx_thread_initialize.c.o +[233/441] Building C object thread_transition/CMakeFiles/tx_tt_no_error_checking.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/common/src/txe_thread_delete.c.o +[234/441] Linking C executable thread_transition/tx_tt_ni +[235/441] Linking C executable thread_transition/tx_tt_ni_no_error_checking +[236/441] Linking C executable thread_transition/tx_tt_ni_no_notify +[237/441] Linking C executable thread_transition/tx_tt_no_error_checking +[238/441] Linking C shared library threadx/libthreadx.so +[239/441] Generating tx_initialize_low_level.c for test +[240/441] Building C object regression/CMakeFiles/threadx_block_memory_thread_terminate_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_block_memory_thread_terminate_test.c.o +[241/441] Building C object regression/CMakeFiles/threadx_block_memory_error_detection_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_block_memory_error_detection_test.c.o +[242/441] Building C object regression/CMakeFiles/threadx_byte_memory_suspension_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_byte_memory_suspension_test.c.o +[243/441] Building C object regression/CMakeFiles/threadx_block_memory_information_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_block_memory_information_test.c.o +[244/441] Building C object regression/CMakeFiles/threadx_block_memory_prioritize_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_block_memory_prioritize_test.c.o +[245/441] Building C object regression/CMakeFiles/threadx_block_memory_suspension_timeout_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_block_memory_suspension_timeout_test.c.o +[246/441] Building C object regression/CMakeFiles/threadx_byte_memory_information_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_byte_memory_information_test.c.o +[247/441] Building C object regression/CMakeFiles/threadx_block_memory_basic_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_block_memory_basic_test.c.o +[248/441] Building C object regression/CMakeFiles/threadx_block_memory_suspension_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_block_memory_suspension_test.c.o +[249/441] Building C object regression/CMakeFiles/threadx_byte_memory_suspension_timeout_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_byte_memory_suspension_timeout_test.c.o +[250/441] Building C object regression/CMakeFiles/threadx_byte_memory_prioritize_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_byte_memory_prioritize_test.c.o +[251/441] Building C object regression/CMakeFiles/threadx_byte_memory_basic_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_byte_memory_basic_test.c.o +[252/441] Building C object regression/CMakeFiles/test_utility.dir/tx_initialize_low_level.c.o +[253/441] Building C object regression/CMakeFiles/threadx_byte_memory_thread_contention_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_byte_memory_thread_contention_test.c.o +[254/441] Building C object regression/CMakeFiles/test_utility.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/testcontrol.c.o +[255/441] Building C object regression/CMakeFiles/threadx_byte_memory_thread_terminate_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_byte_memory_thread_terminate_test.c.o +[256/441] Building C object regression/CMakeFiles/threadx_interrupt_control_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_interrupt_control_test.c.o +[257/441] Building C object regression/CMakeFiles/threadx_event_flag_suspension_different_bits_consume_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_event_flag_suspension_different_bits_consume_test.c.o +[258/441] Building C object regression/CMakeFiles/threadx_event_flag_suspension_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_event_flag_suspension_test.c.o +[259/441] Building C object regression/CMakeFiles/threadx_event_flag_isr_wait_abort_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_event_flag_isr_wait_abort_test.c.o +[260/441] Building C object regression/CMakeFiles/threadx_event_flag_isr_set_clear_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_event_flag_isr_set_clear_test.c.o +[261/441] Building C object regression/CMakeFiles/threadx_event_flag_basic_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_event_flag_basic_test.c.o +[262/441] Building C object regression/CMakeFiles/threadx_event_flag_suspension_consume_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_event_flag_suspension_consume_test.c.o +[263/441] Building C object regression/CMakeFiles/threadx_event_flag_single_thread_terminate_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_event_flag_single_thread_terminate_test.c.o +[264/441] Building C object regression/CMakeFiles/threadx_event_flag_suspension_different_bits_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_event_flag_suspension_different_bits_test.c.o +[265/441] Building C object regression/CMakeFiles/threadx_event_flag_thread_terminate_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_event_flag_thread_terminate_test.c.o +[266/441] Building C object regression/CMakeFiles/threadx_event_flag_suspension_timeout_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_event_flag_suspension_timeout_test.c.o +[267/441] Building C object regression/CMakeFiles/threadx_event_flag_information_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_event_flag_information_test.c.o +[268/441] Building C object regression/CMakeFiles/threadx_mutex_delete_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_mutex_delete_test.c.o +[269/441] Building C object regression/CMakeFiles/threadx_mutex_basic_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_mutex_basic_test.c.o +[270/441] Linking C executable samples/sample_threadx +[271/441] Linking C executable regression/threadx_initialize_kernel_setup_test +[272/441] Linking C executable regression/threadx_block_memory_suspension_test +[273/441] Linking C executable regression/threadx_block_memory_basic_test +[274/441] Linking C executable regression/threadx_block_memory_error_detection_test +[275/441] Linking C executable regression/threadx_block_memory_information_test +[276/441] Linking C executable regression/threadx_byte_memory_suspension_timeout_test +[277/441] Linking C executable regression/threadx_byte_memory_prioritize_test +[278/441] Linking C executable regression/threadx_block_memory_thread_terminate_test +[279/441] Linking C executable regression/threadx_byte_memory_information_test +[280/441] Linking C executable regression/threadx_byte_memory_suspension_test +[281/441] Linking C executable regression/threadx_event_flag_basic_test +[282/441] Linking C executable regression/threadx_byte_memory_basic_test +[283/441] Linking C executable regression/threadx_byte_memory_thread_contention_test +[284/441] Linking C executable regression/threadx_block_memory_suspension_timeout_test +[285/441] Linking C executable regression/threadx_block_memory_prioritize_test +[286/441] Linking C executable regression/threadx_event_flag_information_test +[287/441] Linking C executable regression/threadx_byte_memory_thread_terminate_test +[288/441] Building C object regression/CMakeFiles/threadx_mutex_preemption_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_mutex_preemption_test.c.o +[289/441] Building C object regression/CMakeFiles/threadx_mutex_no_preemption_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_mutex_no_preemption_test.c.o +[290/441] Linking C executable regression/threadx_event_flag_isr_set_clear_test +[291/441] Linking C executable regression/threadx_event_flag_isr_wait_abort_test +[292/441] Building C object regression/CMakeFiles/threadx_mutex_information_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_mutex_information_test.c.o +[293/441] Building C object regression/CMakeFiles/threadx_mutex_nested_priority_inheritance_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_mutex_nested_priority_inheritance_test.c.o +[294/441] Building C object regression/CMakeFiles/threadx_mutex_priority_inheritance_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_mutex_priority_inheritance_test.c.o +[295/441] Building C object regression/CMakeFiles/threadx_mutex_proritize_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_mutex_proritize_test.c.o +[296/441] Building C object regression/CMakeFiles/threadx_mutex_thread_terminate_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_mutex_thread_terminate_test.c.o +[297/441] Building C object regression/CMakeFiles/threadx_mutex_suspension_timeout_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_mutex_suspension_timeout_test.c.o +[298/441] Linking C executable regression/threadx_event_flag_suspension_consume_test +[299/441] Linking C executable regression/threadx_event_flag_single_thread_terminate_test +[300/441] Linking C executable regression/threadx_event_flag_suspension_different_bits_consume_test +[301/441] Linking C executable regression/threadx_event_flag_suspension_timeout_test +[302/441] Linking C executable regression/threadx_interrupt_control_test +[303/441] Linking C executable regression/threadx_event_flag_suspension_test +[304/441] Linking C executable regression/threadx_event_flag_thread_terminate_test +[305/441] Linking C executable regression/threadx_mutex_basic_test +[306/441] Linking C executable regression/threadx_event_flag_suspension_different_bits_test +[307/441] Linking C executable regression/threadx_mutex_delete_test +[308/441] Building C object regression/CMakeFiles/threadx_queue_basic_four_word_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_queue_basic_four_word_test.c.o +[309/441] Building C object regression/CMakeFiles/threadx_queue_basic_eight_word_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_queue_basic_eight_word_test.c.o +[310/441] Building C object regression/CMakeFiles/threadx_queue_basic_one_word_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_queue_basic_one_word_test.c.o +[311/441] Linking C executable regression/threadx_mutex_no_preemption_test +[312/441] Linking C executable regression/threadx_mutex_preemption_test +[313/441] Building C object regression/CMakeFiles/threadx_queue_flush_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_queue_flush_test.c.o +[314/441] Building C object regression/CMakeFiles/threadx_queue_empty_suspension_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_queue_empty_suspension_test.c.o +[315/441] Building C object regression/CMakeFiles/threadx_queue_flush_no_suspension_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_queue_flush_no_suspension_test.c.o +[316/441] Building C object regression/CMakeFiles/threadx_queue_basic_max_message_size_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_queue_basic_max_message_size_test.c.o +[317/441] Building C object regression/CMakeFiles/threadx_queue_basic_two_word_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_queue_basic_two_word_test.c.o +[318/441] Building C object regression/CMakeFiles/threadx_queue_basic_sixteen_word_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_queue_basic_sixteen_word_test.c.o +[319/441] Linking C executable regression/threadx_mutex_nested_priority_inheritance_test +[320/441] Linking C executable regression/threadx_mutex_priority_inheritance_test +[321/441] Building C object regression/CMakeFiles/threadx_queue_front_send_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_queue_front_send_test.c.o +[322/441] Building C object regression/CMakeFiles/threadx_queue_full_suspension_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_queue_full_suspension_test.c.o +[323/441] Building C object regression/CMakeFiles/threadx_queue_information_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_queue_information_test.c.o +[324/441] Linking C executable regression/threadx_mutex_information_test +[325/441] Linking C executable regression/threadx_mutex_suspension_timeout_test +[326/441] Building C object regression/CMakeFiles/threadx_queue_suspension_timeout_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_queue_suspension_timeout_test.c.o +[327/441] Building C object regression/CMakeFiles/threadx_queue_prioritize.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_queue_prioritize.c.o +[328/441] Linking C executable regression/threadx_mutex_thread_terminate_test +[329/441] Linking C executable regression/threadx_mutex_proritize_test +[330/441] Building C object regression/CMakeFiles/threadx_queue_thread_terminate_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_queue_thread_terminate_test.c.o +[331/441] Building C object regression/CMakeFiles/threadx_semaphore_basic_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_semaphore_basic_test.c.o +[332/441] Building C object regression/CMakeFiles/threadx_semaphore_ceiling_put_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_semaphore_ceiling_put_test.c.o +[333/441] Building C object regression/CMakeFiles/threadx_semaphore_delete_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_semaphore_delete_test.c.o +[334/441] Linking C executable regression/threadx_queue_basic_eight_word_test +[335/441] Linking C executable regression/threadx_queue_basic_four_word_test +[336/441] Linking C executable regression/threadx_queue_basic_one_word_test +[337/441] Linking C executable regression/threadx_queue_flush_no_suspension_test +[338/441] Linking C executable regression/threadx_queue_empty_suspension_test +[339/441] Linking C executable regression/threadx_queue_basic_max_message_size_test +[340/441] Linking C executable regression/threadx_queue_basic_two_word_test +[341/441] Linking C executable regression/threadx_queue_flush_test +[342/441] Linking C executable regression/threadx_queue_basic_sixteen_word_test +[343/441] Building C object regression/CMakeFiles/threadx_semaphore_non_preemption_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_semaphore_non_preemption_test.c.o +[344/441] Building C object regression/CMakeFiles/threadx_semaphore_information_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_semaphore_information_test.c.o +[345/441] Building C object regression/CMakeFiles/threadx_semaphore_preemption_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_semaphore_preemption_test.c.o +[346/441] Linking C executable regression/threadx_queue_full_suspension_test +[347/441] Linking C executable regression/threadx_queue_front_send_test +[348/441] Building C object regression/CMakeFiles/threadx_semaphore_timeout_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_semaphore_timeout_test.c.o +[349/441] Building C object regression/CMakeFiles/threadx_semaphore_thread_terminate_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_semaphore_thread_terminate_test.c.o +[350/441] Building C object regression/CMakeFiles/threadx_thread_basic_time_slice_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_basic_time_slice_test.c.o +[351/441] Building C object regression/CMakeFiles/threadx_semaphore_prioritize.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_semaphore_prioritize.c.o +[352/441] Building C object regression/CMakeFiles/threadx_thread_basic_execution_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_basic_execution_test.c.o +[353/441] Linking C executable regression/threadx_queue_suspension_timeout_test +[354/441] Linking C executable regression/threadx_queue_information_test +[355/441] Building C object regression/CMakeFiles/threadx_thread_completed_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_completed_test.c.o +[356/441] Building C object regression/CMakeFiles/threadx_thread_create_preemption_threshold_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_create_preemption_threshold_test.c.o +[357/441] Building C object regression/CMakeFiles/threadx_thread_delayed_suspension_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_delayed_suspension_test.c.o +[358/441] Linking C executable regression/threadx_queue_prioritize +[359/441] Linking C executable regression/threadx_semaphore_basic_test +[360/441] Linking C executable regression/threadx_queue_thread_terminate_test +[361/441] Linking C executable regression/threadx_semaphore_ceiling_put_test +[362/441] Building C object regression/CMakeFiles/threadx_thread_misaligned_stack_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_misaligned_stack_test.c.o +[363/441] Linking C executable regression/threadx_semaphore_delete_test +[364/441] Building C object regression/CMakeFiles/threadx_thread_information_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_information_test.c.o +[365/441] Building C object regression/CMakeFiles/threadx_thread_multiple_sleep_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_multiple_sleep_test.c.o +[366/441] Building C object regression/CMakeFiles/threadx_thread_multiple_non_current_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_multiple_non_current_test.c.o +[367/441] Building C object regression/CMakeFiles/threadx_thread_multiple_suspension_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_multiple_suspension_test.c.o +[368/441] Building C object regression/CMakeFiles/threadx_thread_multiple_time_slice_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_multiple_time_slice_test.c.o +[369/441] Building C object regression/CMakeFiles/threadx_thread_multi_level_preemption_threshold_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_multi_level_preemption_threshold_test.c.o +[370/441] Linking C executable regression/threadx_semaphore_non_preemption_test +[371/441] Linking C executable regression/threadx_semaphore_information_test +[372/441] Linking C executable regression/threadx_semaphore_timeout_test +[373/441] Linking C executable regression/threadx_semaphore_preemption_test +[374/441] Linking C executable regression/threadx_semaphore_thread_terminate_test +[375/441] Linking C executable regression/threadx_semaphore_prioritize +[376/441] Linking C executable regression/threadx_thread_basic_time_slice_test +[377/441] Building C object regression/CMakeFiles/threadx_thread_preemptable_suspension_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_preemptable_suspension_test.c.o +[378/441] Linking C executable regression/threadx_thread_basic_execution_test +[379/441] Linking C executable regression/threadx_thread_completed_test +[380/441] Building C object regression/CMakeFiles/threadx_thread_preemption_change_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_preemption_change_test.c.o +[381/441] Linking C executable regression/threadx_thread_delayed_suspension_test +[382/441] Linking C executable regression/threadx_thread_create_preemption_threshold_test +[383/441] Building C object regression/CMakeFiles/threadx_thread_reset_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_reset_test.c.o +[384/441] Building C object regression/CMakeFiles/threadx_thread_relinquish_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_relinquish_test.c.o +[385/441] Building C object regression/CMakeFiles/threadx_thread_priority_change.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_priority_change.c.o +[386/441] Building C object regression/CMakeFiles/threadx_thread_simple_sleep_non_clear_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_simple_sleep_non_clear_test.c.o +[387/441] Linking C executable regression/threadx_thread_misaligned_stack_test +[388/441] Building C object regression/CMakeFiles/threadx_thread_simple_sleep_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_simple_sleep_test.c.o +[389/441] Building C object regression/CMakeFiles/threadx_thread_simple_suspend_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_simple_suspend_test.c.o +[390/441] Building C object regression/CMakeFiles/threadx_thread_sleep_for_100ticks_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_sleep_for_100ticks_test.c.o +[391/441] Building C object regression/CMakeFiles/threadx_thread_sleep_terminate_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_sleep_terminate_test.c.o +[392/441] Building C object regression/CMakeFiles/threadx_thread_stack_checking_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_stack_checking_test.c.o +[393/441] Linking C executable regression/threadx_thread_multiple_non_current_test +[394/441] Linking C executable regression/threadx_thread_multiple_suspension_test +[395/441] Building C object regression/CMakeFiles/threadx_thread_stack_fill_value_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_stack_fill_value_test.c.o +[396/441] Linking C executable regression/threadx_thread_multiple_sleep_test +[397/441] Linking C executable regression/threadx_thread_information_test +[398/441] Linking C executable regression/threadx_thread_multiple_time_slice_test +[399/441] Building C object regression/CMakeFiles/threadx_thread_time_slice_change_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_time_slice_change_test.c.o +[400/441] Building C object regression/CMakeFiles/threadx_thread_terminate_delete_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_terminate_delete_test.c.o +[401/441] Building C object regression/CMakeFiles/threadx_thread_wait_abort_and_isr_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_wait_abort_and_isr_test.c.o +[402/441] Building C object regression/CMakeFiles/threadx_thread_wait_abort_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_wait_abort_test.c.o +[403/441] Linking C executable regression/threadx_thread_multi_level_preemption_threshold_test +[404/441] Building C object regression/CMakeFiles/threadx_thread_exit_callback_transition_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_thread_exit_callback_transition_test.c.o +[405/441] Linking C executable regression/threadx_thread_preemptable_suspension_test +[406/441] Building C object regression/CMakeFiles/threadx_time_get_set_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_time_get_set_test.c.o +[407/441] Linking C executable regression/threadx_thread_preemption_change_test +[408/441] Linking C executable regression/threadx_thread_reset_test +[409/441] Linking C executable regression/threadx_thread_priority_change +[410/441] Linking C executable regression/threadx_thread_relinquish_test +[411/441] Linking C executable regression/threadx_thread_simple_suspend_test +[412/441] Linking C executable regression/threadx_thread_simple_sleep_test +[413/441] Building C object regression/CMakeFiles/threadx_timer_activate_deactivate_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_timer_activate_deactivate_test.c.o +[414/441] Linking C executable regression/threadx_thread_simple_sleep_non_clear_test +[415/441] Linking C executable regression/threadx_thread_sleep_terminate_test +[416/441] Building C object regression/CMakeFiles/threadx_timer_deactivate_accuracy_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_timer_deactivate_accuracy_test.c.o +[417/441] Linking C executable regression/threadx_thread_sleep_for_100ticks_test +[418/441] Linking C executable regression/threadx_thread_stack_checking_test +[419/441] Building C object regression/CMakeFiles/threadx_timer_information_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_timer_information_test.c.o +[420/441] Building C object regression/CMakeFiles/threadx_timer_large_timer_accuracy_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_timer_large_timer_accuracy_test.c.o +[421/441] Building C object regression/CMakeFiles/threadx_timer_multiple_accuracy_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_timer_multiple_accuracy_test.c.o +[422/441] Building C object regression/CMakeFiles/threadx_timer_multiple_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_timer_multiple_test.c.o +[423/441] Building C object regression/CMakeFiles/threadx_timer_simple_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_timer_simple_test.c.o +[424/441] Building C object regression/CMakeFiles/threadx_trace_entry_update_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_trace_entry_update_test.c.o +[425/441] Linking C executable regression/threadx_thread_time_slice_change_test +[426/441] Linking C executable regression/threadx_thread_stack_fill_value_test +[427/441] Building C object regression/CMakeFiles/threadx_trace_basic_test.dir/tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/regression/threadx_trace_basic_test.c.o +[428/441] Linking C executable regression/threadx_thread_terminate_delete_test +[429/441] Linking C executable regression/threadx_thread_exit_callback_transition_test +[430/441] Linking C executable regression/threadx_thread_wait_abort_and_isr_test +[431/441] Linking C executable regression/threadx_thread_wait_abort_test +[432/441] Linking C executable regression/threadx_time_get_set_test +[433/441] Linking C executable regression/threadx_timer_activate_deactivate_test +[434/441] Linking C executable regression/threadx_timer_deactivate_accuracy_test +[435/441] Linking C executable regression/threadx_timer_large_timer_accuracy_test +[436/441] Linking C executable regression/threadx_timer_multiple_accuracy_test +[437/441] Linking C executable regression/threadx_timer_information_test +[438/441] Linking C executable regression/threadx_timer_simple_test +[439/441] Linking C executable regression/threadx_timer_multiple_test +[440/441] Linking C executable regression/threadx_trace_entry_update_test +[441/441] Linking C executable regression/threadx_trace_basic_test +BUILD_RC=0 diff --git a/common_modules/module_lib/src/txm_module_object_deallocate.c b/common_modules/module_lib/src/txm_module_object_deallocate.c index 480c61005..e0c0d6c48 100644 --- a/common_modules/module_lib/src/txm_module_object_deallocate.c +++ b/common_modules/module_lib/src/txm_module_object_deallocate.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Claude Code (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -36,14 +38,18 @@ * WHAT TO DO: remove any call to txm_module_object_deallocate() from your * module. The corresponding tx_*_delete() call already handles everything. * - * RISK: calling txm_module_object_deallocate() on a live kernel object (one - * whose tx_*_delete() has not yet been called) frees the backing pool memory - * while the object is still referenced by the kernel, which is undefined - * behaviour (use-after-free). + * BEHAVIOUR: calling txm_module_object_deallocate() on a live kernel object + * (one whose tx_*_delete() has not yet been called) returns TX_DELETE_ERROR + * and changes nothing. The Module Manager will not release the memory of a + * created object, because the kernel goes on using those bytes as a control + * block after the byte pool has handed them to somebody else. Storage that + * was allocated but never made into an object is still released, so cleaning + * up after a create that failed or was abandoned still works. */ #pragma message("txm_module_object_deallocate() is deprecated and must not be used. " \ "Call tx_*_delete() instead; the Module Manager dispatch layer " \ - "releases pool memory automatically on success.") + "releases pool memory automatically on success. Deallocating a " \ + "live kernel object returns TX_DELETE_ERROR.") /**************************************************************************/ /* */ /* FUNCTION RELEASE */ @@ -64,7 +70,8 @@ /* */ /* OUTPUT */ /* */ -/* status Completion status */ +/* status Completion status, TX_DELETE_ERROR*/ +/* if a live object is there */ /* */ /* CALLS */ /* */ diff --git a/common_modules/module_manager/inc/txm_module_manager_dispatch.h b/common_modules/module_manager/inc/txm_module_manager_dispatch.h index 6b75be7f8..0160a1d17 100644 --- a/common_modules/module_manager/inc/txm_module_manager_dispatch.h +++ b/common_modules/module_manager/inc/txm_module_manager_dispatch.h @@ -15,6 +15,8 @@ // Some portions generated by Claude Code (Opus 5). +// Some portions generated by Claude Code (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -3285,41 +3287,6 @@ static ALIGN_TYPE _txm_module_manager_txm_module_object_deallocate_dispatch(TXM_ { ALIGN_TYPE return_value; -TXM_MODULE_ALLOCATED_OBJECT *object_ptr; -ALIGN_TYPE object_end; -ALIGN_TYPE object_pool_end; - - if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) - { - /* Is the object pool created? */ - if (_txm_module_manager_object_pool_created == TX_TRUE) - { - - /* Get the module allocated object. */ - object_ptr = ((TXM_MODULE_ALLOCATED_OBJECT *) param_0) - 1; - - /* Get the end address of the object pool. */ - object_pool_end = (ALIGN_TYPE) (_txm_module_manager_object_pool.tx_byte_pool_start + _txm_module_manager_object_pool.tx_byte_pool_size); - - /* Check that the pointer is in the object pool. */ - if ((ALIGN_TYPE) object_ptr < (ALIGN_TYPE) _txm_module_manager_object_pool.tx_byte_pool_start || - (ALIGN_TYPE) object_ptr >= (ALIGN_TYPE) object_pool_end) - { - /* Pointer is outside of the object pool. */ - return(TXM_MODULE_INVALID_MEMORY); - } - - /* Get the end addresses of the object. */ - object_end = ((ALIGN_TYPE) object_ptr) + sizeof(TXM_MODULE_ALLOCATED_OBJECT) + object_ptr -> txm_module_object_size; - - /* Check that the object is in the object pool. */ - if (object_end >= object_pool_end) - { - /* Object is outside of the object pool. */ - return(TXM_MODULE_INVALID_MEMORY); - } - } - } return_value = (ALIGN_TYPE) _txm_module_manager_object_deallocate( (VOID *) param_0 diff --git a/common_modules/module_manager/inc/txm_module_manager_util.h b/common_modules/module_manager/inc/txm_module_manager_util.h index 2630fe290..22b9570e3 100644 --- a/common_modules/module_manager/inc/txm_module_manager_util.h +++ b/common_modules/module_manager/inc/txm_module_manager_util.h @@ -162,6 +162,7 @@ TXM_MODULE_ALLOCATED_OBJECT UINT _txm_module_manager_object_type_size_get(UINT object_type, ULONG *object_size); UINT _txm_module_manager_created_object_type_check(ALIGN_TYPE object_ptr, UINT object_type); UINT _txm_module_manager_object_id_check(ALIGN_TYPE object_ptr, UINT object_type); +UINT _txm_module_manager_live_object_check(ALIGN_TYPE object_ptr); UINT _txm_module_manager_util_code_allocation_size_and_alignment_get(TXM_MODULE_PREAMBLE *module_preamble, ULONG *code_alignment_dest, ULONG *code_allocation_size_dest); #endif diff --git a/common_modules/module_manager/src/txm_module_manager_object_deallocate.c b/common_modules/module_manager/src/txm_module_manager_object_deallocate.c index 43d96f3c1..dd4c105db 100644 --- a/common_modules/module_manager/src/txm_module_manager_object_deallocate.c +++ b/common_modules/module_manager/src/txm_module_manager_object_deallocate.c @@ -44,9 +44,7 @@ /* DEPRECATED. This function is called internally by the Module */ /* Manager dispatch layer after a successful tx_*_delete() call from */ /* a module. It must not be called directly by module or application */ -/* code. Calling it on a live kernel object (one whose tx_*_delete() */ -/* has not yet been called) frees the backing pool memory while the */ -/* object is still referenced by the kernel (use-after-free). */ +/* code. */ /* */ /* Module authors: remove any explicit call to */ /* txm_module_object_deallocate(). Calling the appropriate */ @@ -59,6 +57,13 @@ /* header from in front of the address the caller supplied. An */ /* address that names none of this module's allocations returns */ /* TX_PTR_ERROR and is not dereferenced. */ +/* Memory holding a live kernel object is not given back. Such a */ +/* request returns TX_DELETE_ERROR and changes nothing: the object */ +/* stays created, the allocation stays on the module's allocation */ +/* list, and the memory stays owned by the module. Storage that was */ +/* allocated but never made into an object is still released, so a */ +/* module can still clean up after a create that failed or was */ +/* abandoned. */ /* */ /* INPUT */ /* */ @@ -74,6 +79,7 @@ /* _txe_mutex_put Release module instance mutex */ /* _txm_module_manager_allocated_object_find */ /* Find the module's allocation */ +/* _txm_module_manager_live_object_check Check for a live object */ /* _txe_byte_release Release object back to pool */ /* */ /* */ @@ -130,6 +136,35 @@ UINT return_value; /* Set return value to invalid pointer. */ return_value = TX_PTR_ERROR; } + + /* Determine if a live kernel object is in this memory. + + Releasing the memory of a created object leaves the kernel holding the + only references to it. The object stays on the created list for its + type, a thread stays on the ready or suspension list it was on and stays + schedulable, and an active timer stays on the timer list. None of those + consult a control block ID, so nothing about the freed memory stops the + kernel using it: a created list walk reads a name pointer out of it, a + create or delete of another object of the same type writes through the + links in it, the scheduler restores a context from the stack pointer in + it, and timer expiration calls the function pointer in it. The byte pool + is meanwhile free to hand those bytes to the next allocation, so what the + kernel goes on reading as a control block is whatever the next owner of + the memory puts there. + + This is asked before the allocation is unlinked, so a refusal leaves the + allocation list, the object and the memory exactly as they were. What is + refused is releasing the memory of an object that is still created; an + allocation that was never made into an object, or one whose object has + been deleted, is released as before, which is what keeps cleanup after a + failed or abandoned create working and what makes the release the delete + dispatchers perform after a successful delete go through. */ + else if (_txm_module_manager_live_object_check((ALIGN_TYPE) object_ptr) == TX_TRUE) + { + + /* Set return value to indicate the object must be deleted first. */ + return_value = TX_DELETE_ERROR; + } else { diff --git a/common_modules/module_manager/src/txm_module_manager_util.c b/common_modules/module_manager/src/txm_module_manager_util.c index ba7e5a291..756120fa4 100644 --- a/common_modules/module_manager/src/txm_module_manager_util.c +++ b/common_modules/module_manager/src/txm_module_manager_util.c @@ -1021,13 +1021,18 @@ UINT exact_object; /* This function determines whether an address is the exact address */ /* of an object on the kernel's created list for a module object type. */ /* */ -/* This is how an object the application created and shared with a */ -/* module is authenticated. Such an object is not in the manager's */ -/* object pool and the manager has no allocation record of it, so the */ -/* kernel's own created list is the only record of it that a module */ -/* cannot influence. Being on that list establishes at once that the */ -/* address is an object start, that the object is of this type, and */ -/* that it is created. */ +/* The created list is the record the create and delete services */ +/* maintain, so being on it establishes at once that the address is an */ +/* object start rather than an address inside an object, that the */ +/* object is of this type, and that it has not been deleted. It is */ +/* also the only record of an object the application created and */ +/* shared with a module, since the manager allocated no such object. */ +/* */ +/* Nothing the module can influence is consulted. In particular the */ +/* control block ID is not: a module can arrange for the value of an */ +/* ID to appear inside memory it owns, and distinct object types of */ +/* equal size exist, so an ID is not evidence that an object is there */ +/* nor of what type it is. */ /* */ /* INPUT */ /* */ @@ -1045,6 +1050,7 @@ UINT exact_object; /* */ /* CALLED BY */ /* */ +/* _txm_module_manager_live_object_check Module object liveness check */ /* _txm_module_manager_param_check_typed_object_for_use */ /* Module object authentication */ /* */ @@ -1402,6 +1408,96 @@ UINT status; } +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txm_module_manager_live_object_check PORTABLE C */ +/* 6.4.3 */ +/* AUTHOR */ +/* */ +/* Eclipse ThreadX contributors */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function determines whether an address is the exact address */ +/* of a live kernel object of any type the Module Manager knows. */ +/* */ +/* It answers the question object deallocation has to ask before it */ +/* gives memory back: is the kernel still going to use these bytes as */ +/* a control block. Deallocation is told an address and nothing else, */ +/* so unlike the checks a typed service makes it cannot be given the */ +/* type to look for, and every type has to be looked for in turn. */ +/* */ +/* The eight created lists are searched whatever the size of the */ +/* allocation at the address. Skipping a type whose control block is */ +/* larger than the allocation would be sound only if every object had */ +/* been created through a size-checked path, and a module running */ +/* without memory protection creates objects without one. */ +/* */ +/* Each list is searched in its own interrupts-disabled window rather */ +/* than all of them in one, so the longest window is bounded by the */ +/* number of objects of a single type. The whole search costs one pass */ +/* over the objects the system has created, and is paid once per */ +/* object deallocation. */ +/* */ +/* INPUT */ +/* */ +/* object_ptr Address of object memory area */ +/* */ +/* OUTPUT */ +/* */ +/* TX_TRUE A live kernel object is there */ +/* TX_FALSE Anything else */ +/* */ +/* CALLS */ +/* */ +/* _txm_module_manager_created_object_type_check */ +/* Check one kernel created list */ +/* */ +/* CALLED BY */ +/* */ +/* _txm_module_manager_object_deallocate Deallocate object memory */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* xx-xx-2026 Eclipse ThreadX Initial Version 6.4.3 */ +/* contributors */ +/* */ +/**************************************************************************/ +UINT _txm_module_manager_live_object_check(ALIGN_TYPE object_ptr) +{ + +UINT object_type; +UINT status; + + + /* Assume no live object is there. */ + status = TX_FALSE; + + /* The eight module object types that have a kernel created list occupy a + contiguous range, so each is asked in turn by walking the range. A value in + the range that the per-type check does not recognise answers TX_FALSE, so a + type the manager stops knowing does not silently pass this search. */ + for (object_type = ((UINT) TXM_BLOCK_POOL_OBJECT); object_type <= ((UINT) TXM_TIMER_OBJECT); object_type++) + { + + if (_txm_module_manager_created_object_type_check(object_ptr, object_type) == TX_TRUE) + { + + /* An address is the start of at most one object, so there is nothing + further to look for. */ + status = TX_TRUE; + break; + } + } + + return(status); +} + + /**************************************************************************/ /* */ /* FUNCTION RELEASE */ diff --git a/ctest-all.log b/ctest-all.log new file mode 100644 index 000000000..51a050e1e --- /dev/null +++ b/ctest-all.log @@ -0,0 +1,220 @@ +Test project /tmp/claude-1000/-home-fdesbiens-652/bc81907a-b0a7-43d2-b3f5-83c3cfaa53e2/scratchpad/mm/test/tx/cmake/build/default_build_coverage + Start 1: default_build_coverage::threadx_block_memory_basic_test + 1/107 Test #1: default_build_coverage::threadx_block_memory_basic_test ............................. Passed 0.08 sec + Start 2: default_build_coverage::threadx_block_memory_error_detection_test + 2/107 Test #2: default_build_coverage::threadx_block_memory_error_detection_test ................... Passed 0.01 sec + Start 3: default_build_coverage::threadx_block_memory_information_test + 3/107 Test #3: default_build_coverage::threadx_block_memory_information_test ....................... Passed 0.02 sec + Start 4: default_build_coverage::threadx_block_memory_prioritize_test + 4/107 Test #4: default_build_coverage::threadx_block_memory_prioritize_test ........................ Passed 0.03 sec + Start 5: default_build_coverage::threadx_block_memory_suspension_test + 5/107 Test #5: default_build_coverage::threadx_block_memory_suspension_test ........................ Passed 0.01 sec + Start 6: default_build_coverage::threadx_block_memory_suspension_timeout_test + 6/107 Test #6: default_build_coverage::threadx_block_memory_suspension_timeout_test ................ Passed 0.65 sec + Start 7: default_build_coverage::threadx_block_memory_thread_terminate_test + 7/107 Test #7: default_build_coverage::threadx_block_memory_thread_terminate_test .................. Passed 0.01 sec + Start 8: default_build_coverage::threadx_byte_memory_basic_test + 8/107 Test #8: default_build_coverage::threadx_byte_memory_basic_test .............................. Passed 0.03 sec + Start 9: default_build_coverage::threadx_byte_memory_information_test + 9/107 Test #9: default_build_coverage::threadx_byte_memory_information_test ........................ Passed 0.02 sec + Start 10: default_build_coverage::threadx_byte_memory_prioritize_test + 10/107 Test #10: default_build_coverage::threadx_byte_memory_prioritize_test ......................... Passed 0.03 sec + Start 11: default_build_coverage::threadx_byte_memory_suspension_test + 11/107 Test #11: default_build_coverage::threadx_byte_memory_suspension_test ......................... Passed 0.01 sec + Start 12: default_build_coverage::threadx_byte_memory_suspension_timeout_test + 12/107 Test #12: default_build_coverage::threadx_byte_memory_suspension_timeout_test ................. Passed 0.65 sec + Start 13: default_build_coverage::threadx_byte_memory_thread_contention_test + 13/107 Test #13: default_build_coverage::threadx_byte_memory_thread_contention_test .................. Passed 1.36 sec + Start 14: default_build_coverage::threadx_byte_memory_thread_terminate_test + 14/107 Test #14: default_build_coverage::threadx_byte_memory_thread_terminate_test ................... Passed 0.01 sec + Start 15: default_build_coverage::threadx_event_flag_basic_test + 15/107 Test #15: default_build_coverage::threadx_event_flag_basic_test ............................... Passed 0.07 sec + Start 16: default_build_coverage::threadx_event_flag_information_test + 16/107 Test #16: default_build_coverage::threadx_event_flag_information_test ......................... Passed 0.01 sec + Start 17: default_build_coverage::threadx_event_flag_isr_set_clear_test + 17/107 Test #17: default_build_coverage::threadx_event_flag_isr_set_clear_test ....................... Passed 0.91 sec + Start 18: default_build_coverage::threadx_event_flag_isr_wait_abort_test + 18/107 Test #18: default_build_coverage::threadx_event_flag_isr_wait_abort_test ...................... Passed 0.81 sec + Start 19: default_build_coverage::threadx_event_flag_single_thread_terminate_test + 19/107 Test #19: default_build_coverage::threadx_event_flag_single_thread_terminate_test ............. Passed 0.31 sec + Start 20: default_build_coverage::threadx_event_flag_suspension_consume_test + 20/107 Test #20: default_build_coverage::threadx_event_flag_suspension_consume_test .................. Passed 0.01 sec + Start 21: default_build_coverage::threadx_event_flag_suspension_different_bits_consume_test + 21/107 Test #21: default_build_coverage::threadx_event_flag_suspension_different_bits_consume_test ... Passed 0.01 sec + Start 22: default_build_coverage::threadx_event_flag_suspension_different_bits_test + 22/107 Test #22: default_build_coverage::threadx_event_flag_suspension_different_bits_test ........... Passed 0.01 sec + Start 23: default_build_coverage::threadx_event_flag_suspension_test + 23/107 Test #23: default_build_coverage::threadx_event_flag_suspension_test .......................... Passed 0.01 sec + Start 24: default_build_coverage::threadx_event_flag_suspension_timeout_test + 24/107 Test #24: default_build_coverage::threadx_event_flag_suspension_timeout_test .................. Passed 0.68 sec + Start 25: default_build_coverage::threadx_event_flag_thread_terminate_test + 25/107 Test #25: default_build_coverage::threadx_event_flag_thread_terminate_test .................... Passed 0.01 sec + Start 26: default_build_coverage::threadx_interrupt_control_test + 26/107 Test #26: default_build_coverage::threadx_interrupt_control_test .............................. Passed 0.03 sec + Start 27: default_build_coverage::threadx_mutex_basic_test + 27/107 Test #27: default_build_coverage::threadx_mutex_basic_test .................................... Passed 0.09 sec + Start 28: default_build_coverage::threadx_mutex_delete_test + 28/107 Test #28: default_build_coverage::threadx_mutex_delete_test ................................... Passed 0.01 sec + Start 29: default_build_coverage::threadx_mutex_information_test + 29/107 Test #29: default_build_coverage::threadx_mutex_information_test .............................. Passed 0.01 sec + Start 30: default_build_coverage::threadx_mutex_nested_priority_inheritance_test + 30/107 Test #30: default_build_coverage::threadx_mutex_nested_priority_inheritance_test .............. Passed 0.10 sec + Start 31: default_build_coverage::threadx_mutex_no_preemption_test + 31/107 Test #31: default_build_coverage::threadx_mutex_no_preemption_test ............................ Passed 0.01 sec + Start 32: default_build_coverage::threadx_mutex_preemption_test + 32/107 Test #32: default_build_coverage::threadx_mutex_preemption_test ............................... Passed 0.01 sec + Start 33: default_build_coverage::threadx_mutex_priority_inheritance_test + 33/107 Test #33: default_build_coverage::threadx_mutex_priority_inheritance_test ..................... Passed 0.21 sec + Start 34: default_build_coverage::threadx_mutex_proritize_test + 34/107 Test #34: default_build_coverage::threadx_mutex_proritize_test ................................ Passed 0.03 sec + Start 35: default_build_coverage::threadx_mutex_suspension_timeout_test + 35/107 Test #35: default_build_coverage::threadx_mutex_suspension_timeout_test ....................... Passed 0.37 sec + Start 36: default_build_coverage::threadx_mutex_thread_terminate_test + 36/107 Test #36: default_build_coverage::threadx_mutex_thread_terminate_test ......................... Passed 0.01 sec + Start 37: default_build_coverage::threadx_queue_basic_eight_word_test + 37/107 Test #37: default_build_coverage::threadx_queue_basic_eight_word_test ......................... Passed 0.00 sec + Start 38: default_build_coverage::threadx_queue_basic_four_word_test + 38/107 Test #38: default_build_coverage::threadx_queue_basic_four_word_test .......................... Passed 0.00 sec + Start 39: default_build_coverage::threadx_queue_basic_one_word_test + 39/107 Test #39: default_build_coverage::threadx_queue_basic_one_word_test ........................... Passed 0.07 sec + Start 40: default_build_coverage::threadx_queue_basic_sixteen_word_test + 40/107 Test #40: default_build_coverage::threadx_queue_basic_sixteen_word_test ....................... Passed 0.01 sec + Start 41: default_build_coverage::threadx_queue_basic_two_word_test + 41/107 Test #41: default_build_coverage::threadx_queue_basic_two_word_test ........................... Passed 0.00 sec + Start 42: default_build_coverage::threadx_queue_basic_max_message_size_test + 42/107 Test #42: default_build_coverage::threadx_queue_basic_max_message_size_test ................... Passed 0.00 sec + Start 43: default_build_coverage::threadx_queue_empty_suspension_test + 43/107 Test #43: default_build_coverage::threadx_queue_empty_suspension_test ......................... Passed 0.01 sec + Start 44: default_build_coverage::threadx_queue_flush_no_suspension_test + 44/107 Test #44: default_build_coverage::threadx_queue_flush_no_suspension_test ...................... Passed 0.00 sec + Start 45: default_build_coverage::threadx_queue_flush_test + 45/107 Test #45: default_build_coverage::threadx_queue_flush_test .................................... Passed 0.01 sec + Start 46: default_build_coverage::threadx_queue_front_send_test + 46/107 Test #46: default_build_coverage::threadx_queue_front_send_test ............................... Passed 0.01 sec + Start 47: default_build_coverage::threadx_queue_full_suspension_test + 47/107 Test #47: default_build_coverage::threadx_queue_full_suspension_test .......................... Passed 0.01 sec + Start 48: default_build_coverage::threadx_queue_information_test + 48/107 Test #48: default_build_coverage::threadx_queue_information_test .............................. Passed 0.00 sec + Start 49: default_build_coverage::threadx_queue_prioritize + 49/107 Test #49: default_build_coverage::threadx_queue_prioritize .................................... Passed 0.03 sec + Start 50: default_build_coverage::threadx_queue_suspension_timeout_test + 50/107 Test #50: default_build_coverage::threadx_queue_suspension_timeout_test ....................... Passed 0.36 sec + Start 51: default_build_coverage::threadx_queue_thread_terminate_test + 51/107 Test #51: default_build_coverage::threadx_queue_thread_terminate_test ......................... Passed 0.01 sec + Start 52: default_build_coverage::threadx_semaphore_basic_test + 52/107 Test #52: default_build_coverage::threadx_semaphore_basic_test ................................ Passed 0.07 sec + Start 53: default_build_coverage::threadx_semaphore_ceiling_put_test + 53/107 Test #53: default_build_coverage::threadx_semaphore_ceiling_put_test .......................... Passed 0.01 sec + Start 54: default_build_coverage::threadx_semaphore_delete_test + 54/107 Test #54: default_build_coverage::threadx_semaphore_delete_test ............................... Passed 0.01 sec + Start 55: default_build_coverage::threadx_semaphore_information_test + 55/107 Test #55: default_build_coverage::threadx_semaphore_information_test .......................... Passed 0.00 sec + Start 56: default_build_coverage::threadx_semaphore_non_preemption_test + 56/107 Test #56: default_build_coverage::threadx_semaphore_non_preemption_test ....................... Passed 0.01 sec + Start 57: default_build_coverage::threadx_semaphore_preemption_test + 57/107 Test #57: default_build_coverage::threadx_semaphore_preemption_test ........................... Passed 0.01 sec + Start 58: default_build_coverage::threadx_semaphore_prioritize + 58/107 Test #58: default_build_coverage::threadx_semaphore_prioritize ................................ Passed 0.03 sec + Start 59: default_build_coverage::threadx_semaphore_thread_terminate_test + 59/107 Test #59: default_build_coverage::threadx_semaphore_thread_terminate_test ..................... Passed 0.01 sec + Start 60: default_build_coverage::threadx_semaphore_timeout_test + 60/107 Test #60: default_build_coverage::threadx_semaphore_timeout_test .............................. Passed 0.36 sec + Start 61: default_build_coverage::threadx_thread_basic_execution_test + 61/107 Test #61: default_build_coverage::threadx_thread_basic_execution_test ......................... Passed 0.05 sec + Start 62: default_build_coverage::threadx_thread_basic_time_slice_test + 62/107 Test #62: default_build_coverage::threadx_thread_basic_time_slice_test ........................ Passed 0.20 sec + Start 63: default_build_coverage::threadx_thread_completed_test + 63/107 Test #63: default_build_coverage::threadx_thread_completed_test ............................... Passed 0.02 sec + Start 64: default_build_coverage::threadx_thread_create_preemption_threshold_test + 64/107 Test #64: default_build_coverage::threadx_thread_create_preemption_threshold_test ............. Passed 0.03 sec + Start 65: default_build_coverage::threadx_thread_delayed_suspension_test + 65/107 Test #65: default_build_coverage::threadx_thread_delayed_suspension_test ...................... Passed 7.26 sec + Start 66: default_build_coverage::threadx_thread_information_test + 66/107 Test #66: default_build_coverage::threadx_thread_information_test ............................. Passed 0.01 sec + Start 67: default_build_coverage::threadx_thread_misaligned_stack_test + 67/107 Test #67: default_build_coverage::threadx_thread_misaligned_stack_test ........................ Passed 0.06 sec + Start 68: default_build_coverage::threadx_thread_multi_level_preemption_threshold_test + 68/107 Test #68: default_build_coverage::threadx_thread_multi_level_preemption_threshold_test ........ Passed 0.02 sec + Start 69: default_build_coverage::threadx_thread_multiple_non_current_test + 69/107 Test #69: default_build_coverage::threadx_thread_multiple_non_current_test .................... Passed 0.01 sec + Start 70: default_build_coverage::threadx_thread_multiple_sleep_test + 70/107 Test #70: default_build_coverage::threadx_thread_multiple_sleep_test .......................... Passed 1.02 sec + Start 71: default_build_coverage::threadx_thread_multiple_suspension_test + 71/107 Test #71: default_build_coverage::threadx_thread_multiple_suspension_test ..................... Passed 0.01 sec + Start 72: default_build_coverage::threadx_thread_multiple_time_slice_test + 72/107 Test #72: default_build_coverage::threadx_thread_multiple_time_slice_test ..................... Passed 0.54 sec + Start 73: default_build_coverage::threadx_thread_preemptable_suspension_test + 73/107 Test #73: default_build_coverage::threadx_thread_preemptable_suspension_test .................. Passed 0.01 sec + Start 74: default_build_coverage::threadx_thread_preemption_change_test + 74/107 Test #74: default_build_coverage::threadx_thread_preemption_change_test ....................... Passed 0.01 sec + Start 75: default_build_coverage::threadx_thread_priority_change + 75/107 Test #75: default_build_coverage::threadx_thread_priority_change .............................. Passed 0.18 sec + Start 76: default_build_coverage::threadx_thread_relinquish_test + 76/107 Test #76: default_build_coverage::threadx_thread_relinquish_test .............................. Passed 0.01 sec + Start 77: default_build_coverage::threadx_thread_reset_test + 77/107 Test #77: default_build_coverage::threadx_thread_reset_test ................................... Passed 0.01 sec + Start 78: default_build_coverage::threadx_thread_simple_sleep_non_clear_test + 78/107 Test #78: default_build_coverage::threadx_thread_simple_sleep_non_clear_test .................. Passed 0.20 sec + Start 79: default_build_coverage::threadx_thread_simple_sleep_test + 79/107 Test #79: default_build_coverage::threadx_thread_simple_sleep_test ............................ Passed 0.19 sec + Start 80: default_build_coverage::threadx_thread_simple_suspend_test + 80/107 Test #80: default_build_coverage::threadx_thread_simple_suspend_test .......................... Passed 0.00 sec + Start 81: default_build_coverage::threadx_thread_sleep_for_100ticks_test + 81/107 Test #81: default_build_coverage::threadx_thread_sleep_for_100ticks_test ...................... Passed 1.01 sec + Start 82: default_build_coverage::threadx_thread_sleep_terminate_test + 82/107 Test #82: default_build_coverage::threadx_thread_sleep_terminate_test ......................... Passed 0.05 sec + Start 83: default_build_coverage::threadx_thread_stack_checking_test + 83/107 Test #83: default_build_coverage::threadx_thread_stack_checking_test .......................... Passed 0.01 sec + Start 84: default_build_coverage::threadx_thread_stack_fill_value_test + 84/107 Test #84: default_build_coverage::threadx_thread_stack_fill_value_test ........................ Passed 0.01 sec + Start 85: default_build_coverage::threadx_thread_terminate_delete_test + 85/107 Test #85: default_build_coverage::threadx_thread_terminate_delete_test ........................ Passed 0.00 sec + Start 86: default_build_coverage::threadx_thread_exit_callback_transition_test + 86/107 Test #86: default_build_coverage::threadx_thread_exit_callback_transition_test ................ Passed 0.25 sec + Start 87: default_build_coverage::threadx_thread_time_slice_change_test + 87/107 Test #87: default_build_coverage::threadx_thread_time_slice_change_test ....................... Passed 0.10 sec + Start 88: default_build_coverage::threadx_thread_wait_abort_and_isr_test + 88/107 Test #88: default_build_coverage::threadx_thread_wait_abort_and_isr_test ...................... Passed 0.22 sec + Start 89: default_build_coverage::threadx_thread_wait_abort_test + 89/107 Test #89: default_build_coverage::threadx_thread_wait_abort_test .............................. Passed 0.01 sec + Start 90: default_build_coverage::threadx_time_get_set_test + 90/107 Test #90: default_build_coverage::threadx_time_get_set_test ................................... Passed 0.37 sec + Start 91: default_build_coverage::threadx_timer_activate_deactivate_test + 91/107 Test #91: default_build_coverage::threadx_timer_activate_deactivate_test ...................... Passed 0.86 sec + Start 92: default_build_coverage::threadx_timer_deactivate_accuracy_test + 92/107 Test #92: default_build_coverage::threadx_timer_deactivate_accuracy_test ...................... Passed 0.40 sec + Start 93: default_build_coverage::threadx_timer_information_test + 93/107 Test #93: default_build_coverage::threadx_timer_information_test .............................. Passed 1.61 sec + Start 94: default_build_coverage::threadx_timer_large_timer_accuracy_test + 94/107 Test #94: default_build_coverage::threadx_timer_large_timer_accuracy_test ..................... Passed 1.11 sec + Start 95: default_build_coverage::threadx_timer_multiple_accuracy_test + 95/107 Test #95: default_build_coverage::threadx_timer_multiple_accuracy_test ........................ Passed 3.05 sec + Start 96: default_build_coverage::threadx_timer_multiple_test + 96/107 Test #96: default_build_coverage::threadx_timer_multiple_test ................................. Passed 6.07 sec + Start 97: default_build_coverage::threadx_timer_simple_test + 97/107 Test #97: default_build_coverage::threadx_timer_simple_test ................................... Passed 1.65 sec + Start 98: default_build_coverage::threadx_trace_basic_test + 98/107 Test #98: default_build_coverage::threadx_trace_basic_test .................................... Passed 0.01 sec + Start 99: default_build_coverage::threadx_trace_entry_update_test + 99/107 Test #99: default_build_coverage::threadx_trace_entry_update_test ............................. Passed 0.05 sec + Start 100: default_build_coverage::threadx_initialize_kernel_setup_test +100/107 Test #100: default_build_coverage::threadx_initialize_kernel_setup_test ........................ Passed 0.00 sec + Start 101: default_build_coverage::threadx_thread_transition_ni_test +101/107 Test #101: default_build_coverage::threadx_thread_transition_ni_test ........................... Passed 0.00 sec + Start 102: default_build_coverage::threadx_thread_transition_ni_no_error_checking_test +102/107 Test #102: default_build_coverage::threadx_thread_transition_ni_no_error_checking_test ......... Passed 0.00 sec + Start 103: default_build_coverage::threadx_thread_transition_ni_no_notify_test +103/107 Test #103: default_build_coverage::threadx_thread_transition_ni_no_notify_test ................. Passed 0.00 sec + Start 104: default_build_coverage::threadx_thread_transition_no_error_checking_test +104/107 Test #104: default_build_coverage::threadx_thread_transition_no_error_checking_test ............ Passed 0.00 sec + Start 105: default_build_coverage::threadx_module_manager_thread_kernel_stack_test +105/107 Test #105: default_build_coverage::threadx_module_manager_thread_kernel_stack_test ............. Passed 0.00 sec + Start 106: default_build_coverage::threadx_module_manager_object_authentication_test +106/107 Test #106: default_build_coverage::threadx_module_manager_object_authentication_test ........... Passed 0.00 sec + Start 107: default_build_coverage::threadx_module_manager_delete_ownership_test +107/107 Test #107: default_build_coverage::threadx_module_manager_delete_ownership_test ................ Passed 0.00 sec + +100% tests passed out of 107 + +Total Test time (real) = 34.26 sec +CTEST_RC=0 diff --git a/test/tx/cmake/module_manager/CMakeLists.txt b/test/tx/cmake/module_manager/CMakeLists.txt index 695a1fe5a..cfc0835c1 100644 --- a/test/tx/cmake/module_manager/CMakeLists.txt +++ b/test/tx/cmake/module_manager/CMakeLists.txt @@ -127,3 +127,29 @@ target_compile_options( add_test(${CMAKE_BUILD_TYPE}::threadx_module_manager_delete_ownership_test threadx_module_manager_delete_ownership_test) + +# This test drives the allocation and deallocation services directly rather than +# through a dispatcher, so it needs none of the dispatch table and no guard list. +add_executable( + threadx_module_manager_live_object_deallocation_test + ${SOURCE_DIR}/threadx_module_manager_live_object_deallocation_test.c + ${module_manager_dir}/src/txm_module_manager_util.c + ${module_manager_dir}/src/txm_module_manager_object_allocate.c + ${module_manager_dir}/src/txm_module_manager_object_deallocate.c) + +target_include_directories( + threadx_module_manager_live_object_deallocation_test + PRIVATE ${SOURCE_DIR} + ${REPO_ROOT}/common/inc + ${REPO_ROOT}/common_modules/inc + ${module_manager_dir}/inc + ${cortex_a7_module_dir}/inc) + +target_compile_options( + threadx_module_manager_live_object_deallocation_test + PRIVATE -Wall + -Wextra + -include ${SOURCE_DIR}/threadx_module_manager_host_test_port.h) + +add_test(${CMAKE_BUILD_TYPE}::threadx_module_manager_live_object_deallocation_test + threadx_module_manager_live_object_deallocation_test) diff --git a/test/tx/module_manager/threadx_module_manager_live_object_deallocation_test.c b/test/tx/module_manager/threadx_module_manager_live_object_deallocation_test.c new file mode 100644 index 000000000..3eaf95c67 --- /dev/null +++ b/test/tx/module_manager/threadx_module_manager_live_object_deallocation_test.c @@ -0,0 +1,1223 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Test */ +/** */ +/** Module Manager live kernel object deallocation */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +/* A module allocates the memory for its kernel objects from the Module Manager's + object pool, and can ask for that memory back by address. The manager gave that + memory back whatever was in it, including a control block the kernel was still + using: the object stays on the created list for its type, a thread stays on the + ready or suspension list it was on and stays schedulable, and an active timer + stays on the timer list. None of those consult a control block ID, so nothing + about the freed memory stops the kernel reading a name pointer out of it, + writing through the created links in it, restoring a context from the stack + pointer in it, or calling the timeout function pointer in it -- while the byte + pool is free to have handed those same bytes to the next allocation. + + The manager now refuses to release the memory of an object that is still + created, and answers the question from the kernel's created lists rather than + from the control block, because a control block is not evidence: an allocation + that was never made into an object can carry the value of an ID, and objects of + distinct types share a size. + + This test drives that refusal on the host. The object pool behind it is + modelled -- a bump allocator that hands back the block it most recently + released, so that the address of a freed object can be seen to come back -- but + the two records the manager consults are built the way the system builds them: + the module allocation list by running the real + _txm_module_manager_object_allocate, and the kernel created lists the way the + create and delete services maintain them. + + What the test asserts is that memory is given back when, and only when, no live + kernel object is in it: refused for every one of the eight object types, and + still released for storage that was never created, for storage carrying nothing + but a plausible ID, and for an object that has been deleted -- which is the + release the delete dispatchers perform, and the one this must not break. */ + +#include + +#include "threadx_module_manager_host_test_port.h" + +#include "tx_thread.h" +#include "tx_timer.h" +#include "tx_queue.h" +#include "tx_event_flags.h" +#include "tx_semaphore.h" +#include "tx_mutex.h" +#include "tx_block_pool.h" +#include "tx_byte_pool.h" +#include "txm_module.h" +#include "txm_module_manager_util.h" + + +/* Define the stand-in interrupt lock the port shim counts through. */ + +unsigned int test_interrupt_disable_depth; +unsigned int test_interrupt_disable_max_depth; +unsigned int test_interrupt_restore_underflows; + + +/* Define the modelled object pool. */ + +#define TEST_POOL_BYTES ((ULONG) 8192) +#define TEST_MODULE_MEMORY_BYTES 512U + +static union +{ + ALIGN_TYPE test_pool_alignment; + UCHAR test_pool_bytes[TEST_POOL_BYTES]; +} test_pool_arena; + +static ULONG test_pool_offset; + + +/* Define the memory that stands for the calling module's own code and data. */ + +static union +{ + ALIGN_TYPE test_data_alignment; + UCHAR test_data_bytes[TEST_MODULE_MEMORY_BYTES]; +} test_module_data; + +static union +{ + ALIGN_TYPE test_code_alignment; + UCHAR test_code_bytes[TEST_MODULE_MEMORY_BYTES]; +} test_module_code; + + +/* Define an object that stands for one the application owns and shared with a + module. It lives outside the pool, so the manager has no allocation record of + it and the kernel created list is the only record of it there is. */ + +static TX_QUEUE test_host_queue; + + +/* Define the thread that stands for the module thread making the request. The + manager takes the calling module from it. */ + +static TX_THREAD test_current_thread; + + +/* Define the block the modelled pool most recently released, so that a later + allocation of the same size lands on the address a freed object had, and so + that a case can see whether anything was released at all. */ + +static UCHAR *test_released_start; +static ULONG test_released_bytes; +static ULONG test_releases; + + +/* Define the manager state the code under test reaches for. */ + +TX_BYTE_POOL _txm_module_manager_object_pool; +UINT _txm_module_manager_object_pool_created; +TX_MUTEX _txm_module_manager_mutex; +TX_THREAD *_tx_thread_current_ptr; + + +/* Define the kernel created lists the liveness check walks. */ + +TX_BLOCK_POOL *_tx_block_pool_created_ptr; +ULONG _tx_block_pool_created_count; +TX_BYTE_POOL *_tx_byte_pool_created_ptr; +ULONG _tx_byte_pool_created_count; +TX_EVENT_FLAGS_GROUP *_tx_event_flags_created_ptr; +ULONG _tx_event_flags_created_count; +TX_MUTEX *_tx_mutex_created_ptr; +ULONG _tx_mutex_created_count; +TX_QUEUE *_tx_queue_created_ptr; +ULONG _tx_queue_created_count; +TX_SEMAPHORE *_tx_semaphore_created_ptr; +ULONG _tx_semaphore_created_count; +TX_THREAD *_tx_thread_created_ptr; +ULONG _tx_thread_created_count; +TX_TIMER *_tx_timer_created_ptr; +ULONG _tx_timer_created_count; + + +static UINT test_failures; +static ULONG test_checks; + + +/* Record the outcome of one expectation. */ +static VOID test_expect(const char *description, ULONG actual, ULONG expected) +{ + test_checks++; + + if (actual != expected) + { + printf("FAIL: %s (expected %lu, got %lu)\n", description, (unsigned long) expected, (unsigned long) actual); + test_failures++; + } +} + + +/* Report every module object type the manager knows, and the name, control block + size and control block ID of each, so that the cases below can be written once + and run against all of them. */ + +typedef struct TEST_OBJECT_KIND_STRUCT +{ + UINT test_kind_type; + const char *test_kind_name; + ULONG test_kind_size; + ULONG test_kind_id; +} TEST_OBJECT_KIND; + +static const TEST_OBJECT_KIND test_object_kinds[] = +{ + { TXM_BLOCK_POOL_OBJECT, "block pool", (ULONG) sizeof(TX_BLOCK_POOL), TX_BLOCK_POOL_ID }, + { TXM_BYTE_POOL_OBJECT, "byte pool", (ULONG) sizeof(TX_BYTE_POOL), TX_BYTE_POOL_ID }, + { TXM_EVENT_FLAGS_OBJECT, "event flags", (ULONG) sizeof(TX_EVENT_FLAGS_GROUP), TX_EVENT_FLAGS_ID }, + { TXM_MUTEX_OBJECT, "mutex", (ULONG) sizeof(TX_MUTEX), TX_MUTEX_ID }, + { TXM_QUEUE_OBJECT, "queue", (ULONG) sizeof(TX_QUEUE), TX_QUEUE_ID }, + { TXM_SEMAPHORE_OBJECT, "semaphore", (ULONG) sizeof(TX_SEMAPHORE), TX_SEMAPHORE_ID }, + { TXM_THREAD_OBJECT, "thread", (ULONG) sizeof(TX_THREAD), TX_THREAD_ID }, + { TXM_TIMER_OBJECT, "timer", (ULONG) sizeof(TX_TIMER), TX_TIMER_ID } +}; + +#define TEST_OBJECT_KIND_COUNT (sizeof(test_object_kinds) / sizeof(test_object_kinds[0])) + + +/* Round a request up the way _tx_byte_allocate does. */ +static ULONG test_round_up(ULONG memory_size) +{ + return((((memory_size + ((ULONG) sizeof(ALIGN_TYPE))) - ((ULONG) 1)) / ((ULONG) sizeof(ALIGN_TYPE))) * ((ULONG) sizeof(ALIGN_TYPE))); +} + + +/* Stand in for the byte pool the manager allocates object memory from. + + The two size bounds are the real ones. The placement is a bump allocator with + one refinement: a request that exactly fits the block most recently released is + given that block back. A first-fit byte pool reuses freed memory, and the cases + about an address that has been released need the address to actually come back. */ +UINT _txe_byte_allocate(TX_BYTE_POOL *pool_ptr, VOID **memory_ptr, ULONG memory_size, ULONG wait_option) +{ + +ULONG rounded_size; +UCHAR *block_start; + + + (VOID) wait_option; + + if ((pool_ptr != &_txm_module_manager_object_pool) || (memory_ptr == TX_NULL)) + { + return(TX_POOL_ERROR); + } + + if (memory_size == ((ULONG) 0)) + { + return(TX_SIZE_ERROR); + } + + if (memory_size > pool_ptr -> tx_byte_pool_size) + { + return(TX_SIZE_ERROR); + } + + rounded_size = test_round_up(memory_size); + + if ((test_released_start != TX_NULL) && (test_released_bytes == rounded_size)) + { + block_start = test_released_start; + test_released_start = TX_NULL; + test_released_bytes = ((ULONG) 0); + } + else + { + if ((test_pool_offset + rounded_size) > TEST_POOL_BYTES) + { + return(TX_NO_MEMORY); + } + + block_start = &test_pool_arena.test_pool_bytes[test_pool_offset]; + test_pool_offset = test_pool_offset + rounded_size; + } + + pool_ptr -> tx_byte_pool_available = pool_ptr -> tx_byte_pool_available - rounded_size; + + *memory_ptr = (VOID *) block_start; + + return(TX_SUCCESS); +} + + +/* Stand in for the release side, remembering the block so it can come back, and + counting releases so that a case can see whether one happened. */ +UINT _txe_byte_release(VOID *memory_ptr) +{ + +UCHAR *block_start; + + + block_start = (UCHAR *) memory_ptr; + + if ((block_start < test_pool_arena.test_pool_bytes) || + (block_start >= &test_pool_arena.test_pool_bytes[TEST_POOL_BYTES])) + { + return(TX_PTR_ERROR); + } + + test_releases++; + + /* The model does not track block lengths, and the only released block a case + needs to come back is the one it just released, whose length it knows. The + length is recorded by the caller through test_release_size. */ + test_released_start = block_start; + + return(TX_SUCCESS); +} + + +/* Tell the model how long the block just released was. */ +static VOID test_release_size(ULONG object_size) +{ + test_released_bytes = test_round_up(object_size + ((ULONG) sizeof(TXM_MODULE_ALLOCATED_OBJECT))); +} + + +/* Stand in for the protection mutex. */ +UINT _txe_mutex_get(TX_MUTEX *mutex_ptr, ULONG wait_option) +{ + (VOID) mutex_ptr; + (VOID) wait_option; + + return(TX_SUCCESS); +} + + +UINT _txe_mutex_put(TX_MUTEX *mutex_ptr) +{ + (VOID) mutex_ptr; + + return(TX_SUCCESS); +} + + +/* Stand in for the module port's data range check. */ +UINT _txm_module_manager_inside_data_check(ULONG obj_ptr) +{ + +ULONG data_start; +ULONG data_end; + + + data_start = (ULONG) (ALIGN_TYPE) test_module_data.test_data_bytes; + data_end = data_start + ((ULONG) TEST_MODULE_MEMORY_BYTES); + + if ((obj_ptr >= data_start) && (obj_ptr < data_end)) + { + return(TX_TRUE); + } + + return(TX_FALSE); +} + + +/* Stand in for the port primitive a manager source under test refers to but that + no case here exercises. */ +VOID _txm_module_manager_alignment_adjust(TXM_MODULE_PREAMBLE *module_preamble, ULONG *code_size, + ULONG *code_alignment, ULONG *data_size, ULONG *data_alignment) +{ + (VOID) module_preamble; + (VOID) code_size; + (VOID) code_alignment; + (VOID) data_size; + (VOID) data_alignment; +} + + +/* Do to an object what the kernel's create service does: write the control block + ID, and link the object onto the created list for its type. + + The chain each list is built as ends in a self-link on its oldest member rather + than closing back on the head, so that a walk bounded by the created count + visits every member and a walk that ignored the count would not run off the + end. What is being tested is the bound, not the model. */ +static VOID test_object_create(VOID *object_ptr, UINT object_type) +{ + switch (object_type) + { + + case TXM_BLOCK_POOL_OBJECT: + { + TX_BLOCK_POOL *block_pool_ptr = (TX_BLOCK_POOL *) object_ptr; + + block_pool_ptr -> tx_block_pool_id = TX_BLOCK_POOL_ID; + block_pool_ptr -> tx_block_pool_created_next = (_tx_block_pool_created_ptr == TX_NULL) ? block_pool_ptr : _tx_block_pool_created_ptr; + _tx_block_pool_created_ptr = block_pool_ptr; + _tx_block_pool_created_count++; + break; + } + + case TXM_BYTE_POOL_OBJECT: + { + TX_BYTE_POOL *byte_pool_ptr = (TX_BYTE_POOL *) object_ptr; + + byte_pool_ptr -> tx_byte_pool_id = TX_BYTE_POOL_ID; + byte_pool_ptr -> tx_byte_pool_created_next = (_tx_byte_pool_created_ptr == TX_NULL) ? byte_pool_ptr : _tx_byte_pool_created_ptr; + _tx_byte_pool_created_ptr = byte_pool_ptr; + _tx_byte_pool_created_count++; + break; + } + + case TXM_EVENT_FLAGS_OBJECT: + { + TX_EVENT_FLAGS_GROUP *event_flags_ptr = (TX_EVENT_FLAGS_GROUP *) object_ptr; + + event_flags_ptr -> tx_event_flags_group_id = TX_EVENT_FLAGS_ID; + event_flags_ptr -> tx_event_flags_group_created_next = (_tx_event_flags_created_ptr == TX_NULL) ? event_flags_ptr : _tx_event_flags_created_ptr; + _tx_event_flags_created_ptr = event_flags_ptr; + _tx_event_flags_created_count++; + break; + } + + case TXM_MUTEX_OBJECT: + { + TX_MUTEX *mutex_ptr = (TX_MUTEX *) object_ptr; + + mutex_ptr -> tx_mutex_id = TX_MUTEX_ID; + mutex_ptr -> tx_mutex_created_next = (_tx_mutex_created_ptr == TX_NULL) ? mutex_ptr : _tx_mutex_created_ptr; + _tx_mutex_created_ptr = mutex_ptr; + _tx_mutex_created_count++; + break; + } + + case TXM_QUEUE_OBJECT: + { + TX_QUEUE *queue_ptr = (TX_QUEUE *) object_ptr; + + queue_ptr -> tx_queue_id = TX_QUEUE_ID; + queue_ptr -> tx_queue_created_next = (_tx_queue_created_ptr == TX_NULL) ? queue_ptr : _tx_queue_created_ptr; + _tx_queue_created_ptr = queue_ptr; + _tx_queue_created_count++; + break; + } + + case TXM_SEMAPHORE_OBJECT: + { + TX_SEMAPHORE *semaphore_ptr = (TX_SEMAPHORE *) object_ptr; + + semaphore_ptr -> tx_semaphore_id = TX_SEMAPHORE_ID; + semaphore_ptr -> tx_semaphore_created_next = (_tx_semaphore_created_ptr == TX_NULL) ? semaphore_ptr : _tx_semaphore_created_ptr; + _tx_semaphore_created_ptr = semaphore_ptr; + _tx_semaphore_created_count++; + break; + } + + case TXM_THREAD_OBJECT: + { + TX_THREAD *thread_ptr = (TX_THREAD *) object_ptr; + + thread_ptr -> tx_thread_id = TX_THREAD_ID; + thread_ptr -> tx_thread_created_next = (_tx_thread_created_ptr == TX_NULL) ? thread_ptr : _tx_thread_created_ptr; + _tx_thread_created_ptr = thread_ptr; + _tx_thread_created_count++; + break; + } + + case TXM_TIMER_OBJECT: + default: + { + TX_TIMER *timer_ptr = (TX_TIMER *) object_ptr; + + timer_ptr -> tx_timer_id = TX_TIMER_ID; + timer_ptr -> tx_timer_created_next = (_tx_timer_created_ptr == TX_NULL) ? timer_ptr : _tx_timer_created_ptr; + _tx_timer_created_ptr = timer_ptr; + _tx_timer_created_count++; + break; + } + } +} + + +/* Do to an object what the kernel's delete service does: clear the control block + ID, and take the object off the created list for its type. + + Every case that deletes has one object of that type on the list, which is the + shape that matters here, so the model empties the list rather than unlinking a + member of a longer one. */ +static VOID test_object_delete(VOID *object_ptr, UINT object_type) +{ + switch (object_type) + { + + case TXM_BLOCK_POOL_OBJECT: + + ((TX_BLOCK_POOL *) object_ptr) -> tx_block_pool_id = TX_CLEAR_ID; + _tx_block_pool_created_ptr = TX_NULL; + _tx_block_pool_created_count = ((ULONG) 0); + break; + + case TXM_BYTE_POOL_OBJECT: + + ((TX_BYTE_POOL *) object_ptr) -> tx_byte_pool_id = TX_CLEAR_ID; + _tx_byte_pool_created_ptr = TX_NULL; + _tx_byte_pool_created_count = ((ULONG) 0); + break; + + case TXM_EVENT_FLAGS_OBJECT: + + ((TX_EVENT_FLAGS_GROUP *) object_ptr) -> tx_event_flags_group_id = TX_CLEAR_ID; + _tx_event_flags_created_ptr = TX_NULL; + _tx_event_flags_created_count = ((ULONG) 0); + break; + + case TXM_MUTEX_OBJECT: + + ((TX_MUTEX *) object_ptr) -> tx_mutex_id = TX_CLEAR_ID; + _tx_mutex_created_ptr = TX_NULL; + _tx_mutex_created_count = ((ULONG) 0); + break; + + case TXM_QUEUE_OBJECT: + + ((TX_QUEUE *) object_ptr) -> tx_queue_id = TX_CLEAR_ID; + _tx_queue_created_ptr = TX_NULL; + _tx_queue_created_count = ((ULONG) 0); + break; + + case TXM_SEMAPHORE_OBJECT: + + ((TX_SEMAPHORE *) object_ptr) -> tx_semaphore_id = TX_CLEAR_ID; + _tx_semaphore_created_ptr = TX_NULL; + _tx_semaphore_created_count = ((ULONG) 0); + break; + + case TXM_THREAD_OBJECT: + + ((TX_THREAD *) object_ptr) -> tx_thread_id = TX_CLEAR_ID; + _tx_thread_created_ptr = TX_NULL; + _tx_thread_created_count = ((ULONG) 0); + break; + + case TXM_TIMER_OBJECT: + default: + + ((TX_TIMER *) object_ptr) -> tx_timer_id = TX_CLEAR_ID; + _tx_timer_created_ptr = TX_NULL; + _tx_timer_created_count = ((ULONG) 0); + break; + } +} + + +/* Break the created list for a type after its first member, and tell the kernel it + is longer than it is. A search bounded only by the count would run off the end of + the chain; this is what makes the second bound observable for every type. */ +static VOID test_object_orphan(VOID *object_ptr, UINT object_type) +{ + switch (object_type) + { + + case TXM_BLOCK_POOL_OBJECT: + + ((TX_BLOCK_POOL *) object_ptr) -> tx_block_pool_created_next = TX_NULL; + _tx_block_pool_created_count = ((ULONG) 64); + break; + + case TXM_BYTE_POOL_OBJECT: + + ((TX_BYTE_POOL *) object_ptr) -> tx_byte_pool_created_next = TX_NULL; + _tx_byte_pool_created_count = ((ULONG) 64); + break; + + case TXM_EVENT_FLAGS_OBJECT: + + ((TX_EVENT_FLAGS_GROUP *) object_ptr) -> tx_event_flags_group_created_next = TX_NULL; + _tx_event_flags_created_count = ((ULONG) 64); + break; + + case TXM_MUTEX_OBJECT: + + ((TX_MUTEX *) object_ptr) -> tx_mutex_created_next = TX_NULL; + _tx_mutex_created_count = ((ULONG) 64); + break; + + case TXM_QUEUE_OBJECT: + + ((TX_QUEUE *) object_ptr) -> tx_queue_created_next = TX_NULL; + _tx_queue_created_count = ((ULONG) 64); + break; + + case TXM_SEMAPHORE_OBJECT: + + ((TX_SEMAPHORE *) object_ptr) -> tx_semaphore_created_next = TX_NULL; + _tx_semaphore_created_count = ((ULONG) 64); + break; + + case TXM_THREAD_OBJECT: + + ((TX_THREAD *) object_ptr) -> tx_thread_created_next = TX_NULL; + _tx_thread_created_count = ((ULONG) 64); + break; + + case TXM_TIMER_OBJECT: + default: + + ((TX_TIMER *) object_ptr) -> tx_timer_created_next = TX_NULL; + _tx_timer_created_count = ((ULONG) 64); + break; + } +} + + +/* Read the control block ID word of an object. */ +static ULONG test_object_id(VOID *object_ptr) +{ + return(*((ULONG *) object_ptr)); +} + + +/* Plant a value at an offset into an allocation, and report what was there. */ +static ULONG test_plant(VOID *object_ptr, ULONG offset, ULONG value) +{ + +ULONG *word_ptr; +ULONG previous; + + + word_ptr = (ULONG *) (VOID *) (((UCHAR *) object_ptr) + offset); + previous = *word_ptr; + *word_ptr = value; + + return(previous); +} + + +/* Bring the pool, the created lists and the modules back to a known state. + + Everything is reset together deliberately. The allocation lists point into the + pool and the created lists point at objects in it, so a case that left either + behind would have the next case reading the wreckage of an earlier one rather + than what it was written to check. */ +static VOID test_reset(TXM_MODULE_INSTANCE *module_a, TXM_MODULE_INSTANCE *module_b) +{ + +UINT index; + + + for (index = 0U; index < (UINT) TEST_POOL_BYTES; index++) + { + test_pool_arena.test_pool_bytes[index] = (UCHAR) 0; + } + + for (index = 0U; index < TEST_MODULE_MEMORY_BYTES; index++) + { + test_module_data.test_data_bytes[index] = (UCHAR) 0; + test_module_code.test_code_bytes[index] = (UCHAR) 0; + } + + test_pool_offset = ((ULONG) 0); + test_released_start = TX_NULL; + test_released_bytes = ((ULONG) 0); + test_releases = ((ULONG) 0); + + _txm_module_manager_object_pool.tx_byte_pool_id = TX_BYTE_POOL_ID; + _txm_module_manager_object_pool.tx_byte_pool_start = test_pool_arena.test_pool_bytes; + _txm_module_manager_object_pool.tx_byte_pool_size = TEST_POOL_BYTES; + _txm_module_manager_object_pool.tx_byte_pool_available = TEST_POOL_BYTES; + _txm_module_manager_object_pool_created = TX_TRUE; + + _tx_block_pool_created_ptr = TX_NULL; + _tx_block_pool_created_count = ((ULONG) 0); + _tx_byte_pool_created_ptr = TX_NULL; + _tx_byte_pool_created_count = ((ULONG) 0); + _tx_event_flags_created_ptr = TX_NULL; + _tx_event_flags_created_count = ((ULONG) 0); + _tx_mutex_created_ptr = TX_NULL; + _tx_mutex_created_count = ((ULONG) 0); + _tx_queue_created_ptr = TX_NULL; + _tx_queue_created_count = ((ULONG) 0); + _tx_semaphore_created_ptr = TX_NULL; + _tx_semaphore_created_count = ((ULONG) 0); + _tx_thread_created_ptr = TX_NULL; + _tx_thread_created_count = ((ULONG) 0); + _tx_timer_created_ptr = TX_NULL; + _tx_timer_created_count = ((ULONG) 0); + + module_a -> txm_module_instance_object_list_count = ((ULONG) 0); + module_a -> txm_module_instance_object_list_head = TX_NULL; + module_b -> txm_module_instance_object_list_count = ((ULONG) 0); + module_b -> txm_module_instance_object_list_head = TX_NULL; + + /* The requesting thread belongs to module A throughout. It is not in the pool + and not on a created list, so it is nothing the cases below can find. */ + test_current_thread.tx_thread_module_instance_ptr = module_a; + _tx_thread_current_ptr = &test_current_thread; +} + + +/* Allocate object memory for a module through the real manager path. */ +static VOID *test_allocate(TXM_MODULE_INSTANCE *module_instance, ULONG object_size) +{ + +VOID *object_ptr; +UINT status; + + + object_ptr = TX_NULL; + status = _txm_module_manager_object_allocate(&object_ptr, object_size, module_instance); + + if (status != TX_SUCCESS) + { + printf("FAIL: the modelled pool refused an allocation of %lu bytes (status %u)\n", + (unsigned long) object_size, status); + test_failures++; + + return(TX_NULL); + } + + return(object_ptr); +} + + +/* Allocate and create one object of a type, the way a module does. */ +static VOID *test_allocate_and_create(TXM_MODULE_INSTANCE *module_instance, const TEST_OBJECT_KIND *kind) +{ + +VOID *object_ptr; + + + object_ptr = test_allocate(module_instance, kind -> test_kind_size); + + if (object_ptr != TX_NULL) + { + test_object_create(object_ptr, kind -> test_kind_type); + } + + return(object_ptr); +} + + +/* Ask the manager to give an address back, and report what it said. Whatever it + decided, it must have left the interrupt lock as it found it. */ +static ULONG test_deallocate(VOID *object_ptr) +{ + +ULONG status; + + + test_interrupt_disable_depth = 0U; + test_interrupt_disable_max_depth = 0U; + test_interrupt_restore_underflows = 0U; + + status = (ULONG) _txm_module_manager_object_deallocate(object_ptr); + + if ((test_interrupt_disable_depth != 0U) || (test_interrupt_restore_underflows != 0U)) + { + printf("FAIL: deallocation left the interrupt lock unbalanced (depth %u, underflows %u)\n", + test_interrupt_disable_depth, test_interrupt_restore_underflows); + test_failures++; + } + + return(status); +} + + +/* Ask the manager whether a live kernel object is at an address, with the same + accounting. */ +static ULONG test_live_check(VOID *object_ptr) +{ + +ULONG status; + + + test_interrupt_disable_depth = 0U; + test_interrupt_disable_max_depth = 0U; + test_interrupt_restore_underflows = 0U; + + status = (ULONG) _txm_module_manager_live_object_check((ALIGN_TYPE) object_ptr); + + if ((test_interrupt_disable_depth != 0U) || (test_interrupt_restore_underflows != 0U)) + { + printf("FAIL: the liveness check left the interrupt lock unbalanced (depth %u, underflows %u)\n", + test_interrupt_disable_depth, test_interrupt_restore_underflows); + test_failures++; + } + + return(status); +} + + +int main(void) +{ + +TXM_MODULE_INSTANCE module_a; +TXM_MODULE_INSTANCE module_b; +const TEST_OBJECT_KIND *kind; +const TEST_OBJECT_KIND *other_kind; +VOID *object; +VOID *other_object; +VOID *raw_object; +VOID *reused_object; +ULONG index; +ULONG other_index; +ULONG saved; +ULONG status; +char description[160]; + + + /* Report expectations before anything can crash, so that a case that brings + the process down is still preceded by everything that passed. */ + setvbuf(stdout, TX_NULL, _IONBF, 0); + + test_failures = 0U; + test_checks = ((ULONG) 0); + + /* Set up two memory-protected modules. Module A does the asking throughout; + module B is there to own allocations A did not make. */ + module_a.txm_module_instance_property_flags = TXM_MODULE_MEMORY_PROTECTION; + module_a.txm_module_instance_code_start = (VOID *) test_module_code.test_code_bytes; + module_a.txm_module_instance_code_end = (VOID *) &test_module_code.test_code_bytes[TEST_MODULE_MEMORY_BYTES - 1U]; + module_a.txm_module_instance_data_start = (VOID *) test_module_data.test_data_bytes; + module_a.txm_module_instance_data_end = (VOID *) &test_module_data.test_data_bytes[TEST_MODULE_MEMORY_BYTES - 1U]; + + module_b = module_a; + + /**********************************************************************/ + /* The reported call: giving back the memory of a live object. */ + /**********************************************************************/ + + for (index = ((ULONG) 0); index < (ULONG) TEST_OBJECT_KIND_COUNT; index++) + { + kind = &test_object_kinds[index]; + + test_reset(&module_a, &module_b); + + object = test_allocate_and_create(&module_a, kind); + + (void) snprintf(description, sizeof(description), + "a live %s is on the created list before anything is asked", kind -> test_kind_name); + test_expect(description, test_live_check(object), (ULONG) TX_TRUE); + + /* The scan has to have run with interrupts disabled, which is the + protection the created lists are maintained under. */ + test_expect("...found with interrupts disabled, one deep", + (ULONG) test_interrupt_disable_max_depth, ((ULONG) 1)); + + status = test_deallocate(object); + + (void) snprintf(description, sizeof(description), + "the memory of a live %s is not given back", kind -> test_kind_name); + test_expect(description, status, (ULONG) TX_DELETE_ERROR); + + test_expect("...nothing was released to the pool", test_releases, ((ULONG) 0)); + + test_expect("...the allocation is still on the module's list", + module_a.txm_module_instance_object_list_count, ((ULONG) 1)); + + test_expect("...at the head of it", + (ULONG) (module_a.txm_module_instance_object_list_head == (((TXM_MODULE_ALLOCATED_OBJECT *) object) - 1)), + (ULONG) TX_TRUE); + + (void) snprintf(description, sizeof(description), + "...the %s still carries its control block ID", kind -> test_kind_name); + test_expect(description, test_object_id(object), kind -> test_kind_id); + + (void) snprintf(description, sizeof(description), + "...and is still a live %s", kind -> test_kind_name); + test_expect(description, test_live_check(object), (ULONG) TX_TRUE); + + /* Deleting it is what makes the memory releasable, and the release the + delete dispatchers perform after a successful delete then goes through. */ + test_object_delete(object, kind -> test_kind_type); + + (void) snprintf(description, sizeof(description), + "a deleted %s is no longer live", kind -> test_kind_name); + test_expect(description, test_live_check(object), (ULONG) TX_FALSE); + + test_release_size(kind -> test_kind_size); + status = test_deallocate(object); + + test_expect("and its memory is given back", status, (ULONG) TX_SUCCESS); + + test_expect("...leaving the module's allocation list empty", + module_a.txm_module_instance_object_list_count, ((ULONG) 0)); + + /* The address is free to come back now, which is what the kernel would + have been sharing with the next owner had the live object been freed. */ + reused_object = test_allocate(&module_a, kind -> test_kind_size); + + test_expect("...and the address free to be handed out again", + (ULONG) (reused_object == object), (ULONG) TX_TRUE); + } + + /**********************************************************************/ + /* Storage that is not an object is still released. */ + /**********************************************************************/ + + test_reset(&module_a, &module_b); + + /* An allocation that was never made into an object. This is what a module has + after a create that failed or was abandoned, and releasing it is the reason + the request exists at all. */ + raw_object = test_allocate(&module_a, (ULONG) sizeof(TX_QUEUE)); + + test_expect("an uncreated allocation holds no live object", + test_live_check(raw_object), (ULONG) TX_FALSE); + + test_release_size((ULONG) sizeof(TX_QUEUE)); + test_expect("and its memory is given back", + test_deallocate(raw_object), (ULONG) TX_SUCCESS); + test_expect("...leaving the module's allocation list empty", + module_a.txm_module_instance_object_list_count, ((ULONG) 0)); + + /* An allocation carrying nothing but the value of a control block ID. A + control block ID is not evidence that an object is there, and refusing on + one would strand memory a module is entitled to have back. */ + for (index = ((ULONG) 0); index < (ULONG) TEST_OBJECT_KIND_COUNT; index++) + { + kind = &test_object_kinds[index]; + + test_reset(&module_a, &module_b); + + raw_object = test_allocate(&module_a, kind -> test_kind_size); + (VOID) test_plant(raw_object, ((ULONG) 0), kind -> test_kind_id); + + (void) snprintf(description, sizeof(description), + "an uncreated allocation carrying a %s ID holds no live object", kind -> test_kind_name); + test_expect(description, test_live_check(raw_object), (ULONG) TX_FALSE); + + test_release_size(kind -> test_kind_size); + + test_expect("...and its memory is given back", + test_deallocate(raw_object), (ULONG) TX_SUCCESS); + } + + /**********************************************************************/ + /* The allocation size is not what decides it. */ + /**********************************************************************/ + + test_reset(&module_a, &module_b); + + /* A module running without memory protection creates objects through no + size-checked path, so an object can be at the start of an allocation far + larger than its control block. Deciding which created lists to search from + the size of the allocation would miss it. */ + object = test_allocate(&module_a, (ULONG) sizeof(TX_THREAD)); + test_object_create(object, TXM_QUEUE_OBJECT); + + test_expect("a queue at the start of a thread-sized allocation is live", + test_live_check(object), (ULONG) TX_TRUE); + test_expect("and the memory is not given back", + test_deallocate(object), (ULONG) TX_DELETE_ERROR); + test_expect("...with nothing released to the pool", test_releases, ((ULONG) 0)); + + /**********************************************************************/ + /* Only the exact address of an object counts. */ + /**********************************************************************/ + + test_reset(&module_a, &module_b); + + kind = &test_object_kinds[6]; + object = test_allocate_and_create(&module_a, kind); + + /* Every aligned interior offset of a live object, with that object's own ID + planted at the offset. None of them is the address of an object. */ + for (index = (ULONG) sizeof(ULONG); index < kind -> test_kind_size; index = index + ((ULONG) sizeof(ULONG))) + { + saved = test_plant(object, index, kind -> test_kind_id); + + (void) snprintf(description, sizeof(description), + "an address %lu bytes into a live thread holds no live object", (unsigned long) index); + test_expect(description, test_live_check((VOID *) (((UCHAR *) object) + index)), (ULONG) TX_FALSE); + + (VOID) test_plant(object, index, saved); + } + + test_expect("the address one past a live thread holds no live object", + test_live_check((VOID *) (((UCHAR *) object) + kind -> test_kind_size)), (ULONG) TX_FALSE); + + /**********************************************************************/ + /* Every type is searched, and each type only finds its own. */ + /**********************************************************************/ + + for (index = ((ULONG) 0); index < (ULONG) TEST_OBJECT_KIND_COUNT; index++) + { + kind = &test_object_kinds[index]; + + test_reset(&module_a, &module_b); + + /* One object of this type, and one allocation of every other type's size + that was never created. Only the created one is found, whatever ID the + others are carrying. */ + object = test_allocate_and_create(&module_a, kind); + + for (other_index = ((ULONG) 0); other_index < (ULONG) TEST_OBJECT_KIND_COUNT; other_index++) + { + if (other_index == index) + { + continue; + } + + other_kind = &test_object_kinds[other_index]; + other_object = test_allocate(&module_a, other_kind -> test_kind_size); + (VOID) test_plant(other_object, ((ULONG) 0), other_kind -> test_kind_id); + + (void) snprintf(description, sizeof(description), + "with a live %s created, an uncreated %s is not found", + kind -> test_kind_name, other_kind -> test_kind_name); + test_expect(description, test_live_check(other_object), (ULONG) TX_FALSE); + } + + (void) snprintf(description, sizeof(description), + "and the live %s is", kind -> test_kind_name); + test_expect(description, test_live_check(object), (ULONG) TX_TRUE); + } + + /**********************************************************************/ + /* Liveness is the kernel's record, not the pool's. */ + /**********************************************************************/ + + test_reset(&module_a, &module_b); + + /* An object the application created lives outside the pool, and the manager + has no allocation record of it. The kernel created list is the only record + there is, and it is the record this consults. */ + test_object_create(&test_host_queue, TXM_QUEUE_OBJECT); + + test_expect("an application-owned queue outside the pool is live", + test_live_check(&test_host_queue), (ULONG) TX_TRUE); + + test_object_delete(&test_host_queue, TXM_QUEUE_OBJECT); + + test_expect("and is not once it has been deleted", + test_live_check(&test_host_queue), (ULONG) TX_FALSE); + + /**********************************************************************/ + /* The bounds on the search. */ + /**********************************************************************/ + + test_reset(&module_a, &module_b); + + /* Three queues, and a created count that says one. A list whose links have + been damaged must not make the scan run past the count the kernel keeps + beside it. */ + object = test_allocate_and_create(&module_a, &test_object_kinds[4]); + other_object = test_allocate_and_create(&module_a, &test_object_kinds[4]); + raw_object = test_allocate_and_create(&module_a, &test_object_kinds[4]); + + test_expect("all three queues are on the list", _tx_queue_created_count, ((ULONG) 3)); + test_expect("the newest is found", test_live_check(raw_object), (ULONG) TX_TRUE); + test_expect("the oldest is found too", test_live_check(object), (ULONG) TX_TRUE); + + _tx_queue_created_count = ((ULONG) 1); + + test_expect("with the count saying one, the head is still found", + test_live_check(raw_object), (ULONG) TX_TRUE); + test_expect("...but the second member is not walked to", + test_live_check(other_object), (ULONG) TX_FALSE); + test_expect("...nor the third", + test_live_check(object), (ULONG) TX_FALSE); + + /* A count larger than the list. The walk has to stop at the end of the chain + as well as at the count. */ + _tx_queue_created_count = ((ULONG) 64); + ((TX_QUEUE *) raw_object) -> tx_queue_created_next = TX_NULL; + + test_expect("a count larger than the list does not run the scan off the end", + test_live_check(&test_host_queue), (ULONG) TX_FALSE); + + /* An empty list is the ordinary state of most types on most systems. */ + _tx_queue_created_ptr = TX_NULL; + _tx_queue_created_count = ((ULONG) 0); + + test_expect("nothing is live once every list is empty", + test_live_check(raw_object), (ULONG) TX_FALSE); + + /* The same bound, for every type: a chain that ends before the count does. */ + for (index = ((ULONG) 0); index < (ULONG) TEST_OBJECT_KIND_COUNT; index++) + { + kind = &test_object_kinds[index]; + + test_reset(&module_a, &module_b); + + object = test_allocate_and_create(&module_a, kind); + test_object_orphan(object, kind -> test_kind_type); + + (void) snprintf(description, sizeof(description), + "a %s list that ends before its count does not run the scan off the end", + kind -> test_kind_name); + test_expect(description, test_live_check(&test_host_queue), (ULONG) TX_FALSE); + + (void) snprintf(description, sizeof(description), + "...and the %s at its head is still found", kind -> test_kind_name); + test_expect(description, test_live_check(object), (ULONG) TX_TRUE); + } + + /**********************************************************************/ + /* Allocations belonging to another module. */ + /**********************************************************************/ + + test_reset(&module_a, &module_b); + + /* Module B's live object. Module A is refused, and the refusal is the + ownership one: whether A may operate on B's objects at all is a separate + question, and this request never reaches the liveness one. */ + object = test_allocate_and_create(&module_b, &test_object_kinds[5]); + + test_expect("module A cannot give back module B's live allocation", + test_deallocate(object), (ULONG) TX_PTR_ERROR); + test_expect("...and B's allocation list is untouched", + module_b.txm_module_instance_object_list_count, ((ULONG) 1)); + test_expect("...with nothing released to the pool", test_releases, ((ULONG) 0)); + + /* And B's uncreated storage, which A is refused for the same reason. */ + raw_object = test_allocate(&module_b, (ULONG) sizeof(TX_QUEUE)); + + test_expect("module A cannot give back module B's uncreated allocation", + test_deallocate(raw_object), (ULONG) TX_PTR_ERROR); + test_expect("...and B's allocation list still holds both", + module_b.txm_module_instance_object_list_count, ((ULONG) 2)); + + /* B can give its own uncreated storage back, so the ownership test has not + been turned into a refusal of everything. */ + test_current_thread.tx_thread_module_instance_ptr = &module_b; + + test_release_size((ULONG) sizeof(TX_QUEUE)); + test_expect("module B can give back its own uncreated allocation", + test_deallocate(raw_object), (ULONG) TX_SUCCESS); + test_expect("...but not its own live object", + test_deallocate(object), (ULONG) TX_DELETE_ERROR); + + test_current_thread.tx_thread_module_instance_ptr = &module_a; + + /**********************************************************************/ + /* An address that is not the start of one of this module's allocations.*/ + /**********************************************************************/ + + test_reset(&module_a, &module_b); + + object = test_allocate(&module_a, (ULONG) sizeof(TX_QUEUE)); + + /* An address inside an allocation names none of this module's allocations. + The search establishes that without reading the words in front of the + address, so an interior address is refused rather than taken for a header. */ + test_expect("an address inside an allocation is refused as naming no allocation", + test_deallocate((VOID *) (((UCHAR *) object) + sizeof(ULONG))), (ULONG) TX_PTR_ERROR); + + test_expect("...leaving the module's allocation list as it was", + module_a.txm_module_instance_object_list_count, ((ULONG) 1)); + + /**********************************************************************/ + /* Types the manager does not know. */ + /**********************************************************************/ + + test_reset(&module_a, &module_b); + + object = test_allocate_and_create(&module_a, &test_object_kinds[4]); + + /* The per-type check is asked directly here, because the search over the + types the manager knows can never present it with one it does not. A + kernel stack allocation is the case that exists: the manager allocates it + from the same pool and gives it a type of its own, and there is no created + list for it. */ + test_expect("a kernel stack is not a type with a created list", + (ULONG) _txm_module_manager_created_object_type_check((ALIGN_TYPE) object, + (UINT) TXM_THREAD_KERNEL_STACK_OBJECT), + (ULONG) TX_FALSE); + + test_expect("nor is a type of zero", + (ULONG) _txm_module_manager_created_object_type_check((ALIGN_TYPE) object, 0U), + (ULONG) TX_FALSE); + + test_expect("and the live queue is still found by the search", + test_live_check(object), (ULONG) TX_TRUE); + + /**********************************************************************/ + /* Releasing one allocation out of several. */ + /**********************************************************************/ + + test_reset(&module_a, &module_b); + + /* Allocations are appended behind the head, so the first one made is the + head. Releasing it has to move the head on rather than leave it pointing + at memory that has gone back to the pool. */ + object = test_allocate(&module_a, (ULONG) sizeof(TX_QUEUE)); + other_object = test_allocate(&module_a, (ULONG) sizeof(TX_QUEUE)); + + test_expect("the first allocation is the list head", + (ULONG) (module_a.txm_module_instance_object_list_head == (((TXM_MODULE_ALLOCATED_OBJECT *) object) - 1)), + (ULONG) TX_TRUE); + + test_release_size((ULONG) sizeof(TX_QUEUE)); + test_expect("releasing the head allocation succeeds", + test_deallocate(object), (ULONG) TX_SUCCESS); + test_expect("...leaving one allocation on the list", + module_a.txm_module_instance_object_list_count, ((ULONG) 1)); + test_expect("...and the head moved on to it", + (ULONG) (module_a.txm_module_instance_object_list_head == (((TXM_MODULE_ALLOCATED_OBJECT *) other_object) - 1)), + (ULONG) TX_TRUE); + + test_release_size((ULONG) sizeof(TX_QUEUE)); + test_expect("releasing the last allocation succeeds", + test_deallocate(other_object), (ULONG) TX_SUCCESS); + test_expect("...emptying the list", + module_a.txm_module_instance_object_list_count, ((ULONG) 0)); + test_expect("...and clearing its head", + (ULONG) (module_a.txm_module_instance_object_list_head == TX_NULL), (ULONG) TX_TRUE); + + /* Asking for the same address again. The header in front of it still names this + module, because nothing has overwritten it, so the empty allocation list is + what has to refuse the second release rather than the owner test. */ + test_expect("releasing the same address a second time is refused", + test_deallocate(other_object), (ULONG) TX_PTR_ERROR); + + /* An address with no room for a header in front of it anywhere in the address + space. The header pointer is null, and the address itself is never read. */ + test_expect("an address whose header would be at zero is refused", + test_deallocate((VOID *) ((ALIGN_TYPE) sizeof(TXM_MODULE_ALLOCATED_OBJECT))), + (ULONG) TX_PTR_ERROR); + + /**********************************************************************/ + /* An object pool that was never created. */ + /**********************************************************************/ + + test_reset(&module_a, &module_b); + + _txm_module_manager_object_pool_created = TX_FALSE; + + test_expect("and the deallocation reports the feature is not available", + test_deallocate((VOID *) test_pool_arena.test_pool_bytes), (ULONG) TX_NOT_AVAILABLE); + + _txm_module_manager_object_pool_created = TX_TRUE; + + /**********************************************************************/ + /* What the whole run has to have held. */ + /**********************************************************************/ + + test_expect("every case ran", (ULONG) (test_checks > ((ULONG) 100)), (ULONG) TX_TRUE); + + if (test_failures == 0U) + { + printf("SUCCESS! %lu expectations\n", (unsigned long) test_checks); + return(0); + } + + printf("ERROR: %u expectation(s) failed of %lu\n", test_failures, (unsigned long) test_checks); + return(1); +} diff --git a/test/tx/module_manager/threadx_module_manager_object_authentication_test.c b/test/tx/module_manager/threadx_module_manager_object_authentication_test.c index ca583956f..576ed532f 100644 --- a/test/tx/module_manager/threadx_module_manager_object_authentication_test.c +++ b/test/tx/module_manager/threadx_module_manager_object_authentication_test.c @@ -854,26 +854,33 @@ char description[128]; test_expect("a live queue is accepted before anything is given back", test_authenticate(&module_a, object, TXM_QUEUE_OBJECT), (ULONG) TX_TRUE); - /* Give the memory back without deleting the object first. The manager stops - vouching for the control block at the moment it stops owning the memory, so - the address is refused even though the created list has not been told. */ + /* Memory holding a live object is not given back at all. The object stays + created, the allocation stays owned, and the address stays authentic, so + the state this once had to defend against -- an object on the created list + whose memory the manager no longer owns -- cannot be reached. */ _tx_thread_current_ptr = (TX_THREAD *) test_allocate(&module_a, (ULONG) sizeof(TX_THREAD)); _tx_thread_current_ptr -> tx_thread_module_instance_ptr = &module_a; - test_release_size(kind -> test_kind_size); status = _txm_module_manager_object_deallocate(object); - test_expect("the object memory is given back", (ULONG) status, (ULONG) TX_SUCCESS); + test_expect("memory holding a live object is not given back", (ULONG) status, (ULONG) TX_DELETE_ERROR); + + test_expect("and the live object is still accepted afterwards", + test_authenticate(&module_a, object, TXM_QUEUE_OBJECT), (ULONG) TX_TRUE); - test_expect("an address whose memory was given back without a delete is refused", - test_authenticate(&module_a, object, TXM_QUEUE_OBJECT), (ULONG) TX_FALSE); + /* Deleted first, the same memory is given back, and the address comes round + again as a fresh, raw allocation. It is once again an exact allocation start + of the right size, and the ID of the object that used to be there can be + written back into it by the module that now owns it, so the created list is + the only thing that refuses it. */ + test_object_delete(object, kind -> test_kind_type); + test_release_size(kind -> test_kind_size); + status = _txm_module_manager_object_deallocate(object); + test_expect("a deleted object's memory is given back", (ULONG) status, (ULONG) TX_SUCCESS); - /* The same address now comes back as a fresh, raw allocation. It is once - again an exact allocation start of the right size, and it is still on the - created list, so nothing but the cleared ID stands between it and being - taken for the object that used to be there. */ raw_object = test_allocate(&module_a, kind -> test_kind_size); test_expect("the freed address is handed out again", (ULONG) (raw_object == object), (ULONG) TX_TRUE); + (VOID) test_plant(raw_object, ((ULONG) 0), kind -> test_kind_id); test_expect("and is not accepted as the object that used to be there", test_authenticate(&module_a, raw_object, TXM_QUEUE_OBJECT), (ULONG) TX_FALSE); From ff4be30656bf105ca9599feae8198790eb7f9c45 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 28 Sep 2026 10:22:07 -0400 Subject: [PATCH 155/181] Covered the control block ID cleared when module memory is given back (#779) The control block ID that _txm_module_manager_object_deallocate clears on its way out is read by the size-based object check, which is the one kept for dispatchers outside this repository. Nothing exercised that path. The expectations covering the clearing all went through object authentication, which consults the kernel's created list and would refuse a recycled address whatever its ID said, so they would have passed with the clearing removed. A section drives the size-based check directly. A module plants the value of an ID into memory it owns, gives the allocation back, and is handed the same address again; the check accepts the planted ID before the deallocation and refuses it afterwards, which is the difference the clearing makes. The authentication test holds 125 expectations and passes. Removing the ID clearing fails it. The full suite passes 107/107 in default_build_coverage with no warnings. Assisted-by: Claude Code (Opus 5) --- ...odule_manager_object_authentication_test.c | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/test/tx/module_manager/threadx_module_manager_object_authentication_test.c b/test/tx/module_manager/threadx_module_manager_object_authentication_test.c index 576ed532f..6c79efaec 100644 --- a/test/tx/module_manager/threadx_module_manager_object_authentication_test.c +++ b/test/tx/module_manager/threadx_module_manager_object_authentication_test.c @@ -886,6 +886,44 @@ char description[128]; _tx_thread_current_ptr = TX_NULL; + /**********************************************************************/ + /* The control block ID in memory the manager gives back. */ + /**********************************************************************/ + + /* Authentication reads the kernel's created list, so it refuses a recycled + address whatever the words in it say. The size-based check is the one that + reads the control block ID, and it is kept for dispatchers outside this + repository, so clearing the ID on the way out is what stops memory a module + wrote an ID into presenting that ID to whoever holds the address next. */ + + test_reset(&module_a, &module_b); + + kind = &test_object_kinds[4]; + raw_object = test_allocate(&module_a, kind -> test_kind_size); + + _tx_thread_current_ptr = (TX_THREAD *) test_allocate(&module_a, (ULONG) sizeof(TX_THREAD)); + _tx_thread_current_ptr -> tx_thread_module_instance_ptr = &module_a; + + (VOID) test_plant(raw_object, ((ULONG) 0), kind -> test_kind_id); + + test_expect("memory carrying a planted ID reads as an object of that type", + (ULONG) _txm_module_manager_object_id_check((ALIGN_TYPE) raw_object, TXM_QUEUE_OBJECT), + (ULONG) TX_TRUE); + + test_release_size(kind -> test_kind_size); + status = _txm_module_manager_object_deallocate(raw_object); + test_expect("the allocation is given back", (ULONG) status, (ULONG) TX_SUCCESS); + + object = test_allocate(&module_a, kind -> test_kind_size); + test_expect("the address comes round again", + (ULONG) (object == raw_object), (ULONG) TX_TRUE); + + test_expect("and no longer reads as an object of that type", + (ULONG) _txm_module_manager_object_id_check((ALIGN_TYPE) object, TXM_QUEUE_OBJECT), + (ULONG) TX_FALSE); + + _tx_thread_current_ptr = TX_NULL; + /**********************************************************************/ /* Objects the application owns, and objects nobody owns. */ /**********************************************************************/ From 35d41371262a77eac2ad9dc359f913826e0b2718 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 28 Sep 2026 10:37:13 -0400 Subject: [PATCH 156/181] Merge commit from fork A module calls txm_module_object_allocate and chooses object_size. The manager adds sizeof(TXM_MODULE_ALLOCATED_OBJECT) to it and asked the object pool for the result without checking the addition, so a size near the top of a ULONG wrapped: object_size 0xFFFFFFF8 asked for eight bytes, the pool served them, and the manager then wrote its sixteen-byte header -- owner, list links and size -- into that eight-byte block and linked it into the module's allocation list. Eight bytes of the next block's contents or header are gone by the time the call returns, and the shared object pool that every module allocates from is the thing that was corrupted. The addition is now made with the repository's own overflow-checked helper, which was already used on both load paths and simply never reached this one, and it is made before the protection mutex is taken so a refused request leaves the pool, the allocation list and its count exactly as they were. Sizes that survive the addition need no further bound here: _txe_byte_allocate refuses a request larger than the pool, so the alignment round-up in _tx_byte_allocate is never reached with a value that could wrap in its turn. Regression coverage runs on the host by modelling the byte pool behind the manager. The model applies the two bounds _txe_byte_allocate applies and hands out a block of precisely the requested length with a guard band immediately after it, so an undersized allocation is caught as the out-of-bounds write it is rather than inferred from arithmetic. Thirty-two of its expectations fail against the previous implementation, twenty reporting state a refused request must not have touched and two reporting the eight and twelve bytes written past the end of the block. It reaches 100% line, branch and call coverage of the changed function; the lines it leaves uncovered are its own failure reporting, plus the modelled pool's zero-size refusal, which only an unfixed build reaches. Assisted-by: Claude Code (Opus 5) --- .../src/txm_module_manager_object_allocate.c | 27 +- test/tx/cmake/module_manager/CMakeLists.txt | 20 + ...le_manager_object_allocate_overflow_test.c | 814 ++++++++++++++++++ 3 files changed, 858 insertions(+), 3 deletions(-) create mode 100644 test/tx/module_manager/threadx_module_manager_object_allocate_overflow_test.c diff --git a/common_modules/module_manager/src/txm_module_manager_object_allocate.c b/common_modules/module_manager/src/txm_module_manager_object_allocate.c index 92ae128c2..7729ad322 100644 --- a/common_modules/module_manager/src/txm_module_manager_object_allocate.c +++ b/common_modules/module_manager/src/txm_module_manager_object_allocate.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Claude Code (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -23,6 +25,7 @@ #define TX_SOURCE_CODE #include "txm_module.h" +#include "txm_module_manager_util.h" /**************************************************************************/ /* */ @@ -51,6 +54,11 @@ /* OUTPUT */ /* */ /* status Completion status */ +/* TXM_MODULE_MATH_OVERFLOW is */ +/* returned when object_size is so */ +/* large that adding the manager's */ +/* own object header to it would */ +/* not be representable */ /* */ /* CALLS */ /* */ @@ -67,6 +75,7 @@ UINT _txm_module_manager_object_allocate(VOID **object_ptr_ptr, ULONG object_siz { TXM_MODULE_ALLOCATED_OBJECT *object_ptr; +ULONG allocation_size; UINT return_value; @@ -81,6 +90,18 @@ UINT return_value; /* Initialize the return pointer to NULL. */ *((VOID **) object_ptr_ptr) = TX_NULL; + /* Work out how much memory the pool must supply: the size the caller asked for plus + the private header this function writes in front of it. The size is supplied by + the module, so the addition is checked. An unchecked one wraps for sizes near the + top of a ULONG and asks the pool for fewer bytes than the header alone occupies, + after which the header stores below run past the end of the allocation and into + the neighbouring pool block. Sizes that survive the addition but exceed the pool + are refused by _txe_byte_allocate, which bounds every request by the pool size. + + This is done before the protection mutex is taken so that a refused request leaves + the object pool, the module's allocated object list and its count untouched. */ + TXM_MODULE_MANAGER_UTIL_MATH_ADD_ULONG(object_size, (ULONG) sizeof(TXM_MODULE_ALLOCATED_OBJECT), allocation_size); + /* Get module manager protection mutex. */ _txe_mutex_get(&_txm_module_manager_mutex, TX_WAIT_FOREVER); @@ -90,10 +111,10 @@ UINT return_value; TXM_MODULE_ALLOCATED_OBJECT *next_object, *previous_object; - /* Allocate the object requested by the module - adding an extra ULONG in order to - store the module instance pointer. */ + /* Allocate the object requested by the module, including the header checked above + that holds the owning module instance, the allocation list links and the size. */ return_value = (ULONG) _txe_byte_allocate(&_txm_module_manager_object_pool, (VOID **) &object_ptr, - (ULONG) (object_size + sizeof(TXM_MODULE_ALLOCATED_OBJECT)), TX_NO_WAIT); + allocation_size, TX_NO_WAIT); /* Determine if the request was successful. */ if (return_value == TX_SUCCESS) diff --git a/test/tx/cmake/module_manager/CMakeLists.txt b/test/tx/cmake/module_manager/CMakeLists.txt index cfc0835c1..f87970adf 100644 --- a/test/tx/cmake/module_manager/CMakeLists.txt +++ b/test/tx/cmake/module_manager/CMakeLists.txt @@ -153,3 +153,23 @@ target_compile_options( add_test(${CMAKE_BUILD_TYPE}::threadx_module_manager_live_object_deallocation_test threadx_module_manager_live_object_deallocation_test) +add_executable( + threadx_module_manager_object_allocate_overflow_test + ${SOURCE_DIR}/threadx_module_manager_object_allocate_overflow_test.c + ${module_manager_dir}/src/txm_module_manager_util.c + ${module_manager_dir}/src/txm_module_manager_object_allocate.c + ${module_manager_dir}/src/txm_module_manager_object_deallocate.c) + +target_include_directories( + threadx_module_manager_object_allocate_overflow_test + PRIVATE ${REPO_ROOT}/common/inc + ${REPO_ROOT}/common_modules/inc + ${module_manager_dir}/inc + ${cortex_a7_module_dir}/inc) + +target_compile_options( + threadx_module_manager_object_allocate_overflow_test + PRIVATE -include ${SOURCE_DIR}/threadx_module_manager_host_test_port.h) + +add_test(${CMAKE_BUILD_TYPE}::threadx_module_manager_object_allocate_overflow_test + threadx_module_manager_object_allocate_overflow_test) diff --git a/test/tx/module_manager/threadx_module_manager_object_allocate_overflow_test.c b/test/tx/module_manager/threadx_module_manager_object_allocate_overflow_test.c new file mode 100644 index 000000000..5989ca48f --- /dev/null +++ b/test/tx/module_manager/threadx_module_manager_object_allocate_overflow_test.c @@ -0,0 +1,814 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Test */ +/** */ +/** Module Manager object allocation size arithmetic */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +/* A module asks the Module Manager for object memory and chooses the size. The + manager adds its own private header to that size, and the header it writes is + larger than the smallest allocation the byte pool will hand out, so the + addition has to be checked before the pool is asked for anything. + + This test drives _txm_module_manager_object_allocate on the host with the + Cortex-A7 module port's control blocks. The byte pool behind it is modelled + rather than run: the model applies exactly the two bounds _txe_byte_allocate + applies, refusing a zero size and a size larger than the pool, and it hands + out a block of precisely the requested length with a guard band immediately + after it. An allocation that the manager then overruns is therefore caught as + a real out-of-bounds write rather than inferred from arithmetic, which is what + makes the refusals below testable: revert the check and the manager writes its + sixteen-byte header into an eight-byte block and stamps on the guard. */ + +#include + +#define TX_SOURCE_CODE + +#include "tx_api.h" +#include "tx_byte_pool.h" +#include "tx_thread.h" +#include "txm_module.h" +#include "txm_module_manager_util.h" + + +/* Define the modelled pool. + + The arena is physically larger than the pool the manager is told about, so the + guard band that follows every block has somewhere to live without the pool's + own accounting having to know about it. */ + +#define TEST_ARENA_BYTES 8192U +#define TEST_POOL_BYTES 4096UL +#define TEST_GUARD_BYTES 32U +#define TEST_GUARD_PATTERN 0xE7U +#define TEST_MAX_BLOCKS 32U + +#define TEST_HEADER_BYTES ((ULONG) sizeof(TXM_MODULE_ALLOCATED_OBJECT)) +#define TEST_ULONG_MAX ((ULONG) ~((ULONG) 0)) + +/* The object size that makes the unchecked addition wrap to a chosen value. */ +#define TEST_SIZE_WRAPPING_TO(want) ((ULONG) (((ULONG) (want)) - TEST_HEADER_BYTES)) + + +/* Define one block the modelled pool has handed out. */ + +typedef struct TEST_BLOCK_STRUCT +{ + UCHAR *test_block_start; + ULONG test_block_bytes; + UINT test_block_live; +} TEST_BLOCK; + + +/* Define the state the modelled pool and the stubbed services answer from. */ + +static union +{ + ALIGN_TYPE test_arena_alignment; + UCHAR test_arena_bytes[TEST_ARENA_BYTES]; +} test_arena; + +static ULONG test_arena_offset; +static TEST_BLOCK test_blocks[TEST_MAX_BLOCKS]; +static UINT test_block_count; + +static ULONG test_allocate_calls; +static ULONG test_allocate_size; +static ULONG test_allocate_wait; +static ULONG test_release_calls; +static ULONG test_mutex_get_calls; +static ULONG test_mutex_put_calls; + +/* Counted across the whole run rather than per case, because what they answer -- + was the pool ever asked for less than the header the manager then writes, and + was it ever asked on behalf of something other than itself -- is about the run + as a whole. */ +static UINT test_undersized_requests; +static UINT test_misdirected_requests; + +static UINT test_failures; + + +/* Define the manager state the code under test reaches for. */ + +TX_BYTE_POOL _txm_module_manager_object_pool; +UINT _txm_module_manager_object_pool_created; +TX_MUTEX _txm_module_manager_mutex; +TX_THREAD *_tx_thread_current_ptr; + + +/* Define the stand-in interrupt lock the port shim counts through. */ + +unsigned int test_interrupt_disable_depth; +unsigned int test_interrupt_disable_max_depth; +unsigned int test_interrupt_restore_underflows; + + +/* The kernel's created lists. A created object lives on the list for its type, and + the manager reads those lists, so a test that stands in for the kernel has to + provide them. All stay empty here, because this test creates no kernel object; + it exercises the arithmetic the allocation does before any object exists. */ + +TX_BLOCK_POOL *_tx_block_pool_created_ptr; +ULONG _tx_block_pool_created_count; +TX_BYTE_POOL *_tx_byte_pool_created_ptr; +ULONG _tx_byte_pool_created_count; +TX_EVENT_FLAGS_GROUP *_tx_event_flags_created_ptr; +ULONG _tx_event_flags_created_count; +TX_MUTEX *_tx_mutex_created_ptr; +ULONG _tx_mutex_created_count; +TX_QUEUE *_tx_queue_created_ptr; +ULONG _tx_queue_created_count; +TX_SEMAPHORE *_tx_semaphore_created_ptr; +ULONG _tx_semaphore_created_count; +TX_THREAD *_tx_thread_created_ptr; +ULONG _tx_thread_created_count; +TX_TIMER *_tx_timer_created_ptr; +ULONG _tx_timer_created_count; + + +/* This test models no module memory of its own, so no address is ever inside the + calling module's data. */ +UINT _txm_module_manager_inside_data_check(ULONG obj_ptr) +{ + (VOID) obj_ptr; + + return(TX_FALSE); +} + + +/* Not reached from the allocation path under test. */ +VOID _txm_module_manager_alignment_adjust(TXM_MODULE_PREAMBLE *module_preamble, ULONG *code_size, + ULONG *code_alignment, ULONG *data_size, ULONG *data_alignment) +{ + (VOID) module_preamble; + (VOID) code_size; + (VOID) code_alignment; + (VOID) data_size; + (VOID) data_alignment; +} + + +/* Record the outcome of one expectation. */ +static VOID test_expect(const char *description, ULONG actual, ULONG expected) +{ + if (actual != expected) + { + printf("FAIL: %s (expected %lu, got %lu)\n", description, (unsigned long) expected, (unsigned long) actual); + test_failures++; + } +} + + +/* Round a request up the way _tx_byte_allocate does. */ +static ULONG test_round_up(ULONG memory_size) +{ + return((((memory_size + ((ULONG) sizeof(ALIGN_TYPE))) - ((ULONG) 1)) / ((ULONG) sizeof(ALIGN_TYPE))) * ((ULONG) sizeof(ALIGN_TYPE))); +} + + +/* Lay a guard band down after a block. */ +static VOID test_guard_write(UCHAR *guard_ptr) +{ + +UINT index; + + + for (index = 0U; index < TEST_GUARD_BYTES; index++) + { + guard_ptr[index] = (UCHAR) TEST_GUARD_PATTERN; + } +} + + +/* Report how many guard bytes anything has written through, across every block + the modelled pool has ever handed out, live or released. */ +static ULONG test_guard_damage(VOID) +{ + +UINT block; +UINT index; +UCHAR *guard_ptr; +ULONG damaged; + + + damaged = ((ULONG) 0); + + for (block = 0U; block < test_block_count; block++) + { + guard_ptr = test_blocks[block].test_block_start + test_blocks[block].test_block_bytes; + + for (index = 0U; index < TEST_GUARD_BYTES; index++) + { + if (guard_ptr[index] != (UCHAR) TEST_GUARD_PATTERN) + { + damaged++; + } + } + } + + return(damaged); +} + + +/* Stand in for the byte pool the manager allocates objects from. + + The two size bounds and the alignment round-up are the real ones. What is not + real is the placement: every block ends where a guard band begins, so nothing + the manager writes past the end of its allocation can land in memory that a + later assertion would have accepted. */ +UINT _txe_byte_allocate(TX_BYTE_POOL *pool_ptr, VOID **memory_ptr, ULONG memory_size, ULONG wait_option) +{ + +ULONG rounded_size; +UCHAR *block_start; + + + test_allocate_calls++; + test_allocate_size = memory_size; + test_allocate_wait = wait_option; + + /* The manager must never ask for less than the header it is about to write. + This is the invariant the checked addition exists to hold, so the model + records a breach here as well as letting the guard band catch the write. */ + if (memory_size < TEST_HEADER_BYTES) + { + test_undersized_requests++; + } + + /* _txe_byte_allocate answers a null pool, a pool that is not one, and a null + destination with TX_POOL_ERROR and TX_PTR_ERROR. The manager always supplies + its own pool and a real destination, so rather than model arms this test + could never reach, note a breach and let the assertion at the end of the run + report it. */ + if ((pool_ptr != &_txm_module_manager_object_pool) || + (pool_ptr -> tx_byte_pool_id != TX_BYTE_POOL_ID) || + (memory_ptr == TX_NULL)) + { + test_misdirected_requests++; + + return(TX_POOL_ERROR); + } + + if (memory_size == ((ULONG) 0)) + { + return(TX_SIZE_ERROR); + } + + if (memory_size > pool_ptr -> tx_byte_pool_size) + { + return(TX_SIZE_ERROR); + } + + rounded_size = test_round_up(memory_size); + + if ((rounded_size > pool_ptr -> tx_byte_pool_available) || + (test_block_count == TEST_MAX_BLOCKS) || + ((test_arena_offset + rounded_size + ((ULONG) TEST_GUARD_BYTES)) > ((ULONG) TEST_ARENA_BYTES))) + { + return(TX_NO_MEMORY); + } + + block_start = &test_arena.test_arena_bytes[test_arena_offset]; + + test_blocks[test_block_count].test_block_start = block_start; + test_blocks[test_block_count].test_block_bytes = rounded_size; + test_blocks[test_block_count].test_block_live = TX_TRUE; + test_block_count++; + + test_guard_write(block_start + rounded_size); + test_arena_offset = test_arena_offset + rounded_size + ((ULONG) TEST_GUARD_BYTES); + + pool_ptr -> tx_byte_pool_available = pool_ptr -> tx_byte_pool_available - rounded_size; + pool_ptr -> tx_byte_pool_fragments++; + pool_ptr -> tx_byte_pool_search = block_start; + + *memory_ptr = (VOID *) block_start; + + return(TX_SUCCESS); +} + + +/* Stand in for the release side, so a normal allocation can be given back. */ +UINT _txe_byte_release(VOID *memory_ptr) +{ + +UINT block; + + + test_release_calls++; + + for (block = 0U; block < test_block_count; block++) + { + if ((test_blocks[block].test_block_start == (UCHAR *) memory_ptr) && + (test_blocks[block].test_block_live == TX_TRUE)) + { + test_blocks[block].test_block_live = TX_FALSE; + _txm_module_manager_object_pool.tx_byte_pool_available = + _txm_module_manager_object_pool.tx_byte_pool_available + test_blocks[block].test_block_bytes; + + return(TX_SUCCESS); + } + } + + /* A release of something this pool never handed out, or handed out twice. */ + return(TX_PTR_ERROR); +} + + +/* Stand in for the protection mutex, to show when it is and is not taken. */ +UINT _txe_mutex_get(TX_MUTEX *mutex_ptr, ULONG wait_option) +{ + (VOID) mutex_ptr; + (VOID) wait_option; + test_mutex_get_calls++; + + return(TX_SUCCESS); +} + + +UINT _txe_mutex_put(TX_MUTEX *mutex_ptr) +{ + (VOID) mutex_ptr; + test_mutex_put_calls++; + + return(TX_SUCCESS); +} + + +/* Bring the modelled pool up, empty. */ +static VOID test_pool_reset(VOID) +{ + +UINT index; + + + for (index = 0U; index < TEST_ARENA_BYTES; index++) + { + test_arena.test_arena_bytes[index] = (UCHAR) 0; + } + + test_arena_offset = ((ULONG) 0); + test_block_count = 0U; + test_allocate_calls = ((ULONG) 0); + test_allocate_size = ((ULONG) 0); + test_allocate_wait = ((ULONG) 0); + test_release_calls = ((ULONG) 0); + test_mutex_get_calls = ((ULONG) 0); + test_mutex_put_calls = ((ULONG) 0); + + _txm_module_manager_object_pool.tx_byte_pool_id = TX_BYTE_POOL_ID; + _txm_module_manager_object_pool.tx_byte_pool_start = test_arena.test_arena_bytes; + _txm_module_manager_object_pool.tx_byte_pool_size = TEST_POOL_BYTES; + _txm_module_manager_object_pool.tx_byte_pool_available = TEST_POOL_BYTES; + _txm_module_manager_object_pool.tx_byte_pool_fragments = 0U; + _txm_module_manager_object_pool.tx_byte_pool_search = test_arena.test_arena_bytes; + _txm_module_manager_object_pool_created = TX_TRUE; +} + + +/* Bring the pool and the module that allocates from it back to a known state. + + Both are reset together deliberately. The module's allocation list points into + the pool, so a case that left objects behind would have the next case linking + new objects onto addresses this function has just zeroed, and every later + assertion would then be reading the wreckage of an earlier one rather than + what it was written to check. */ +static VOID test_reset(TXM_MODULE_INSTANCE *module_instance) +{ + test_pool_reset(); + + module_instance -> txm_module_instance_object_list_count = ((ULONG) 0); + module_instance -> txm_module_instance_object_list_head = TX_NULL; +} + + +/* Describe everything a refused request must have left alone. */ +typedef struct TEST_SNAPSHOT_STRUCT +{ + ULONG test_snapshot_available; + UINT test_snapshot_fragments; + UCHAR *test_snapshot_search; + ULONG test_snapshot_list_count; + TXM_MODULE_ALLOCATED_OBJECT *test_snapshot_list_head; + ULONG test_snapshot_allocate_calls; + ULONG test_snapshot_mutex_get_calls; +} TEST_SNAPSHOT; + + +static VOID test_snapshot_take(TEST_SNAPSHOT *snapshot, TXM_MODULE_INSTANCE *module_instance) +{ + snapshot -> test_snapshot_available = _txm_module_manager_object_pool.tx_byte_pool_available; + snapshot -> test_snapshot_fragments = _txm_module_manager_object_pool.tx_byte_pool_fragments; + snapshot -> test_snapshot_search = _txm_module_manager_object_pool.tx_byte_pool_search; + snapshot -> test_snapshot_list_count = module_instance -> txm_module_instance_object_list_count; + snapshot -> test_snapshot_list_head = module_instance -> txm_module_instance_object_list_head; + snapshot -> test_snapshot_allocate_calls = test_allocate_calls; + snapshot -> test_snapshot_mutex_get_calls = test_mutex_get_calls; +} + + +/* Assert that a refused request changed nothing an accepted one would have. */ +static VOID test_refusal_check(const char *description, TEST_SNAPSHOT *snapshot, + TXM_MODULE_INSTANCE *module_instance, VOID *object, UINT status) +{ + test_expect(description, (ULONG) status, (ULONG) TXM_MODULE_MATH_OVERFLOW); + test_expect("...returning a null object pointer", (ULONG) (object == TX_NULL), (ULONG) TX_TRUE); + test_expect("...without asking the pool for anything", + test_allocate_calls, snapshot -> test_snapshot_allocate_calls); + test_expect("...without taking the protection mutex", + test_mutex_get_calls, snapshot -> test_snapshot_mutex_get_calls); + test_expect("...leaving the bytes available unchanged", + _txm_module_manager_object_pool.tx_byte_pool_available, snapshot -> test_snapshot_available); + test_expect("...leaving the fragment count unchanged", + (ULONG) _txm_module_manager_object_pool.tx_byte_pool_fragments, (ULONG) snapshot -> test_snapshot_fragments); + test_expect("...leaving the search pointer unchanged", + (ULONG) (_txm_module_manager_object_pool.tx_byte_pool_search == snapshot -> test_snapshot_search), (ULONG) TX_TRUE); + test_expect("...leaving the module's object count unchanged", + module_instance -> txm_module_instance_object_list_count, snapshot -> test_snapshot_list_count); + test_expect("...leaving the module's object list head unchanged", + (ULONG) (module_instance -> txm_module_instance_object_list_head == snapshot -> test_snapshot_list_head), (ULONG) TX_TRUE); + test_expect("...and touching no guard band", test_guard_damage(), ((ULONG) 0)); +} + + +/* Model the arithmetic this test guards against, so that each refused size can + show what the previous implementation would have asked the pool for. */ +static ULONG test_unchecked_allocation_size(ULONG object_size) +{ + return((ULONG) (object_size + sizeof(TXM_MODULE_ALLOCATED_OBJECT))); +} + + +/* Confirm that one accepted allocation is shaped the way the rest of the manager + requires: the pool was asked for the object plus the header, the module was + handed the address just past the header, and the header records the size that + _txm_module_manager_object_size_check will later be asked to match. */ +static VOID test_accepted_check(const char *description, TXM_MODULE_INSTANCE *module_instance, + VOID *object, UINT status, ULONG object_size) +{ + +TXM_MODULE_ALLOCATED_OBJECT *header; + + + test_expect(description, (ULONG) status, (ULONG) TX_SUCCESS); + test_expect("...returning a non-null object pointer", (ULONG) (object != TX_NULL), (ULONG) TX_TRUE); + + if (object == TX_NULL) + { + return; + } + + test_expect("...having asked the pool for the object and the header", + test_allocate_size, object_size + TEST_HEADER_BYTES); + test_expect("...without waiting", test_allocate_wait, (ULONG) TX_NO_WAIT); + + header = ((TXM_MODULE_ALLOCATED_OBJECT *) object) - 1; + + test_expect("...placing the object immediately after the header", + (ULONG) (((UCHAR *) header) == test_blocks[test_block_count - 1U].test_block_start), (ULONG) TX_TRUE); + /* The size recorded here is what _txm_module_manager_object_size_check later + compares an object-creation request against, so a size the header did not + record faithfully would fail every creation dispatcher. */ + test_expect("...recording the requested size in the header", + header -> txm_module_object_size, object_size); + test_expect("...recording the owning module in the header", + (ULONG) (header -> txm_module_allocated_object_module_instance == module_instance), (ULONG) TX_TRUE); + test_expect("...and touching no guard band", test_guard_damage(), ((ULONG) 0)); +} + + +/* Walk the module's allocation list and report whether it is a consistent ring + of the expected length, owned throughout by the expected module. */ +static UINT test_list_consistent(TXM_MODULE_INSTANCE *module_instance, ULONG expected_count) +{ + +TXM_MODULE_ALLOCATED_OBJECT *object; +ULONG walked; + + + if (module_instance -> txm_module_instance_object_list_count != expected_count) + { + return(TX_FALSE); + } + + if (expected_count == ((ULONG) 0)) + { + return((UINT) (module_instance -> txm_module_instance_object_list_head == TX_NULL)); + } + + object = module_instance -> txm_module_instance_object_list_head; + + if (object == TX_NULL) + { + return(TX_FALSE); + } + + for (walked = ((ULONG) 0); walked < expected_count; walked++) + { + if (object -> txm_module_allocated_object_module_instance != module_instance) + { + return(TX_FALSE); + } + + if (object -> txm_module_allocated_object_next -> txm_module_allocated_object_previous != object) + { + return(TX_FALSE); + } + + object = object -> txm_module_allocated_object_next; + } + + /* The ring must close on the head after exactly the expected number of steps. */ + return((UINT) (object == module_instance -> txm_module_instance_object_list_head)); +} + + +/* The control block sizes a module can ask the manager to allocate for it. */ +typedef struct TEST_OBJECT_SIZE_STRUCT +{ + const char *test_object_name; + ULONG test_object_size; +} TEST_OBJECT_SIZE; + + +int main(void) +{ + +TXM_MODULE_INSTANCE module; +TXM_MODULE_INSTANCE *module_instance; +TX_THREAD module_thread; +TEST_SNAPSHOT snapshot; +VOID *object; +VOID *objects[8]; +UINT status; +UINT index; +ULONG object_size; +ULONG wrapped_size; + +TEST_OBJECT_SIZE object_sizes[] = +{ + {"a thread", (ULONG) sizeof(TX_THREAD)}, + {"a queue", (ULONG) sizeof(TX_QUEUE)}, + {"a semaphore", (ULONG) sizeof(TX_SEMAPHORE)}, + {"a mutex", (ULONG) sizeof(TX_MUTEX)}, + {"an event flags group",(ULONG) sizeof(TX_EVENT_FLAGS_GROUP)}, + {"a block pool", (ULONG) sizeof(TX_BLOCK_POOL)}, + {"a byte pool", (ULONG) sizeof(TX_BYTE_POOL)}, + {"a timer", (ULONG) sizeof(TX_TIMER)} +}; + +#define TEST_OBJECT_SIZE_ENTRIES (sizeof(object_sizes) / sizeof(object_sizes[0])) + + + /* Unbuffered, so that the expectations reported below survive a crash. An + undersized allocation is a memory-safety failure, and a build in which one + gets through has to say which expectation noticed before it dies. */ + setvbuf(stdout, TX_NULL, _IONBF, 0U); + + printf("Module Manager object allocation size arithmetic test.................. "); + + module_instance = &module; + module.txm_module_instance_id = TXM_MODULE_ID; + module.txm_module_instance_object_list_count = ((ULONG) 0); + module.txm_module_instance_object_list_head = TX_NULL; + + module_thread.tx_thread_module_instance_ptr = (VOID *) module_instance; + _tx_thread_current_ptr = &module_thread; + + test_reset(module_instance); + + /**********************************************************************/ + /* The header the manager writes is larger than the smallest block */ + /* the pool will hand out, which is what makes a wrapped size unsafe. */ + /**********************************************************************/ + + test_expect("the object header spans more than one pool alignment unit", + (ULONG) (TEST_HEADER_BYTES > (ULONG) sizeof(ALIGN_TYPE)), (ULONG) TX_TRUE); + + /**********************************************************************/ + /* Sizes for which the header-inclusive addition wraps. */ + /**********************************************************************/ + + /* The smallest size that overflows at all, and so the tight side of the new + comparison. It wraps to exactly zero, a request the pool would have refused + on its own, so this boundary fails safe even unfixed; it is here for the + boundary rather than for the consequence. */ + test_reset(module_instance); + + object_size = (TEST_ULONG_MAX - TEST_HEADER_BYTES) + ((ULONG) 1); + test_expect("the smallest overflowing size is one past the largest that fits", + object_size, TEST_SIZE_WRAPPING_TO(0UL)); + test_expect("...and wraps to zero", test_unchecked_allocation_size(object_size), ((ULONG) 0)); + test_snapshot_take(&snapshot, module_instance); + object = (VOID *) &module; + status = _txm_module_manager_object_allocate(&object, object_size, module_instance); + test_refusal_check("the smallest overflowing size is refused", + &snapshot, module_instance, object, status); + + /* Wrapping to eight. This is the exploitable one: the pool accepts an eight + byte request and the manager then writes sixteen bytes into it. */ + test_reset(module_instance); + + object_size = TEST_SIZE_WRAPPING_TO(8UL); + wrapped_size = test_unchecked_allocation_size(object_size); + test_expect("the size that wraps to eight is the one expected", wrapped_size, ((ULONG) 8)); + test_expect("...a request the pool would have accepted", + (ULONG) ((wrapped_size != ((ULONG) 0)) && (wrapped_size <= TEST_POOL_BYTES)), (ULONG) TX_TRUE); + test_expect("...for fewer bytes than the header alone occupies", + (ULONG) (wrapped_size < TEST_HEADER_BYTES), (ULONG) TX_TRUE); + test_snapshot_take(&snapshot, module_instance); + object = (VOID *) &module; + status = _txm_module_manager_object_allocate(&object, object_size, module_instance); + test_refusal_check("a size whose header-inclusive total wraps to a block smaller than the header is refused", + &snapshot, module_instance, object, status); + + /* Wrapping to one, the smallest request the pool would have served at all. */ + test_reset(module_instance); + + object_size = TEST_SIZE_WRAPPING_TO(1UL); + test_expect("the size that wraps to one is the one expected", + test_unchecked_allocation_size(object_size), ((ULONG) 1)); + test_snapshot_take(&snapshot, module_instance); + object = (VOID *) &module; + status = _txm_module_manager_object_allocate(&object, object_size, module_instance); + test_refusal_check("a size whose header-inclusive total wraps to a single byte is refused", + &snapshot, module_instance, object, status); + + /* The largest size expressible at all, which wraps to one byte less than the + header. */ + test_reset(module_instance); + + test_snapshot_take(&snapshot, module_instance); + object = (VOID *) &module; + status = _txm_module_manager_object_allocate(&object, TEST_ULONG_MAX, module_instance); + test_refusal_check("the largest expressible size is refused", &snapshot, module_instance, object, status); + + /**********************************************************************/ + /* The largest size that does not overflow. */ + /**********************************************************************/ + + /* This one must pass the check and reach the pool carrying its true total, + which the pool then refuses on its own size bound. It covers the accepting + side of the new comparison at the tightest point there is. */ + test_reset(module_instance); + + object_size = TEST_ULONG_MAX - TEST_HEADER_BYTES; + test_snapshot_take(&snapshot, module_instance); + object = (VOID *) &module; + status = _txm_module_manager_object_allocate(&object, object_size, module_instance); + + test_expect("the largest non-overflowing size is refused by the pool, not by the check", + (ULONG) status, (ULONG) TX_SIZE_ERROR); + test_expect("...having reached the pool", test_allocate_calls, snapshot.test_snapshot_allocate_calls + ((ULONG) 1)); + test_expect("...asking for the full untruncated total", test_allocate_size, TEST_ULONG_MAX); + test_expect("...returning a null object pointer", (ULONG) (object == TX_NULL), (ULONG) TX_TRUE); + test_expect("...leaving the module's object count unchanged", + module_instance -> txm_module_instance_object_list_count, snapshot.test_snapshot_list_count); + test_expect("...leaving the bytes available unchanged", + _txm_module_manager_object_pool.tx_byte_pool_available, snapshot.test_snapshot_available); + test_expect("...and releasing the protection mutex it took", + test_mutex_get_calls, test_mutex_put_calls); + + /**********************************************************************/ + /* Ordinary allocations, one for every control block a module can own. */ + /**********************************************************************/ + + test_reset(module_instance); + + for (index = 0U; index < (UINT) TEST_OBJECT_SIZE_ENTRIES; index++) + { + object = TX_NULL; + status = _txm_module_manager_object_allocate(&object, object_sizes[index].test_object_size, module_instance); + test_accepted_check(object_sizes[index].test_object_name, module_instance, object, status, + object_sizes[index].test_object_size); + objects[index] = object; + } + + test_expect("the module's allocation list holds every object in a consistent ring", + (ULONG) test_list_consistent(module_instance, (ULONG) TEST_OBJECT_SIZE_ENTRIES), (ULONG) TX_TRUE); + + /* Every one of them can be given back, and the list empties out. */ + for (index = 0U; index < (UINT) TEST_OBJECT_SIZE_ENTRIES; index++) + { + status = _txm_module_manager_object_deallocate(objects[index]); + test_expect("an allocated object can be released", (ULONG) status, (ULONG) TX_SUCCESS); + } + + test_expect("the allocation list is empty again", + (ULONG) test_list_consistent(module_instance, ((ULONG) 0)), (ULONG) TX_TRUE); + test_expect("every byte charged to the pool came back", + _txm_module_manager_object_pool.tx_byte_pool_available, TEST_POOL_BYTES); + test_expect("no guard band was touched by any of it", test_guard_damage(), ((ULONG) 0)); + test_expect("the protection mutex was balanced throughout", test_mutex_get_calls, test_mutex_put_calls); + + /**********************************************************************/ + /* A zero-length object, the other end of the accepted range. */ + /**********************************************************************/ + + test_reset(module_instance); + object = TX_NULL; + status = _txm_module_manager_object_allocate(&object, ((ULONG) 0), module_instance); + test_accepted_check("a zero-length object", module_instance, object, status, ((ULONG) 0)); + test_expect("...for which the pool was asked for exactly the header", + test_allocate_size, TEST_HEADER_BYTES); + (VOID) _txm_module_manager_object_deallocate(object); + + /**********************************************************************/ + /* Sizes the pool cannot serve, which must still not corrupt anything. */ + /**********************************************************************/ + + test_reset(module_instance); + + object = TX_NULL; + status = _txm_module_manager_object_allocate(&object, TEST_POOL_BYTES, module_instance); + test_expect("a size the pool is too small for is refused by the pool", + (ULONG) status, (ULONG) TX_SIZE_ERROR); + test_expect("...returning a null object pointer", (ULONG) (object == TX_NULL), (ULONG) TX_TRUE); + test_expect("...leaving the allocation list empty", + (ULONG) test_list_consistent(module_instance, ((ULONG) 0)), (ULONG) TX_TRUE); + + object = TX_NULL; + status = _txm_module_manager_object_allocate(&object, ((ULONG) 4000), module_instance); + test_expect("a size the pool can serve once succeeds", (ULONG) status, (ULONG) TX_SUCCESS); + + object = TX_NULL; + status = _txm_module_manager_object_allocate(&object, ((ULONG) 4000), module_instance); + test_expect("the same size again finds no memory", (ULONG) status, (ULONG) TX_NO_MEMORY); + test_expect("...returning a null object pointer", (ULONG) (object == TX_NULL), (ULONG) TX_TRUE); + test_expect("...leaving the one live object in the list", + (ULONG) test_list_consistent(module_instance, ((ULONG) 1)), (ULONG) TX_TRUE); + test_expect("...and touching no guard band", test_guard_damage(), ((ULONG) 0)); + + /**********************************************************************/ + /* Invalid and disabled configurations. */ + /**********************************************************************/ + + test_reset(module_instance); + + /* A null destination is rejected before the size is looked at, so it keeps + its own error even when the size would also have been refused. */ + status = _txm_module_manager_object_allocate(TX_NULL, TEST_ULONG_MAX, module_instance); + test_expect("a null destination pointer is rejected on its own terms", + (ULONG) status, (ULONG) TXM_MODULE_INVALID_MEMORY); + test_expect("...without asking the pool for anything", test_allocate_calls, ((ULONG) 0)); + test_expect("...without taking the protection mutex", test_mutex_get_calls, ((ULONG) 0)); + + /* With no object pool, an overflowing size is still refused as one: the + check runs before the manager looks at its own configuration. */ + _txm_module_manager_object_pool_created = TX_FALSE; + + test_snapshot_take(&snapshot, module_instance); + object = (VOID *) &module; + status = _txm_module_manager_object_allocate(&object, TEST_ULONG_MAX, module_instance); + test_refusal_check("an overflowing size is refused with no object pool created", + &snapshot, module_instance, object, status); + + object = TX_NULL; + status = _txm_module_manager_object_allocate(&object, (ULONG) sizeof(TX_MUTEX), module_instance); + test_expect("an ordinary size reports the pool is not available", + (ULONG) status, (ULONG) TX_NOT_AVAILABLE); + test_expect("...returning a null object pointer", (ULONG) (object == TX_NULL), (ULONG) TX_TRUE); + test_expect("...and releasing the protection mutex it took", + test_mutex_get_calls, test_mutex_put_calls); + + _txm_module_manager_object_pool_created = TX_TRUE; + + /**********************************************************************/ + /* The invariant the whole check exists to hold, over the whole run. */ + /**********************************************************************/ + + test_expect("the pool was never asked for less than the header it must hold", + (ULONG) test_undersized_requests, ((ULONG) 0)); + test_expect("every request named the manager's own pool and a real destination", + (ULONG) test_misdirected_requests, ((ULONG) 0)); + test_expect("and nothing wrote through a guard band", test_guard_damage(), ((ULONG) 0)); + + if (test_failures == 0U) + { + printf("SUCCESS!\n"); + return(0); + } + + printf("ERROR: %u expectation(s) failed\n", test_failures); + return(1); +} From a967d005f6330380f6b36ec85ab296967bf0aa0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 28 Sep 2026 10:52:12 -0400 Subject: [PATCH 157/181] Merge commit from fork _txm_module_manager_tx_block_pool_create_dispatch proved that two ALIGN_TYPE words of the extra-parameter array a module supplies lay inside the module's data, and then used indices 0 through 3. The two words it had not proved were read twice each in privileged context: once by the dispatcher's own buffer check, which takes index 1 as the pool start and index 2 as the length to range-check it over, and once when the argument list for _txe_block_pool_create was built. So the out-of-bounds read was performed by the validation code itself, and the size the caller's pool start was then validated against was a word the manager had not proved the module owned. A module reaches this by calling its kernel dispatcher directly with an array that ends two words before the boundary of its data or of a shared region, which the module library's own four-word array never does. The read window is eight bytes on every module port and there is nothing in it the module can lengthen. The extent becomes sizeof(ALIGN_TYPE[4]), which is what the two siblings of the same shape have always had: queue create validates four words for four, and byte-pool create three for three. Both checks on this path are data-only, with no fallback to the portable code-region check, so the four Cortex-A35 and Cortex-A35 SMP module port combinations whose data check is the constant (TX_SUCCESS) refuse these create requests from a memory-protected module before and after this change alike. The regression test drives all three create dispatchers and measures the extent each one validates rather than sampling either side of it: it anchors the array at the end of each region a module owns and walks it backwards until the dispatcher accepts, and the smallest room accepted is the extent. It measures the highest index each dispatcher uses through what the stubbed service records, so the invariant the three are checked against is measured on both sides. It also measures what a module can learn from the answers, since the buffer check is a comparison against a threshold the module chooses and the dispatcher's refusal is distinguishable from every status these services return. Compiled against the previous dispatch header the test reports the extent as two words and the service reached carrying a word planted past the end of the region; against this one it reports four. Assisted-by: Claude Code (Opus 5) --- .../inc/txm_module_manager_dispatch.h | 4 +- test/tx/cmake/module_manager/CMakeLists.txt | 21 + ...odule_manager_block_pool_parameters_test.c | 1452 +++++++++++++++++ 3 files changed, 1476 insertions(+), 1 deletion(-) create mode 100644 test/tx/module_manager/threadx_module_manager_block_pool_parameters_test.c diff --git a/common_modules/module_manager/inc/txm_module_manager_dispatch.h b/common_modules/module_manager/inc/txm_module_manager_dispatch.h index 0160a1d17..35e493d49 100644 --- a/common_modules/module_manager/inc/txm_module_manager_dispatch.h +++ b/common_modules/module_manager/inc/txm_module_manager_dispatch.h @@ -17,6 +17,8 @@ // Some portions generated by Claude Code (Opus 5). +// Some portions generated by Claude Code (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -79,7 +81,7 @@ ALIGN_TYPE return_value; if (!TXM_MODULE_MANAGER_PARAM_CHECK_DEREFERENCE_STRING(module_instance, param_1)) return(TXM_MODULE_INVALID_MEMORY); - if (!TXM_MODULE_MANAGER_ENSURE_INSIDE_MODULE_DATA(module_instance, (ALIGN_TYPE)extra_parameters, sizeof(ALIGN_TYPE[2]))) + if (!TXM_MODULE_MANAGER_ENSURE_INSIDE_MODULE_DATA(module_instance, (ALIGN_TYPE)extra_parameters, sizeof(ALIGN_TYPE[4]))) return(TXM_MODULE_INVALID_MEMORY); if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, extra_parameters[1], extra_parameters[2])) diff --git a/test/tx/cmake/module_manager/CMakeLists.txt b/test/tx/cmake/module_manager/CMakeLists.txt index f87970adf..109ee72a5 100644 --- a/test/tx/cmake/module_manager/CMakeLists.txt +++ b/test/tx/cmake/module_manager/CMakeLists.txt @@ -21,6 +21,7 @@ set(SOURCE_DIR ${REPO_ROOT}/test/tx/module_manager) set(module_manager_dir ${REPO_ROOT}/common_modules/module_manager) set(cortex_a7_module_dir ${REPO_ROOT}/ports_module/cortex_a7/gnu) +set(cortex_m4_module_dir ${REPO_ROOT}/ports_module/cortex_m4/gnu) add_executable( threadx_module_manager_thread_kernel_stack_test @@ -173,3 +174,23 @@ target_compile_options( add_test(${CMAKE_BUILD_TYPE}::threadx_module_manager_object_allocate_overflow_test threadx_module_manager_object_allocate_overflow_test) + +add_executable( + threadx_module_manager_block_pool_parameters_test + ${SOURCE_DIR}/threadx_module_manager_block_pool_parameters_test.c + ${module_manager_dir}/src/txm_module_manager_util.c) + +target_include_directories( + threadx_module_manager_block_pool_parameters_test + PRIVATE ${SOURCE_DIR} + ${REPO_ROOT}/common/inc + ${REPO_ROOT}/common_modules/inc + ${module_manager_dir}/inc + ${cortex_m4_module_dir}/inc) + +target_compile_options( + threadx_module_manager_block_pool_parameters_test + PRIVATE -include ${SOURCE_DIR}/threadx_module_manager_host_test_port.h) + +add_test(${CMAKE_BUILD_TYPE}::threadx_module_manager_block_pool_parameters_test + threadx_module_manager_block_pool_parameters_test) diff --git a/test/tx/module_manager/threadx_module_manager_block_pool_parameters_test.c b/test/tx/module_manager/threadx_module_manager_block_pool_parameters_test.c new file mode 100644 index 000000000..fb3f6ff96 --- /dev/null +++ b/test/tx/module_manager/threadx_module_manager_block_pool_parameters_test.c @@ -0,0 +1,1452 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Test */ +/** */ +/** Module Manager extra-parameter array range validation */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +/* A kernel service with more parameters than the module-to-manager call carries + receives the surplus in an array the module library builds and the module passes by + pointer. The Module Manager's dispatch layer proves that array lies inside the + requesting module's data before it reads any of it, by handing the port's data check + the array's address and its length as sizeof(ALIGN_TYPE[n]). + + Block-pool create declared n as 2 and then read indices 0 through 3. The two words it + did not prove were read twice each: once by the dispatch layer's own buffer check, + which takes index 1 as a pool start and index 2 as the length to range-check it over, + and once when the argument list was built. So the out-of-bounds read was performed by + the validation code, before the kernel service was reached at all, and the size the + caller's pool start was then validated against was itself a word the manager had not + proved the module owned. Its two siblings have always been right: queue create + validates four words for the same four-word shape, and byte-pool create validates + three for three. + + This test drives all three create dispatchers and measures the extent each one + validates, rather than checking cases either side of it. For each region a module's + parameter array may legitimately live in, it anchors the array at the end of the + region and walks it backwards a byte at a time; the smallest amount of room the + dispatcher accepts is the extent it validated. It must be four words for block-pool + create and queue create and three for byte-pool create, which is one word per index + the dispatcher goes on to use -- and the highest index each one uses is measured too, + through what the stubbed service records, so the invariant the three are checked + against is measured on both sides rather than written down. + + Two things make a dispatcher testable on the host at all, and both come from the + first test in this directory. + + The dispatch table is a header of static functions, one per kernel service, each + wrapped in #ifndef TXM__CALL_NOT_USED so that an integrator can refuse a + service to modules. There are 96 of those guards. Defining the 93 this test does not + exercise compiles the header down to the three create services under test, which is + what keeps the link to a handful of stubs instead of the hundred-odd kernel entry + points the whole table reaches. It also exercises that conditional compilation. + + The extent has to reach a check that honours it. The manager's portable checks do, + and so does the inline data check of the Cortex-M module ports, which is the shape + the memory-protected module ports share: an address range is inside the module's + data, or inside a shared memory region registered to it, or it is not accepted. This + test therefore compiles against a Cortex-M module port's headers. The Cortex-A7 + port's data check translates one address and ignores the length, so on that port no + extent -- right or wrong -- reaches anything; that is corrected separately, and the + defect this test covers is in the portable dispatch layer. + + Both checks on this path are data-only. The array is checked with + ENSURE_INSIDE_MODULE_DATA and the pool start with PARAM_CHECK_BUFFER_WRITE, which is + that same check plus a null clause. Neither falls back to the portable code-region + check, so a parameter array or a pool start in the module's read-only image is + refused however much room is left, and the cases below assert that in both + directions: it is the reason this finding has nothing that survives a data check + which does not honour its length. + + What a module can learn from the answers is measured here too, because it is what + separates a bounded over-read from a disclosure. Acceptance is decided by comparing + a length the module supplies against the room between a pool start the module also + supplies and the end of a region the module owns, and the dispatch layer's refusal + is TXM_MODULE_INVALID_MEMORY, which none of these services can return. So a module + that fixes the length and moves the pool start is running one comparison per request + against a threshold it chooses, and can bisect for the length. The cases below run + that bisection and record how far it gets, on a word the module owns -- which is no + disclosure at all. It becomes one only when composed with the extent measurement + above, which is what says that before the fix the word being bisected for came from + outside the module's region. Index 3 is weaker still: it reaches the service, which + compares it against sizeof(TX_BLOCK_POOL), so it yields one equality bit. + + Nothing on this path disables interrupts, and the port shim counts every disable, so + a run that leaves the counter at zero is also the evidence that nothing here raises + _tx_thread_preempt_disable: in ThreadX that flag is only ever changed between a + TX_DISABLE and its TX_RESTORE. A fault taken during this over-read therefore costs + the requesting thread and not the system's ability to preempt. */ + +#include +#include + +#include "threadx_module_manager_host_test_port.h" + +#include "tx_thread.h" +#include "tx_timer.h" +#include "tx_queue.h" +#include "tx_event_flags.h" +#include "tx_semaphore.h" +#include "tx_mutex.h" +#include "tx_block_pool.h" +#include "tx_byte_pool.h" +#include "txm_module.h" +#include "txm_module_manager_util.h" + + +/* Refuse every service in the dispatch table except the three under test. The list is + the header's own guard names; a service added to the table appears here as a link + error naming the kernel entry point it reaches, which is the right way to find out. */ + +#define TXM_BLOCK_ALLOCATE_CALL_NOT_USED +#define TXM_BLOCK_POOL_DELETE_CALL_NOT_USED +#define TXM_BLOCK_POOL_INFO_GET_CALL_NOT_USED +#define TXM_BLOCK_POOL_PERFORMANCE_INFO_GET_CALL_NOT_USED +#define TXM_BLOCK_POOL_PERFORMANCE_SYSTEM_INFO_GET_CALL_NOT_USED +#define TXM_BLOCK_POOL_PRIORITIZE_CALL_NOT_USED +#define TXM_BLOCK_RELEASE_CALL_NOT_USED +#define TXM_BYTE_ALLOCATE_CALL_NOT_USED +#define TXM_BYTE_POOL_DELETE_CALL_NOT_USED +#define TXM_BYTE_POOL_INFO_GET_CALL_NOT_USED +#define TXM_BYTE_POOL_PERFORMANCE_INFO_GET_CALL_NOT_USED +#define TXM_BYTE_POOL_PERFORMANCE_SYSTEM_INFO_GET_CALL_NOT_USED +#define TXM_BYTE_POOL_PRIORITIZE_CALL_NOT_USED +#define TXM_BYTE_RELEASE_CALL_NOT_USED +#define TXM_EVENT_FLAGS_CREATE_CALL_NOT_USED +#define TXM_EVENT_FLAGS_DELETE_CALL_NOT_USED +#define TXM_EVENT_FLAGS_GET_CALL_NOT_USED +#define TXM_EVENT_FLAGS_INFO_GET_CALL_NOT_USED +#define TXM_EVENT_FLAGS_PERFORMANCE_INFO_GET_CALL_NOT_USED +#define TXM_EVENT_FLAGS_PERFORMANCE_SYSTEM_INFO_GET_CALL_NOT_USED +#define TXM_EVENT_FLAGS_SET_CALL_NOT_USED +#define TXM_EVENT_FLAGS_SET_NOTIFY_CALL_NOT_USED +#define TXM_MODULE_OBJECT_ALLOCATE_CALL_NOT_USED +#define TXM_MODULE_OBJECT_DEALLOCATE_CALL_NOT_USED +#define TXM_MODULE_OBJECT_POINTER_GET_CALL_NOT_USED +#define TXM_MODULE_OBJECT_POINTER_GET_EXTENDED_CALL_NOT_USED +#define TXM_MUTEX_CREATE_CALL_NOT_USED +#define TXM_MUTEX_DELETE_CALL_NOT_USED +#define TXM_MUTEX_GET_CALL_NOT_USED +#define TXM_MUTEX_INFO_GET_CALL_NOT_USED +#define TXM_MUTEX_PERFORMANCE_INFO_GET_CALL_NOT_USED +#define TXM_MUTEX_PERFORMANCE_SYSTEM_INFO_GET_CALL_NOT_USED +#define TXM_MUTEX_PRIORITIZE_CALL_NOT_USED +#define TXM_MUTEX_PUT_CALL_NOT_USED +#define TXM_QUEUE_DELETE_CALL_NOT_USED +#define TXM_QUEUE_FLUSH_CALL_NOT_USED +#define TXM_QUEUE_FRONT_SEND_CALL_NOT_USED +#define TXM_QUEUE_INFO_GET_CALL_NOT_USED +#define TXM_QUEUE_PERFORMANCE_INFO_GET_CALL_NOT_USED +#define TXM_QUEUE_PERFORMANCE_SYSTEM_INFO_GET_CALL_NOT_USED +#define TXM_QUEUE_PRIORITIZE_CALL_NOT_USED +#define TXM_QUEUE_RECEIVE_CALL_NOT_USED +#define TXM_QUEUE_SEND_CALL_NOT_USED +#define TXM_QUEUE_SEND_NOTIFY_CALL_NOT_USED +#define TXM_SEMAPHORE_CEILING_PUT_CALL_NOT_USED +#define TXM_SEMAPHORE_CREATE_CALL_NOT_USED +#define TXM_SEMAPHORE_DELETE_CALL_NOT_USED +#define TXM_SEMAPHORE_GET_CALL_NOT_USED +#define TXM_SEMAPHORE_INFO_GET_CALL_NOT_USED +#define TXM_SEMAPHORE_PERFORMANCE_INFO_GET_CALL_NOT_USED +#define TXM_SEMAPHORE_PERFORMANCE_SYSTEM_INFO_GET_CALL_NOT_USED +#define TXM_SEMAPHORE_PRIORITIZE_CALL_NOT_USED +#define TXM_SEMAPHORE_PUT_CALL_NOT_USED +#define TXM_SEMAPHORE_PUT_NOTIFY_CALL_NOT_USED +#define TXM_THREAD_CREATE_CALL_NOT_USED +#define TXM_THREAD_DELETE_CALL_NOT_USED +#define TXM_THREAD_ENTRY_EXIT_NOTIFY_CALL_NOT_USED +#define TXM_THREAD_IDENTIFY_CALL_NOT_USED +#define TXM_THREAD_INFO_GET_CALL_NOT_USED +#define TXM_THREAD_INTERRUPT_CONTROL_CALL_NOT_USED +#define TXM_THREAD_PERFORMANCE_INFO_GET_CALL_NOT_USED +#define TXM_THREAD_PERFORMANCE_SYSTEM_INFO_GET_CALL_NOT_USED +#define TXM_THREAD_PREEMPTION_CHANGE_CALL_NOT_USED +#define TXM_THREAD_PRIORITY_CHANGE_CALL_NOT_USED +#define TXM_THREAD_RELINQUISH_CALL_NOT_USED +#define TXM_THREAD_RESET_CALL_NOT_USED +#define TXM_THREAD_RESUME_CALL_NOT_USED +#define TXM_THREAD_SLEEP_CALL_NOT_USED +#define TXM_THREAD_STACK_ERROR_NOTIFY_CALL_NOT_USED +#define TXM_THREAD_SUSPEND_CALL_NOT_USED +#define TXM_THREAD_SYSTEM_SUSPEND_CALL_NOT_USED +#define TXM_THREAD_TERMINATE_CALL_NOT_USED +#define TXM_THREAD_TIME_SLICE_CHANGE_CALL_NOT_USED +#define TXM_THREAD_WAIT_ABORT_CALL_NOT_USED +#define TXM_TIMER_ACTIVATE_CALL_NOT_USED +#define TXM_TIMER_CHANGE_CALL_NOT_USED +#define TXM_TIMER_CREATE_CALL_NOT_USED +#define TXM_TIMER_DEACTIVATE_CALL_NOT_USED +#define TXM_TIMER_DELETE_CALL_NOT_USED +#define TXM_TIMER_INFO_GET_CALL_NOT_USED +#define TXM_TIMER_PERFORMANCE_INFO_GET_CALL_NOT_USED +#define TXM_TIMER_PERFORMANCE_SYSTEM_INFO_GET_CALL_NOT_USED +#define TXM_TIME_GET_CALL_NOT_USED +#define TXM_TIME_SET_CALL_NOT_USED +#define TXM_TRACE_BUFFER_FULL_NOTIFY_CALL_NOT_USED +#define TXM_TRACE_DISABLE_CALL_NOT_USED +#define TXM_TRACE_ENABLE_CALL_NOT_USED +#define TXM_TRACE_EVENT_FILTER_CALL_NOT_USED +#define TXM_TRACE_EVENT_UNFILTER_CALL_NOT_USED +#define TXM_TRACE_INTERRUPT_CONTROL_CALL_NOT_USED +#define TXM_TRACE_ISR_ENTER_INSERT_CALL_NOT_USED +#define TXM_TRACE_ISR_EXIT_INSERT_CALL_NOT_USED +#define TXM_TRACE_USER_EVENT_INSERT_CALL_NOT_USED + +#include "txm_module_manager_dispatch.h" + +/* The three under test have to have survived that, and the rest have to have gone. */ + +#if defined(TXM_BLOCK_POOL_CREATE_CALL_NOT_USED) || defined(TXM_BYTE_POOL_CREATE_CALL_NOT_USED) || defined(TXM_QUEUE_CREATE_CALL_NOT_USED) +#error "the create services under test must be compiled in" +#endif + +#ifndef TXM_BLOCK_POOL_DELETE_CALL_NOT_USED +#error "the services this test does not exercise must be compiled out" +#endif + + +/* Define the stand-in interrupt lock the port shim counts through. */ + +unsigned int test_interrupt_disable_depth; +unsigned int test_interrupt_disable_max_depth; +unsigned int test_interrupt_restore_underflows; + + +/* Stand in for the module port's load-time alignment adjustment, which the utility + source declares and no case here reaches. */ + +VOID _txm_module_manager_alignment_adjust(TXM_MODULE_PREAMBLE *module_preamble, ULONG *code_size, + ULONG *code_alignment, ULONG *data_size, ULONG *data_alignment) +{ + (VOID) module_preamble; + (VOID) code_size; + (VOID) code_alignment; + (VOID) data_size; + (VOID) data_alignment; +} + + +static UINT test_failures; +static ULONG test_checks; + + +/* Record the outcome of one expectation. */ +static VOID test_expect(const char *description, ULONG actual, ULONG expected) +{ + test_checks++; + + if (actual != expected) + { + printf("FAIL: %s (expected %lu, got %lu)\n", description, (unsigned long) expected, (unsigned long) actual); + test_failures++; + } +} + + +/* Model the module's memory as one arena, so that the three regions a parameter array + or a pool start may be aimed at have known addresses and known gaps between them. The + gaps are memory the module may not reach: they are what an array anchored to the end + of a region overruns into, and they are inside the arena so that the words a case + plants past the end of a region are words this test owns. */ + +#define TEST_REGION_BYTES ((ULONG) 256) +#define TEST_GAP_BYTES ((ULONG) 64) + +static union +{ + ALIGN_TYPE test_arena_alignment; + UCHAR test_arena_bytes[(((ULONG) 3) * TEST_REGION_BYTES) + (((ULONG) 4) * TEST_GAP_BYTES)]; +} test_arena; + +#define TEST_DATA_START (&test_arena.test_arena_bytes[TEST_GAP_BYTES]) +#define TEST_CODE_START (&test_arena.test_arena_bytes[(((ULONG) 2) * TEST_GAP_BYTES) + TEST_REGION_BYTES]) +#define TEST_SHARED_START (&test_arena.test_arena_bytes[(((ULONG) 3) * TEST_GAP_BYTES) + (((ULONG) 2) * TEST_REGION_BYTES)]) + + +/* Model the manager's object pool, because these three services create objects and the + creation check requires the control block to be one of the module's own allocations + out of that pool: inside it, carrying an allocation header that names this module and + records exactly the size the service expects. */ + +TX_BYTE_POOL _txm_module_manager_object_pool; +UINT _txm_module_manager_object_pool_created; + + +/* The kernel's created lists. A created object lives on the list for its type, and + the manager reads those lists, so a test that stands in for the kernel has to + provide them. All stay empty here, because this test creates no kernel object; it + exercises the parameter checking a create dispatcher does beforehand. */ + +TX_BLOCK_POOL *_tx_block_pool_created_ptr; +ULONG _tx_block_pool_created_count; +TX_BYTE_POOL *_tx_byte_pool_created_ptr; +ULONG _tx_byte_pool_created_count; +TX_EVENT_FLAGS_GROUP *_tx_event_flags_created_ptr; +ULONG _tx_event_flags_created_count; +TX_MUTEX *_tx_mutex_created_ptr; +ULONG _tx_mutex_created_count; +TX_QUEUE *_tx_queue_created_ptr; +ULONG _tx_queue_created_count; +TX_SEMAPHORE *_tx_semaphore_created_ptr; +ULONG _tx_semaphore_created_count; +TX_THREAD *_tx_thread_created_ptr; +ULONG _tx_thread_created_count; +TX_TIMER *_tx_timer_created_ptr; +ULONG _tx_timer_created_count; + +#define TEST_OBJECT_SLOT_BYTES ((ULONG) 256) +#define TEST_OBJECT_SLOTS ((ULONG) 3) + +static union +{ + ALIGN_TYPE test_object_pool_alignment; + UCHAR test_object_pool_bytes[TEST_OBJECT_SLOTS * TEST_OBJECT_SLOT_BYTES]; +} test_object_pool; + + +/* Define the requesting modules. One has memory protection, and is the one every range + case below drives; the other does not, and is how the cases show that the dispatch + layer's checks are not reached for it at all. */ + +static TXM_MODULE_INSTANCE test_protected_module; +static TXM_MODULE_INSTANCE test_unprotected_module; + + +/* Place a module's regions on the arena. */ +static VOID test_module_setup(TXM_MODULE_INSTANCE *module_instance, ULONG property_flags) +{ + memset((VOID *) module_instance, 0, sizeof(TXM_MODULE_INSTANCE)); + + module_instance -> txm_module_instance_property_flags = property_flags; + + module_instance -> txm_module_instance_data_start = (VOID *) TEST_DATA_START; + module_instance -> txm_module_instance_data_end = (VOID *) (TEST_DATA_START + (TEST_REGION_BYTES - ((ULONG) 1))); + + module_instance -> txm_module_instance_code_start = (VOID *) TEST_CODE_START; + module_instance -> txm_module_instance_code_end = (VOID *) (TEST_CODE_START + (TEST_REGION_BYTES - ((ULONG) 1))); + + module_instance -> txm_module_instance_shared_memory_address = (ULONG) TEST_SHARED_START; + module_instance -> txm_module_instance_shared_memory_length = TEST_REGION_BYTES; +} + + +/* Hand one slot of the object pool to a module as an allocation of a given size, and + return the control block address inside it. The allocation header sits in front of + the object, which is what the creation check reads. */ +static VOID *test_object_allocate(ULONG slot, TXM_MODULE_INSTANCE *module_instance, ULONG object_size) +{ + +TXM_MODULE_ALLOCATED_OBJECT *allocated_object_ptr; + + + allocated_object_ptr = (TXM_MODULE_ALLOCATED_OBJECT *) &test_object_pool.test_object_pool_bytes[slot * TEST_OBJECT_SLOT_BYTES]; + + memset((VOID *) allocated_object_ptr, 0, (size_t) TEST_OBJECT_SLOT_BYTES); + + allocated_object_ptr -> txm_module_allocated_object_module_instance = module_instance; + allocated_object_ptr -> txm_module_object_size = object_size; + + return((VOID *) (allocated_object_ptr + 1)); +} + + +/* Record what the privileged create services were handed. + + Whether the service was reached at all is half of every expectation below: a refusal + that still calls the service has refused nothing. What each index of the parameter + array carried when it arrived is the other half, and it is what measures the highest + index a dispatcher actually uses. */ + +static ULONG test_service_calls; +static ALIGN_TYPE test_service_object_ptr; +static ALIGN_TYPE test_service_name_ptr; +static ALIGN_TYPE test_service_extra[4]; +static ULONG test_service_extra_count; + + +/* Stand in for the three privileged create services. + + Each keeps the two checks the real one makes before it touches the caller's pool + memory, in the real one's order: a control-block size that is not the size of the + control block is refused with that object's own error, and a null pool start is + refused with TX_PTR_ERROR. Both matter here. The first is the whole of what a module + can learn from the last word of the array, since it reaches the service and nothing + else does. The second is why the dispatch layer's buffer check accepting a null pool + start outright -- whatever length it was given, proved or not -- costs nothing: the + service refuses the pointer before dereferencing it. + + What the real services do that these do not is search the created list for a + duplicate. That is reached only after both checks above and touches nothing the + caller supplied, so no case here depends on it. */ + +static UINT test_service_record(ALIGN_TYPE object_ptr, ALIGN_TYPE name_ptr, ULONG extra_count, + ALIGN_TYPE extra_0, ALIGN_TYPE extra_1, ALIGN_TYPE extra_2, ALIGN_TYPE extra_3) +{ + test_service_calls++; + test_service_object_ptr = object_ptr; + test_service_name_ptr = name_ptr; + test_service_extra_count = extra_count; + test_service_extra[0] = extra_0; + test_service_extra[1] = extra_1; + test_service_extra[2] = extra_2; + test_service_extra[3] = extra_3; + + return(TX_SUCCESS); +} + + +UINT _txe_block_pool_create(TX_BLOCK_POOL *pool_ptr, CHAR *name_ptr, ULONG block_size, + VOID *pool_start, ULONG pool_size, UINT pool_control_block_size) +{ + +UINT status; + + + (VOID) test_service_record((ALIGN_TYPE) pool_ptr, (ALIGN_TYPE) name_ptr, ((ULONG) 4), + (ALIGN_TYPE) block_size, (ALIGN_TYPE) pool_start, + (ALIGN_TYPE) pool_size, (ALIGN_TYPE) pool_control_block_size); + + if (pool_ptr == TX_NULL) + { + status = TX_POOL_ERROR; + } + else if (pool_control_block_size != ((UINT) sizeof(TX_BLOCK_POOL))) + { + status = TX_POOL_ERROR; + } + else if (pool_start == TX_NULL) + { + status = TX_PTR_ERROR; + } + else + { + status = TX_SUCCESS; + } + + return(status); +} + + +UINT _txe_byte_pool_create(TX_BYTE_POOL *pool_ptr, CHAR *name_ptr, VOID *pool_start, + ULONG pool_size, UINT pool_control_block_size) +{ + +UINT status; + + + (VOID) test_service_record((ALIGN_TYPE) pool_ptr, (ALIGN_TYPE) name_ptr, ((ULONG) 3), + (ALIGN_TYPE) pool_start, (ALIGN_TYPE) pool_size, + (ALIGN_TYPE) pool_control_block_size, ((ALIGN_TYPE) 0)); + + if (pool_ptr == TX_NULL) + { + status = TX_POOL_ERROR; + } + else if (pool_control_block_size != ((UINT) sizeof(TX_BYTE_POOL))) + { + status = TX_POOL_ERROR; + } + else if (pool_start == TX_NULL) + { + status = TX_PTR_ERROR; + } + else + { + status = TX_SUCCESS; + } + + return(status); +} + + +UINT _txe_queue_create(TX_QUEUE *queue_ptr, CHAR *name_ptr, UINT message_size, + VOID *queue_start, ULONG queue_size, UINT queue_control_block_size) +{ + +UINT status; + + + (VOID) test_service_record((ALIGN_TYPE) queue_ptr, (ALIGN_TYPE) name_ptr, ((ULONG) 4), + (ALIGN_TYPE) message_size, (ALIGN_TYPE) queue_start, + (ALIGN_TYPE) queue_size, (ALIGN_TYPE) queue_control_block_size); + + if (queue_ptr == TX_NULL) + { + status = TX_QUEUE_ERROR; + } + else if (queue_control_block_size != ((UINT) sizeof(TX_QUEUE))) + { + status = TX_QUEUE_ERROR; + } + else if (queue_start == TX_NULL) + { + status = TX_PTR_ERROR; + } + else + { + status = TX_SUCCESS; + } + + return(status); +} + + +/* Name the three services under test, and record for each one the shape the finding is + about: how many words its parameter array must hold, which index carries the pool or + queue start, which index carries the length that start is range-checked over, and + which index carries the control-block size. Every one of those numbers is checked + against the dispatcher's behaviour below rather than trusted. */ + +#define TEST_SERVICE_BLOCK_POOL_CREATE ((UINT) 0) +#define TEST_SERVICE_BYTE_POOL_CREATE ((UINT) 1) +#define TEST_SERVICE_QUEUE_CREATE ((UINT) 2) +#define TEST_SERVICE_COUNT ((UINT) 3) + +typedef struct TEST_SERVICE_SHAPE_STRUCT +{ + const char *test_service_name; + ULONG test_service_words; + ULONG test_service_start_index; + ULONG test_service_length_index; + ULONG test_service_control_block_index; + ULONG test_service_control_block_size; + ULONG test_service_control_block_error; +} TEST_SERVICE_SHAPE; + +static const TEST_SERVICE_SHAPE test_service_shapes[TEST_SERVICE_COUNT] = +{ + { "block-pool create", ((ULONG) 4), ((ULONG) 1), ((ULONG) 2), ((ULONG) 3), (ULONG) sizeof(TX_BLOCK_POOL), (ULONG) TX_POOL_ERROR }, + { "byte-pool create", ((ULONG) 3), ((ULONG) 0), ((ULONG) 1), ((ULONG) 2), (ULONG) sizeof(TX_BYTE_POOL), (ULONG) TX_POOL_ERROR }, + { "queue create", ((ULONG) 4), ((ULONG) 1), ((ULONG) 2), ((ULONG) 3), (ULONG) sizeof(TX_QUEUE), (ULONG) TX_QUEUE_ERROR } +}; + + +/* The control block each service's request names, and the name pointer it carries. The + control blocks are the module's own allocations out of the object pool, which is what + the creation check requires; the name lives in the module's data. */ + +static VOID *test_service_control_block[TEST_SERVICE_COUNT]; + +#define TEST_NAME_PTR ((ALIGN_TYPE) TEST_DATA_START) + + +/* Build the parameter array a request will carry, at a chosen address, and hand back + that address as the array pointer the request carries. + + Every word is written, including any that lies past the end of the region the array + is anchored to: those are the words the dispatcher must not read, and writing them + here is what makes a read of them observable rather than a read of whatever the arena + happened to hold. The words are assembled aligned and copied into place, because the + addresses these cases use advance a byte at a time and neither check on this path + requires the array to be aligned. */ + +#define TEST_PARAMETER_FILL ((ALIGN_TYPE) 0xA5A5A5A5UL) +#define TEST_PARAMETER_WORDS ((ULONG) 4) + +static ALIGN_TYPE *test_build_parameters(UINT service, UCHAR *address, + ALIGN_TYPE start_value, ALIGN_TYPE length_value, + ALIGN_TYPE control_block_value) +{ + +const TEST_SERVICE_SHAPE *shape; +ALIGN_TYPE words[TEST_PARAMETER_WORDS]; +ULONG index; + + + shape = &test_service_shapes[service]; + + /* Fill every word with a value that is wrong for every index, so that a word the + lines below leave unset would be visible in what the service records. */ + for (index = ((ULONG) 0); index < TEST_PARAMETER_WORDS; index++) + { + words[index] = TEST_PARAMETER_FILL; + } + + words[shape -> test_service_start_index] = start_value; + words[shape -> test_service_length_index] = length_value; + words[shape -> test_service_control_block_index] = control_block_value; + + memcpy((VOID *) address, (VOID *) words, sizeof(words)); + + return((ALIGN_TYPE *) address); +} + + +/* Read back one word of a parameter array that may be unaligned. */ +static ALIGN_TYPE test_parameter_word(const ALIGN_TYPE *extra_parameters, ULONG index) +{ + +ALIGN_TYPE word; + + + memcpy((VOID *) &word, (VOID *) (((const UCHAR *) extra_parameters) + (index * sizeof(ALIGN_TYPE))), sizeof(word)); + + return(word); +} + + +/* Make one request of one dispatcher, resetting the record of the service behind it + first so that a caller can tell a refusal from an acceptance. */ +static ALIGN_TYPE test_dispatch(UINT service, TXM_MODULE_INSTANCE *module_instance, + ALIGN_TYPE object_ptr, ALIGN_TYPE name_ptr, ALIGN_TYPE *extra_parameters) +{ + +ALIGN_TYPE return_value; +ULONG index; + + + test_service_calls = ((ULONG) 0); + test_service_object_ptr = ((ALIGN_TYPE) 0); + test_service_name_ptr = ((ALIGN_TYPE) 0); + test_service_extra_count = ((ULONG) 0); + + for (index = ((ULONG) 0); index < TEST_PARAMETER_WORDS; index++) + { + test_service_extra[index] = ((ALIGN_TYPE) 0); + } + + if (service == TEST_SERVICE_BLOCK_POOL_CREATE) + { + return_value = _txm_module_manager_tx_block_pool_create_dispatch(module_instance, object_ptr, name_ptr, extra_parameters); + } + else if (service == TEST_SERVICE_BYTE_POOL_CREATE) + { + return_value = _txm_module_manager_tx_byte_pool_create_dispatch(module_instance, object_ptr, name_ptr, extra_parameters); + } + else + { + return_value = _txm_module_manager_tx_queue_create_dispatch(module_instance, object_ptr, name_ptr, extra_parameters); + } + + return(return_value); +} + + +/* Report whether one request was accepted, checking as it goes that acceptance and + refusal are each consistent. + + A refused request returns TXM_MODULE_INVALID_MEMORY and does not reach the service. + An accepted one reaches it exactly once, carrying the control block and name the + caller named and, at every index the service has a parameter for, the word that is + in the array at that index. That last part is the measurement of how far the + dispatcher reads: the service's own parameter list bounds the highest index it can + be handed, and each of those indices arriving with the array's own word is what says + the dispatcher read it. */ +static UINT test_accepted(UINT service, TXM_MODULE_INSTANCE *module_instance, + ALIGN_TYPE object_ptr, ALIGN_TYPE name_ptr, ALIGN_TYPE *extra_parameters) +{ + +const TEST_SERVICE_SHAPE *shape; +ALIGN_TYPE return_value; +UINT accepted; +ULONG index; +char description[160]; + + + shape = &test_service_shapes[service]; + + return_value = test_dispatch(service, module_instance, object_ptr, name_ptr, extra_parameters); + + if (test_service_calls == ((ULONG) 0)) + { + accepted = TX_FALSE; + + test_expect("a refused request returns TXM_MODULE_INVALID_MEMORY", + (ULONG) return_value, (ULONG) TXM_MODULE_INVALID_MEMORY); + } + else + { + accepted = TX_TRUE; + + test_expect("an accepted request reaches the service once", test_service_calls, ((ULONG) 1)); + test_expect("...with the control block the caller named", (ULONG) test_service_object_ptr, (ULONG) object_ptr); + test_expect("...and the name the caller supplied", (ULONG) test_service_name_ptr, (ULONG) name_ptr); + test_expect("...and one parameter per word the service declares", + test_service_extra_count, shape -> test_service_words); + + for (index = ((ULONG) 0); index < shape -> test_service_words; index++) + { + snprintf(description, sizeof(description), "...and the array's word %lu at parameter %lu of %s", + (unsigned long) index, (unsigned long) index, shape -> test_service_name); + test_expect(description, + (ULONG) test_service_extra[index], + (ULONG) test_parameter_word(extra_parameters, index)); + } + } + + return(accepted); +} + + +/* Measure the extent a dispatcher validates. + + The array is anchored so that its first word sits at the end of one of the module's + regions and walked backwards into it a byte at a time, so that the room left between + the array and the end of the region grows by one on each step. The smallest amount of + room the dispatcher accepts is the extent it validated. Everything else about the + request is valid, so acceptance turns on the extent alone. + + TEST_NOT_ACCEPTED means nothing within the walk was accepted, which is the right + answer for a region a parameter array may not be in at all. */ + +#define TEST_NOT_ACCEPTED ((ULONG) 0xFFFFFFFF) + +/* A length that no region can satisfy, and one that any of them can, chosen so that + either is recognisable in what a service records if a dispatcher reads a word the + cases below plant past the end of a region. */ +#define TEST_LENGTH_UNSATISFIABLE ((ALIGN_TYPE) 0xFFFFFFFFUL) +#define TEST_LENGTH_SATISFIABLE ((ALIGN_TYPE) 0xB4) + +/* Walking two words past the widest extent any of the three validates is enough to + establish that none of them validates more. */ +#define TEST_WALK_WORDS ((ULONG) 6) + +static ULONG test_measure_extent(UINT service, TXM_MODULE_INSTANCE *module_instance, UCHAR *region_start) +{ + +const TEST_SERVICE_SHAPE *shape; +ALIGN_TYPE *extra_parameters; +UCHAR *region_end_plus_one; +ULONG room; +ULONG extent; + + + shape = &test_service_shapes[service]; + + region_end_plus_one = region_start + TEST_REGION_BYTES; + + extent = TEST_NOT_ACCEPTED; + + for (room = ((ULONG) 0); room <= (TEST_WALK_WORDS * ((ULONG) sizeof(ALIGN_TYPE))); room++) + { + extra_parameters = test_build_parameters(service, region_end_plus_one - room, + (ALIGN_TYPE) TEST_DATA_START, ((ALIGN_TYPE) sizeof(ALIGN_TYPE)), + (ALIGN_TYPE) shape -> test_service_control_block_size); + + if (test_accepted(service, module_instance, (ALIGN_TYPE) test_service_control_block[service], + TEST_NAME_PTR, extra_parameters) == TX_TRUE) + { + extent = room; + break; + } + } + + return(extent); +} + + +/* Recover a length word by bisection, the way a module could. + + The dispatch layer's buffer check answers one comparison per request: with the length + word fixed, a request is accepted exactly when that length is at least one and fits + between the pool start the module chose and the end of a region the module owns. The + module therefore chooses the right-hand side of the comparison by moving the pool + start, and its refusal -- TXM_MODULE_INVALID_MEMORY, which none of these services can + return -- is distinguishable from every answer the service gives. Bisecting on the + room recovers the length in a number of requests logarithmic in the size of the + module's own region. + + Run here on a word the module owns, which discloses nothing. It becomes disclosure + only composed with the extent measurement, which is what says that before the fix the + word bisected for lay outside the module's region. */ + +#define TEST_NOT_RECOVERED ((ULONG) 0xFFFFFFFF) + +/* Somewhere inside the module's data with room for the whole array and clear of the + pool starts the bisection sweeps over. */ +#define TEST_BISECT_ARRAY (TEST_DATA_START + ((ULONG) 128)) + +static UINT test_bisect_probe(UINT service, ULONG room, ALIGN_TYPE hidden_length) +{ + +const TEST_SERVICE_SHAPE *shape; +ALIGN_TYPE *extra_parameters; + + + shape = &test_service_shapes[service]; + + extra_parameters = test_build_parameters(service, TEST_BISECT_ARRAY, + (ALIGN_TYPE) ((TEST_DATA_START + TEST_REGION_BYTES) - room), + hidden_length, + (ALIGN_TYPE) shape -> test_service_control_block_size); + + return(test_accepted(service, &test_protected_module, (ALIGN_TYPE) test_service_control_block[service], + TEST_NAME_PTR, extra_parameters)); +} + +static ULONG test_bisect_length(UINT service, ALIGN_TYPE hidden_length, ULONG *probes) +{ + +ULONG low; +ULONG high; +ULONG middle; +ULONG recovered; + + + *probes = ((ULONG) 0); + + /* All the room there is. A length the module cannot fit even here is one the + bisection cannot resolve: all it learns is that the word exceeds the region. */ + high = TEST_REGION_BYTES; + (*probes)++; + + if (test_bisect_probe(service, high, hidden_length) == TX_FALSE) + { + recovered = TEST_NOT_RECOVERED; + } + else + { + /* The smallest accepted room lies in (low, high]. No room at all is refused for + every length, so low starts there and needs no probe. */ + low = ((ULONG) 0); + + while ((high - low) > ((ULONG) 1)) + { + middle = low + ((high - low) / ((ULONG) 2)); + (*probes)++; + + if (test_bisect_probe(service, middle, hidden_length) == TX_TRUE) + { + high = middle; + } + else + { + low = middle; + } + } + + recovered = high; + } + + return(recovered); +} + + +/* Define an array and a control block outside every region the module owns, for the + cases about a module that has no memory protection and is therefore checked + nowhere. */ + +static ALIGN_TYPE test_outside_parameters[TEST_PARAMETER_WORDS]; +static TX_BLOCK_POOL test_outside_block_pool; +static TX_BYTE_POOL test_outside_byte_pool; +static TX_QUEUE test_outside_queue; + +static VOID *test_outside_control_block[TEST_SERVICE_COUNT]; + + +/* The lengths the bisection is run for. The first is the smallest a pool start can be + checked over, the last two are the resolution limit: a length no room in the module's + own region can satisfy tells the module only that, and a length of zero is refused + outright by the overflow guard in the data check. */ + +static const ALIGN_TYPE test_bisect_lengths[] = +{ + ((ALIGN_TYPE) 1), + ((ALIGN_TYPE) 7), + ((ALIGN_TYPE) 64), + ((ALIGN_TYPE) 255), + (ALIGN_TYPE) TEST_REGION_BYTES, + (ALIGN_TYPE) (TEST_REGION_BYTES + ((ULONG) 1)), + ((ALIGN_TYPE) 0xDEADBEEFUL), + ((ALIGN_TYPE) 0) +}; + +#define TEST_BISECT_LENGTH_COUNT (sizeof(test_bisect_lengths) / sizeof(test_bisect_lengths[0])) + +/* One initial probe plus one per halving of a 256-byte region. */ +#define TEST_BISECT_PROBE_LIMIT ((ULONG) 9) + + +int main(void) +{ + +const TEST_SERVICE_SHAPE *shape; +UINT service; +UINT length_index; +ULONG words_in_region; +ULONG room; +ULONG probes; +ULONG recovered; +ALIGN_TYPE hidden_length; +ALIGN_TYPE return_value; +ALIGN_TYPE *extra_parameters; +UCHAR saved_object_pool[sizeof(test_object_pool)]; +char description[200]; + + + memset((VOID *) &test_arena, 0, sizeof(test_arena)); + memset((VOID *) &test_object_pool, 0, sizeof(test_object_pool)); + + test_module_setup(&test_protected_module, (ULONG) TXM_MODULE_MEMORY_PROTECTION); + test_module_setup(&test_unprotected_module, ((ULONG) 0)); + + /* Stand up the manager's object pool over the arena the control blocks come out + of, and give each service's request a control block the module allocated from + it, sized as that service's creation check requires. */ + memset((VOID *) &_txm_module_manager_object_pool, 0, sizeof(TX_BYTE_POOL)); + _txm_module_manager_object_pool.tx_byte_pool_start = test_object_pool.test_object_pool_bytes; + _txm_module_manager_object_pool.tx_byte_pool_size = (ULONG) sizeof(test_object_pool); + _txm_module_manager_object_pool_created = TX_TRUE; + + test_service_control_block[TEST_SERVICE_BLOCK_POOL_CREATE] = + test_object_allocate(((ULONG) 0), &test_protected_module, (ULONG) sizeof(TX_BLOCK_POOL)); + test_service_control_block[TEST_SERVICE_BYTE_POOL_CREATE] = + test_object_allocate(((ULONG) 1), &test_protected_module, (ULONG) sizeof(TX_BYTE_POOL)); + test_service_control_block[TEST_SERVICE_QUEUE_CREATE] = + test_object_allocate(((ULONG) 2), &test_protected_module, (ULONG) sizeof(TX_QUEUE)); + + test_outside_control_block[TEST_SERVICE_BLOCK_POOL_CREATE] = (VOID *) &test_outside_block_pool; + test_outside_control_block[TEST_SERVICE_BYTE_POOL_CREATE] = (VOID *) &test_outside_byte_pool; + test_outside_control_block[TEST_SERVICE_QUEUE_CREATE] = (VOID *) &test_outside_queue; + + printf("Module Manager extra-parameter array range validation test\n"); + + /**********************************************************************/ + /* The extent each dispatcher validates. */ + /**********************************************************************/ + + /* One word per index the service has a parameter for: four for block-pool create + and queue create, three for byte-pool create. In the module's writable data and + in a shared region registered to it, which are the two regions the data check + accepts. */ + + for (service = ((UINT) 0); service < TEST_SERVICE_COUNT; service++) + { + shape = &test_service_shapes[service]; + + snprintf(description, sizeof(description), "%s validates %lu words of a parameter array in the module's data", + shape -> test_service_name, (unsigned long) shape -> test_service_words); + test_expect(description, + test_measure_extent(service, &test_protected_module, TEST_DATA_START), + shape -> test_service_words * ((ULONG) sizeof(ALIGN_TYPE))); + + snprintf(description, sizeof(description), "%s validates %lu words of a parameter array in a shared region", + shape -> test_service_name, (unsigned long) shape -> test_service_words); + test_expect(description, + test_measure_extent(service, &test_protected_module, TEST_SHARED_START), + shape -> test_service_words * ((ULONG) sizeof(ALIGN_TYPE))); + + /* Both checks on this path are the data check, with no fallback to the portable + code-region check, so a parameter array in the module's read-only image is + refused however much room is left. */ + snprintf(description, sizeof(description), + "%s refuses a parameter array in the module's read-only image at any extent", + shape -> test_service_name); + test_expect(description, + test_measure_extent(service, &test_protected_module, TEST_CODE_START), + TEST_NOT_ACCEPTED); + } + + /**********************************************************************/ + /* A word the dispatcher did not prove cannot decide the answer. */ + /**********************************************************************/ + + /* This is the defect stated at the anchor point it turned on. With fewer words of + room than the service has parameters, the request must be refused whatever the + words past the end of the region hold -- and the two plantings below differ only + in those words: one describes a pool start and length inside the module, the other + a length no region can satisfy. Block-pool create accepted the first of them with + two words of room and went on to read four. */ + + for (service = ((UINT) 0); service < TEST_SERVICE_COUNT; service++) + { + shape = &test_service_shapes[service]; + + for (words_in_region = ((ULONG) 1); words_in_region < shape -> test_service_words; words_in_region++) + { + room = words_in_region * ((ULONG) sizeof(ALIGN_TYPE)); + + extra_parameters = test_build_parameters(service, (TEST_DATA_START + TEST_REGION_BYTES) - room, + (ALIGN_TYPE) TEST_DATA_START, TEST_LENGTH_SATISFIABLE, + (ALIGN_TYPE) shape -> test_service_control_block_size); + + snprintf(description, sizeof(description), + "%s refuses %lu words of room with a satisfiable length past the end of the region", + shape -> test_service_name, (unsigned long) words_in_region); + test_expect(description, + (ULONG) test_accepted(service, &test_protected_module, + (ALIGN_TYPE) test_service_control_block[service], + TEST_NAME_PTR, extra_parameters), + (ULONG) TX_FALSE); + + if (test_service_calls != ((ULONG) 0)) + { + printf(" ...and reached the service carrying word %lu from outside the region: 0x%lX\n", + (unsigned long) shape -> test_service_length_index, + (unsigned long) test_service_extra[shape -> test_service_length_index]); + } + + extra_parameters = test_build_parameters(service, (TEST_DATA_START + TEST_REGION_BYTES) - room, + (ALIGN_TYPE) TEST_DATA_START, TEST_LENGTH_UNSATISFIABLE, + (ALIGN_TYPE) shape -> test_service_control_block_size); + + snprintf(description, sizeof(description), + "%s refuses %lu words of room with an unsatisfiable length past the end of the region", + shape -> test_service_name, (unsigned long) words_in_region); + test_expect(description, + (ULONG) test_accepted(service, &test_protected_module, + (ALIGN_TYPE) test_service_control_block[service], + TEST_NAME_PTR, extra_parameters), + (ULONG) TX_FALSE); + } + + /* And the boundary the other way: an array whose last word ends exactly at the + end of the region is accepted, and every one of its words reaches the + service, which is what test_accepted checks of an acceptance. */ + + room = shape -> test_service_words * ((ULONG) sizeof(ALIGN_TYPE)); + + extra_parameters = test_build_parameters(service, (TEST_DATA_START + TEST_REGION_BYTES) - room, + (ALIGN_TYPE) TEST_DATA_START, ((ALIGN_TYPE) sizeof(ALIGN_TYPE)), + (ALIGN_TYPE) shape -> test_service_control_block_size); + + snprintf(description, sizeof(description), + "%s accepts a parameter array that reaches exactly the end of the region", + shape -> test_service_name); + test_expect(description, + (ULONG) test_accepted(service, &test_protected_module, + (ALIGN_TYPE) test_service_control_block[service], + TEST_NAME_PTR, extra_parameters), + (ULONG) TX_TRUE); + } + + /**********************************************************************/ + /* What a refusal tells the module apart from. */ + /**********************************************************************/ + + /* The bisection below depends on the dispatch layer's refusal being distinguishable + from every status the services can return. It is, and none of these services has + TXM_MODULE_INVALID_MEMORY among its return values, so a module can always tell + "the manager refused this" from "the kernel refused this". */ + + test_expect("TXM_MODULE_INVALID_MEMORY is not TX_SUCCESS", + (ULONG) (TXM_MODULE_INVALID_MEMORY != TX_SUCCESS), (ULONG) TX_TRUE); + test_expect("TXM_MODULE_INVALID_MEMORY is not TX_POOL_ERROR", + (ULONG) (TXM_MODULE_INVALID_MEMORY != TX_POOL_ERROR), (ULONG) TX_TRUE); + test_expect("TXM_MODULE_INVALID_MEMORY is not TX_QUEUE_ERROR", + (ULONG) (TXM_MODULE_INVALID_MEMORY != TX_QUEUE_ERROR), (ULONG) TX_TRUE); + test_expect("TXM_MODULE_INVALID_MEMORY is not TX_PTR_ERROR", + (ULONG) (TXM_MODULE_INVALID_MEMORY != TX_PTR_ERROR), (ULONG) TX_TRUE); + test_expect("TXM_MODULE_INVALID_MEMORY is not TX_SIZE_ERROR", + (ULONG) (TXM_MODULE_INVALID_MEMORY != TX_SIZE_ERROR), (ULONG) TX_TRUE); + + /**********************************************************************/ + /* How much of a length word the answers give back. */ + /**********************************************************************/ + + /* Measured rather than argued, because it is what separates a bounded over-read + from a disclosure and the arithmetic is easy to overstate. The bisection recovers + a length exactly when it lies within the module's own region, in one request per + halving of that region -- nine here for 256 bytes, and the logarithm of the region + size on a real module. Above that it recovers nothing but the fact that the word + exceeds the region, because the room the module can offer is bounded by a region + it already owns: the pool start has to be inside one to be accepted at all. */ + + for (service = ((UINT) 0); service < TEST_SERVICE_COUNT; service++) + { + shape = &test_service_shapes[service]; + + for (length_index = ((UINT) 0); length_index < ((UINT) TEST_BISECT_LENGTH_COUNT); length_index++) + { + hidden_length = test_bisect_lengths[length_index]; + + recovered = test_bisect_length(service, hidden_length, &probes); + + if ((hidden_length >= ((ALIGN_TYPE) 1)) && (hidden_length <= (ALIGN_TYPE) TEST_REGION_BYTES)) + { + snprintf(description, sizeof(description), "%s: bisecting recovers a length of %lu exactly", + shape -> test_service_name, (unsigned long) hidden_length); + test_expect(description, recovered, (ULONG) hidden_length); + } + else + { + snprintf(description, sizeof(description), + "%s: a length of 0x%lX is outside what the module's own region can resolve", + shape -> test_service_name, (unsigned long) hidden_length); + test_expect(description, recovered, TEST_NOT_RECOVERED); + } + + snprintf(description, sizeof(description), "%s: bisecting a length costs no more than %lu requests", + shape -> test_service_name, (unsigned long) TEST_BISECT_PROBE_LIMIT); + test_expect(description, (ULONG) (probes <= TEST_BISECT_PROBE_LIMIT), (ULONG) TX_TRUE); + } + } + + /**********************************************************************/ + /* The last word of the array, which reaches the service. */ + /**********************************************************************/ + + /* The control-block size is the one word no check in the dispatch layer looks at. + It reaches the service, which compares it against the size of the control block + and refuses anything else with that object's own error. So it yields one equality + bit per request and nothing more, which is the weaker of the two things a module + learns from this array. */ + + for (service = ((UINT) 0); service < TEST_SERVICE_COUNT; service++) + { + shape = &test_service_shapes[service]; + + extra_parameters = test_build_parameters(service, TEST_BISECT_ARRAY, + (ALIGN_TYPE) TEST_DATA_START, ((ALIGN_TYPE) sizeof(ALIGN_TYPE)), + (ALIGN_TYPE) shape -> test_service_control_block_size); + + return_value = test_dispatch(service, &test_protected_module, + (ALIGN_TYPE) test_service_control_block[service], + TEST_NAME_PTR, extra_parameters); + + snprintf(description, sizeof(description), "%s accepts the size of its own control block", + shape -> test_service_name); + test_expect(description, (ULONG) return_value, (ULONG) TX_SUCCESS); + + extra_parameters = test_build_parameters(service, TEST_BISECT_ARRAY, + (ALIGN_TYPE) TEST_DATA_START, ((ALIGN_TYPE) sizeof(ALIGN_TYPE)), + (ALIGN_TYPE) (shape -> test_service_control_block_size + ((ULONG) 1))); + + return_value = test_dispatch(service, &test_protected_module, + (ALIGN_TYPE) test_service_control_block[service], + TEST_NAME_PTR, extra_parameters); + + snprintf(description, sizeof(description), "%s refuses any other control-block size, at the service", + shape -> test_service_name); + test_expect(description, (ULONG) return_value, shape -> test_service_control_block_error); + + snprintf(description, sizeof(description), "...having reached the service to do it (%s)", + shape -> test_service_name); + test_expect(description, test_service_calls, ((ULONG) 1)); + } + + /**********************************************************************/ + /* The two null escape hatches. */ + /**********************************************************************/ + + /* The buffer check accepts a null pool start outright, whatever length it is given + and whether or not that length was proved, because a null pointer is how a module + asks for an optional output it does not want. For these three services nothing is + optional, and the service refuses the null pointer with TX_PTR_ERROR before + dereferencing it -- so correcting the extent is not what refuses one, and the + length word is read on this path too, which is why proving it matters here as + much as anywhere. */ + + for (service = ((UINT) 0); service < TEST_SERVICE_COUNT; service++) + { + shape = &test_service_shapes[service]; + + extra_parameters = test_build_parameters(service, TEST_BISECT_ARRAY, + ((ALIGN_TYPE) 0), TEST_LENGTH_UNSATISFIABLE, + (ALIGN_TYPE) shape -> test_service_control_block_size); + + return_value = test_dispatch(service, &test_protected_module, + (ALIGN_TYPE) test_service_control_block[service], + TEST_NAME_PTR, extra_parameters); + + snprintf(description, sizeof(description), "%s passes a null pool start to the service at any length", + shape -> test_service_name); + test_expect(description, test_service_calls, ((ULONG) 1)); + + snprintf(description, sizeof(description), "...and the service refuses it with TX_PTR_ERROR (%s)", + shape -> test_service_name); + test_expect(description, (ULONG) return_value, (ULONG) TX_PTR_ERROR); + } + + /* The array check has no null clause at all, and must not grow one: the array is not + an optional output, it is the request. A null array is refused by the dispatcher + and never reaches the service, which is the only reason nothing dereferences it. */ + + for (service = ((UINT) 0); service < TEST_SERVICE_COUNT; service++) + { + shape = &test_service_shapes[service]; + + return_value = test_dispatch(service, &test_protected_module, + (ALIGN_TYPE) test_service_control_block[service], + TEST_NAME_PTR, (ALIGN_TYPE *) TX_NULL); + + snprintf(description, sizeof(description), "%s refuses a null parameter array", shape -> test_service_name); + test_expect(description, (ULONG) return_value, (ULONG) TXM_MODULE_INVALID_MEMORY); + + snprintf(description, sizeof(description), "...without reaching the service (%s)", shape -> test_service_name); + test_expect(description, test_service_calls, ((ULONG) 0)); + } + + /**********************************************************************/ + /* An array whose extent runs off the end of the address space. */ + /**********************************************************************/ + + /* The data check tests for that before comparing anything, so a module cannot reach + past the top of memory by wrapping the sum. Nothing is written at that address: + the request is refused before the array is read, which is the point. */ + + for (service = ((UINT) 0); service < TEST_SERVICE_COUNT; service++) + { + shape = &test_service_shapes[service]; + + return_value = test_dispatch(service, &test_protected_module, + (ALIGN_TYPE) test_service_control_block[service], + TEST_NAME_PTR, + (ALIGN_TYPE *) (~((ALIGN_TYPE) 0) - ((ALIGN_TYPE) 3))); + + snprintf(description, sizeof(description), "%s refuses an array whose extent wraps the address space", + shape -> test_service_name); + test_expect(description, (ULONG) return_value, (ULONG) TXM_MODULE_INVALID_MEMORY); + + snprintf(description, sizeof(description), "...without reaching the service (%s)", shape -> test_service_name); + test_expect(description, test_service_calls, ((ULONG) 0)); + } + + /**********************************************************************/ + /* A refusal changes nothing. */ + /**********************************************************************/ + + memcpy((VOID *) saved_object_pool, (VOID *) &test_object_pool, sizeof(test_object_pool)); + + for (service = ((UINT) 0); service < TEST_SERVICE_COUNT; service++) + { + shape = &test_service_shapes[service]; + + room = ((ULONG) 1) * ((ULONG) sizeof(ALIGN_TYPE)); + + extra_parameters = test_build_parameters(service, (TEST_DATA_START + TEST_REGION_BYTES) - room, + (ALIGN_TYPE) TEST_DATA_START, ((ALIGN_TYPE) sizeof(ALIGN_TYPE)), + (ALIGN_TYPE) shape -> test_service_control_block_size); + + return_value = test_dispatch(service, &test_protected_module, + (ALIGN_TYPE) test_service_control_block[service], + TEST_NAME_PTR, extra_parameters); + + snprintf(description, sizeof(description), "%s refuses with TXM_MODULE_INVALID_MEMORY", shape -> test_service_name); + test_expect(description, (ULONG) return_value, (ULONG) TXM_MODULE_INVALID_MEMORY); + + snprintf(description, sizeof(description), "...%s does not reach the service", shape -> test_service_name); + test_expect(description, test_service_calls, ((ULONG) 0)); + + snprintf(description, sizeof(description), + "...and %s leaves every control block and allocation header untouched", shape -> test_service_name); + test_expect(description, + (ULONG) (memcmp((VOID *) saved_object_pool, (VOID *) &test_object_pool, sizeof(test_object_pool)) == 0), + (ULONG) TX_TRUE); + } + + /**********************************************************************/ + /* Where the pool start itself may be. */ + /**********************************************************************/ + + /* The pool start is checked with the same data-only check the array is, plus the + null clause, so it may be in the module's writable data or in a shared region + registered to it and nowhere else. A pool in the module's read-only image is + refused however small, which is the second place this path has no code-region + fallback to lean on. */ + + for (service = ((UINT) 0); service < TEST_SERVICE_COUNT; service++) + { + shape = &test_service_shapes[service]; + + extra_parameters = test_build_parameters(service, TEST_BISECT_ARRAY, + (ALIGN_TYPE) TEST_SHARED_START, ((ALIGN_TYPE) sizeof(ALIGN_TYPE)), + (ALIGN_TYPE) shape -> test_service_control_block_size); + + snprintf(description, sizeof(description), "%s accepts a pool start in a shared region", shape -> test_service_name); + test_expect(description, + (ULONG) test_accepted(service, &test_protected_module, + (ALIGN_TYPE) test_service_control_block[service], + TEST_NAME_PTR, extra_parameters), + (ULONG) TX_TRUE); + + extra_parameters = test_build_parameters(service, TEST_BISECT_ARRAY, + (ALIGN_TYPE) TEST_CODE_START, ((ALIGN_TYPE) sizeof(ALIGN_TYPE)), + (ALIGN_TYPE) shape -> test_service_control_block_size); + + snprintf(description, sizeof(description), "%s refuses a pool start in the module's read-only image", + shape -> test_service_name); + test_expect(description, + (ULONG) test_accepted(service, &test_protected_module, + (ALIGN_TYPE) test_service_control_block[service], + TEST_NAME_PTR, extra_parameters), + (ULONG) TX_FALSE); + } + + /**********************************************************************/ + /* The control block and the name still have to be what they were. */ + /**********************************************************************/ + + /* The array extent is the third of four checks, so correcting it must not have + displaced the two in front of it. A creation request still needs a control block + the module allocated from the manager's object pool at exactly the size this + service expects, and a name inside the module. */ + + for (service = ((UINT) 0); service < TEST_SERVICE_COUNT; service++) + { + shape = &test_service_shapes[service]; + + extra_parameters = test_build_parameters(service, TEST_BISECT_ARRAY, + (ALIGN_TYPE) TEST_DATA_START, ((ALIGN_TYPE) sizeof(ALIGN_TYPE)), + (ALIGN_TYPE) shape -> test_service_control_block_size); + + snprintf(description, sizeof(description), "%s refuses a null control block", shape -> test_service_name); + test_expect(description, + (ULONG) test_accepted(service, &test_protected_module, ((ALIGN_TYPE) 0), TEST_NAME_PTR, extra_parameters), + (ULONG) TX_FALSE); + + snprintf(description, sizeof(description), "%s refuses a control block inside the module's data", + shape -> test_service_name); + test_expect(description, + (ULONG) test_accepted(service, &test_protected_module, (ALIGN_TYPE) TEST_DATA_START, + TEST_NAME_PTR, extra_parameters), + (ULONG) TX_FALSE); + + /* An allocation of the module's own, at the wrong size for this service. */ + (VOID) test_object_allocate((ULONG) service, &test_protected_module, + shape -> test_service_control_block_size + ((ULONG) 1)); + + snprintf(description, sizeof(description), "%s refuses an allocation of the wrong size", + shape -> test_service_name); + test_expect(description, + (ULONG) test_accepted(service, &test_protected_module, + (ALIGN_TYPE) test_service_control_block[service], + TEST_NAME_PTR, extra_parameters), + (ULONG) TX_FALSE); + + /* An allocation of the right size belonging to another module. */ + (VOID) test_object_allocate((ULONG) service, &test_unprotected_module, + shape -> test_service_control_block_size); + + snprintf(description, sizeof(description), "%s refuses another module's allocation", + shape -> test_service_name); + test_expect(description, + (ULONG) test_accepted(service, &test_protected_module, + (ALIGN_TYPE) test_service_control_block[service], + TEST_NAME_PTR, extra_parameters), + (ULONG) TX_FALSE); + + /* Put it back the way the rest of the run needs it. */ + (VOID) test_object_allocate((ULONG) service, &test_protected_module, + shape -> test_service_control_block_size); + + /* A module naming a constant names it out of its own read-only image, which the + string check accepts because it is the one check here that is not data-only. */ + snprintf(description, sizeof(description), "%s accepts a name in the module's read-only image", + shape -> test_service_name); + test_expect(description, + (ULONG) test_accepted(service, &test_protected_module, + (ALIGN_TYPE) test_service_control_block[service], + (ALIGN_TYPE) TEST_CODE_START, extra_parameters), + (ULONG) TX_TRUE); + + snprintf(description, sizeof(description), "%s refuses a name outside every region the module owns", + shape -> test_service_name); + test_expect(description, + (ULONG) test_accepted(service, &test_protected_module, + (ALIGN_TYPE) test_service_control_block[service], + (ALIGN_TYPE) &test_outside_parameters[0], extra_parameters), + (ULONG) TX_FALSE); + + snprintf(description, sizeof(description), "%s accepts a null name, which the kernel allows", + shape -> test_service_name); + test_expect(description, + (ULONG) test_accepted(service, &test_protected_module, + (ALIGN_TYPE) test_service_control_block[service], + ((ALIGN_TYPE) 0), extra_parameters), + (ULONG) TX_TRUE); + } + + /**********************************************************************/ + /* A module without memory protection is unaffected. */ + /**********************************************************************/ + + /* Every check the fix touches sits inside the dispatchers' memory-protection block. + A module that was loaded without protection reaches the kernel service with no + check of any kind, before the fix and after it, and these cases are here so that + a later change to the extent cannot quietly start refusing its requests. */ + + for (service = ((UINT) 0); service < TEST_SERVICE_COUNT; service++) + { + shape = &test_service_shapes[service]; + + extra_parameters = test_build_parameters(service, (UCHAR *) test_outside_parameters, + (ALIGN_TYPE) test_outside_parameters, ((ALIGN_TYPE) sizeof(ALIGN_TYPE)), + (ALIGN_TYPE) shape -> test_service_control_block_size); + + snprintf(description, sizeof(description), + "an unprotected module's %s is accepted with an array, a pool and a control block outside every region", + shape -> test_service_name); + test_expect(description, + (ULONG) test_accepted(service, &test_unprotected_module, + (ALIGN_TYPE) test_outside_control_block[service], + (ALIGN_TYPE) test_outside_parameters, extra_parameters), + (ULONG) TX_TRUE); + + /* And with one word of room, which is the shape a protected module is refused + for above. */ + room = ((ULONG) 1) * ((ULONG) sizeof(ALIGN_TYPE)); + + extra_parameters = test_build_parameters(service, (TEST_DATA_START + TEST_REGION_BYTES) - room, + (ALIGN_TYPE) TEST_DATA_START, ((ALIGN_TYPE) sizeof(ALIGN_TYPE)), + (ALIGN_TYPE) shape -> test_service_control_block_size); + + snprintf(description, sizeof(description), + "an unprotected module's %s is accepted with one word of room", shape -> test_service_name); + test_expect(description, + (ULONG) test_accepted(service, &test_unprotected_module, + (ALIGN_TYPE) test_outside_control_block[service], + TEST_NAME_PTR, extra_parameters), + (ULONG) TX_TRUE); + + /* Nothing screens an unprotected module's control block before the service, so + the service is where a null one is refused. For a protected module the + creation check refuses it first, which is why this case is here and not + above. */ + return_value = test_dispatch(service, &test_unprotected_module, ((ALIGN_TYPE) 0), + TEST_NAME_PTR, extra_parameters); + + snprintf(description, sizeof(description), + "an unprotected module's %s reaches the service with a null control block", + shape -> test_service_name); + test_expect(description, test_service_calls, ((ULONG) 1)); + + snprintf(description, sizeof(description), "...and the service refuses it (%s)", shape -> test_service_name); + test_expect(description, (ULONG) return_value, shape -> test_service_control_block_error); + } + + /**********************************************************************/ + /* What the whole run has to have held. */ + /**********************************************************************/ + + /* Nothing on these paths disables interrupts, and the shim counts every disable, so + the lock has to have been left as it was found and never taken at all. The second + of those is also the evidence that nothing here raises _tx_thread_preempt_disable: + in ThreadX that flag is only ever changed between a TX_DISABLE and its TX_RESTORE. + A fault taken on this over-read therefore costs the requesting thread, not the + system's ability to preempt. */ + + test_expect("the interrupt lock is balanced", (ULONG) test_interrupt_disable_depth, ((ULONG) 0)); + test_expect("the interrupt lock was never taken", (ULONG) test_interrupt_disable_max_depth, ((ULONG) 0)); + test_expect("the interrupt lock never underflowed", (ULONG) test_interrupt_restore_underflows, ((ULONG) 0)); + + test_expect("every case ran", (ULONG) (test_checks > ((ULONG) 700)), (ULONG) TX_TRUE); + + if (test_failures == 0U) + { + printf("SUCCESS! %lu expectations\n", (unsigned long) test_checks); + return(0); + } + + printf("ERROR: %u expectation(s) failed of %lu\n", test_failures, (unsigned long) test_checks); + return(1); +} From ee4c2fb6c7909521cc6ea42d5d7c22f103707c52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 28 Sep 2026 10:58:58 -0400 Subject: [PATCH 158/181] Merge commit from fork A memory-protected module's object lookup arrives at the Module Manager's dispatch layer, which decides how much of the module's name buffer the privileged comparison may touch. It checked one byte. _txm_module_manager_object_name_compare reads a character from each name at the top of every iteration and tests the remaining search length at the bottom, so a declared length N permits reads at offsets 0 through N: N+1 bytes, the extra one being the terminator a length excludes. The extended service receives that length in its extra parameter array, validates the array correctly, and then never uses the length to bound the buffer it describes. The deprecated service carries no length at all; its manager wrapper calls the same implementation with the largest value a UINT can hold, so it removes the bound rather than lacking one. The comparison stops at the first differing character, so a walk past the end of the module's memory looks as though it needs the bytes there to match a name the module chose. It does not. A create service stores the name pointer a module supplies in the control block rather than copying the string, so a module can register an object whose name is the very buffer it then searches for. Both sides of the comparison are then the same address, every character matches by construction, and the walk continues until it meets a terminator in memory the module does not own and cannot see. That walk runs in privileged mode with _tx_thread_preempt_disable raised, and none of the 27 memory fault handlers lowers it again, so a fault on it costs more than the requesting thread. The fix validates the range the comparison may reach. The extended dispatcher now checks the name over name_length + 1 bytes, refusing a length whose range cannot be expressed, and the extra parameter array is checked first because the length comes out of it. The deprecated dispatcher refuses a memory-protected module outright, because no range can be derived from a pointer alone; a module without protection is unchanged, as it is for every other check in this layer. _txm_module_manager_object_name_compare is left as it is. Reading N+1 bytes for a declared length of N is the documented contract, and the defect is that the contract was never checked. The regression test drives both lookup dispatchers and measures two extents rather than sampling either side of a boundary, because the finding is the relationship between them. It anchors the name buffer to the end of one of the module's regions and walks it backwards to find the smallest room the dispatcher accepts, which is the extent validated; and it fills memory with a filler character, plants the only terminator at a chosen depth, and asks for an object named with exactly the bytes up to it, so that the deepest depth the lookup can be made to return from is the extent read. Against dev's copy of the two headers the test exits 1 with 408 failed expectations of 1130: a 31-character name with one byte of room is accepted and read 31 bytes past the region, and the aliased walk reaches every depth offered. With the fix it exits 0 with 1490 expectations and none failed. Assisted-by: Claude Code (Opus 5) --- .../inc/txm_module_manager_dispatch.h | 18 +- .../inc/txm_module_manager_util.h | 9 + test/tx/cmake/module_manager/CMakeLists.txt | 22 + ...dx_module_manager_object_name_range_test.c | 1608 +++++++++++++++++ 4 files changed, 1650 insertions(+), 7 deletions(-) create mode 100644 test/tx/module_manager/threadx_module_manager_object_name_range_test.c diff --git a/common_modules/module_manager/inc/txm_module_manager_dispatch.h b/common_modules/module_manager/inc/txm_module_manager_dispatch.h index 35e493d49..2233ec00f 100644 --- a/common_modules/module_manager/inc/txm_module_manager_dispatch.h +++ b/common_modules/module_manager/inc/txm_module_manager_dispatch.h @@ -19,6 +19,8 @@ // Some portions generated by Claude Code (Opus 5). +// Some portions generated by Claude Code (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -3310,11 +3312,10 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_DEREFERENCE_STRING(module_instance, param_1)) - return(TXM_MODULE_INVALID_MEMORY); - - if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, param_2, sizeof(VOID *))) - return(TXM_MODULE_INVALID_MEMORY); + /* This service carries no name length, so the manager searches with the largest + length a UINT can hold and no readable range can be proven for the name. A + memory-protected module must use the extended service, which declares one. */ + return(TXM_MODULE_INVALID_MEMORY); } return_value = (ALIGN_TYPE) _txm_module_manager_object_pointer_get( @@ -3340,10 +3341,13 @@ ALIGN_TYPE return_value; if (module_instance -> txm_module_instance_property_flags & TXM_MODULE_MEMORY_PROTECTION) { - if (!TXM_MODULE_MANAGER_PARAM_CHECK_DEREFERENCE_STRING(module_instance, param_1)) + if (!TXM_MODULE_MANAGER_ENSURE_INSIDE_MODULE_DATA(module_instance, (ALIGN_TYPE)extra_parameters, sizeof(ALIGN_TYPE[2]))) return(TXM_MODULE_INVALID_MEMORY); - if (!TXM_MODULE_MANAGER_ENSURE_INSIDE_MODULE_DATA(module_instance, (ALIGN_TYPE)extra_parameters, sizeof(ALIGN_TYPE[2]))) + /* The name length has to be checked before it is trusted, so the extra parameter + array is checked first. The comparison reads the declared length plus the + terminator that follows it, and all of that must be inside the module. */ + if (!TXM_MODULE_MANAGER_PARAM_CHECK_DEREFERENCE_STRING_RANGE(module_instance, param_1, (UINT) extra_parameters[0])) return(TXM_MODULE_INVALID_MEMORY); if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, extra_parameters[1], sizeof(VOID *))) diff --git a/common_modules/module_manager/inc/txm_module_manager_util.h b/common_modules/module_manager/inc/txm_module_manager_util.h index 22b9570e3..92bb55dd9 100644 --- a/common_modules/module_manager/inc/txm_module_manager_util.h +++ b/common_modules/module_manager/inc/txm_module_manager_util.h @@ -135,6 +135,15 @@ ((TXM_MODULE_MANAGER_ENSURE_INSIDE_MODULE(module_instance, string_ptr, 1)) || \ ((void *) (string_ptr) == TX_NULL)) +/* Strings we walk are checked over the whole range the walk may reach: the declared + length plus the terminating character that follows it, since a length excludes the + terminator and the comparison reads it. A length whose range cannot be expressed + is refused rather than truncated. */ +#define TXM_MODULE_MANAGER_PARAM_CHECK_DEREFERENCE_STRING_RANGE(module_instance, string_ptr, string_length) \ + (((((ALIGN_TYPE) (string_length)) < (~((ALIGN_TYPE) 0))) && \ + (TXM_MODULE_MANAGER_ENSURE_INSIDE_MODULE(module_instance, string_ptr, ((ALIGN_TYPE) (string_length)) + ((ALIGN_TYPE) 1)))) || \ + ((void *) (string_ptr) == TX_NULL)) + #define TXM_MODULE_MANAGER_UTIL_MAX_VALUE_OF_TYPE_UNSIGNED(type) ((1ULL << (sizeof(type) * 8)) - 1) #define TXM_MODULE_MANAGER_UTIL_MATH_ADD_ULONG(augend, addend, result) \ diff --git a/test/tx/cmake/module_manager/CMakeLists.txt b/test/tx/cmake/module_manager/CMakeLists.txt index 109ee72a5..f9830d44d 100644 --- a/test/tx/cmake/module_manager/CMakeLists.txt +++ b/test/tx/cmake/module_manager/CMakeLists.txt @@ -194,3 +194,25 @@ target_compile_options( add_test(${CMAKE_BUILD_TYPE}::threadx_module_manager_block_pool_parameters_test threadx_module_manager_block_pool_parameters_test) + +add_executable( + threadx_module_manager_object_name_range_test + ${SOURCE_DIR}/threadx_module_manager_object_name_range_test.c + ${module_manager_dir}/src/txm_module_manager_object_pointer_get.c + ${module_manager_dir}/src/txm_module_manager_object_pointer_get_extended.c + ${module_manager_dir}/src/txm_module_manager_util.c) + +target_include_directories( + threadx_module_manager_object_name_range_test + PRIVATE ${SOURCE_DIR} + ${REPO_ROOT}/common/inc + ${REPO_ROOT}/common_modules/inc + ${module_manager_dir}/inc + ${cortex_m4_module_dir}/inc) + +target_compile_options( + threadx_module_manager_object_name_range_test + PRIVATE -include ${SOURCE_DIR}/threadx_module_manager_host_test_port.h) + +add_test(${CMAKE_BUILD_TYPE}::threadx_module_manager_object_name_range_test + threadx_module_manager_object_name_range_test) diff --git a/test/tx/module_manager/threadx_module_manager_object_name_range_test.c b/test/tx/module_manager/threadx_module_manager_object_name_range_test.c new file mode 100644 index 000000000..7e6ee5e5d --- /dev/null +++ b/test/tx/module_manager/threadx_module_manager_object_name_range_test.c @@ -0,0 +1,1608 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Test */ +/** */ +/** Module Manager object name range validation */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +/* A memory-protected module asks the Module Manager to find a kernel object by name. + The dispatch layer decides how much of the module's name buffer the privileged + comparison may touch. It checked one byte. + + _txm_module_manager_object_name_compare reads a character from each name at the top + of every iteration and tests the remaining search length at the bottom, so a declared + length N permits reads at offsets 0 through N -- N+1 bytes, the extra one being the + terminator a length excludes. The extended service receives that length in its extra + parameter array, validates the array correctly, and then never uses the length to + bound the buffer it describes. The deprecated service carries no length at all: its + manager wrapper calls the same implementation with the largest value a UINT can hold, + so it removes the bound rather than lacking one. + + The comparison stops at the first differing character, so the walk past the end of + the module's memory is not free -- unless the module arranges for it to match. It can: + a create service stores the name pointer a module supplies in the control block + rather than copying the string, so a module can register an object whose name is the + very buffer it then searches for. Both sides of the comparison are then the same + address, every character matches by construction, and the walk continues until it + meets a terminator in memory the module does not own and cannot see. + + This test drives both lookup dispatchers directly and measures two things rather than + sampling either side of a boundary, because there are two dials here and the finding + is about the relationship between them: + + - the extent the dispatcher validates, found by anchoring the name buffer to the end + of one of the module's regions and walking it backwards a byte at a time until the + request is accepted; and + + - the extent the comparison reads, found by filling memory with a filler character, + planting the only terminator at a chosen depth from the buffer, and asking for an + object whose name is exactly the bytes up to it. The lookup returns that object + only if the comparison read that deep, so the deepest depth it can be made to + return is the read extent. + + The assertion is the relationship: the comparison never reads further than the + dispatcher validated, and the dispatcher validates the length the module declared plus + its terminator. Before the fix the read extent follows the declared length and the + validated extent stays at one byte, which is the defect stated as a measurement. + + Two mechanics come from the queue message range test, which was the first test in the + tree to drive a dispatcher, and both are the reason this one is possible. + + The dispatch table is a header of static functions, one per kernel service, each + wrapped in #ifndef TXM__CALL_NOT_USED. There are 96 of those guards. Defining + the 94 this test does not exercise compiles the header down to the two lookup services, + which keeps the link to the manager sources under test and a handful of kernel globals + instead of the hundred-odd kernel entry points the whole table reaches. + + The extent has to reach a check that honours it, so this test compiles against a + Cortex-M module port's headers, whose inline data check is the shape the memory + protected module ports share. The Cortex-A7 port's data check takes the pointer alone, + so a test built on it would pass equally with and without this fix. + + Unlike the queue test, this one cannot stub the service behind the dispatcher: the + comparison being measured is the service. It links the real lookup implementation and + the real comparison, and stands up the kernel created lists they walk. */ + +#include +#include + +#include "threadx_module_manager_host_test_port.h" + +#include "tx_thread.h" +#include "tx_timer.h" +#include "tx_queue.h" +#include "tx_event_flags.h" +#include "tx_semaphore.h" +#include "tx_mutex.h" +#include "tx_block_pool.h" +#include "tx_byte_pool.h" +#include "txm_module.h" +#include "txm_module_manager_util.h" + + +/* Refuse every service in the dispatch table except the two under test. The list is the + header's own guard names; a service added to the table appears here as a link error + naming the kernel entry point it reaches, which is the right way to find out. */ + +#define TXM_BLOCK_ALLOCATE_CALL_NOT_USED +#define TXM_BLOCK_POOL_CREATE_CALL_NOT_USED +#define TXM_BLOCK_POOL_DELETE_CALL_NOT_USED +#define TXM_BLOCK_POOL_INFO_GET_CALL_NOT_USED +#define TXM_BLOCK_POOL_PERFORMANCE_INFO_GET_CALL_NOT_USED +#define TXM_BLOCK_POOL_PERFORMANCE_SYSTEM_INFO_GET_CALL_NOT_USED +#define TXM_BLOCK_POOL_PRIORITIZE_CALL_NOT_USED +#define TXM_BLOCK_RELEASE_CALL_NOT_USED +#define TXM_BYTE_ALLOCATE_CALL_NOT_USED +#define TXM_BYTE_POOL_CREATE_CALL_NOT_USED +#define TXM_BYTE_POOL_DELETE_CALL_NOT_USED +#define TXM_BYTE_POOL_INFO_GET_CALL_NOT_USED +#define TXM_BYTE_POOL_PERFORMANCE_INFO_GET_CALL_NOT_USED +#define TXM_BYTE_POOL_PERFORMANCE_SYSTEM_INFO_GET_CALL_NOT_USED +#define TXM_BYTE_POOL_PRIORITIZE_CALL_NOT_USED +#define TXM_BYTE_RELEASE_CALL_NOT_USED +#define TXM_EVENT_FLAGS_CREATE_CALL_NOT_USED +#define TXM_EVENT_FLAGS_DELETE_CALL_NOT_USED +#define TXM_EVENT_FLAGS_GET_CALL_NOT_USED +#define TXM_EVENT_FLAGS_INFO_GET_CALL_NOT_USED +#define TXM_EVENT_FLAGS_PERFORMANCE_INFO_GET_CALL_NOT_USED +#define TXM_EVENT_FLAGS_PERFORMANCE_SYSTEM_INFO_GET_CALL_NOT_USED +#define TXM_EVENT_FLAGS_SET_CALL_NOT_USED +#define TXM_EVENT_FLAGS_SET_NOTIFY_CALL_NOT_USED +#define TXM_MUTEX_CREATE_CALL_NOT_USED +#define TXM_MUTEX_DELETE_CALL_NOT_USED +#define TXM_MUTEX_GET_CALL_NOT_USED +#define TXM_MUTEX_INFO_GET_CALL_NOT_USED +#define TXM_MUTEX_PERFORMANCE_INFO_GET_CALL_NOT_USED +#define TXM_MUTEX_PERFORMANCE_SYSTEM_INFO_GET_CALL_NOT_USED +#define TXM_MUTEX_PRIORITIZE_CALL_NOT_USED +#define TXM_MUTEX_PUT_CALL_NOT_USED +#define TXM_QUEUE_CREATE_CALL_NOT_USED +#define TXM_QUEUE_DELETE_CALL_NOT_USED +#define TXM_QUEUE_FLUSH_CALL_NOT_USED +#define TXM_QUEUE_FRONT_SEND_CALL_NOT_USED +#define TXM_QUEUE_INFO_GET_CALL_NOT_USED +#define TXM_QUEUE_PERFORMANCE_INFO_GET_CALL_NOT_USED +#define TXM_QUEUE_PERFORMANCE_SYSTEM_INFO_GET_CALL_NOT_USED +#define TXM_QUEUE_PRIORITIZE_CALL_NOT_USED +#define TXM_QUEUE_RECEIVE_CALL_NOT_USED +#define TXM_QUEUE_SEND_CALL_NOT_USED +#define TXM_QUEUE_SEND_NOTIFY_CALL_NOT_USED +#define TXM_SEMAPHORE_CEILING_PUT_CALL_NOT_USED +#define TXM_SEMAPHORE_CREATE_CALL_NOT_USED +#define TXM_SEMAPHORE_DELETE_CALL_NOT_USED +#define TXM_SEMAPHORE_GET_CALL_NOT_USED +#define TXM_SEMAPHORE_INFO_GET_CALL_NOT_USED +#define TXM_SEMAPHORE_PERFORMANCE_INFO_GET_CALL_NOT_USED +#define TXM_SEMAPHORE_PERFORMANCE_SYSTEM_INFO_GET_CALL_NOT_USED +#define TXM_SEMAPHORE_PRIORITIZE_CALL_NOT_USED +#define TXM_SEMAPHORE_PUT_CALL_NOT_USED +#define TXM_SEMAPHORE_PUT_NOTIFY_CALL_NOT_USED +#define TXM_THREAD_CREATE_CALL_NOT_USED +#define TXM_THREAD_DELETE_CALL_NOT_USED +#define TXM_THREAD_ENTRY_EXIT_NOTIFY_CALL_NOT_USED +#define TXM_THREAD_IDENTIFY_CALL_NOT_USED +#define TXM_THREAD_INFO_GET_CALL_NOT_USED +#define TXM_THREAD_INTERRUPT_CONTROL_CALL_NOT_USED +#define TXM_THREAD_PERFORMANCE_INFO_GET_CALL_NOT_USED +#define TXM_THREAD_PERFORMANCE_SYSTEM_INFO_GET_CALL_NOT_USED +#define TXM_THREAD_PREEMPTION_CHANGE_CALL_NOT_USED +#define TXM_THREAD_PRIORITY_CHANGE_CALL_NOT_USED +#define TXM_THREAD_RELINQUISH_CALL_NOT_USED +#define TXM_THREAD_RESET_CALL_NOT_USED +#define TXM_THREAD_RESUME_CALL_NOT_USED +#define TXM_THREAD_SLEEP_CALL_NOT_USED +#define TXM_THREAD_STACK_ERROR_NOTIFY_CALL_NOT_USED +#define TXM_THREAD_SUSPEND_CALL_NOT_USED +#define TXM_THREAD_SYSTEM_SUSPEND_CALL_NOT_USED +#define TXM_THREAD_TERMINATE_CALL_NOT_USED +#define TXM_THREAD_TIME_SLICE_CHANGE_CALL_NOT_USED +#define TXM_THREAD_WAIT_ABORT_CALL_NOT_USED +#define TXM_TIME_GET_CALL_NOT_USED +#define TXM_TIME_SET_CALL_NOT_USED +#define TXM_TIMER_ACTIVATE_CALL_NOT_USED +#define TXM_TIMER_CHANGE_CALL_NOT_USED +#define TXM_TIMER_CREATE_CALL_NOT_USED +#define TXM_TIMER_DEACTIVATE_CALL_NOT_USED +#define TXM_TIMER_DELETE_CALL_NOT_USED +#define TXM_TIMER_INFO_GET_CALL_NOT_USED +#define TXM_TIMER_PERFORMANCE_INFO_GET_CALL_NOT_USED +#define TXM_TIMER_PERFORMANCE_SYSTEM_INFO_GET_CALL_NOT_USED +#define TXM_TRACE_BUFFER_FULL_NOTIFY_CALL_NOT_USED +#define TXM_TRACE_DISABLE_CALL_NOT_USED +#define TXM_TRACE_ENABLE_CALL_NOT_USED +#define TXM_TRACE_EVENT_FILTER_CALL_NOT_USED +#define TXM_TRACE_EVENT_UNFILTER_CALL_NOT_USED +#define TXM_TRACE_INTERRUPT_CONTROL_CALL_NOT_USED +#define TXM_TRACE_ISR_ENTER_INSERT_CALL_NOT_USED +#define TXM_TRACE_ISR_EXIT_INSERT_CALL_NOT_USED +#define TXM_TRACE_USER_EVENT_INSERT_CALL_NOT_USED +#define TXM_MODULE_OBJECT_ALLOCATE_CALL_NOT_USED +#define TXM_MODULE_OBJECT_DEALLOCATE_CALL_NOT_USED + +#include "txm_module_manager_dispatch.h" + +/* The two under test have to have survived that, and the rest have to have gone. */ + +#if defined(TXM_MODULE_OBJECT_POINTER_GET_CALL_NOT_USED) || defined(TXM_MODULE_OBJECT_POINTER_GET_EXTENDED_CALL_NOT_USED) +#error "the lookup services under test must be compiled in" +#endif + +#ifndef TXM_QUEUE_FLUSH_CALL_NOT_USED +#error "the services this test does not exercise must be compiled out" +#endif + + +/* Define the stand-in interrupt lock the port shim counts through. */ + +unsigned int test_interrupt_disable_depth; +unsigned int test_interrupt_disable_max_depth; +unsigned int test_interrupt_restore_underflows; + + +/* Define the manager state the utility source under test links against. No case here + reaches the object pool: a lookup names no control block. */ + +TX_BYTE_POOL _txm_module_manager_object_pool; +UINT _txm_module_manager_object_pool_created; + + +/* Define the kernel state the lookup reaches for. It walks a created list per object + type, holds off preemption while it does, and asks the current thread which module it + belongs to before it will search the two pool types. */ + +TX_THREAD *_tx_thread_current_ptr; +volatile UINT _tx_thread_preempt_disable; + +TX_BLOCK_POOL *_tx_block_pool_created_ptr; +ULONG _tx_block_pool_created_count; +TX_BYTE_POOL *_tx_byte_pool_created_ptr; +ULONG _tx_byte_pool_created_count; +TX_EVENT_FLAGS_GROUP *_tx_event_flags_created_ptr; +ULONG _tx_event_flags_created_count; +TX_MUTEX *_tx_mutex_created_ptr; +ULONG _tx_mutex_created_count; +TX_QUEUE *_tx_queue_created_ptr; +ULONG _tx_queue_created_count; +TX_SEMAPHORE *_tx_semaphore_created_ptr; +ULONG _tx_semaphore_created_count; +TX_THREAD *_tx_thread_created_ptr; +ULONG _tx_thread_created_count; +TX_TIMER *_tx_timer_created_ptr; +ULONG _tx_timer_created_count; + + +/* Count the lookup's final preemption check, and record what it left behind. + + The lookup calls this once, on its way out, after restoring the preemption count it + raised on the way in. Counting it is how a case tells a request the dispatch layer + refused from one it let through: a refusal returns before the lookup is entered at + all. Recording the preemption count as the lookup leaves it is how the run as a whole + asserts that the hold is balanced. */ + +static ULONG test_lookup_exits; +static ULONG test_preempt_disable_on_exit; + +VOID _tx_thread_system_preempt_check(VOID) +{ + test_lookup_exits++; + test_preempt_disable_on_exit = (ULONG) _tx_thread_preempt_disable; +} + + +/* Stand in for the port primitive a manager source under test refers to but that no case + here exercises. */ + +VOID _txm_module_manager_alignment_adjust(TXM_MODULE_PREAMBLE *module_preamble, ULONG *code_size, + ULONG *code_alignment, ULONG *data_size, ULONG *data_alignment) +{ + (VOID) module_preamble; + (VOID) code_size; + (VOID) code_alignment; + (VOID) data_size; + (VOID) data_alignment; +} + + +static UINT test_failures; +static ULONG test_checks; + + +/* Record the outcome of one expectation. */ +static VOID test_expect(const char *description, ULONG actual, ULONG expected) +{ + test_checks++; + + if (actual != expected) + { + printf("FAIL: %s (expected %lu, got %lu)\n", description, (unsigned long) expected, (unsigned long) actual); + test_failures++; + } +} + + +/* Model the module's memory as one arena, so that the three regions a name buffer may + legitimately live in have known addresses and known gaps between them. The gaps are + memory the module may not reach: they are what a buffer anchored to the end of a + region overruns into, and they are inside the arena so that the overrun a case + describes is memory this test owns. */ + +#define TEST_REGION_BYTES ((ULONG) 256) +#define TEST_GAP_BYTES ((ULONG) 128) + +static union +{ + ALIGN_TYPE test_arena_alignment; + UCHAR test_arena_bytes[(((ULONG) 3) * TEST_REGION_BYTES) + (((ULONG) 4) * TEST_GAP_BYTES)]; +} test_arena; + +#define TEST_DATA_START (&test_arena.test_arena_bytes[TEST_GAP_BYTES]) +#define TEST_CODE_START (&test_arena.test_arena_bytes[(((ULONG) 2) * TEST_GAP_BYTES) + TEST_REGION_BYTES]) +#define TEST_SHARED_START (&test_arena.test_arena_bytes[(((ULONG) 3) * TEST_GAP_BYTES) + (((ULONG) 2) * TEST_REGION_BYTES)]) + + +/* The character memory is filled with. Any non-zero value will do: what matters is that + a case can plant the only terminator in memory where it wants one, and that the bytes + before it match a name the module chose. */ + +#define TEST_FILLER ((UCHAR) 0x5A) + + +/* The module's outgoing parameters live at the front of its data region, because the + extra parameter array must be inside module data and the result slot must be + writable by the module. Every name buffer is anchored to the end of a region, so the + two never meet. */ + +#define TEST_EXTRA_PARAMETERS ((ALIGN_TYPE *) TEST_DATA_START) +#define TEST_RESULT_SLOT ((VOID **) (TEST_DATA_START + (((ULONG) 2) * sizeof(ALIGN_TYPE)))) + + +/* Define the requesting modules. One has memory protection, and is the one every range + case below drives; the other does not, and is how the cases show that the dispatch + layer's checks are not reached for it at all. */ + +static TXM_MODULE_INSTANCE test_protected_module; +static TXM_MODULE_INSTANCE test_unprotected_module; + + +/* Place a module's regions on the arena. */ +static VOID test_module_setup(TXM_MODULE_INSTANCE *module_instance, ULONG property_flags) +{ + memset((VOID *) module_instance, 0, sizeof(TXM_MODULE_INSTANCE)); + + module_instance -> txm_module_instance_property_flags = property_flags; + + module_instance -> txm_module_instance_data_start = (VOID *) TEST_DATA_START; + module_instance -> txm_module_instance_data_end = (VOID *) (TEST_DATA_START + (TEST_REGION_BYTES - ((ULONG) 1))); + + module_instance -> txm_module_instance_code_start = (VOID *) TEST_CODE_START; + module_instance -> txm_module_instance_code_end = (VOID *) (TEST_CODE_START + (TEST_REGION_BYTES - ((ULONG) 1))); + + module_instance -> txm_module_instance_shared_memory_address = (ULONG) TEST_SHARED_START; + module_instance -> txm_module_instance_shared_memory_length = TEST_REGION_BYTES; +} + + +/* Define the thread the lookup asks which module is calling, and the objects the created + lists are built from. The objects are outside the arena, where a kernel object belongs. */ + +static TX_THREAD test_current_thread; +static TX_SEMAPHORE test_semaphore; +static TX_SEMAPHORE test_decoy_semaphore; + + +/* Define three control blocks of each type for the cases that search every list the + lookup knows: the match, and two ahead of it so that a list is walked rather than + looked at. */ + +#define TEST_OBJECTS_PER_TYPE ((UINT) 3) + +static TX_THREAD test_thread_objects[TEST_OBJECTS_PER_TYPE]; +static TX_TIMER test_timer_objects[TEST_OBJECTS_PER_TYPE]; +static TX_QUEUE test_queue_objects[TEST_OBJECTS_PER_TYPE]; +static TX_EVENT_FLAGS_GROUP test_event_flags_objects[TEST_OBJECTS_PER_TYPE]; +static TX_SEMAPHORE test_semaphore_objects[TEST_OBJECTS_PER_TYPE]; +static TX_MUTEX test_mutex_objects[TEST_OBJECTS_PER_TYPE]; +static TX_BLOCK_POOL test_block_pool_objects[TEST_OBJECTS_PER_TYPE]; +static TX_BYTE_POOL test_byte_pool_objects[TEST_OBJECTS_PER_TYPE]; + + +/* Define the name a probing case gives an object. It is outside the arena too, because + an object's name is not the module's memory even when the module supplied the pointer; + the aliasing cases are the ones that make it so deliberately. */ + +static CHAR test_probe_name[TEST_REGION_BYTES + TEST_GAP_BYTES]; + + +/* Put one object on the created list for its type, newest last, the way the kernel's + create service links a new object in ahead of the head of the ring. The name is stored + as the pointer the caller gave, because that is what a create service does with it and + it is the reason the aliasing cases below are possible at all. + + Every list is built the same way and the eight blocks differ only in the type they + name, which is how the lookup itself is written. */ +static VOID test_object_create(UINT object_type, VOID *object_ptr, CHAR *name) +{ + switch (object_type) + { + + case TXM_THREAD_OBJECT: + { + TX_THREAD *thread_ptr = (TX_THREAD *) object_ptr; + TX_THREAD *tail_ptr; + + memset(object_ptr, 0, sizeof(TX_THREAD)); + thread_ptr -> tx_thread_id = TX_THREAD_ID; + thread_ptr -> tx_thread_name = name; + + if (_tx_thread_created_ptr == TX_NULL) + { + thread_ptr -> tx_thread_created_next = thread_ptr; + _tx_thread_created_ptr = thread_ptr; + } + else + { + tail_ptr = _tx_thread_created_ptr; + while (tail_ptr -> tx_thread_created_next != _tx_thread_created_ptr) + { + tail_ptr = tail_ptr -> tx_thread_created_next; + } + tail_ptr -> tx_thread_created_next = thread_ptr; + thread_ptr -> tx_thread_created_next = _tx_thread_created_ptr; + } + _tx_thread_created_count++; + break; + } + + case TXM_TIMER_OBJECT: + { + TX_TIMER *timer_ptr = (TX_TIMER *) object_ptr; + TX_TIMER *tail_ptr; + + memset(object_ptr, 0, sizeof(TX_TIMER)); + timer_ptr -> tx_timer_id = TX_TIMER_ID; + timer_ptr -> tx_timer_name = name; + + if (_tx_timer_created_ptr == TX_NULL) + { + timer_ptr -> tx_timer_created_next = timer_ptr; + _tx_timer_created_ptr = timer_ptr; + } + else + { + tail_ptr = _tx_timer_created_ptr; + while (tail_ptr -> tx_timer_created_next != _tx_timer_created_ptr) + { + tail_ptr = tail_ptr -> tx_timer_created_next; + } + tail_ptr -> tx_timer_created_next = timer_ptr; + timer_ptr -> tx_timer_created_next = _tx_timer_created_ptr; + } + _tx_timer_created_count++; + break; + } + + case TXM_QUEUE_OBJECT: + { + TX_QUEUE *queue_ptr = (TX_QUEUE *) object_ptr; + TX_QUEUE *tail_ptr; + + memset(object_ptr, 0, sizeof(TX_QUEUE)); + queue_ptr -> tx_queue_id = TX_QUEUE_ID; + queue_ptr -> tx_queue_name = name; + + if (_tx_queue_created_ptr == TX_NULL) + { + queue_ptr -> tx_queue_created_next = queue_ptr; + _tx_queue_created_ptr = queue_ptr; + } + else + { + tail_ptr = _tx_queue_created_ptr; + while (tail_ptr -> tx_queue_created_next != _tx_queue_created_ptr) + { + tail_ptr = tail_ptr -> tx_queue_created_next; + } + tail_ptr -> tx_queue_created_next = queue_ptr; + queue_ptr -> tx_queue_created_next = _tx_queue_created_ptr; + } + _tx_queue_created_count++; + break; + } + + case TXM_EVENT_FLAGS_OBJECT: + { + TX_EVENT_FLAGS_GROUP *event_flags_ptr = (TX_EVENT_FLAGS_GROUP *) object_ptr; + TX_EVENT_FLAGS_GROUP *tail_ptr; + + memset(object_ptr, 0, sizeof(TX_EVENT_FLAGS_GROUP)); + event_flags_ptr -> tx_event_flags_group_id = TX_EVENT_FLAGS_ID; + event_flags_ptr -> tx_event_flags_group_name = name; + + if (_tx_event_flags_created_ptr == TX_NULL) + { + event_flags_ptr -> tx_event_flags_group_created_next = event_flags_ptr; + _tx_event_flags_created_ptr = event_flags_ptr; + } + else + { + tail_ptr = _tx_event_flags_created_ptr; + while (tail_ptr -> tx_event_flags_group_created_next != _tx_event_flags_created_ptr) + { + tail_ptr = tail_ptr -> tx_event_flags_group_created_next; + } + tail_ptr -> tx_event_flags_group_created_next = event_flags_ptr; + event_flags_ptr -> tx_event_flags_group_created_next = _tx_event_flags_created_ptr; + } + _tx_event_flags_created_count++; + break; + } + + case TXM_SEMAPHORE_OBJECT: + { + TX_SEMAPHORE *semaphore_ptr = (TX_SEMAPHORE *) object_ptr; + TX_SEMAPHORE *tail_ptr; + + memset(object_ptr, 0, sizeof(TX_SEMAPHORE)); + semaphore_ptr -> tx_semaphore_id = TX_SEMAPHORE_ID; + semaphore_ptr -> tx_semaphore_name = name; + + if (_tx_semaphore_created_ptr == TX_NULL) + { + semaphore_ptr -> tx_semaphore_created_next = semaphore_ptr; + _tx_semaphore_created_ptr = semaphore_ptr; + } + else + { + tail_ptr = _tx_semaphore_created_ptr; + while (tail_ptr -> tx_semaphore_created_next != _tx_semaphore_created_ptr) + { + tail_ptr = tail_ptr -> tx_semaphore_created_next; + } + tail_ptr -> tx_semaphore_created_next = semaphore_ptr; + semaphore_ptr -> tx_semaphore_created_next = _tx_semaphore_created_ptr; + } + _tx_semaphore_created_count++; + break; + } + + case TXM_MUTEX_OBJECT: + { + TX_MUTEX *mutex_ptr = (TX_MUTEX *) object_ptr; + TX_MUTEX *tail_ptr; + + memset(object_ptr, 0, sizeof(TX_MUTEX)); + mutex_ptr -> tx_mutex_id = TX_MUTEX_ID; + mutex_ptr -> tx_mutex_name = name; + + if (_tx_mutex_created_ptr == TX_NULL) + { + mutex_ptr -> tx_mutex_created_next = mutex_ptr; + _tx_mutex_created_ptr = mutex_ptr; + } + else + { + tail_ptr = _tx_mutex_created_ptr; + while (tail_ptr -> tx_mutex_created_next != _tx_mutex_created_ptr) + { + tail_ptr = tail_ptr -> tx_mutex_created_next; + } + tail_ptr -> tx_mutex_created_next = mutex_ptr; + mutex_ptr -> tx_mutex_created_next = _tx_mutex_created_ptr; + } + _tx_mutex_created_count++; + break; + } + + case TXM_BLOCK_POOL_OBJECT: + { + TX_BLOCK_POOL *block_pool_ptr = (TX_BLOCK_POOL *) object_ptr; + TX_BLOCK_POOL *tail_ptr; + + memset(object_ptr, 0, sizeof(TX_BLOCK_POOL)); + block_pool_ptr -> tx_block_pool_id = TX_BLOCK_POOL_ID; + block_pool_ptr -> tx_block_pool_name = name; + + if (_tx_block_pool_created_ptr == TX_NULL) + { + block_pool_ptr -> tx_block_pool_created_next = block_pool_ptr; + _tx_block_pool_created_ptr = block_pool_ptr; + } + else + { + tail_ptr = _tx_block_pool_created_ptr; + while (tail_ptr -> tx_block_pool_created_next != _tx_block_pool_created_ptr) + { + tail_ptr = tail_ptr -> tx_block_pool_created_next; + } + tail_ptr -> tx_block_pool_created_next = block_pool_ptr; + block_pool_ptr -> tx_block_pool_created_next = _tx_block_pool_created_ptr; + } + _tx_block_pool_created_count++; + break; + } + + case TXM_BYTE_POOL_OBJECT: + default: + { + TX_BYTE_POOL *byte_pool_ptr = (TX_BYTE_POOL *) object_ptr; + TX_BYTE_POOL *tail_ptr; + + memset(object_ptr, 0, sizeof(TX_BYTE_POOL)); + byte_pool_ptr -> tx_byte_pool_id = TX_BYTE_POOL_ID; + byte_pool_ptr -> tx_byte_pool_name = name; + + if (_tx_byte_pool_created_ptr == TX_NULL) + { + byte_pool_ptr -> tx_byte_pool_created_next = byte_pool_ptr; + _tx_byte_pool_created_ptr = byte_pool_ptr; + } + else + { + tail_ptr = _tx_byte_pool_created_ptr; + while (tail_ptr -> tx_byte_pool_created_next != _tx_byte_pool_created_ptr) + { + tail_ptr = tail_ptr -> tx_byte_pool_created_next; + } + tail_ptr -> tx_byte_pool_created_next = byte_pool_ptr; + byte_pool_ptr -> tx_byte_pool_created_next = _tx_byte_pool_created_ptr; + } + _tx_byte_pool_created_count++; + break; + } + } +} + + +/* Empty every created list. */ +static VOID test_lists_clear(VOID) +{ + _tx_block_pool_created_ptr = TX_NULL; + _tx_block_pool_created_count = ((ULONG) 0); + _tx_byte_pool_created_ptr = TX_NULL; + _tx_byte_pool_created_count = ((ULONG) 0); + _tx_event_flags_created_ptr = TX_NULL; + _tx_event_flags_created_count = ((ULONG) 0); + _tx_mutex_created_ptr = TX_NULL; + _tx_mutex_created_count = ((ULONG) 0); + _tx_queue_created_ptr = TX_NULL; + _tx_queue_created_count = ((ULONG) 0); + _tx_semaphore_created_ptr = TX_NULL; + _tx_semaphore_created_count = ((ULONG) 0); + _tx_thread_created_ptr = TX_NULL; + _tx_thread_created_count = ((ULONG) 0); + _tx_timer_created_ptr = TX_NULL; + _tx_timer_created_count = ((ULONG) 0); +} + + +/* Fill the arena, then restore the module's outgoing parameters, which live in it. */ +static VOID test_arena_fill(VOID) +{ + memset((VOID *) &test_arena, (int) TEST_FILLER, sizeof(test_arena)); + + TEST_EXTRA_PARAMETERS[0] = ((ALIGN_TYPE) 0); + TEST_EXTRA_PARAMETERS[1] = (ALIGN_TYPE) TEST_RESULT_SLOT; + *TEST_RESULT_SLOT = TX_NULL; +} + + +/* What one request came back with. */ + +#define TEST_RESULT_POISON ((VOID *) (ALIGN_TYPE) 0xD0D0D0D0) + +static ALIGN_TYPE test_return_value; +static VOID *test_result; +static ULONG test_reached_lookup; + + +/* Make one request of the extended dispatcher, the way a module makes it: the declared + length and the result slot go in the extra parameter array, which is in the module's + own data. */ +static VOID test_lookup_extended_result_slot(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE object_type, + UCHAR *name, UINT name_length, ALIGN_TYPE *extra_parameters, + VOID **result_slot) +{ + *TEST_RESULT_SLOT = TEST_RESULT_POISON; + test_lookup_exits = ((ULONG) 0); + + /* The lookup asks the running thread which module is calling before it will search + the two pool types, so the request has to come from one. */ + test_current_thread.tx_thread_module_instance_ptr = (VOID *) module_instance; + _tx_thread_current_ptr = &test_current_thread; + + extra_parameters[0] = (ALIGN_TYPE) name_length; + extra_parameters[1] = (ALIGN_TYPE) result_slot; + + test_return_value = _txm_module_manager_txm_module_object_pointer_get_extended_dispatch(module_instance, object_type, + (ALIGN_TYPE) name, extra_parameters); + test_result = *TEST_RESULT_SLOT; + test_reached_lookup = test_lookup_exits; +} + + +/* Make one request without writing to the extra parameter array first, for the cases + whose whole point is an array the module could not have written to either. */ +static VOID test_lookup_extended_raw(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE object_type, + UCHAR *name, ALIGN_TYPE *extra_parameters) +{ + *TEST_RESULT_SLOT = TEST_RESULT_POISON; + test_lookup_exits = ((ULONG) 0); + + test_current_thread.tx_thread_module_instance_ptr = (VOID *) module_instance; + _tx_thread_current_ptr = &test_current_thread; + + test_return_value = _txm_module_manager_txm_module_object_pointer_get_extended_dispatch(module_instance, object_type, + (ALIGN_TYPE) name, extra_parameters); + test_result = *TEST_RESULT_SLOT; + test_reached_lookup = test_lookup_exits; +} + + +/* The same request with the result slot the module normally uses. */ +static VOID test_lookup_extended(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE object_type, + UCHAR *name, UINT name_length, ALIGN_TYPE *extra_parameters) +{ + test_lookup_extended_result_slot(module_instance, object_type, name, name_length, extra_parameters, TEST_RESULT_SLOT); +} + + +/* Make one request of the deprecated dispatcher, which carries no length. */ +static VOID test_lookup_deprecated(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE object_type, UCHAR *name) +{ + *TEST_RESULT_SLOT = TEST_RESULT_POISON; + test_lookup_exits = ((ULONG) 0); + + test_current_thread.tx_thread_module_instance_ptr = (VOID *) module_instance; + _tx_thread_current_ptr = &test_current_thread; + + test_return_value = _txm_module_manager_txm_module_object_pointer_get_dispatch(module_instance, object_type, + (ALIGN_TYPE) name, (ALIGN_TYPE) TEST_RESULT_SLOT); + test_result = *TEST_RESULT_SLOT; + test_reached_lookup = test_lookup_exits; +} + + +/* Report whether the dispatch layer let the last request through to the lookup, checking + as it goes that a refusal is a whole refusal: TXM_MODULE_INVALID_MEMORY, the lookup not + entered, and the module's result slot not written. */ +static UINT test_accepted(VOID) +{ + +UINT accepted; + + + if (test_reached_lookup == ((ULONG) 0)) + { + accepted = TX_FALSE; + + test_expect("a refused request returns TXM_MODULE_INVALID_MEMORY", + (ULONG) test_return_value, (ULONG) TXM_MODULE_INVALID_MEMORY); + test_expect("...and writes nothing to the module's result slot", + (ULONG) (test_result == TEST_RESULT_POISON), (ULONG) TX_TRUE); + } + else + { + accepted = TX_TRUE; + + test_expect("an accepted request enters the lookup once", test_reached_lookup, ((ULONG) 1)); + test_expect("...and the lookup gives back the preemption it took", + test_preempt_disable_on_exit, ((ULONG) 0)); + } + + return(accepted); +} + + +/* Measure the extent the dispatcher validates. + + The name buffer is anchored to the end of one of the module's regions and walked + backwards into it a byte at a time, so that the room left between the buffer and the + end of the region grows by one on each step. The smallest amount of room the + dispatcher accepts is the extent it validated. TEST_NOT_ACCEPTED means it accepted + nothing within the region. */ + +#define TEST_NOT_ACCEPTED ((ULONG) 0xFFFFFFFF) + +static ULONG test_measure_validated_extent(TXM_MODULE_INSTANCE *module_instance, UCHAR *region_start, UINT name_length) +{ + +ULONG room; +ULONG walk_limit; +ULONG extent; +UCHAR *region_end_plus_one; + + + region_end_plus_one = region_start + TEST_REGION_BYTES; + + /* Walking past the length plus its terminator is enough to establish that nothing + validates more than that. */ + walk_limit = ((ULONG) name_length) + ((ULONG) 4); + + extent = TEST_NOT_ACCEPTED; + + for (room = ((ULONG) 0); room <= walk_limit; room++) + { + test_arena_fill(); + test_lists_clear(); + + test_lookup_extended(module_instance, (ALIGN_TYPE) TXM_SEMAPHORE_OBJECT, + region_end_plus_one - room, name_length, TEST_EXTRA_PARAMETERS); + + if (test_accepted() == TX_TRUE) + { + extent = room; + break; + } + } + + return(extent); +} + + +/* Measure the extent the comparison reads. + + Memory is filled with a filler character and the only terminator in it is planted at a + chosen depth from the name buffer. The object the module asks for is named with + exactly the bytes up to that terminator, so the lookup returns it if and only if the + comparison read that deep. Scanning the depth and keeping the deepest one that comes + back is therefore the read extent, measured rather than inferred. + + TEST_NOT_READ means no depth came back, which is what a refused request looks like. */ + +#define TEST_NOT_READ ((ULONG) 0xFFFFFFFF) + +static ULONG test_measure_read_depth(TXM_MODULE_INSTANCE *module_instance, UCHAR *region_start, + ULONG room, UINT name_length, ULONG max_depth) +{ + +ULONG depth; +ULONG deepest; +UCHAR *name; + + + deepest = TEST_NOT_READ; + + for (depth = ((ULONG) 0); depth <= max_depth; depth++) + { + test_arena_fill(); + + name = (region_start + TEST_REGION_BYTES) - room; + name[depth] = ((UCHAR) 0); + + memcpy((VOID *) test_probe_name, (VOID *) name, (size_t) depth); + test_probe_name[depth] = ((CHAR) 0); + + test_lists_clear(); + test_object_create((UINT) TXM_SEMAPHORE_OBJECT, (VOID *) &test_semaphore, test_probe_name); + + test_lookup_extended(module_instance, (ALIGN_TYPE) TXM_SEMAPHORE_OBJECT, name, name_length, TEST_EXTRA_PARAMETERS); + + if ((test_reached_lookup != ((ULONG) 0)) && + (test_return_value == ((ALIGN_TYPE) TX_SUCCESS)) && + (test_result == (VOID *) &test_semaphore)) + { + deepest = depth; + } + } + + return(deepest); +} + + +/* Measure how far the comparison walks when the object's name is the module's own search + buffer. + + A create service stores the name pointer a module hands it rather than copying the + string, so a module can register an object whose name is the buffer it then searches + for. Both sides of the comparison are then the same address and every character + matches whatever it is, so the walk is bounded by nothing the module knows or supplied: + it runs to the first terminator in memory. This returns the deepest depth at which a + terminator is still reached, which is that walk length. */ +static ULONG test_measure_alias_walk(TXM_MODULE_INSTANCE *module_instance, UCHAR *region_start, + ULONG room, UINT name_length, ULONG max_depth, UINT use_deprecated) +{ + +ULONG depth; +ULONG deepest; +UCHAR *name; + + + deepest = TEST_NOT_READ; + + for (depth = ((ULONG) 0); depth <= max_depth; depth++) + { + test_arena_fill(); + + name = (region_start + TEST_REGION_BYTES) - room; + name[depth] = ((UCHAR) 0); + + test_lists_clear(); + test_object_create((UINT) TXM_SEMAPHORE_OBJECT, (VOID *) &test_semaphore, (CHAR *) name); + + if (use_deprecated == TX_TRUE) + { + test_lookup_deprecated(module_instance, (ALIGN_TYPE) TXM_SEMAPHORE_OBJECT, name); + } + else + { + test_lookup_extended(module_instance, (ALIGN_TYPE) TXM_SEMAPHORE_OBJECT, name, name_length, TEST_EXTRA_PARAMETERS); + } + + if ((test_reached_lookup != ((ULONG) 0)) && + (test_return_value == ((ALIGN_TYPE) TX_SUCCESS)) && + (test_result == (VOID *) &test_semaphore)) + { + deepest = depth; + } + } + + return(deepest); +} + + +/* The declared lengths the cases run through: none, one character, and lengths either + side of the room a case can leave in a region. */ + +static const UINT test_name_lengths[] = +{ + ((UINT) 0), + ((UINT) 1), + ((UINT) 2), + ((UINT) 3), + ((UINT) 7), + ((UINT) 16), + ((UINT) 31) +}; + +#define TEST_NAME_LENGTH_COUNT (sizeof(test_name_lengths) / sizeof(test_name_lengths[0])) + + +/* The three regions a name buffer may legitimately be in. A search name is read, never + written, so all three are permitted -- a module searching for a literal searches for + one out of its own read-only image. */ + +#define TEST_REGION_COUNT ((UINT) 3) + +static const char *test_region_names[TEST_REGION_COUNT] = +{ + "the module's data", + "a shared region", + "the module's read-only image" +}; + +static UCHAR *test_region_start(UINT region) +{ + +UCHAR *start; + + + if (region == ((UINT) 0)) + { + start = TEST_DATA_START; + } + else if (region == ((UINT) 1)) + { + start = TEST_SHARED_START; + } + else + { + start = TEST_CODE_START; + } + + return(start); +} + + +/* The eight object types the lookup knows, and one it does not. */ + +#define TEST_OBJECT_TYPE_COUNT ((UINT) 8) + +static const ALIGN_TYPE test_object_types[TEST_OBJECT_TYPE_COUNT] = +{ + (ALIGN_TYPE) TXM_THREAD_OBJECT, + (ALIGN_TYPE) TXM_TIMER_OBJECT, + (ALIGN_TYPE) TXM_QUEUE_OBJECT, + (ALIGN_TYPE) TXM_EVENT_FLAGS_OBJECT, + (ALIGN_TYPE) TXM_SEMAPHORE_OBJECT, + (ALIGN_TYPE) TXM_MUTEX_OBJECT, + (ALIGN_TYPE) TXM_BLOCK_POOL_OBJECT, + (ALIGN_TYPE) TXM_BYTE_POOL_OBJECT +}; + +static const char *test_object_type_names[TEST_OBJECT_TYPE_COUNT] = +{ + "thread", + "timer", + "queue", + "event flags group", + "semaphore", + "mutex", + "block pool", + "byte pool" +}; + +#define TEST_INVALID_OBJECT_TYPE ((ALIGN_TYPE) 0x7EU) + + +/* One of the two control blocks held for each type, in the order the type table lists + them. */ +static VOID *test_object_block(UINT type_index, UINT which) +{ + +VOID *object_ptr; + + + switch (type_index) + { + case ((UINT) 0): object_ptr = (VOID *) &test_thread_objects[which]; break; + case ((UINT) 1): object_ptr = (VOID *) &test_timer_objects[which]; break; + case ((UINT) 2): object_ptr = (VOID *) &test_queue_objects[which]; break; + case ((UINT) 3): object_ptr = (VOID *) &test_event_flags_objects[which]; break; + case ((UINT) 4): object_ptr = (VOID *) &test_semaphore_objects[which]; break; + case ((UINT) 5): object_ptr = (VOID *) &test_mutex_objects[which]; break; + case ((UINT) 6): object_ptr = (VOID *) &test_block_pool_objects[which]; break; + default: object_ptr = (VOID *) &test_byte_pool_objects[which]; break; + } + + return(object_ptr); +} + + +int main(void) +{ + +UINT length_index; +UINT region; +UINT type_index; +UINT name_length; +UCHAR *region_start; +UCHAR *name; +ULONG room; +ULONG depth; +ULONG expected_extent; +char description[192]; + + + memset((VOID *) &test_current_thread, 0, sizeof(TX_THREAD)); + test_current_thread.tx_thread_id = TX_THREAD_ID; + + test_module_setup(&test_protected_module, (ULONG) TXM_MODULE_MEMORY_PROTECTION); + test_module_setup(&test_unprotected_module, ((ULONG) 0)); + + printf("Module Manager object name range validation test\n"); + + /**********************************************************************/ + /* The extent the extended dispatcher validates. */ + /**********************************************************************/ + + /* A declared length excludes the terminator and the comparison reads it, so the range + the module has to have made readable is the length plus one byte, in whichever of + the three regions a search name may live in. */ + + for (length_index = ((UINT) 0); length_index < ((UINT) TEST_NAME_LENGTH_COUNT); length_index++) + { + name_length = test_name_lengths[length_index]; + expected_extent = ((ULONG) name_length) + ((ULONG) 1); + + for (region = ((UINT) 0); region < TEST_REGION_COUNT; region++) + { + snprintf(description, sizeof(description), + "a declared length of %u is checked over %lu bytes of a name in %s", + name_length, (unsigned long) expected_extent, test_region_names[region]); + test_expect(description, + test_measure_validated_extent(&test_protected_module, test_region_start(region), name_length), + expected_extent); + } + } + + /**********************************************************************/ + /* The extent the comparison reads, against the extent validated. */ + /**********************************************************************/ + + /* The two dials are the declared length and the object's name, and the finding is the + relationship between them: the comparison reads through the declared length, so a + request must not be accepted unless that whole range is inside the module. For every + length and every amount of room, the request is accepted exactly when the room + covers the length and its terminator, and when it is accepted the deepest byte the + comparison can be made to read is the last byte of the declared name -- which the + room then guarantees is inside the module. */ + + for (length_index = ((UINT) 0); length_index < ((UINT) TEST_NAME_LENGTH_COUNT); length_index++) + { + name_length = test_name_lengths[length_index]; + + for (region = ((UINT) 0); region < TEST_REGION_COUNT; region++) + { + region_start = test_region_start(region); + + for (room = ((ULONG) 1); room <= (((ULONG) name_length) + ((ULONG) 2)); room++) + { + depth = test_measure_read_depth(&test_protected_module, region_start, room, + name_length, ((ULONG) name_length) + ((ULONG) 2)); + + if (room >= (((ULONG) name_length) + ((ULONG) 1))) + { + snprintf(description, sizeof(description), + "a %u-character name with %lu bytes of room in %s is read to its declared end", + name_length, (unsigned long) room, test_region_names[region]); + test_expect(description, depth, (ULONG) name_length); + + snprintf(description, sizeof(description), + "...and every byte it read was inside the module (%u characters, %lu bytes of room)", + name_length, (unsigned long) room); + test_expect(description, (ULONG) (depth < room), (ULONG) TX_TRUE); + } + else + { + snprintf(description, sizeof(description), + "a %u-character name with only %lu bytes of room in %s is not read at all", + name_length, (unsigned long) room, test_region_names[region]); + test_expect(description, depth, TEST_NOT_READ); + } + } + } + } + + /**********************************************************************/ + /* The name a module registered for an object can be the name it */ + /* searches for. */ + /**********************************************************************/ + + /* A create service stores the name pointer rather than the string, so a module can + give an object the address of the buffer it then searches for. Both sides of the + comparison are the same address, so it matches whatever is there and the walk is + bounded by nothing the module supplied. That is the case the one-byte check could + not survive, and it is why the length has to bound the buffer rather than the + comparison having to discover the end of it. + + With the range checked, the walk cannot start: the only placements accepted are the + ones whose whole declared range is inside the module, and there the walk ends inside + it too. */ + + for (region = ((UINT) 0); region < TEST_REGION_COUNT; region++) + { + region_start = test_region_start(region); + + snprintf(description, sizeof(description), + "an aliased name with one byte of room in %s reaches no depth at all", test_region_names[region]); + test_expect(description, + test_measure_alias_walk(&test_protected_module, region_start, ((ULONG) 1), + ((UINT) 31), ((ULONG) 31), TX_FALSE), + TEST_NOT_READ); + + snprintf(description, sizeof(description), + "an aliased name with room for its whole declared range in %s walks no further than that range", + test_region_names[region]); + test_expect(description, + test_measure_alias_walk(&test_protected_module, region_start, ((ULONG) 32), + ((UINT) 31), ((ULONG) 63), TX_FALSE), + ((ULONG) 31)); + } + + /**********************************************************************/ + /* The deprecated service, which carries no length. */ + /**********************************************************************/ + + /* Its manager wrapper searches with the largest length a UINT can hold, so there is no + range to check and none can be derived from a pointer. A memory-protected module is + refused it; the extended service is what such a module uses. */ + + for (region = ((UINT) 0); region < TEST_REGION_COUNT; region++) + { + region_start = test_region_start(region); + + for (room = ((ULONG) 1); room <= ((ULONG) 64); room++) + { + test_arena_fill(); + test_lists_clear(); + + test_lookup_deprecated(&test_protected_module, (ALIGN_TYPE) TXM_SEMAPHORE_OBJECT, + (region_start + TEST_REGION_BYTES) - room); + + if (room == ((ULONG) 1)) + { + snprintf(description, sizeof(description), + "a memory-protected module's lookup without a length in %s is refused", + test_region_names[region]); + test_expect(description, (ULONG) test_accepted(), (ULONG) TX_FALSE); + } + else + { + test_expect("a memory-protected module's lookup without a length is refused at every placement", + (ULONG) test_accepted(), (ULONG) TX_FALSE); + } + } + + snprintf(description, sizeof(description), + "...including an aliased name in %s, which is the walk it cannot bound", test_region_names[region]); + test_expect(description, + test_measure_alias_walk(&test_protected_module, region_start, ((ULONG) 1), + ((UINT) 0), ((ULONG) 63), TX_TRUE), + TEST_NOT_READ); + } + + /* A module without memory protection still has it, and there it shows what the absent + length means: with the object's name aliased to the search buffer the walk runs to + whatever terminator memory happens to hold, however far away, because no length + stops it. The extended service on the same module stops exactly where the module + said to. */ + + test_expect("an unprotected module's lookup without a length walks to any depth memory puts a terminator at", + test_measure_alias_walk(&test_unprotected_module, TEST_DATA_START, ((ULONG) 1), + ((UINT) 0), ((ULONG) 100), TX_TRUE), + ((ULONG) 100)); + + test_expect("an unprotected module's extended lookup walks exactly as far as the length it declared", + test_measure_alias_walk(&test_unprotected_module, TEST_DATA_START, ((ULONG) 1), + ((UINT) 40), ((ULONG) 100), TX_FALSE), + ((ULONG) 40)); + + /**********************************************************************/ + /* A null name, and a null result slot. */ + /**********************************************************************/ + + /* The range check accepts a null pointer outright, as the one-byte check it replaces + did and as the buffer checks do, because passing null is how a module declines an + optional argument. Neither of these is optional, and it is the lookup that refuses + them, before it dereferences either. These cases assert that sequence rather than + the macro, so that neither side can change quietly. */ + + test_arena_fill(); + test_lists_clear(); + + test_lookup_extended(&test_protected_module, (ALIGN_TYPE) TXM_SEMAPHORE_OBJECT, TX_NULL, ((UINT) 31), TEST_EXTRA_PARAMETERS); + test_expect("the extended dispatcher passes a null name through", (ULONG) test_return_value, (ULONG) TX_PTR_ERROR); + test_expect("...and the lookup refuses it before dereferencing it", test_reached_lookup, ((ULONG) 0)); + + test_arena_fill(); + test_lists_clear(); + TEST_EXTRA_PARAMETERS[0] = ((ALIGN_TYPE) 31); + TEST_EXTRA_PARAMETERS[1] = ((ALIGN_TYPE) 0); + test_return_value = _txm_module_manager_txm_module_object_pointer_get_extended_dispatch(&test_protected_module, + (ALIGN_TYPE) TXM_SEMAPHORE_OBJECT, + (ALIGN_TYPE) TEST_DATA_START, + TEST_EXTRA_PARAMETERS); + test_expect("the extended dispatcher passes a null result slot through", (ULONG) test_return_value, (ULONG) TX_PTR_ERROR); + + /* The deprecated service refuses a memory-protected module before it gets that far, + which is a change from the one-byte check and is recorded here as one. */ + + test_arena_fill(); + test_lists_clear(); + test_lookup_deprecated(&test_protected_module, (ALIGN_TYPE) TXM_SEMAPHORE_OBJECT, TX_NULL); + test_expect("a memory-protected module's null name is refused by the deprecated dispatcher", + (ULONG) test_return_value, (ULONG) TXM_MODULE_INVALID_MEMORY); + + test_arena_fill(); + test_lists_clear(); + test_lookup_deprecated(&test_unprotected_module, (ALIGN_TYPE) TXM_SEMAPHORE_OBJECT, TX_NULL); + test_expect("an unprotected module's null name still reaches the lookup", (ULONG) test_return_value, (ULONG) TX_PTR_ERROR); + + /**********************************************************************/ + /* The extra parameter array itself. */ + /**********************************************************************/ + + /* The length is read out of that array, so checking the name's range depends on the + array having been checked first. Reordering the two checks is what the fix required, + and a request that fails both still fails the same way. */ + + test_arena_fill(); + test_lists_clear(); + test_lookup_extended(&test_protected_module, (ALIGN_TYPE) TXM_SEMAPHORE_OBJECT, TEST_DATA_START, + ((UINT) 1), (ALIGN_TYPE *) TEST_CODE_START); + test_expect("an extra parameter array in the module's read-only image is refused", + (ULONG) test_accepted(), (ULONG) TX_FALSE); + + test_arena_fill(); + test_lists_clear(); + test_lookup_extended(&test_protected_module, (ALIGN_TYPE) TXM_SEMAPHORE_OBJECT, + (TEST_DATA_START + TEST_REGION_BYTES) - ((ULONG) 1), + ((UINT) 31), (ALIGN_TYPE *) TEST_CODE_START); + test_expect("an unreadable name and an unreadable array are refused the same way", + (ULONG) test_accepted(), (ULONG) TX_FALSE); + + test_arena_fill(); + test_lists_clear(); + test_lookup_extended(&test_protected_module, (ALIGN_TYPE) TXM_SEMAPHORE_OBJECT, TEST_DATA_START, + ((UINT) 1), (ALIGN_TYPE *) ((TEST_DATA_START + TEST_REGION_BYTES) - sizeof(ALIGN_TYPE))); + test_expect("an extra parameter array with room for one word of two is refused", + (ULONG) test_accepted(), (ULONG) TX_FALSE); + + /* A shared region registered to the module is writable by it, so an array there is + as good as one in its own data, and so is a result slot. */ + + test_arena_fill(); + test_lists_clear(); + test_lookup_extended_result_slot(&test_protected_module, (ALIGN_TYPE) TXM_SEMAPHORE_OBJECT, TEST_DATA_START, + ((UINT) 1), (ALIGN_TYPE *) TEST_SHARED_START, (VOID **) TEST_SHARED_START); + test_expect("an extra parameter array and result slot in a shared region are accepted", + (ULONG) test_accepted(), (ULONG) TX_TRUE); + + test_arena_fill(); + test_lists_clear(); + test_lookup_extended(&test_protected_module, (ALIGN_TYPE) TXM_SEMAPHORE_OBJECT, TEST_DATA_START, + ((UINT) 1), (ALIGN_TYPE *) ((TEST_SHARED_START + TEST_REGION_BYTES) - sizeof(ALIGN_TYPE))); + test_expect("an extra parameter array running off the end of a shared region is refused", + (ULONG) test_accepted(), (ULONG) TX_FALSE); + + test_arena_fill(); + test_lists_clear(); + test_lookup_extended(&test_protected_module, (ALIGN_TYPE) TXM_SEMAPHORE_OBJECT, TEST_DATA_START, + ((UINT) 1), (ALIGN_TYPE *) &test_arena.test_arena_bytes[0]); + test_expect("an extra parameter array below the module's data is refused", + (ULONG) test_accepted(), (ULONG) TX_FALSE); + + test_arena_fill(); + test_lists_clear(); + test_lookup_extended_raw(&test_protected_module, (ALIGN_TYPE) TXM_SEMAPHORE_OBJECT, TEST_DATA_START, + (ALIGN_TYPE *) (~((ALIGN_TYPE) 0) - ((ALIGN_TYPE) 3))); + test_expect("an extra parameter array whose two words wrap the address space is refused", + (ULONG) test_accepted(), (ULONG) TX_FALSE); + + /* The module's read-only image is not, and a result slot the module cannot write is + refused whatever else is right about the request. */ + + test_arena_fill(); + test_lists_clear(); + test_lookup_extended_result_slot(&test_protected_module, (ALIGN_TYPE) TXM_SEMAPHORE_OBJECT, TEST_DATA_START, + ((UINT) 1), TEST_EXTRA_PARAMETERS, (VOID **) TEST_CODE_START); + test_expect("a result slot in the module's read-only image is refused", + (ULONG) test_accepted(), (ULONG) TX_FALSE); + + test_arena_fill(); + test_lists_clear(); + test_lookup_extended_result_slot(&test_protected_module, (ALIGN_TYPE) TXM_SEMAPHORE_OBJECT, TEST_DATA_START, + ((UINT) 1), TEST_EXTRA_PARAMETERS, (VOID **) test_probe_name); + test_expect("a result slot outside every region the module owns is refused", + (ULONG) test_accepted(), (ULONG) TX_FALSE); + + test_arena_fill(); + test_lists_clear(); + test_lookup_extended_result_slot(&test_protected_module, (ALIGN_TYPE) TXM_SEMAPHORE_OBJECT, TEST_DATA_START, + ((UINT) 1), TEST_EXTRA_PARAMETERS, (VOID **) (~((ALIGN_TYPE) 0) - ((ALIGN_TYPE) 1))); + test_expect("a result slot whose word wraps the address space is refused", + (ULONG) test_accepted(), (ULONG) TX_FALSE); + + /**********************************************************************/ + /* Lengths that cannot describe a range. */ + /**********************************************************************/ + + /* The length plus its terminator has to be expressible, and the range has to fit + under the top of memory. Neither is a range a module can be given. */ + + test_arena_fill(); + test_lists_clear(); + test_lookup_extended(&test_protected_module, (ALIGN_TYPE) TXM_SEMAPHORE_OBJECT, TEST_DATA_START, + (UINT) TXM_MODULE_MANAGER_UTIL_MAX_VALUE_OF_TYPE_UNSIGNED(UINT), TEST_EXTRA_PARAMETERS); + test_expect("the largest length a UINT can hold is refused", (ULONG) test_accepted(), (ULONG) TX_FALSE); + + test_arena_fill(); + test_lists_clear(); + test_lookup_extended(&test_protected_module, (ALIGN_TYPE) TXM_SEMAPHORE_OBJECT, TEST_DATA_START, + ((UINT) TXM_MODULE_MANAGER_UTIL_MAX_VALUE_OF_TYPE_UNSIGNED(UINT)) - ((UINT) 1), TEST_EXTRA_PARAMETERS); + test_expect("a length one below it is refused too", (ULONG) test_accepted(), (ULONG) TX_FALSE); + + test_arena_fill(); + test_lists_clear(); + test_lookup_extended(&test_protected_module, (ALIGN_TYPE) TXM_SEMAPHORE_OBJECT, + (UCHAR *) (~((ALIGN_TYPE) 0) - ((ALIGN_TYPE) 3)), ((UINT) 31), TEST_EXTRA_PARAMETERS); + test_expect("a name whose range wraps the address space is refused", (ULONG) test_accepted(), (ULONG) TX_FALSE); + + /**********************************************************************/ + /* The range check is the dispatcher's, not the object type's. */ + /**********************************************************************/ + + /* It runs before the lookup and does not depend on what is being looked up, so the + boundary is in the same place for all eight types the lookup knows and for one it + does not. What the lookup then does with the type is its own business, and the two + pool types it refuses a memory-protected module outright. */ + + for (type_index = ((UINT) 0); type_index < TEST_OBJECT_TYPE_COUNT; type_index++) + { + test_arena_fill(); + test_lists_clear(); + test_lookup_extended(&test_protected_module, test_object_types[type_index], + (TEST_DATA_START + TEST_REGION_BYTES) - ((ULONG) 4), ((UINT) 4), TEST_EXTRA_PARAMETERS); + + snprintf(description, sizeof(description), "a %s name one byte short of its range is refused", + test_object_type_names[type_index]); + test_expect(description, (ULONG) test_accepted(), (ULONG) TX_FALSE); + + test_arena_fill(); + test_lists_clear(); + test_lookup_extended(&test_protected_module, test_object_types[type_index], + (TEST_DATA_START + TEST_REGION_BYTES) - ((ULONG) 5), ((UINT) 4), TEST_EXTRA_PARAMETERS); + + snprintf(description, sizeof(description), "a %s name with its whole range is accepted", + test_object_type_names[type_index]); + test_expect(description, (ULONG) test_accepted(), (ULONG) TX_TRUE); + + if ((test_object_types[type_index] == ((ALIGN_TYPE) TXM_BLOCK_POOL_OBJECT)) || + (test_object_types[type_index] == ((ALIGN_TYPE) TXM_BYTE_POOL_OBJECT))) + { + snprintf(description, sizeof(description), "...and the lookup refuses a memory-protected module a %s", + test_object_type_names[type_index]); + test_expect(description, (ULONG) test_return_value, (ULONG) TXM_MODULE_INVALID); + } + else + { + snprintf(description, sizeof(description), "...and the lookup searches for the %s and finds none", + test_object_type_names[type_index]); + test_expect(description, (ULONG) test_return_value, (ULONG) TX_NO_INSTANCE); + } + } + + test_arena_fill(); + test_lists_clear(); + test_lookup_extended(&test_protected_module, TEST_INVALID_OBJECT_TYPE, + (TEST_DATA_START + TEST_REGION_BYTES) - ((ULONG) 4), ((UINT) 4), TEST_EXTRA_PARAMETERS); + test_expect("an unknown object type is refused for its range first", (ULONG) test_accepted(), (ULONG) TX_FALSE); + + test_arena_fill(); + test_lists_clear(); + test_lookup_extended(&test_protected_module, TEST_INVALID_OBJECT_TYPE, + (TEST_DATA_START + TEST_REGION_BYTES) - ((ULONG) 5), ((UINT) 4), TEST_EXTRA_PARAMETERS); + test_expect("...and once its range is right, by the lookup for being unknown", + (ULONG) test_return_value, (ULONG) TX_OPTION_ERROR); + + /**********************************************************************/ + /* Every created list the lookup walks. */ + /**********************************************************************/ + + /* The comparison the range check protects runs once per object on the list for the + requested type, and there are eight such lists. These cases put two objects on each + of them and search for the second, so that every list is walked, every comparison + is reached, and the name pointer the lookup dereferences out of each kind of control + block is the one a create service stored there. + + The two pool types are refused to a memory-protected module by the lookup itself, so + these run as the module without protection, which is the caller that can reach them. */ + + for (type_index = ((UINT) 0); type_index < TEST_OBJECT_TYPE_COUNT; type_index++) + { + test_arena_fill(); + test_lists_clear(); + + name = (TEST_DATA_START + TEST_REGION_BYTES) - ((ULONG) 8); + memcpy((VOID *) name, "target", (size_t) 7); + memcpy((VOID *) test_probe_name, "target", (size_t) 7); + + test_object_create((UINT) test_object_types[type_index], test_object_block(type_index, ((UINT) 0)), "other"); + test_object_create((UINT) test_object_types[type_index], test_object_block(type_index, ((UINT) 1)), "another"); + test_object_create((UINT) test_object_types[type_index], test_object_block(type_index, ((UINT) 2)), test_probe_name); + + test_lookup_extended(&test_unprotected_module, test_object_types[type_index], name, ((UINT) 6), TEST_EXTRA_PARAMETERS); + + snprintf(description, sizeof(description), "the %s list is walked past its earlier members to the match", + test_object_type_names[type_index]); + test_expect(description, (ULONG) test_return_value, (ULONG) TX_SUCCESS); + + snprintf(description, sizeof(description), "...and the %s that comes back is the one whose name matched", + test_object_type_names[type_index]); + test_expect(description, + (ULONG) (test_result == test_object_block(type_index, ((UINT) 2))), (ULONG) TX_TRUE); + + /* A name on no list walks the whole of it and comes back empty, which is the + traversal running to the created count rather than to a match. */ + + memcpy((VOID *) name, "absent", (size_t) 7); + + test_lookup_extended(&test_unprotected_module, test_object_types[type_index], name, ((UINT) 6), TEST_EXTRA_PARAMETERS); + + snprintf(description, sizeof(description), "a name on no %s finds none of them", test_object_type_names[type_index]); + test_expect(description, (ULONG) test_return_value, (ULONG) TX_NO_INSTANCE); + } + + /* The two pool lists are also reachable from application code, which is not a module + at all. That caller does not come through the dispatch layer, so these two cases + call the lookup the dispatchers call. */ + + test_arena_fill(); + test_lists_clear(); + memcpy((VOID *) test_probe_name, "target", (size_t) 7); + test_object_create((UINT) TXM_BLOCK_POOL_OBJECT, (VOID *) &test_block_pool_objects[0], test_probe_name); + test_object_create((UINT) TXM_BYTE_POOL_OBJECT, (VOID *) &test_byte_pool_objects[0], test_probe_name); + test_current_thread.tx_thread_module_instance_ptr = TX_NULL; + _tx_thread_current_ptr = &test_current_thread; + + test_result = TEST_RESULT_POISON; + test_expect("a caller that is not a module may look a block pool up by name", + (ULONG) _txm_module_manager_object_pointer_get_extended((UINT) TXM_BLOCK_POOL_OBJECT, test_probe_name, + ((UINT) 6), &test_result), + (ULONG) TX_SUCCESS); + test_expect("...and gets the block pool it named", + (ULONG) (test_result == (VOID *) &test_block_pool_objects[0]), (ULONG) TX_TRUE); + + test_result = TEST_RESULT_POISON; + test_expect("a caller that is not a module may look a byte pool up by name", + (ULONG) _txm_module_manager_object_pointer_get_extended((UINT) TXM_BYTE_POOL_OBJECT, test_probe_name, + ((UINT) 6), &test_result), + (ULONG) TX_SUCCESS); + test_expect("...and gets the byte pool it named", + (ULONG) (test_result == (VOID *) &test_byte_pool_objects[0]), (ULONG) TX_TRUE); + + /* An object with no name at all is on the list like any other, and the comparison has + to refuse it without dereferencing the null. */ + + test_arena_fill(); + test_lists_clear(); + memcpy((VOID *) test_probe_name, "target", (size_t) 7); + test_object_create((UINT) TXM_SEMAPHORE_OBJECT, (VOID *) &test_semaphore_objects[0], TX_NULL); + test_object_create((UINT) TXM_SEMAPHORE_OBJECT, (VOID *) &test_semaphore_objects[1], test_probe_name); + + name = (TEST_DATA_START + TEST_REGION_BYTES) - ((ULONG) 8); + memcpy((VOID *) name, "target", (size_t) 7); + + test_lookup_extended(&test_protected_module, (ALIGN_TYPE) TXM_SEMAPHORE_OBJECT, name, ((UINT) 6), TEST_EXTRA_PARAMETERS); + test_expect("an unnamed object on the list is passed over", (ULONG) test_return_value, (ULONG) TX_SUCCESS); + test_expect("...and the named one behind it is found", + (ULONG) (test_result == (VOID *) &test_semaphore_objects[1]), (ULONG) TX_TRUE); + + /**********************************************************************/ + /* The object the module was looking for is still found. */ + /**********************************************************************/ + + /* A name that fits, matching an object whose name is a string of that length, comes + back -- and the first match on the list is the one that comes back, which is the + property the probing cases above rely on. */ + + test_arena_fill(); + test_lists_clear(); + + name = (TEST_DATA_START + TEST_REGION_BYTES) - ((ULONG) 8); + memcpy((VOID *) name, "object", (size_t) 7); + memcpy((VOID *) test_probe_name, "object", (size_t) 7); + + test_object_create((UINT) TXM_SEMAPHORE_OBJECT, (VOID *) &test_decoy_semaphore, "objec"); + test_object_create((UINT) TXM_SEMAPHORE_OBJECT, (VOID *) &test_semaphore, test_probe_name); + + test_lookup_extended(&test_protected_module, (ALIGN_TYPE) TXM_SEMAPHORE_OBJECT, name, ((UINT) 6), TEST_EXTRA_PARAMETERS); + test_expect("a name that fits finds the object it names", (ULONG) test_return_value, (ULONG) TX_SUCCESS); + test_expect("...and it is the matching object, not the one whose name is a prefix of it", + (ULONG) (test_result == (VOID *) &test_semaphore), (ULONG) TX_TRUE); + + /* The same search declared one character short stops before the end of the name and + finds nothing, which is the comparison obeying the length rather than the string. */ + + test_lookup_extended(&test_protected_module, (ALIGN_TYPE) TXM_SEMAPHORE_OBJECT, name, ((UINT) 5), TEST_EXTRA_PARAMETERS); + test_expect("the same search one character short finds nothing", (ULONG) test_return_value, (ULONG) TX_NO_INSTANCE); + test_expect("...and leaves the module's result slot null", (ULONG) (test_result == TX_NULL), (ULONG) TX_TRUE); + + /**********************************************************************/ + /* A module without memory protection is unaffected. */ + /**********************************************************************/ + + /* Every check the fix touches is inside the dispatchers' memory protection block. A + module loaded without protection reaches the lookup with no range check of any kind, + before the fix and after it, and these cases are here so that a later change cannot + quietly start refusing its requests. */ + + for (length_index = ((UINT) 0); length_index < ((UINT) TEST_NAME_LENGTH_COUNT); length_index++) + { + name_length = test_name_lengths[length_index]; + + snprintf(description, sizeof(description), + "an unprotected module's %u-character name is accepted with one byte of room", name_length); + test_expect(description, + test_measure_validated_extent(&test_unprotected_module, TEST_DATA_START, name_length), + ((ULONG) 0)); + + snprintf(description, sizeof(description), + "an unprotected module's %u-character name is read to its declared end wherever it sits", name_length); + test_expect(description, + test_measure_read_depth(&test_unprotected_module, TEST_DATA_START, ((ULONG) 1), + name_length, ((ULONG) name_length) + ((ULONG) 2)), + (ULONG) name_length); + } + + test_arena_fill(); + test_lists_clear(); + test_lookup_extended(&test_unprotected_module, (ALIGN_TYPE) TXM_SEMAPHORE_OBJECT, TEST_DATA_START, + ((UINT) 31), (ALIGN_TYPE *) test_probe_name); + test_expect("an unprotected module's extra parameter array is accepted outside every region it owns", + (ULONG) test_accepted(), (ULONG) TX_TRUE); + + /**********************************************************************/ + /* What the whole run has to have held. */ + /**********************************************************************/ + + /* The lookup raises the preemption hold and lowers it again around every search, and + the port shim counts the interrupt lock it takes to do so. A search that returned + without giving either back is a fault path this test cannot take, and one that never + took them is a search that did not happen. */ + + test_expect("the interrupt lock is balanced", (ULONG) test_interrupt_disable_depth, ((ULONG) 0)); + test_expect("the interrupt lock never underflowed", (ULONG) test_interrupt_restore_underflows, ((ULONG) 0)); + test_expect("the interrupt lock was never nested", (ULONG) test_interrupt_disable_max_depth, ((ULONG) 1)); + test_expect("the preemption hold is balanced", (ULONG) _tx_thread_preempt_disable, ((ULONG) 0)); + + test_expect("every case ran", (ULONG) (test_checks > ((ULONG) 1000)), (ULONG) TX_TRUE); + + if (test_failures == 0U) + { + printf("SUCCESS! %lu expectations\n", (unsigned long) test_checks); + return(0); + } + + printf("ERROR: %u expectation(s) failed of %lu\n", test_failures, (unsigned long) test_checks); + return(1); +} From 5f9ebde847a94d54f0248fc8e77f2594425ed28a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 28 Sep 2026 11:07:09 -0400 Subject: [PATCH 159/181] Merge commit from fork A memory-protected module's queue request reaches the Module Manager's dispatch layer, which decides how much of the module's buffer the privileged queue copy may touch and hands that extent to the module port's range check. A queue's tx_queue_message_size is a count of ULONGs and the copy moves that many words, so the extent is message_size * sizeof(ULONG) bytes. Front-send passed the word count itself. Send and receive, either side of it in the same header, have always multiplied. So a source buffer ending message_size bytes into memory the module may reach was accepted, and _txe_queue_front_send then read message_size * sizeof(ULONG) bytes from it in privileged mode: 3 * message_size bytes past the end of what the module is allowed to read, which is 48 bytes at ThreadX's default message size limit and 96 at the limit this test tree builds with. The words land in the queue, and a module that can receive from that queue reads them back, so the over-read is disclosed rather than merely performed. Where the memory past the region is not mapped for the requesting module, the privileged read faults instead. The buffer cannot be aimed: it has to pass the same check to be accepted at all, so it is anchored to the end of a region the module can already read and the overrun is the fixed window immediately after it. That bounds what this reaches; it does not make it the module's business. The fix is the multiplication the other two services do, in the units the port check has always expected. It changes nothing for a module loaded without memory protection, because the check it corrects is inside the dispatcher's memory protection block, and the tests hold that. The regression test drives the three queue dispatchers directly, which nothing in the tree did before, and measures the extent each one validates rather than sampling either side of it: for a given message size it walks the room left between the buffer and the end of the module's region and finds the smallest amount the dispatcher accepts. That number is the extent. It has to be message_size * sizeof(ULONG) for all three services, in the module's data, in a shared region registered to it, and -- for the two services that read the buffer rather than write it -- in the module's read-only image, which is where a module sending a constant message sends it from. A receive destination in the read-only image is refused at every extent. Two things had to be arranged for a dispatcher to be testable on the host at all. The dispatch table is a header of static functions wrapped one per service in #ifndef TXM__CALL_NOT_USED, and at -O0 a compiler emits them all, so linking the whole table would mean standing up every kernel entry point it reaches. Defining the 93 guards the test does not exercise compiles the header down to the three queue services, which leaves four symbols to stub and exercises that conditional compilation, which nothing else in the tree does. The extent also has to reach a check that honours it, so the test takes its module port headers from a Cortex-M port, whose inline data check is the shape the memory-protected module ports share. The Cortex-A7 port's data check takes the pointer alone and translates a single address, so on that port no extent reaches anything and a test built on it would pass equally with and without this change. That is also the affected-port claim: the defect is in the portable dispatch layer and was live on every memory-protected module port that honours the size it is given, which is all of them except Cortex-A7, where the port's own check discarded the size before this one's error could matter. Assisted-by: Claude Code (Opus 5) --- .../inc/txm_module_manager_dispatch.h | 4 +- test/tx/cmake/module_manager/CMakeLists.txt | 20 + ..._module_manager_queue_message_range_test.c | 836 ++++++++++++++++++ 3 files changed, 859 insertions(+), 1 deletion(-) create mode 100644 test/tx/module_manager/threadx_module_manager_queue_message_range_test.c diff --git a/common_modules/module_manager/inc/txm_module_manager_dispatch.h b/common_modules/module_manager/inc/txm_module_manager_dispatch.h index 2233ec00f..2df1491b0 100644 --- a/common_modules/module_manager/inc/txm_module_manager_dispatch.h +++ b/common_modules/module_manager/inc/txm_module_manager_dispatch.h @@ -21,6 +21,8 @@ // Some portions generated by Claude Code (Opus 5). +// Some portions generated by Claude Code (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -1382,7 +1384,7 @@ TX_QUEUE *queue_ptr; /* We need to get the size of the message from the queue. */ queue_ptr = (TX_QUEUE *) param_0; - if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_READ(module_instance, param_1, queue_ptr -> tx_queue_message_size)) + if (!TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_READ(module_instance, param_1, sizeof(ULONG)*queue_ptr -> tx_queue_message_size)) return(TXM_MODULE_INVALID_MEMORY); } diff --git a/test/tx/cmake/module_manager/CMakeLists.txt b/test/tx/cmake/module_manager/CMakeLists.txt index f9830d44d..2ebd9684a 100644 --- a/test/tx/cmake/module_manager/CMakeLists.txt +++ b/test/tx/cmake/module_manager/CMakeLists.txt @@ -216,3 +216,23 @@ target_compile_options( add_test(${CMAKE_BUILD_TYPE}::threadx_module_manager_object_name_range_test threadx_module_manager_object_name_range_test) + +add_executable( + threadx_module_manager_queue_message_range_test + ${SOURCE_DIR}/threadx_module_manager_queue_message_range_test.c + ${module_manager_dir}/src/txm_module_manager_util.c) + +target_include_directories( + threadx_module_manager_queue_message_range_test + PRIVATE ${SOURCE_DIR} + ${REPO_ROOT}/common/inc + ${REPO_ROOT}/common_modules/inc + ${module_manager_dir}/inc + ${cortex_m4_module_dir}/inc) + +target_compile_options( + threadx_module_manager_queue_message_range_test + PRIVATE -include ${SOURCE_DIR}/threadx_module_manager_host_test_port.h) + +add_test(${CMAKE_BUILD_TYPE}::threadx_module_manager_queue_message_range_test + threadx_module_manager_queue_message_range_test) diff --git a/test/tx/module_manager/threadx_module_manager_queue_message_range_test.c b/test/tx/module_manager/threadx_module_manager_queue_message_range_test.c new file mode 100644 index 000000000..a4f55920f --- /dev/null +++ b/test/tx/module_manager/threadx_module_manager_queue_message_range_test.c @@ -0,0 +1,836 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Test */ +/** */ +/** Module Manager queue message range validation */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +/* A memory-protected module's queue request arrives at the Module Manager's dispatch + layer, which decides how much of the module's buffer the privileged queue copy is + allowed to touch and hands that extent to the port's range check. A queue's + tx_queue_message_size is a count of ULONGs, and the copy moves that many words, so + the extent is message_size * sizeof(ULONG) bytes. Front-send passed the word count + itself, which is a quarter of that on every target ThreadX supports, so a buffer + ending message_size bytes into the module's permitted memory was accepted and then + read message_size * sizeof(ULONG) bytes -- 3 * message_size bytes past the end of + what the module may reach. Send and receive have always multiplied. + + This test drives the three queue dispatchers directly and measures the extent each + one validates, rather than checking a handful of cases either side of it. For a + given message size it walks the number of bytes left between the buffer and the end + of the module's region and finds the smallest number the dispatcher accepts. That + number is the extent, and it must be message_size * sizeof(ULONG) for all three + services and for every region a queue buffer may legitimately live in. + + Two things make a dispatcher testable on the host at all. + + The dispatch table is a header of static functions, one per kernel service, each + wrapped in #ifndef TXM__CALL_NOT_USED so that an integrator can refuse a + service to modules. There are 96 of those guards. Defining the 93 this test does not + exercise compiles the header down to the three queue services under test, which is + what keeps the link to a handful of stubs instead of the hundred-odd kernel entry + points the whole table reaches. It also exercises that conditional compilation, + which nothing else in the tree does. + + The extent has to reach a check that honours it. The manager's portable checks do, + and so does the inline data check of the Cortex-M module ports, which is the shape + the memory-protected module ports share: an address range is inside the module's + data, or inside a shared memory region registered to it, or it is not accepted. This + test therefore compiles against a Cortex-M module port's headers. The Cortex-A7 + port's data check is a function that takes the pointer alone and translates one + address, so on that port no extent -- right or wrong -- reaches anything, and a test + built on it would pass equally before and after this fix. That check is being + corrected separately; the defect this test covers is in the portable dispatch layer + and was live on every other memory-protected module port. + + The three regions the cases below use are the three a queue buffer can be in. A read + source may be in the module's writable data, in a shared region, or in the module's + read-only image, since a module sending a constant message sends it out of its own + .rodata. A receive destination may not be in the read-only image, and the case that + asks for that must be refused however much room is left. */ + +#include +#include + +#include "threadx_module_manager_host_test_port.h" + +#include "tx_thread.h" +#include "tx_timer.h" +#include "tx_queue.h" +#include "tx_event_flags.h" +#include "tx_semaphore.h" +#include "tx_mutex.h" +#include "tx_block_pool.h" +#include "tx_byte_pool.h" +#include "txm_module.h" +#include "txm_module_manager_util.h" + + +/* Refuse every service in the dispatch table except the three under test. The list is + the header's own guard names; a service added to the table appears here as a link + error naming the kernel entry point it reaches, which is the right way to find out. */ + +#define TXM_BLOCK_ALLOCATE_CALL_NOT_USED +#define TXM_BLOCK_POOL_CREATE_CALL_NOT_USED +#define TXM_BLOCK_POOL_DELETE_CALL_NOT_USED +#define TXM_BLOCK_POOL_INFO_GET_CALL_NOT_USED +#define TXM_BLOCK_POOL_PERFORMANCE_INFO_GET_CALL_NOT_USED +#define TXM_BLOCK_POOL_PERFORMANCE_SYSTEM_INFO_GET_CALL_NOT_USED +#define TXM_BLOCK_POOL_PRIORITIZE_CALL_NOT_USED +#define TXM_BLOCK_RELEASE_CALL_NOT_USED +#define TXM_BYTE_ALLOCATE_CALL_NOT_USED +#define TXM_BYTE_POOL_CREATE_CALL_NOT_USED +#define TXM_BYTE_POOL_DELETE_CALL_NOT_USED +#define TXM_BYTE_POOL_INFO_GET_CALL_NOT_USED +#define TXM_BYTE_POOL_PERFORMANCE_INFO_GET_CALL_NOT_USED +#define TXM_BYTE_POOL_PERFORMANCE_SYSTEM_INFO_GET_CALL_NOT_USED +#define TXM_BYTE_POOL_PRIORITIZE_CALL_NOT_USED +#define TXM_BYTE_RELEASE_CALL_NOT_USED +#define TXM_EVENT_FLAGS_CREATE_CALL_NOT_USED +#define TXM_EVENT_FLAGS_DELETE_CALL_NOT_USED +#define TXM_EVENT_FLAGS_GET_CALL_NOT_USED +#define TXM_EVENT_FLAGS_INFO_GET_CALL_NOT_USED +#define TXM_EVENT_FLAGS_PERFORMANCE_INFO_GET_CALL_NOT_USED +#define TXM_EVENT_FLAGS_PERFORMANCE_SYSTEM_INFO_GET_CALL_NOT_USED +#define TXM_EVENT_FLAGS_SET_CALL_NOT_USED +#define TXM_EVENT_FLAGS_SET_NOTIFY_CALL_NOT_USED +#define TXM_MUTEX_CREATE_CALL_NOT_USED +#define TXM_MUTEX_DELETE_CALL_NOT_USED +#define TXM_MUTEX_GET_CALL_NOT_USED +#define TXM_MUTEX_INFO_GET_CALL_NOT_USED +#define TXM_MUTEX_PERFORMANCE_INFO_GET_CALL_NOT_USED +#define TXM_MUTEX_PERFORMANCE_SYSTEM_INFO_GET_CALL_NOT_USED +#define TXM_MUTEX_PRIORITIZE_CALL_NOT_USED +#define TXM_MUTEX_PUT_CALL_NOT_USED +#define TXM_QUEUE_CREATE_CALL_NOT_USED +#define TXM_QUEUE_DELETE_CALL_NOT_USED +#define TXM_QUEUE_FLUSH_CALL_NOT_USED +#define TXM_QUEUE_INFO_GET_CALL_NOT_USED +#define TXM_QUEUE_PERFORMANCE_INFO_GET_CALL_NOT_USED +#define TXM_QUEUE_PERFORMANCE_SYSTEM_INFO_GET_CALL_NOT_USED +#define TXM_QUEUE_PRIORITIZE_CALL_NOT_USED +#define TXM_QUEUE_SEND_NOTIFY_CALL_NOT_USED +#define TXM_SEMAPHORE_CEILING_PUT_CALL_NOT_USED +#define TXM_SEMAPHORE_CREATE_CALL_NOT_USED +#define TXM_SEMAPHORE_DELETE_CALL_NOT_USED +#define TXM_SEMAPHORE_GET_CALL_NOT_USED +#define TXM_SEMAPHORE_INFO_GET_CALL_NOT_USED +#define TXM_SEMAPHORE_PERFORMANCE_INFO_GET_CALL_NOT_USED +#define TXM_SEMAPHORE_PERFORMANCE_SYSTEM_INFO_GET_CALL_NOT_USED +#define TXM_SEMAPHORE_PRIORITIZE_CALL_NOT_USED +#define TXM_SEMAPHORE_PUT_CALL_NOT_USED +#define TXM_SEMAPHORE_PUT_NOTIFY_CALL_NOT_USED +#define TXM_THREAD_CREATE_CALL_NOT_USED +#define TXM_THREAD_DELETE_CALL_NOT_USED +#define TXM_THREAD_ENTRY_EXIT_NOTIFY_CALL_NOT_USED +#define TXM_THREAD_IDENTIFY_CALL_NOT_USED +#define TXM_THREAD_INFO_GET_CALL_NOT_USED +#define TXM_THREAD_INTERRUPT_CONTROL_CALL_NOT_USED +#define TXM_THREAD_PERFORMANCE_INFO_GET_CALL_NOT_USED +#define TXM_THREAD_PERFORMANCE_SYSTEM_INFO_GET_CALL_NOT_USED +#define TXM_THREAD_PREEMPTION_CHANGE_CALL_NOT_USED +#define TXM_THREAD_PRIORITY_CHANGE_CALL_NOT_USED +#define TXM_THREAD_RELINQUISH_CALL_NOT_USED +#define TXM_THREAD_RESET_CALL_NOT_USED +#define TXM_THREAD_RESUME_CALL_NOT_USED +#define TXM_THREAD_SLEEP_CALL_NOT_USED +#define TXM_THREAD_STACK_ERROR_NOTIFY_CALL_NOT_USED +#define TXM_THREAD_SUSPEND_CALL_NOT_USED +#define TXM_THREAD_SYSTEM_SUSPEND_CALL_NOT_USED +#define TXM_THREAD_TERMINATE_CALL_NOT_USED +#define TXM_THREAD_TIME_SLICE_CHANGE_CALL_NOT_USED +#define TXM_THREAD_WAIT_ABORT_CALL_NOT_USED +#define TXM_TIME_GET_CALL_NOT_USED +#define TXM_TIME_SET_CALL_NOT_USED +#define TXM_TIMER_ACTIVATE_CALL_NOT_USED +#define TXM_TIMER_CHANGE_CALL_NOT_USED +#define TXM_TIMER_CREATE_CALL_NOT_USED +#define TXM_TIMER_DEACTIVATE_CALL_NOT_USED +#define TXM_TIMER_DELETE_CALL_NOT_USED +#define TXM_TIMER_INFO_GET_CALL_NOT_USED +#define TXM_TIMER_PERFORMANCE_INFO_GET_CALL_NOT_USED +#define TXM_TIMER_PERFORMANCE_SYSTEM_INFO_GET_CALL_NOT_USED +#define TXM_TRACE_BUFFER_FULL_NOTIFY_CALL_NOT_USED +#define TXM_TRACE_DISABLE_CALL_NOT_USED +#define TXM_TRACE_ENABLE_CALL_NOT_USED +#define TXM_TRACE_EVENT_FILTER_CALL_NOT_USED +#define TXM_TRACE_EVENT_UNFILTER_CALL_NOT_USED +#define TXM_TRACE_INTERRUPT_CONTROL_CALL_NOT_USED +#define TXM_TRACE_ISR_ENTER_INSERT_CALL_NOT_USED +#define TXM_TRACE_ISR_EXIT_INSERT_CALL_NOT_USED +#define TXM_TRACE_USER_EVENT_INSERT_CALL_NOT_USED +#define TXM_MODULE_OBJECT_ALLOCATE_CALL_NOT_USED +#define TXM_MODULE_OBJECT_DEALLOCATE_CALL_NOT_USED +#define TXM_MODULE_OBJECT_POINTER_GET_CALL_NOT_USED +#define TXM_MODULE_OBJECT_POINTER_GET_EXTENDED_CALL_NOT_USED + +#include "txm_module_manager_dispatch.h" + +/* The three under test have to have survived that, and the rest have to have gone. */ + +#if defined(TXM_QUEUE_FRONT_SEND_CALL_NOT_USED) || defined(TXM_QUEUE_SEND_CALL_NOT_USED) || defined(TXM_QUEUE_RECEIVE_CALL_NOT_USED) +#error "the queue services under test must be compiled in" +#endif + +#ifndef TXM_QUEUE_FLUSH_CALL_NOT_USED +#error "the services this test does not exercise must be compiled out" +#endif + + +/* Define the stand-in interrupt lock the port shim counts through. */ + +unsigned int test_interrupt_disable_depth; +unsigned int test_interrupt_disable_max_depth; +unsigned int test_interrupt_restore_underflows; + + +/* Define the manager state the utility source under test links against. The object + pool plays no part in a queue request: the object check these dispatchers run asks + only that the queue lie outside the module. */ + +TX_BYTE_POOL _txm_module_manager_object_pool; +UINT _txm_module_manager_object_pool_created; + + +/* The kernel's created lists. A created object lives on the list for its type, and + the manager reads those lists, so a test that stands in for the kernel has to + provide them. All stay empty here, because this test creates no kernel object; it + exercises the range a queue request hands the port's buffer check. */ + +TX_BLOCK_POOL *_tx_block_pool_created_ptr; +ULONG _tx_block_pool_created_count; +TX_BYTE_POOL *_tx_byte_pool_created_ptr; +ULONG _tx_byte_pool_created_count; +TX_EVENT_FLAGS_GROUP *_tx_event_flags_created_ptr; +ULONG _tx_event_flags_created_count; +TX_MUTEX *_tx_mutex_created_ptr; +ULONG _tx_mutex_created_count; +TX_QUEUE *_tx_queue_created_ptr; +ULONG _tx_queue_created_count; +TX_SEMAPHORE *_tx_semaphore_created_ptr; +ULONG _tx_semaphore_created_count; +TX_THREAD *_tx_thread_created_ptr; +ULONG _tx_thread_created_count; +TX_TIMER *_tx_timer_created_ptr; +ULONG _tx_timer_created_count; + + +/* Stand in for the module port's load-time alignment adjustment, which the utility + source declares and no case here reaches. */ + +VOID _txm_module_manager_alignment_adjust(TXM_MODULE_PREAMBLE *module_preamble, ULONG *code_size, + ULONG *code_alignment, ULONG *data_size, ULONG *data_alignment) +{ + (VOID) module_preamble; + (VOID) code_size; + (VOID) code_alignment; + (VOID) data_size; + (VOID) data_alignment; +} + + +static UINT test_failures; +static ULONG test_checks; + + +/* Record the outcome of one expectation. */ +static VOID test_expect(const char *description, ULONG actual, ULONG expected) +{ + test_checks++; + + if (actual != expected) + { + printf("FAIL: %s (expected %lu, got %lu)\n", description, (unsigned long) expected, (unsigned long) actual); + test_failures++; + } +} + + +/* Model the module's memory as one arena, so that the three regions a queue buffer may + legitimately live in have known addresses and known gaps between them. The gaps are + memory the module may not reach: they are what a buffer anchored to the end of a + region overruns into, and they are inside the arena so that the overrun a case + describes is memory this test owns. */ + +#define TEST_REGION_BYTES ((ULONG) 256) +#define TEST_GAP_BYTES ((ULONG) 64) + +static union +{ + ALIGN_TYPE test_arena_alignment; + UCHAR test_arena_bytes[(((ULONG) 3) * TEST_REGION_BYTES) + (((ULONG) 4) * TEST_GAP_BYTES)]; +} test_arena; + +#define TEST_DATA_START (&test_arena.test_arena_bytes[TEST_GAP_BYTES]) +#define TEST_CODE_START (&test_arena.test_arena_bytes[(((ULONG) 2) * TEST_GAP_BYTES) + TEST_REGION_BYTES]) +#define TEST_SHARED_START (&test_arena.test_arena_bytes[(((ULONG) 3) * TEST_GAP_BYTES) + (((ULONG) 2) * TEST_REGION_BYTES)]) + + +/* Define the queue the requests name. It is outside the arena, which is what the + object check requires of a kernel object a module uses. */ + +static TX_QUEUE test_queue; + + +/* Define the requesting modules. One has memory protection, and is the one every + range case below drives; the other does not, and is how the cases show that the + dispatch layer's buffer checks are not reached for it at all. */ + +static TXM_MODULE_INSTANCE test_protected_module; +static TXM_MODULE_INSTANCE test_unprotected_module; + + +/* Place a module's regions on the arena. */ +static VOID test_module_setup(TXM_MODULE_INSTANCE *module_instance, ULONG property_flags) +{ + memset((VOID *) module_instance, 0, sizeof(TXM_MODULE_INSTANCE)); + + module_instance -> txm_module_instance_property_flags = property_flags; + + module_instance -> txm_module_instance_data_start = (VOID *) TEST_DATA_START; + module_instance -> txm_module_instance_data_end = (VOID *) (TEST_DATA_START + (TEST_REGION_BYTES - ((ULONG) 1))); + + module_instance -> txm_module_instance_code_start = (VOID *) TEST_CODE_START; + module_instance -> txm_module_instance_code_end = (VOID *) (TEST_CODE_START + (TEST_REGION_BYTES - ((ULONG) 1))); + + module_instance -> txm_module_instance_shared_memory_address = (ULONG) TEST_SHARED_START; + module_instance -> txm_module_instance_shared_memory_length = TEST_REGION_BYTES; +} + + +/* Record what the privileged queue services were handed. + + Whether the service was reached at all is half of every expectation below: a refusal + that still calls the service has refused nothing, and it is the service that reads or + writes the caller's buffer. */ + +static ULONG test_service_calls; +static ALIGN_TYPE test_service_queue_ptr; +static ALIGN_TYPE test_service_buffer_ptr; +static ULONG test_service_wait_option; + + +/* Stand in for the three privileged queue services. + + They keep the two checks the real ones make before they touch the caller's buffer: a + queue pointer that is null or carries the wrong ID is refused with TX_QUEUE_ERROR, + and a null buffer pointer is refused with TX_PTR_ERROR. The second one matters here. + The dispatch layer's buffer checks accept a null buffer pointer -- passing one is how + a module asks for an optional output it does not want -- and for these three services + nothing is optional, so it is the service's own null check that keeps the extent + question from arising at all. A case below drives that. */ + +static UINT test_service_record(TX_QUEUE *queue_ptr, VOID *buffer_ptr, ULONG wait_option) +{ + +UINT status; + + + test_service_calls++; + test_service_queue_ptr = (ALIGN_TYPE) queue_ptr; + test_service_buffer_ptr = (ALIGN_TYPE) buffer_ptr; + test_service_wait_option = wait_option; + + if (queue_ptr == TX_NULL) + { + status = TX_QUEUE_ERROR; + } + else if (queue_ptr -> tx_queue_id != TX_QUEUE_ID) + { + status = TX_QUEUE_ERROR; + } + else if (buffer_ptr == TX_NULL) + { + status = TX_PTR_ERROR; + } + else + { + status = TX_SUCCESS; + } + + return(status); +} + + +UINT _txe_queue_front_send(TX_QUEUE *queue_ptr, VOID *source_ptr, ULONG wait_option) +{ + return(test_service_record(queue_ptr, source_ptr, wait_option)); +} + + +UINT _txe_queue_send(TX_QUEUE *queue_ptr, VOID *source_ptr, ULONG wait_option) +{ + return(test_service_record(queue_ptr, source_ptr, wait_option)); +} + + +UINT _txe_queue_receive(TX_QUEUE *queue_ptr, VOID *destination_ptr, ULONG wait_option) +{ + return(test_service_record(queue_ptr, destination_ptr, wait_option)); +} + + +/* Name the three services under test. */ + +#define TEST_SERVICE_FRONT_SEND ((UINT) 0) +#define TEST_SERVICE_SEND ((UINT) 1) +#define TEST_SERVICE_RECEIVE ((UINT) 2) +#define TEST_SERVICE_COUNT ((UINT) 3) + +static const char *test_service_names[TEST_SERVICE_COUNT] = +{ + "front-send", + "send", + "receive" +}; + +#define TEST_WAIT_OPTION ((ALIGN_TYPE) 27) + + +/* Make one request of one dispatcher, resetting the record of the service behind it + first so that a caller can tell a refusal from an acceptance. */ +static ALIGN_TYPE test_dispatch(UINT service, TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE queue_ptr, ALIGN_TYPE buffer_ptr) +{ + +ALIGN_TYPE return_value; + + + test_service_calls = ((ULONG) 0); + test_service_queue_ptr = ((ALIGN_TYPE) 0); + test_service_buffer_ptr = ((ALIGN_TYPE) 0); + test_service_wait_option = ((ULONG) 0); + + if (service == TEST_SERVICE_FRONT_SEND) + { + return_value = _txm_module_manager_tx_queue_front_send_dispatch(module_instance, queue_ptr, buffer_ptr, TEST_WAIT_OPTION); + } + else if (service == TEST_SERVICE_SEND) + { + return_value = _txm_module_manager_tx_queue_send_dispatch(module_instance, queue_ptr, buffer_ptr, TEST_WAIT_OPTION); + } + else + { + return_value = _txm_module_manager_tx_queue_receive_dispatch(module_instance, queue_ptr, buffer_ptr, TEST_WAIT_OPTION); + } + + return(return_value); +} + + +/* Report whether one request was accepted, checking as it goes that acceptance and + refusal are each consistent: a refused request returns TXM_MODULE_INVALID_MEMORY and + does not reach the service, and an accepted one reaches it exactly once and is given + the caller's own arguments. */ +static UINT test_accepted(UINT service, TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE queue_ptr, ALIGN_TYPE buffer_ptr) +{ + +ALIGN_TYPE return_value; +UINT accepted; + + + return_value = test_dispatch(service, module_instance, queue_ptr, buffer_ptr); + + if (test_service_calls == ((ULONG) 0)) + { + accepted = TX_FALSE; + + test_expect("a refused request returns TXM_MODULE_INVALID_MEMORY", + (ULONG) return_value, (ULONG) TXM_MODULE_INVALID_MEMORY); + } + else + { + accepted = TX_TRUE; + + test_expect("an accepted request reaches the service once", test_service_calls, ((ULONG) 1)); + test_expect("...with the queue the caller named", (ULONG) test_service_queue_ptr, (ULONG) queue_ptr); + test_expect("...the buffer the caller supplied", (ULONG) test_service_buffer_ptr, (ULONG) buffer_ptr); + test_expect("...and the wait option the caller chose", test_service_wait_option, (ULONG) TEST_WAIT_OPTION); + } + + return(accepted); +} + + +/* Measure the extent a dispatcher validates. + + The buffer is anchored to the end of one of the module's regions and walked backwards + into it a byte at a time, so that the room left between the buffer and the end of the + region grows by one on each step. The smallest amount of room the dispatcher accepts + is the extent it validated. TEST_NOT_ACCEPTED means it accepted nothing within the + region, which is the right answer for a service that may not use that region at all. */ + +#define TEST_NOT_ACCEPTED ((ULONG) 0xFFFFFFFF) + +static ULONG test_measure_extent(UINT service, TXM_MODULE_INSTANCE *module_instance, ULONG message_size, UCHAR *region_start) +{ + +ULONG room; +ULONG walk_limit; +ULONG extent; +UCHAR *region_end_plus_one; + + + test_queue.tx_queue_message_size = message_size; + + region_end_plus_one = region_start + TEST_REGION_BYTES; + + /* Walking past the extent send and receive validate is enough to establish that + nothing validates more than they do. */ + walk_limit = (message_size * ((ULONG) sizeof(ULONG))) + ((ULONG) sizeof(ULONG)); + + extent = TEST_NOT_ACCEPTED; + + for (room = ((ULONG) 0); room <= walk_limit; room++) + { + if (test_accepted(service, module_instance, (ALIGN_TYPE) &test_queue, + (ALIGN_TYPE) (region_end_plus_one - room)) == TX_TRUE) + { + extent = room; + break; + } + } + + return(extent); +} + + +/* Define a buffer outside every region the module owns, for the cases about a module + that has no memory protection and is therefore range-checked nowhere. */ + +static ULONG test_outside_buffer[TX_QUEUE_MESSAGE_MAX_SIZE]; + + +/* The message sizes the cases run through. One word is the smallest a queue can carry + and the case where the wrong extent is smallest; the configured maximum is the case + where it is largest. TX_QUEUE_MESSAGE_MAX_SIZE is what an integrator sets, so the + largest case follows the build rather than a number written here. */ + +static const ULONG test_message_sizes[] = +{ + ((ULONG) 1), + ((ULONG) 2), + ((ULONG) 3), + ((ULONG) TX_QUEUE_MESSAGE_MAX_SIZE) +}; + +#define TEST_MESSAGE_SIZE_COUNT (sizeof(test_message_sizes) / sizeof(test_message_sizes[0])) + + +int main(void) +{ + +UINT service; +UINT size_index; +ULONG message_size; +ULONG expected_extent; +ALIGN_TYPE return_value; +UCHAR *buffer_ptr; +TX_QUEUE saved_queue; +char description[160]; + + + memset((VOID *) &test_arena, 0, sizeof(test_arena)); + + memset((VOID *) &test_queue, 0, sizeof(test_queue)); + test_queue.tx_queue_id = TX_QUEUE_ID; + + /* Put the queue on the kernel's created list. The dispatchers authenticate the + object a module names against that list before they validate anything about + the buffer, so a queue that is not on it is refused before the range check + this test is about is ever reached. */ + test_queue.tx_queue_created_next = &test_queue; + _tx_queue_created_ptr = &test_queue; + _tx_queue_created_count = ((ULONG) 1); + + test_module_setup(&test_protected_module, (ULONG) TXM_MODULE_MEMORY_PROTECTION); + test_module_setup(&test_unprotected_module, ((ULONG) 0)); + + printf("Module Manager queue message range validation test\n"); + + /**********************************************************************/ + /* The extent each service validates. */ + /**********************************************************************/ + + /* A queue's message size is a count of ULONGs and the copy moves that many words, + so the extent every one of the three services must validate is the message size + times the width of a word -- in the module's data, in a shared region registered + to it, and, for the two services that read the buffer, in the module's read-only + image. */ + + for (size_index = ((UINT) 0); size_index < ((UINT) TEST_MESSAGE_SIZE_COUNT); size_index++) + { + message_size = test_message_sizes[size_index]; + expected_extent = message_size * ((ULONG) sizeof(ULONG)); + + for (service = ((UINT) 0); service < TEST_SERVICE_COUNT; service++) + { + snprintf(description, sizeof(description), + "%s validates %lu * sizeof(ULONG) bytes of a buffer in the module's data", + test_service_names[service], (unsigned long) message_size); + test_expect(description, + test_measure_extent(service, &test_protected_module, message_size, TEST_DATA_START), + expected_extent); + + snprintf(description, sizeof(description), + "%s validates %lu * sizeof(ULONG) bytes of a buffer in a shared region", + test_service_names[service], (unsigned long) message_size); + test_expect(description, + test_measure_extent(service, &test_protected_module, message_size, TEST_SHARED_START), + expected_extent); + } + + /* A module sending a constant message sends it out of its own read-only image, + which a read source may be in and a receive destination may not. */ + + snprintf(description, sizeof(description), + "front-send validates %lu * sizeof(ULONG) bytes of a source in the module's read-only image", + (unsigned long) message_size); + test_expect(description, + test_measure_extent(TEST_SERVICE_FRONT_SEND, &test_protected_module, message_size, TEST_CODE_START), + expected_extent); + + snprintf(description, sizeof(description), + "send validates %lu * sizeof(ULONG) bytes of a source in the module's read-only image", + (unsigned long) message_size); + test_expect(description, + test_measure_extent(TEST_SERVICE_SEND, &test_protected_module, message_size, TEST_CODE_START), + expected_extent); + + snprintf(description, sizeof(description), + "receive refuses a destination in the module's read-only image at any extent (%lu words)", + (unsigned long) message_size); + test_expect(description, + test_measure_extent(TEST_SERVICE_RECEIVE, &test_protected_module, message_size, TEST_CODE_START), + TEST_NOT_ACCEPTED); + } + + /**********************************************************************/ + /* The word count is not the byte count. */ + /**********************************************************************/ + + /* The same statement as the measurements above, made once at the anchor point the + defect turned on: a buffer with exactly as many bytes left as the message has + words. Front-send accepted that and then read four times as far. */ + + for (size_index = ((UINT) 0); size_index < ((UINT) TEST_MESSAGE_SIZE_COUNT); size_index++) + { + message_size = test_message_sizes[size_index]; + test_queue.tx_queue_message_size = message_size; + + for (service = ((UINT) 0); service < TEST_SERVICE_COUNT; service++) + { + buffer_ptr = (TEST_DATA_START + TEST_REGION_BYTES) - message_size; + + snprintf(description, sizeof(description), + "%s refuses a %lu-word message given room for the word count in bytes", + test_service_names[service], (unsigned long) message_size); + test_expect(description, + (ULONG) test_accepted(service, &test_protected_module, (ALIGN_TYPE) &test_queue, (ALIGN_TYPE) buffer_ptr), + (ULONG) TX_FALSE); + + buffer_ptr = (TEST_DATA_START + TEST_REGION_BYTES) - ((message_size * ((ULONG) sizeof(ULONG))) - ((ULONG) 1)); + + snprintf(description, sizeof(description), + "%s refuses a buffer one byte short of the whole message", test_service_names[service]); + test_expect(description, + (ULONG) test_accepted(service, &test_protected_module, (ALIGN_TYPE) &test_queue, (ALIGN_TYPE) buffer_ptr), + (ULONG) TX_FALSE); + + buffer_ptr = (TEST_DATA_START + TEST_REGION_BYTES) - (message_size * ((ULONG) sizeof(ULONG))); + + snprintf(description, sizeof(description), + "%s accepts a buffer that reaches exactly the end of the region", test_service_names[service]); + test_expect(description, + (ULONG) test_accepted(service, &test_protected_module, (ALIGN_TYPE) &test_queue, (ALIGN_TYPE) buffer_ptr), + (ULONG) TX_TRUE); + } + } + + /**********************************************************************/ + /* A refusal changes nothing. */ + /**********************************************************************/ + + test_queue.tx_queue_message_size = (ULONG) TX_QUEUE_MESSAGE_MAX_SIZE; + memcpy((VOID *) &saved_queue, (VOID *) &test_queue, sizeof(TX_QUEUE)); + + buffer_ptr = (TEST_DATA_START + TEST_REGION_BYTES) - test_queue.tx_queue_message_size; + + for (service = ((UINT) 0); service < TEST_SERVICE_COUNT; service++) + { + return_value = test_dispatch(service, &test_protected_module, (ALIGN_TYPE) &test_queue, (ALIGN_TYPE) buffer_ptr); + + snprintf(description, sizeof(description), "%s refuses with TXM_MODULE_INVALID_MEMORY", test_service_names[service]); + test_expect(description, (ULONG) return_value, (ULONG) TXM_MODULE_INVALID_MEMORY); + + snprintf(description, sizeof(description), "...%s does not reach the queue service", test_service_names[service]); + test_expect(description, test_service_calls, ((ULONG) 0)); + + snprintf(description, sizeof(description), "...and %s leaves the queue control block untouched", test_service_names[service]); + test_expect(description, + (ULONG) (memcmp((VOID *) &saved_queue, (VOID *) &test_queue, sizeof(TX_QUEUE)) == 0), + (ULONG) TX_TRUE); + } + + /**********************************************************************/ + /* The queue itself still has to be a kernel object outside the module.*/ + /**********************************************************************/ + + /* The message size is read out of the queue, so the extent check depends on the + object check having run first. A buffer with all the room in the world does not + excuse a queue pointer aimed into the module or at nothing at all. */ + + buffer_ptr = TEST_DATA_START; + + for (service = ((UINT) 0); service < TEST_SERVICE_COUNT; service++) + { + snprintf(description, sizeof(description), "%s refuses a queue inside the module's data", test_service_names[service]); + test_expect(description, + (ULONG) test_accepted(service, &test_protected_module, (ALIGN_TYPE) TEST_DATA_START, (ALIGN_TYPE) buffer_ptr), + (ULONG) TX_FALSE); + + snprintf(description, sizeof(description), "%s refuses a queue inside the module's read-only image", test_service_names[service]); + test_expect(description, + (ULONG) test_accepted(service, &test_protected_module, (ALIGN_TYPE) TEST_CODE_START, (ALIGN_TYPE) buffer_ptr), + (ULONG) TX_FALSE); + + snprintf(description, sizeof(description), "%s refuses a null queue", test_service_names[service]); + test_expect(description, + (ULONG) test_accepted(service, &test_protected_module, ((ALIGN_TYPE) 0), (ALIGN_TYPE) buffer_ptr), + (ULONG) TX_FALSE); + } + + /**********************************************************************/ + /* The null buffer the dispatch layer lets through. */ + /**********************************************************************/ + + /* The dispatch layer's buffer checks accept a null pointer whatever extent they are + given, so correcting the extent cannot be what refuses one. For these three + services the buffer is not optional and the service refuses it itself, which is + why the extent question never arises for a null buffer. */ + + test_queue.tx_queue_message_size = (ULONG) TX_QUEUE_MESSAGE_MAX_SIZE; + + for (service = ((UINT) 0); service < TEST_SERVICE_COUNT; service++) + { + return_value = test_dispatch(service, &test_protected_module, (ALIGN_TYPE) &test_queue, ((ALIGN_TYPE) 0)); + + snprintf(description, sizeof(description), "%s passes a null buffer to the queue service", test_service_names[service]); + test_expect(description, test_service_calls, ((ULONG) 1)); + + snprintf(description, sizeof(description), "...and the %s service refuses it with TX_PTR_ERROR", test_service_names[service]); + test_expect(description, (ULONG) return_value, (ULONG) TX_PTR_ERROR); + } + + /**********************************************************************/ + /* A buffer whose extent runs off the end of the address space. */ + /**********************************************************************/ + + /* The manager's checks test for that before comparing anything, so a module cannot + reach past the top of memory by wrapping the sum. */ + + test_queue.tx_queue_message_size = (ULONG) TX_QUEUE_MESSAGE_MAX_SIZE; + + for (service = ((UINT) 0); service < TEST_SERVICE_COUNT; service++) + { + snprintf(description, sizeof(description), "%s refuses a buffer whose extent wraps the address space", test_service_names[service]); + test_expect(description, + (ULONG) test_accepted(service, &test_protected_module, (ALIGN_TYPE) &test_queue, + (ALIGN_TYPE) (~((ALIGN_TYPE) 0) - ((ALIGN_TYPE) 3))), + (ULONG) TX_FALSE); + } + + /**********************************************************************/ + /* A module without memory protection is unaffected. */ + /**********************************************************************/ + + /* Every check the fix touches sits inside the dispatchers' memory-protection block. + A module that was loaded without protection reaches the kernel service with no + range check of any kind, before the fix and after it, and these cases are here so + that a later change to the extent cannot quietly start refusing its requests. */ + + for (size_index = ((UINT) 0); size_index < ((UINT) TEST_MESSAGE_SIZE_COUNT); size_index++) + { + message_size = test_message_sizes[size_index]; + test_queue.tx_queue_message_size = message_size; + + for (service = ((UINT) 0); service < TEST_SERVICE_COUNT; service++) + { + buffer_ptr = (TEST_DATA_START + TEST_REGION_BYTES) - message_size; + + snprintf(description, sizeof(description), + "an unprotected module's %lu-word %s is accepted with room for the word count in bytes", + (unsigned long) message_size, test_service_names[service]); + test_expect(description, + (ULONG) test_accepted(service, &test_unprotected_module, (ALIGN_TYPE) &test_queue, (ALIGN_TYPE) buffer_ptr), + (ULONG) TX_TRUE); + + snprintf(description, sizeof(description), + "an unprotected module's %s is accepted with a buffer outside every region it owns", + test_service_names[service]); + test_expect(description, + (ULONG) test_accepted(service, &test_unprotected_module, (ALIGN_TYPE) &test_queue, (ALIGN_TYPE) test_outside_buffer), + (ULONG) TX_TRUE); + + snprintf(description, sizeof(description), + "an unprotected module's %s is accepted with a queue inside its own data", + test_service_names[service]); + test_expect(description, + (ULONG) test_accepted(service, &test_unprotected_module, (ALIGN_TYPE) TEST_DATA_START, (ALIGN_TYPE) test_outside_buffer), + (ULONG) TX_TRUE); + + /* Nothing screens an unprotected module's arguments before the service, so + the service is where a null queue is refused. It is the same for a null + buffer, and for a protected module the object check is what refuses the + queue first -- which is why these two cases are here and not above. */ + return_value = test_dispatch(service, &test_unprotected_module, ((ALIGN_TYPE) 0), (ALIGN_TYPE) test_outside_buffer); + + snprintf(description, sizeof(description), + "an unprotected module's %s reaches the service with a null queue", + test_service_names[service]); + test_expect(description, test_service_calls, ((ULONG) 1)); + + snprintf(description, sizeof(description), + "...and the %s service refuses it with TX_QUEUE_ERROR", test_service_names[service]); + test_expect(description, (ULONG) return_value, (ULONG) TX_QUEUE_ERROR); + } + } + + /**********************************************************************/ + /* What the whole run has to have held. */ + /**********************************************************************/ + + /* Nothing on these paths disables interrupts, and the shim counts them, so the + lock has to have been left exactly as it was found. */ + test_expect("the interrupt lock is balanced", test_interrupt_disable_depth, ((ULONG) 0)); + test_expect("the interrupt lock never underflowed", (ULONG) test_interrupt_restore_underflows, ((ULONG) 0)); + + test_expect("every case ran", (ULONG) (test_checks > ((ULONG) 500)), (ULONG) TX_TRUE); + + if (test_failures == 0U) + { + printf("SUCCESS! %lu expectations\n", (unsigned long) test_checks); + return(0); + } + + printf("ERROR: %u expectation(s) failed of %lu\n", test_failures, (unsigned long) test_checks); + return(1); +} From a9bd72de21ab5554dba77f3c61f9756af7b6070c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 28 Sep 2026 11:31:41 -0400 Subject: [PATCH 160/181] Merge commit from fork * Fixed the Cortex-A7 module data check to validate whole ranges The Cortex-A7 module port received a module instance, a start address and a byte size from the common Module Manager, then discarded the instance and the size and asked the MMU to translate the start address alone, for reading only. A range was therefore accepted whenever its first byte happened to be readable by the module, so privileged dispatch code could read or write past the end of the module's mapping, or use read-only module code as a write destination. The check now takes the size and an access intent. The module's own data region is answered from the manager's records, which name it exactly and cost no translations; everything else is answered by translating every page the range touches with the requested unprivileged access. Empty ranges, ranges whose last byte would wrap, and ranges that leave the recorded data region partway through are all refused, and the walk is bounded by TXM_MODULE_MANAGER_DATA_CHECK_MAX_PAGES so one module request cannot impose unbounded work on the kernel. Translation is only believed while the requesting module's own context is loaded. The outside direction gets its own check rather than negating the inside one: a range that reaches into the module only partway is inside neither answer, and negating a whole-range check would have let it pass as a kernel object. Other ports keep their single data check through backward-compatible fallbacks in the common header; their preprocessed dispatch output is byte-identical. Regression coverage runs on the host by standing a simulated page map behind the one architecture primitive, and reaches 100% line, branch and call coverage of the new logic. Twenty-four of its expectations fail against the previous implementation. Assisted-by: Claude Code (Opus 5) * Drove the Cortex-A7 range check through a live MMU The host test for this check stands a simulated page map behind the port's CP15 primitive, so it never executes an address translation. That leaves the part most easily got wrong unexercised: an encoding naming the wrong operation, or a PAR fault bit read the wrong way round, passes it without complaint. This adds a bare-metal image that builds a short-descriptor translation table, enables the MMU, and drives the real check through the real translations on a real Cortex-A7 translation regime, plus a script that builds and runs it under an emulator. Sections are mapped for unprivileged read/write, unprivileged read only, and privileged only, with an unmapped section behind the read-only one so that a range can be made to leave its mapping partway through. That last case is the one the replaced check accepted, and the test asserts both answers against the same live MMU: the current check rejects the range, and translating only its first address accepts it. It also confirms what the simulated map could only assume, that ATS1CUW denies a write to a read-only mapping while ATS1CUR allows the read. The write intent is the reason the port asks for two translations rather than one. The script skips with a notice when the cross toolchain or the emulator is absent, so a machine without them does not fail the build. Assisted-by: Claude Code (Opus 5) --- .../inc/txm_module_manager_util.h | 32 +- .../ac5/example_build/build_threadx.bat | 3 +- .../cortex_a7/ac5/inc/txm_module_port.h | 44 +- .../txm_module_manager_inside_data_check.c | 538 ++++++++++++++++++ .../txm_module_manager_mm_register_setup.c | 115 +++- .../gnu/example_build/build_threadx.bat | 3 +- .../cortex_a7/gnu/inc/txm_module_port.h | 44 +- .../txm_module_manager_inside_data_check.c | 538 ++++++++++++++++++ .../txm_module_manager_mm_register_setup.c | 115 +++- .../cortex_a7/iar/example_build/tx.ewp | 3 + .../cortex_a7/iar/inc/txm_module_port.h | 44 +- .../txm_module_manager_inside_data_check.c | 538 ++++++++++++++++++ .../txm_module_manager_mm_register_setup.c | 115 +++- scripts/check_module_mmu_a7.sh | 120 ++++ test/tx/cmake/module_manager/CMakeLists.txt | 16 + ...hreadx_module_manager_cortex_a7_mmu_test.c | 205 +++++++ ...odule_manager_cortex_a7_range_check_test.c | 443 ++++++++++++++ ...adx_module_manager_delete_ownership_test.c | 43 +- ...le_manager_live_object_deallocation_test.c | 43 +- ...le_manager_object_allocate_overflow_test.c | 18 +- ...odule_manager_object_authentication_test.c | 43 +- ..._module_manager_thread_kernel_stack_test.c | 19 +- 22 files changed, 3023 insertions(+), 59 deletions(-) create mode 100644 ports_module/cortex_a7/ac5/module_manager/src/txm_module_manager_inside_data_check.c create mode 100644 ports_module/cortex_a7/gnu/module_manager/src/txm_module_manager_inside_data_check.c create mode 100644 ports_module/cortex_a7/iar/module_manager/src/txm_module_manager_inside_data_check.c create mode 100755 scripts/check_module_mmu_a7.sh create mode 100644 test/tx/module_manager/threadx_module_manager_cortex_a7_mmu_test.c create mode 100644 test/tx/module_manager/threadx_module_manager_cortex_a7_range_check_test.c diff --git a/common_modules/module_manager/inc/txm_module_manager_util.h b/common_modules/module_manager/inc/txm_module_manager_util.h index 92bb55dd9..7feb0f3e8 100644 --- a/common_modules/module_manager/inc/txm_module_manager_util.h +++ b/common_modules/module_manager/inc/txm_module_manager_util.h @@ -45,8 +45,32 @@ /* Define check macros for modules. */ +/* A port supplies TXM_MODULE_MANAGER_CHECK_INSIDE_DATA to decide whether a caller-supplied + range lies inside the module's writable data or shared memory. Ports whose check can tell + a read-only region from a writable one also supply the two intent-specific variants below. + Ports that cannot make the distinction inherit their single check for both intents, so + their behaviour is unchanged. */ + +#ifndef TXM_MODULE_MANAGER_CHECK_INSIDE_DATA_READ +#define TXM_MODULE_MANAGER_CHECK_INSIDE_DATA_READ(module_instance, obj_ptr, obj_size) \ + TXM_MODULE_MANAGER_CHECK_INSIDE_DATA(module_instance, obj_ptr, obj_size) +#endif + +#ifndef TXM_MODULE_MANAGER_CHECK_INSIDE_DATA_WRITE +#define TXM_MODULE_MANAGER_CHECK_INSIDE_DATA_WRITE(module_instance, obj_ptr, obj_size) \ + TXM_MODULE_MANAGER_CHECK_INSIDE_DATA(module_instance, obj_ptr, obj_size) +#endif + +/* A range is outside the module's data only when no part of it is reachable by the module. + The read intent is used here because it describes the widest set of reachable addresses. + A port whose inside check cannot prove the whole range at once must supply its own + definition, because negating a partial-range check would report a partly reachable range + as being outside the module. */ + +#ifndef TXM_MODULE_MANAGER_CHECK_OUTSIDE_DATA #define TXM_MODULE_MANAGER_CHECK_OUTSIDE_DATA(module_instance, obj_ptr, obj_size) \ - (!(TXM_MODULE_MANAGER_CHECK_INSIDE_DATA(module_instance, obj_ptr, obj_size))) + (!(TXM_MODULE_MANAGER_CHECK_INSIDE_DATA_READ(module_instance, obj_ptr, obj_size))) +#endif #define TXM_MODULE_MANAGER_CHECK_INSIDE_CODE(module_instance, obj_ptr, obj_size) \ (((obj_ptr) < ((obj_ptr) + (obj_size))) && \ @@ -65,12 +89,14 @@ /* Define macros for module. */ +/* The module reads from these ranges, so a read-only region is acceptable. */ #define TXM_MODULE_MANAGER_ENSURE_INSIDE_MODULE(module_instance, obj_ptr, obj_size) \ - (TXM_MODULE_MANAGER_CHECK_INSIDE_DATA(module_instance, obj_ptr, obj_size) || \ + (TXM_MODULE_MANAGER_CHECK_INSIDE_DATA_READ(module_instance, obj_ptr, obj_size) || \ TXM_MODULE_MANAGER_CHECK_INSIDE_CODE(module_instance, obj_ptr, obj_size)) +/* The kernel writes to these ranges, so the module must be able to write them too. */ #define TXM_MODULE_MANAGER_ENSURE_INSIDE_MODULE_DATA(module_instance, obj_ptr, obj_size) \ - TXM_MODULE_MANAGER_CHECK_INSIDE_DATA(module_instance, obj_ptr, obj_size) + TXM_MODULE_MANAGER_CHECK_INSIDE_DATA_WRITE(module_instance, obj_ptr, obj_size) #define TXM_MODULE_MANAGER_ENSURE_OUTSIDE_MODULE(module_instance, obj_ptr, obj_size) \ (TXM_MODULE_MANAGER_CHECK_OUTSIDE_DATA(module_instance, obj_ptr, obj_size) && \ diff --git a/ports_module/cortex_a7/ac5/example_build/build_threadx.bat b/ports_module/cortex_a7/ac5/example_build/build_threadx.bat index ea349e371..764992f00 100644 --- a/ports_module/cortex_a7/ac5/example_build/build_threadx.bat +++ b/ports_module/cortex_a7/ac5/example_build/build_threadx.bat @@ -223,6 +223,7 @@ armcc -g -O0 --cpu=cortex-a7.no_neon --fpu=softvfp -c -I../inc -I../../../../com armcc -g -O0 --cpu=cortex-a7.no_neon --fpu=softvfp -c -I../inc -I../../../../common/inc -I../../../../common_modules/inc -I../../../../common_modules/module_manager/inc ../../../../common_modules/module_manager/src/txm_module_manager_properties_get.c armcc -g -O0 --cpu=cortex-a7.no_neon --fpu=softvfp -c -I../inc -I../../../../common/inc -I../../../../common_modules/inc -I../../../../common_modules/module_manager/inc ../../../../common_modules/module_manager/src/txm_module_manager_queue_notify_trampoline.c armcc -g -O0 --cpu=cortex-a7.no_neon --fpu=softvfp -c -I../inc -I../../../../common/inc -I../../../../common_modules/inc -I../../../../common_modules/module_manager/inc ../../../../common_modules/module_manager/src/txm_module_manager_semaphore_notify_trampoline.c +armcc -g -O0 --cpu=cortex-a7.no_neon --fpu=softvfp -c -I../inc -I../../../../common/inc -I../../../../common_modules/inc -I../../../../common_modules/module_manager/inc ../module_manager/src/txm_module_manager_inside_data_check.c armcc -g -O0 --cpu=cortex-a7.no_neon --fpu=softvfp -c -I../inc -I../../../../common/inc -I../../../../common_modules/inc -I../../../../common_modules/module_manager/inc ../module_manager/src/txm_module_manager_mm_register_setup.c armcc -g -O0 --cpu=cortex-a7.no_neon --fpu=softvfp -c -I../inc -I../../../../common/inc -I../../../../common_modules/inc -I../../../../common_modules/module_manager/inc ../../../../common_modules/module_manager/src/txm_module_manager_start.c armcc -g -O0 --cpu=cortex-a7.no_neon --fpu=softvfp -c -I../inc -I../../../../common/inc -I../../../../common_modules/inc -I../../../../common_modules/module_manager/inc ../../../../common_modules/module_manager/src/txm_module_manager_stop.c @@ -278,7 +279,7 @@ armar -r tx.a txm_module_manager_in_place_load.o txm_module_manager_initialize.o armar -r tx.a txm_module_manager_kernel_dispatch.o txm_module_manager_maximum_module_priority_set.o txm_module_manager_memory_fault_handler.o armar -r tx.a txm_module_manager_memory_fault_notify.o txm_module_manager_memory_load.o txm_module_manager_object_pointer_get.o armar -r tx.a txm_module_manager_object_pool_create.o txm_module_manager_queue_notify_trampoline.o txm_module_manager_semaphore_notify_trampoline.o -armar -r tx.a txm_module_manager_mm_register_setup.o txm_module_manager_start.o txm_module_manager_stop.o +armar -r tx.a txm_module_manager_inside_data_check.o txm_module_manager_mm_register_setup.o txm_module_manager_start.o txm_module_manager_stop.o armar -r tx.a txm_module_manager_thread_create.o txm_module_manager_thread_notify_trampoline.o txm_module_manager_thread_reset.o armar -r tx.a txm_module_manager_timer_notify_trampoline.o txm_module_manager_unload.o txm_module_manager_thread_stack_build.o armar -r tx.a txm_module_manager_user_mode_entry.o diff --git a/ports_module/cortex_a7/ac5/inc/txm_module_port.h b/ports_module/cortex_a7/ac5/inc/txm_module_port.h index 1102a377b..126be1e82 100644 --- a/ports_module/cortex_a7/ac5/inc/txm_module_port.h +++ b/ports_module/cortex_a7/ac5/inc/txm_module_port.h @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Claude Code (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -240,6 +242,22 @@ The following extensions must also be defined in tx_port.h: #define TXM_ADDRESS_TRANSLATION_FAULT_BIT 1 +/* Mask selecting the ASID field of CONTEXTIDR in the short-descriptor format. */ +#define TXM_CONTEXTIDR_ASID_MASK 0x000000FF + +/* Access intents understood by the module data range check. */ +#define TXM_MODULE_MANAGER_ACCESS_READ 0 +#define TXM_MODULE_MANAGER_ACCESS_WRITE 1 + +/* Define the largest number of MMU pages a single caller-supplied range may span before + the data range check rejects it. This bounds the worst-case, module-controlled cost of + validating one kernel request, which keeps the check deterministic. The default permits + a 4 MB range. Applications that hand larger shared-memory ranges to kernel services can + define a larger value. */ +#ifndef TXM_MODULE_MANAGER_DATA_CHECK_MAX_PAGES +#define TXM_MODULE_MANAGER_DATA_CHECK_MAX_PAGES 1024 +#endif + #define TXM_ASID_RESERVED 0xFFFFFFFF #define TXM_MODULE_ASID_ERROR 0xF6 @@ -375,9 +393,26 @@ typedef struct TXM_MODULE_MANAGER_MEMORY_FAULT_INFO_STRUCT /* Define the macros to perform port-specific checks when passing pointers to the kernel. */ -/* Define macro to make sure object is inside the module's data or shared memory. */ +/* Define macros to make sure a whole object is inside the module's data or shared memory. + The MMU is the authority for shared and external memory, so the check translates every + page the range touches with the requested unprivileged access. Passing the size and the + access intent through is what keeps the check honest: translating only the first address, + and only for reading, would accept a range that leaves the module's mapping partway + through, or a read-only range used as a kernel write destination. */ +#define TXM_MODULE_MANAGER_CHECK_INSIDE_DATA_READ(module_instance, obj_ptr, obj_size) \ + _txm_module_manager_inside_data_check(module_instance, (ALIGN_TYPE) (obj_ptr), (ULONG) (obj_size), TXM_MODULE_MANAGER_ACCESS_READ) + +#define TXM_MODULE_MANAGER_CHECK_INSIDE_DATA_WRITE(module_instance, obj_ptr, obj_size) \ + _txm_module_manager_inside_data_check(module_instance, (ALIGN_TYPE) (obj_ptr), (ULONG) (obj_size), TXM_MODULE_MANAGER_ACCESS_WRITE) + +/* The unqualified check keeps its historical name and takes the stricter write intent. */ #define TXM_MODULE_MANAGER_CHECK_INSIDE_DATA(module_instance, obj_ptr, obj_size) \ - _txm_module_manager_inside_data_check((ULONG) obj_ptr) + TXM_MODULE_MANAGER_CHECK_INSIDE_DATA_WRITE(module_instance, obj_ptr, obj_size) + +/* Negating the inside check would report a range that only partly reaches into the module + as being outside it, so the outside direction gets its own check. */ +#define TXM_MODULE_MANAGER_CHECK_OUTSIDE_DATA(module_instance, obj_ptr, obj_size) \ + _txm_module_manager_outside_data_check(module_instance, (ALIGN_TYPE) (obj_ptr), (ULONG) (obj_size)) /* Define some internal prototypes to this module port. */ @@ -397,7 +432,10 @@ UINT _txm_module_manager_mm_initialize(VOID); VOID _txm_module_manager_mm_register_setup(TXM_MODULE_INSTANCE *module_instance); \ VOID _txm_level2_page_clear(TXM_MODULE_INSTANCE *module_instance); \ VOID _txm_module_manager_remove_asid(TXM_MODULE_INSTANCE *module_instance); \ -UINT _txm_module_manager_inside_data_check(ULONG pointer); +UINT _txm_module_manager_inside_data_check(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE obj_ptr, ULONG obj_size, UINT write_request); \ +UINT _txm_module_manager_outside_data_check(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE obj_ptr, ULONG obj_size); \ +UINT _txm_module_manager_address_probe(ULONG address, UINT write_request); \ +ULONG _txm_module_manager_current_asid_get(VOID); #define TXM_MODULE_MANAGER_VERSION_ID \ CHAR _txm_module_manager_version_id[] = \ diff --git a/ports_module/cortex_a7/ac5/module_manager/src/txm_module_manager_inside_data_check.c b/ports_module/cortex_a7/ac5/module_manager/src/txm_module_manager_inside_data_check.c new file mode 100644 index 000000000..e7ebf262b --- /dev/null +++ b/ports_module/cortex_a7/ac5/module_manager/src/txm_module_manager_inside_data_check.c @@ -0,0 +1,538 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Module Manager */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + +#include "tx_api.h" +#include "txm_module.h" + + +/* Define the ways a caller-supplied range can sit relative to the module's data region. */ + +#define TXM_MODULE_DATA_WINDOW_OUTSIDE 0 /* No byte touches the data mapping. */ +#define TXM_MODULE_DATA_WINDOW_CONTAINED 1 /* Every byte is recorded module data. */ +#define TXM_MODULE_DATA_WINDOW_PARTIAL 2 /* Some, but not all, bytes are. */ + + +/* Define the page mask derived from the smallest MMU page this port maps. */ + +#define TXM_MODULE_PAGE_OFFSET_MASK ((ALIGN_TYPE) (TXM_MODULE_MEMORY_ALIGNMENT - 1)) +#define TXM_MODULE_PAGE_BASE_MASK (~TXM_MODULE_PAGE_OFFSET_MASK) + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txm_module_manager_range_end_get Cortex-A7/MMU/AC5 */ +/* 6.5.0 */ +/* AUTHOR */ +/* */ +/* Eclipse ThreadX contributors */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function derives the inclusive address of the last byte of a */ +/* caller-supplied range. An empty range is rejected, matching the */ +/* portable check macros, and so is a range whose last byte is not */ +/* representable, so that no caller ever works from a wrapped address. */ +/* */ +/* INPUT */ +/* */ +/* obj_ptr Address of the first byte */ +/* obj_size Size of the range in bytes */ +/* last_byte Destination for the last address */ +/* */ +/* OUTPUT */ +/* */ +/* TX_TRUE if the range is non-empty and does not wrap */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _txm_module_manager_inside_data_check */ +/* _txm_module_manager_outside_data_check */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 08-24-2026 Eclipse ThreadX Initial Version 6.5.0 */ +/* contributors */ +/* */ +/**************************************************************************/ +static UINT _txm_module_manager_range_end_get(ALIGN_TYPE obj_ptr, ULONG obj_size, ALIGN_TYPE *last_byte) +{ + +ALIGN_TYPE span; +ALIGN_TYPE highest; +UINT status; + + + /* Assume the range cannot be used until proven otherwise. */ + status = TX_FALSE; + + /* An empty range has no last byte and is rejected, just as the portable macros do. */ + if (obj_size != ((ULONG) 0)) + { + + /* Work with the inclusive span so that a range reaching the top of the address + space stays representable. */ + span = ((ALIGN_TYPE) obj_size) - ((ALIGN_TYPE) 1); + + /* Determine the highest first byte this span can start from. */ + highest = (~((ALIGN_TYPE) 0)) - span; + + /* Determine if the range would run past the end of the address space. */ + if (obj_ptr <= highest) + { + + /* Record the last byte of the range. */ + *last_byte = obj_ptr + span; + + /* The range is usable. */ + status = TX_TRUE; + } + } + + /* Return the completion status. */ + return(status); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txm_module_manager_data_window_classify Cortex-A7/MMU/AC5 */ +/* 6.5.0 */ +/* AUTHOR */ +/* */ +/* Eclipse ThreadX contributors */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function reports how a range sits relative to the module's own */ +/* data region. The module manager records that region exactly, while */ +/* the MMU can only map it a page at a time, so the mapping may reach */ +/* past the recorded end. The recorded region therefore stays the */ +/* authority for the whole mapped window: a range that leaves the */ +/* recorded region but still lands in the window is reported as */ +/* partial, and its caller rejects it rather than asking the MMU, */ +/* which would accept the rounding slack. */ +/* */ +/* INPUT */ +/* */ +/* module_instance Pointer to module instance */ +/* first_byte Address of the first byte */ +/* last_byte Address of the last byte */ +/* */ +/* OUTPUT */ +/* */ +/* One of the TXM_MODULE_DATA_WINDOW_* classifications */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _txm_module_manager_inside_data_check */ +/* _txm_module_manager_outside_data_check */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 08-24-2026 Eclipse ThreadX Initial Version 6.5.0 */ +/* contributors */ +/* */ +/**************************************************************************/ +static UINT _txm_module_manager_data_window_classify(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE first_byte, ALIGN_TYPE last_byte) +{ + +ALIGN_TYPE data_start; +ALIGN_TYPE data_end; +ALIGN_TYPE window_start; +ALIGN_TYPE window_end; +UINT window; + + + /* Pick up the recorded data region. The end address is inclusive. */ + data_start = (ALIGN_TYPE) module_instance -> txm_module_instance_data_start; + data_end = (ALIGN_TYPE) module_instance -> txm_module_instance_data_end; + + /* Determine if the module has a usable data region at all. */ + if (data_start > data_end) + { + + /* An unset or inverted region owns nothing. */ + window = TXM_MODULE_DATA_WINDOW_OUTSIDE; + } + else + { + + /* Widen the region to the pages the MMU actually maps for it. */ + window_start = data_start & TXM_MODULE_PAGE_BASE_MASK; + window_end = data_end | TXM_MODULE_PAGE_OFFSET_MASK; + + /* Determine if every byte is recorded module data. */ + if ((first_byte >= data_start) && (last_byte <= data_end)) + { + + /* The whole range belongs to the module. */ + window = TXM_MODULE_DATA_WINDOW_CONTAINED; + } + else if ((first_byte <= window_end) && (last_byte >= window_start)) + { + + /* The range overlaps the mapped window without being contained by the + recorded region, so it leaves the module's data partway through. */ + window = TXM_MODULE_DATA_WINDOW_PARTIAL; + } + else + { + + /* The range lies elsewhere, so only the MMU can speak for it. */ + window = TXM_MODULE_DATA_WINDOW_OUTSIDE; + } + } + + /* Return the classification. */ + return(window); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txm_module_manager_page_walk Cortex-A7/MMU/AC5 */ +/* 6.5.0 */ +/* AUTHOR */ +/* */ +/* Eclipse ThreadX contributors */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function translates every page a range touches and reports */ +/* whether all of them answered as expected. The walk stops at the */ +/* first page that disagrees, and a range spanning more pages than */ +/* the configured maximum is refused so that one kernel request can */ +/* never impose unbounded work. */ +/* */ +/* INPUT */ +/* */ +/* first_byte Address of the first byte */ +/* last_byte Address of the last byte */ +/* write_request Access intent to translate for */ +/* expected Result every page must return */ +/* */ +/* OUTPUT */ +/* */ +/* TX_TRUE if every page answered as expected */ +/* */ +/* CALLS */ +/* */ +/* _txm_module_manager_address_probe */ +/* */ +/* CALLED BY */ +/* */ +/* _txm_module_manager_inside_data_check */ +/* _txm_module_manager_outside_data_check */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 08-24-2026 Eclipse ThreadX Initial Version 6.5.0 */ +/* contributors */ +/* */ +/**************************************************************************/ +static UINT _txm_module_manager_page_walk(ALIGN_TYPE first_byte, ALIGN_TYPE last_byte, UINT write_request, UINT expected) +{ + +ALIGN_TYPE first_page; +ALIGN_TYPE last_page; +ALIGN_TYPE page; +ULONG pages; +ULONG index; +UINT matched; + + + /* Reduce the range to the pages it touches. */ + first_page = first_byte & TXM_MODULE_PAGE_BASE_MASK; + last_page = last_byte & TXM_MODULE_PAGE_BASE_MASK; + + /* Count them. Both addresses are page-aligned, so the division is exact. */ + pages = ((ULONG) ((last_page - first_page) / ((ALIGN_TYPE) TXM_MODULE_MEMORY_ALIGNMENT))) + ((ULONG) 1); + + /* Determine if the range is longer than this port is willing to translate. */ + if (pages > ((ULONG) TXM_MODULE_MANAGER_DATA_CHECK_MAX_PAGES)) + { + + /* Refuse rather than spend unbounded time in a kernel request. Refusing is safe + for both callers: neither can then claim the range is inside or outside. */ + matched = TX_FALSE; + } + else + { + + /* Assume every page agrees until one does not. */ + matched = TX_TRUE; + index = (ULONG) 0; + + /* Translate each page in turn, stopping as soon as the answer is settled. The + address is rebuilt from the index so that the walk cannot wrap past the top + page of the address space. */ + while ((index < pages) && (matched == TX_TRUE)) + { + + /* Build the address of this page. */ + page = first_page + (((ALIGN_TYPE) index) * ((ALIGN_TYPE) TXM_MODULE_MEMORY_ALIGNMENT)); + + /* Ask the MMU whether the module may reach this page with the requested access. */ + if (_txm_module_manager_address_probe((ULONG) page, write_request) != expected) + { + + /* This page disagrees, so the range as a whole does. */ + matched = TX_FALSE; + } + + /* Move to the next page. */ + index++; + } + } + + /* Return whether the whole range answered as expected. */ + return(matched); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txm_module_manager_inside_data_check Cortex-A7/MMU/AC5 */ +/* 6.5.0 */ +/* AUTHOR */ +/* */ +/* Eclipse ThreadX contributors */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function determines whether every byte of a caller-supplied */ +/* range lies inside the module's data or shared memory and is */ +/* reachable by the module with the requested access. The module's own */ +/* data region is answered from the manager's own records, which are */ +/* exact. Anything else is answered by translating every page the */ +/* range touches, because this port keeps no record of the shared and */ +/* external regions the application maps into the module. */ +/* */ +/* INPUT */ +/* */ +/* module_instance Pointer to module instance */ +/* obj_ptr Address of the first byte */ +/* obj_size Size of the range in bytes */ +/* write_request TXM_MODULE_MANAGER_ACCESS_READ or */ +/* TXM_MODULE_MANAGER_ACCESS_WRITE */ +/* */ +/* OUTPUT */ +/* */ +/* TX_TRUE if the whole range is reachable with that access */ +/* */ +/* CALLS */ +/* */ +/* _txm_module_manager_range_end_get */ +/* _txm_module_manager_current_asid_get */ +/* _txm_module_manager_data_window_classify */ +/* _txm_module_manager_page_walk */ +/* */ +/* CALLED BY */ +/* */ +/* TXM_MODULE_MANAGER_CHECK_INSIDE_DATA_READ */ +/* TXM_MODULE_MANAGER_CHECK_INSIDE_DATA_WRITE */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 08-24-2026 Eclipse ThreadX Initial Version 6.5.0 */ +/* contributors */ +/* */ +/**************************************************************************/ +UINT _txm_module_manager_inside_data_check(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE obj_ptr, ULONG obj_size, UINT write_request) +{ + +ALIGN_TYPE last_byte; +UINT window; +UINT status; + + + /* Assume the range is not usable until every condition is met. */ + status = TX_FALSE; + + /* A range can only belong to a module that exists. */ + if (module_instance != TX_NULL) + { + + /* Determine the last byte, rejecting empty and wrapping ranges. */ + if (_txm_module_manager_range_end_get(obj_ptr, obj_size, &last_byte) == TX_TRUE) + { + + /* Address translation answers for whichever context is loaded, so it can only + be trusted while the requesting module's context is the loaded one. */ + if (_txm_module_manager_current_asid_get() == (module_instance -> txm_module_instance_asid)) + { + + /* Place the range relative to the module's own data region. */ + window = _txm_module_manager_data_window_classify(module_instance, obj_ptr, last_byte); + + if (window == ((UINT) TXM_MODULE_DATA_WINDOW_CONTAINED)) + { + + /* The module's data region is mapped for unprivileged reading and + writing, so both intents are satisfied without translating. */ + status = TX_TRUE; + } + else if (window == ((UINT) TXM_MODULE_DATA_WINDOW_OUTSIDE)) + { + + /* Shared or external memory: every page must grant the access. */ + status = _txm_module_manager_page_walk(obj_ptr, last_byte, write_request, TX_TRUE); + } + else + { + + /* The range leaves the module's data partway through. */ + status = TX_FALSE; + } + } + } + } + + /* Return the completion status. */ + return(status); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txm_module_manager_outside_data_check Cortex-A7/MMU/AC5 */ +/* 6.5.0 */ +/* AUTHOR */ +/* */ +/* Eclipse ThreadX contributors */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function determines whether no byte of a caller-supplied range */ +/* is reachable by the module. It is deliberately not the negation of */ +/* the inside check: a range that reaches into the module's memory */ +/* only partway is inside neither answer, and reporting it as outside */ +/* would let it pass as a kernel object. */ +/* */ +/* INPUT */ +/* */ +/* module_instance Pointer to module instance */ +/* obj_ptr Address of the first byte */ +/* obj_size Size of the range in bytes */ +/* */ +/* OUTPUT */ +/* */ +/* TX_TRUE if no byte of the range is reachable by the module */ +/* */ +/* CALLS */ +/* */ +/* _txm_module_manager_range_end_get */ +/* _txm_module_manager_current_asid_get */ +/* _txm_module_manager_data_window_classify */ +/* _txm_module_manager_page_walk */ +/* */ +/* CALLED BY */ +/* */ +/* TXM_MODULE_MANAGER_CHECK_OUTSIDE_DATA */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 08-24-2026 Eclipse ThreadX Initial Version 6.5.0 */ +/* contributors */ +/* */ +/**************************************************************************/ +UINT _txm_module_manager_outside_data_check(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE obj_ptr, ULONG obj_size) +{ + +ALIGN_TYPE last_byte; +UINT window; +UINT status; + + + /* Assume the range is not provably outside the module. */ + status = TX_FALSE; + + /* A range can only be placed against a module that exists. */ + if (module_instance != TX_NULL) + { + + /* Determine the last byte, rejecting empty and wrapping ranges. */ + if (_txm_module_manager_range_end_get(obj_ptr, obj_size, &last_byte) == TX_TRUE) + { + + /* Address translation answers for whichever context is loaded, so it can only + be trusted while the requesting module's context is the loaded one. */ + if (_txm_module_manager_current_asid_get() == (module_instance -> txm_module_instance_asid)) + { + + /* Place the range relative to the module's own data region. */ + window = _txm_module_manager_data_window_classify(module_instance, obj_ptr, last_byte); + + if (window == ((UINT) TXM_MODULE_DATA_WINDOW_OUTSIDE)) + { + + /* Clear of the module's data region, so the remaining question is + whether any page of it is shared or external memory. */ + status = _txm_module_manager_page_walk(obj_ptr, last_byte, TXM_MODULE_MANAGER_ACCESS_READ, TX_FALSE); + } + else + { + + /* The range touches the module's data region. */ + status = TX_FALSE; + } + } + } + } + + /* Return the completion status. */ + return(status); +} diff --git a/ports_module/cortex_a7/ac5/module_manager/src/txm_module_manager_mm_register_setup.c b/ports_module/cortex_a7/ac5/module_manager/src/txm_module_manager_mm_register_setup.c index bdaa548dd..a86cfbe49 100644 --- a/ports_module/cortex_a7/ac5/module_manager/src/txm_module_manager_mm_register_setup.c +++ b/ports_module/cortex_a7/ac5/module_manager/src/txm_module_manager_mm_register_setup.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Claude Code (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -35,24 +37,34 @@ extern ULONG _txm_ttbr1_page_table[TXM_MAXIMUM_MODULES][TXM_MASTER_PAGE_TABLE_EN /* */ /* FUNCTION RELEASE */ /* */ -/* _txm_module_manager_inside_data_check Cortex-A7/MMU/AC5 */ -/* 6.1 */ +/* _txm_module_manager_address_probe Cortex-A7/MMU/AC5 */ +/* 6.5.0 */ /* AUTHOR */ /* */ /* Scott Larson, Microsoft Corporation */ +/* Eclipse ThreadX contributors */ /* */ /* DESCRIPTION */ /* */ -/* This function determines if pointer is within the module's data or */ -/* shared memory. */ +/* This function asks the MMU whether unprivileged code running in the */ +/* currently loaded translation context may reach one address with the */ +/* requested access. Reading and writing are asked separately, because */ +/* a module's code and its read-only shared memory translate for */ +/* reading while a kernel service writing to them would fault or, */ +/* worse, succeed from privileged mode. */ +/* */ +/* This answers for one address only. Callers that hold a range must */ +/* ask about every page the range touches. */ /* */ /* INPUT */ /* */ -/* pointer Data pointer */ +/* address Address to translate */ +/* write_request TXM_MODULE_MANAGER_ACCESS_READ or */ +/* TXM_MODULE_MANAGER_ACCESS_WRITE */ /* */ /* OUTPUT */ /* */ -/* Completion Status */ +/* TX_TRUE if the translation granted the requested access */ /* */ /* CALLS */ /* */ @@ -60,17 +72,40 @@ extern ULONG _txm_ttbr1_page_table[TXM_MAXIMUM_MODULES][TXM_MASTER_PAGE_TABLE_EN /* */ /* CALLED BY */ /* */ -/* TXM_MODULE_MANAGER_DATA_POINTER_CHECK */ +/* _txm_module_manager_page_walk */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 03-08-2023 Scott Larson Initial Version 6.2.1 */ +/* 08-24-2026 Eclipse ThreadX Added the write intent and */ +/* contributors moved range handling to */ +/* the caller, resulting in */ +/* version 6.5.0 */ /* */ /**************************************************************************/ -UINT _txm_module_manager_inside_data_check(ULONG pointer) +UINT _txm_module_manager_address_probe(ULONG address, UINT write_request) { -ULONG translation; +ULONG translation; + + + /* Determine which unprivileged access the caller needs. */ + if (write_request == ((UINT) TXM_MODULE_MANAGER_ACCESS_WRITE)) + { + + /* ATS1CUW operation on address supplied in address, Stage 1 unprivileged write. */ + __asm("MCR p15, 0, address, c7, c8, 3"); + } + else + { + + /* ATS1CUR operation on address supplied in address, Stage 1 unprivileged read. */ + __asm("MCR p15, 0, address, c7, c8, 2"); + } - /* ATS1CUR operation on address supplied in pointer, Stage 1 unprivileged read. */ - __asm("MCR p15, 0, pointer, c7, c8, 2"); - __asm("ISB"); /* Ensure completion of the MCR write to CP15. */ + __asm("ISB"); /* Ensure completion of the MCR write to CP15. */ __asm("MRC p15, 0, translation, c7, c4, 0"); /* Read result from 32-bit PAR into translation. */ if (translation & TXM_ADDRESS_TRANSLATION_FAULT_BIT) @@ -82,6 +117,62 @@ ULONG translation; } +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txm_module_manager_current_asid_get Cortex-A7/MMU/AC5 */ +/* 6.5.0 */ +/* AUTHOR */ +/* */ +/* Eclipse ThreadX contributors */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns the ASID of the translation context that is */ +/* currently loaded. Address translation always answers for that */ +/* context, so a caller validating a pointer on behalf of a module */ +/* must confirm that the loaded context is that module's before it */ +/* believes the answer. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* ASID of the currently loaded translation context */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _txm_module_manager_inside_data_check */ +/* _txm_module_manager_outside_data_check */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 08-24-2026 Eclipse ThreadX Initial Version 6.5.0 */ +/* contributors */ +/* */ +/**************************************************************************/ +ULONG _txm_module_manager_current_asid_get(VOID) +{ + +ULONG contextidr; + + + /* Read CONTEXTIDR, whose low byte holds the ASID in the short-descriptor format. */ + __asm("MRC p15, 0, contextidr, c13, c0, 1"); + + return(contextidr & TXM_CONTEXTIDR_ASID_MASK); +} + + /**************************************************************************/ /* */ /* FUNCTION RELEASE */ diff --git a/ports_module/cortex_a7/gnu/example_build/build_threadx.bat b/ports_module/cortex_a7/gnu/example_build/build_threadx.bat index 0e094b386..3e6875874 100644 --- a/ports_module/cortex_a7/gnu/example_build/build_threadx.bat +++ b/ports_module/cortex_a7/gnu/example_build/build_threadx.bat @@ -223,6 +223,7 @@ arm-none-eabi-gcc -c -g -O0 -mcpu=cortex-a7 -mfloat-abi=hard -mfpu=neon-vfpv4 -m arm-none-eabi-gcc -c -g -O0 -mcpu=cortex-a7 -mfloat-abi=hard -mfpu=neon-vfpv4 -marm -mthumb-interwork -DTX_ENABLE_VFP_SUPPORT -I../inc -I../../../../common/inc -I../../../../common_modules/inc -I../../../../common_modules/module_manager/inc ../../../../common_modules/module_manager/src/txm_module_manager_properties_get.c arm-none-eabi-gcc -c -g -O0 -mcpu=cortex-a7 -mfloat-abi=hard -mfpu=neon-vfpv4 -marm -mthumb-interwork -DTX_ENABLE_VFP_SUPPORT -I../inc -I../../../../common/inc -I../../../../common_modules/inc -I../../../../common_modules/module_manager/inc ../../../../common_modules/module_manager/src/txm_module_manager_queue_notify_trampoline.c arm-none-eabi-gcc -c -g -O0 -mcpu=cortex-a7 -mfloat-abi=hard -mfpu=neon-vfpv4 -marm -mthumb-interwork -DTX_ENABLE_VFP_SUPPORT -I../inc -I../../../../common/inc -I../../../../common_modules/inc -I../../../../common_modules/module_manager/inc ../../../../common_modules/module_manager/src/txm_module_manager_semaphore_notify_trampoline.c +arm-none-eabi-gcc -c -g -O0 -mcpu=cortex-a7 -mfloat-abi=hard -mfpu=neon-vfpv4 -marm -mthumb-interwork -DTX_ENABLE_VFP_SUPPORT -I../inc -I../../../../common/inc -I../../../../common_modules/inc -I../../../../common_modules/module_manager/inc ../module_manager/src/txm_module_manager_inside_data_check.c arm-none-eabi-gcc -c -g -O0 -mcpu=cortex-a7 -mfloat-abi=hard -mfpu=neon-vfpv4 -marm -mthumb-interwork -DTX_ENABLE_VFP_SUPPORT -I../inc -I../../../../common/inc -I../../../../common_modules/inc -I../../../../common_modules/module_manager/inc ../module_manager/src/txm_module_manager_mm_register_setup.c arm-none-eabi-gcc -c -g -O0 -mcpu=cortex-a7 -mfloat-abi=hard -mfpu=neon-vfpv4 -marm -mthumb-interwork -DTX_ENABLE_VFP_SUPPORT -I../inc -I../../../../common/inc -I../../../../common_modules/inc -I../../../../common_modules/module_manager/inc ../../../../common_modules/module_manager/src/txm_module_manager_start.c arm-none-eabi-gcc -c -g -O0 -mcpu=cortex-a7 -mfloat-abi=hard -mfpu=neon-vfpv4 -marm -mthumb-interwork -DTX_ENABLE_VFP_SUPPORT -I../inc -I../../../../common/inc -I../../../../common_modules/inc -I../../../../common_modules/module_manager/inc ../../../../common_modules/module_manager/src/txm_module_manager_stop.c @@ -278,7 +279,7 @@ arm-none-eabi-ar -r tx.a txm_module_manager_in_place_load.o txm_module_manager_i arm-none-eabi-ar -r tx.a txm_module_manager_kernel_dispatch.o txm_module_manager_maximum_module_priority_set.o txm_module_manager_memory_fault_handler.o arm-none-eabi-ar -r tx.a txm_module_manager_memory_fault_notify.o txm_module_manager_memory_load.o txm_module_manager_object_pointer_get.o arm-none-eabi-ar -r tx.a txm_module_manager_object_pool_create.o txm_module_manager_queue_notify_trampoline.o txm_module_manager_semaphore_notify_trampoline.o -arm-none-eabi-ar -r tx.a txm_module_manager_mm_register_setup.o txm_module_manager_start.o txm_module_manager_stop.o +arm-none-eabi-ar -r tx.a txm_module_manager_inside_data_check.o txm_module_manager_mm_register_setup.o txm_module_manager_start.o txm_module_manager_stop.o arm-none-eabi-ar -r tx.a txm_module_manager_thread_create.o txm_module_manager_thread_notify_trampoline.o txm_module_manager_thread_reset.o arm-none-eabi-ar -r tx.a txm_module_manager_timer_notify_trampoline.o txm_module_manager_unload.o txm_module_manager_thread_stack_build.o arm-none-eabi-ar -r tx.a txm_module_manager_user_mode_entry.o diff --git a/ports_module/cortex_a7/gnu/inc/txm_module_port.h b/ports_module/cortex_a7/gnu/inc/txm_module_port.h index 9cd5a2802..119479922 100644 --- a/ports_module/cortex_a7/gnu/inc/txm_module_port.h +++ b/ports_module/cortex_a7/gnu/inc/txm_module_port.h @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Claude Code (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -240,6 +242,22 @@ The following extensions must also be defined in tx_port.h: #define TXM_ADDRESS_TRANSLATION_FAULT_BIT 1 +/* Mask selecting the ASID field of CONTEXTIDR in the short-descriptor format. */ +#define TXM_CONTEXTIDR_ASID_MASK 0x000000FF + +/* Access intents understood by the module data range check. */ +#define TXM_MODULE_MANAGER_ACCESS_READ 0 +#define TXM_MODULE_MANAGER_ACCESS_WRITE 1 + +/* Define the largest number of MMU pages a single caller-supplied range may span before + the data range check rejects it. This bounds the worst-case, module-controlled cost of + validating one kernel request, which keeps the check deterministic. The default permits + a 4 MB range. Applications that hand larger shared-memory ranges to kernel services can + define a larger value. */ +#ifndef TXM_MODULE_MANAGER_DATA_CHECK_MAX_PAGES +#define TXM_MODULE_MANAGER_DATA_CHECK_MAX_PAGES 1024 +#endif + #define TXM_ASID_RESERVED 0xFFFFFFFF #define TXM_MODULE_ASID_ERROR 0xF6 @@ -375,9 +393,26 @@ typedef struct TXM_MODULE_MANAGER_MEMORY_FAULT_INFO_STRUCT /* Define the macros to perform port-specific checks when passing pointers to the kernel. */ -/* Define macro to make sure object is inside the module's data or shared memory. */ +/* Define macros to make sure a whole object is inside the module's data or shared memory. + The MMU is the authority for shared and external memory, so the check translates every + page the range touches with the requested unprivileged access. Passing the size and the + access intent through is what keeps the check honest: translating only the first address, + and only for reading, would accept a range that leaves the module's mapping partway + through, or a read-only range used as a kernel write destination. */ +#define TXM_MODULE_MANAGER_CHECK_INSIDE_DATA_READ(module_instance, obj_ptr, obj_size) \ + _txm_module_manager_inside_data_check(module_instance, (ALIGN_TYPE) (obj_ptr), (ULONG) (obj_size), TXM_MODULE_MANAGER_ACCESS_READ) + +#define TXM_MODULE_MANAGER_CHECK_INSIDE_DATA_WRITE(module_instance, obj_ptr, obj_size) \ + _txm_module_manager_inside_data_check(module_instance, (ALIGN_TYPE) (obj_ptr), (ULONG) (obj_size), TXM_MODULE_MANAGER_ACCESS_WRITE) + +/* The unqualified check keeps its historical name and takes the stricter write intent. */ #define TXM_MODULE_MANAGER_CHECK_INSIDE_DATA(module_instance, obj_ptr, obj_size) \ - _txm_module_manager_inside_data_check((ULONG) obj_ptr) + TXM_MODULE_MANAGER_CHECK_INSIDE_DATA_WRITE(module_instance, obj_ptr, obj_size) + +/* Negating the inside check would report a range that only partly reaches into the module + as being outside it, so the outside direction gets its own check. */ +#define TXM_MODULE_MANAGER_CHECK_OUTSIDE_DATA(module_instance, obj_ptr, obj_size) \ + _txm_module_manager_outside_data_check(module_instance, (ALIGN_TYPE) (obj_ptr), (ULONG) (obj_size)) /* Define some internal prototypes to this module port. */ @@ -397,7 +432,10 @@ UINT _txm_module_manager_mm_initialize(VOID); VOID _txm_module_manager_mm_register_setup(TXM_MODULE_INSTANCE *module_instance); \ VOID _txm_level2_page_clear(TXM_MODULE_INSTANCE *module_instance); \ VOID _txm_module_manager_remove_asid(TXM_MODULE_INSTANCE *module_instance); \ -UINT _txm_module_manager_inside_data_check(ULONG pointer); +UINT _txm_module_manager_inside_data_check(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE obj_ptr, ULONG obj_size, UINT write_request); \ +UINT _txm_module_manager_outside_data_check(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE obj_ptr, ULONG obj_size); \ +UINT _txm_module_manager_address_probe(ULONG address, UINT write_request); \ +ULONG _txm_module_manager_current_asid_get(VOID); #define TXM_MODULE_MANAGER_VERSION_ID \ CHAR _txm_module_manager_version_id[] = \ diff --git a/ports_module/cortex_a7/gnu/module_manager/src/txm_module_manager_inside_data_check.c b/ports_module/cortex_a7/gnu/module_manager/src/txm_module_manager_inside_data_check.c new file mode 100644 index 000000000..942fd9f68 --- /dev/null +++ b/ports_module/cortex_a7/gnu/module_manager/src/txm_module_manager_inside_data_check.c @@ -0,0 +1,538 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Module Manager */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + +#include "tx_api.h" +#include "txm_module.h" + + +/* Define the ways a caller-supplied range can sit relative to the module's data region. */ + +#define TXM_MODULE_DATA_WINDOW_OUTSIDE 0 /* No byte touches the data mapping. */ +#define TXM_MODULE_DATA_WINDOW_CONTAINED 1 /* Every byte is recorded module data. */ +#define TXM_MODULE_DATA_WINDOW_PARTIAL 2 /* Some, but not all, bytes are. */ + + +/* Define the page mask derived from the smallest MMU page this port maps. */ + +#define TXM_MODULE_PAGE_OFFSET_MASK ((ALIGN_TYPE) (TXM_MODULE_MEMORY_ALIGNMENT - 1)) +#define TXM_MODULE_PAGE_BASE_MASK (~TXM_MODULE_PAGE_OFFSET_MASK) + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txm_module_manager_range_end_get Cortex-A7/MMU/GNU */ +/* 6.5.0 */ +/* AUTHOR */ +/* */ +/* Eclipse ThreadX contributors */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function derives the inclusive address of the last byte of a */ +/* caller-supplied range. An empty range is rejected, matching the */ +/* portable check macros, and so is a range whose last byte is not */ +/* representable, so that no caller ever works from a wrapped address. */ +/* */ +/* INPUT */ +/* */ +/* obj_ptr Address of the first byte */ +/* obj_size Size of the range in bytes */ +/* last_byte Destination for the last address */ +/* */ +/* OUTPUT */ +/* */ +/* TX_TRUE if the range is non-empty and does not wrap */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _txm_module_manager_inside_data_check */ +/* _txm_module_manager_outside_data_check */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 08-24-2026 Eclipse ThreadX Initial Version 6.5.0 */ +/* contributors */ +/* */ +/**************************************************************************/ +static UINT _txm_module_manager_range_end_get(ALIGN_TYPE obj_ptr, ULONG obj_size, ALIGN_TYPE *last_byte) +{ + +ALIGN_TYPE span; +ALIGN_TYPE highest; +UINT status; + + + /* Assume the range cannot be used until proven otherwise. */ + status = TX_FALSE; + + /* An empty range has no last byte and is rejected, just as the portable macros do. */ + if (obj_size != ((ULONG) 0)) + { + + /* Work with the inclusive span so that a range reaching the top of the address + space stays representable. */ + span = ((ALIGN_TYPE) obj_size) - ((ALIGN_TYPE) 1); + + /* Determine the highest first byte this span can start from. */ + highest = (~((ALIGN_TYPE) 0)) - span; + + /* Determine if the range would run past the end of the address space. */ + if (obj_ptr <= highest) + { + + /* Record the last byte of the range. */ + *last_byte = obj_ptr + span; + + /* The range is usable. */ + status = TX_TRUE; + } + } + + /* Return the completion status. */ + return(status); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txm_module_manager_data_window_classify Cortex-A7/MMU/GNU */ +/* 6.5.0 */ +/* AUTHOR */ +/* */ +/* Eclipse ThreadX contributors */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function reports how a range sits relative to the module's own */ +/* data region. The module manager records that region exactly, while */ +/* the MMU can only map it a page at a time, so the mapping may reach */ +/* past the recorded end. The recorded region therefore stays the */ +/* authority for the whole mapped window: a range that leaves the */ +/* recorded region but still lands in the window is reported as */ +/* partial, and its caller rejects it rather than asking the MMU, */ +/* which would accept the rounding slack. */ +/* */ +/* INPUT */ +/* */ +/* module_instance Pointer to module instance */ +/* first_byte Address of the first byte */ +/* last_byte Address of the last byte */ +/* */ +/* OUTPUT */ +/* */ +/* One of the TXM_MODULE_DATA_WINDOW_* classifications */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _txm_module_manager_inside_data_check */ +/* _txm_module_manager_outside_data_check */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 08-24-2026 Eclipse ThreadX Initial Version 6.5.0 */ +/* contributors */ +/* */ +/**************************************************************************/ +static UINT _txm_module_manager_data_window_classify(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE first_byte, ALIGN_TYPE last_byte) +{ + +ALIGN_TYPE data_start; +ALIGN_TYPE data_end; +ALIGN_TYPE window_start; +ALIGN_TYPE window_end; +UINT window; + + + /* Pick up the recorded data region. The end address is inclusive. */ + data_start = (ALIGN_TYPE) module_instance -> txm_module_instance_data_start; + data_end = (ALIGN_TYPE) module_instance -> txm_module_instance_data_end; + + /* Determine if the module has a usable data region at all. */ + if (data_start > data_end) + { + + /* An unset or inverted region owns nothing. */ + window = TXM_MODULE_DATA_WINDOW_OUTSIDE; + } + else + { + + /* Widen the region to the pages the MMU actually maps for it. */ + window_start = data_start & TXM_MODULE_PAGE_BASE_MASK; + window_end = data_end | TXM_MODULE_PAGE_OFFSET_MASK; + + /* Determine if every byte is recorded module data. */ + if ((first_byte >= data_start) && (last_byte <= data_end)) + { + + /* The whole range belongs to the module. */ + window = TXM_MODULE_DATA_WINDOW_CONTAINED; + } + else if ((first_byte <= window_end) && (last_byte >= window_start)) + { + + /* The range overlaps the mapped window without being contained by the + recorded region, so it leaves the module's data partway through. */ + window = TXM_MODULE_DATA_WINDOW_PARTIAL; + } + else + { + + /* The range lies elsewhere, so only the MMU can speak for it. */ + window = TXM_MODULE_DATA_WINDOW_OUTSIDE; + } + } + + /* Return the classification. */ + return(window); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txm_module_manager_page_walk Cortex-A7/MMU/GNU */ +/* 6.5.0 */ +/* AUTHOR */ +/* */ +/* Eclipse ThreadX contributors */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function translates every page a range touches and reports */ +/* whether all of them answered as expected. The walk stops at the */ +/* first page that disagrees, and a range spanning more pages than */ +/* the configured maximum is refused so that one kernel request can */ +/* never impose unbounded work. */ +/* */ +/* INPUT */ +/* */ +/* first_byte Address of the first byte */ +/* last_byte Address of the last byte */ +/* write_request Access intent to translate for */ +/* expected Result every page must return */ +/* */ +/* OUTPUT */ +/* */ +/* TX_TRUE if every page answered as expected */ +/* */ +/* CALLS */ +/* */ +/* _txm_module_manager_address_probe */ +/* */ +/* CALLED BY */ +/* */ +/* _txm_module_manager_inside_data_check */ +/* _txm_module_manager_outside_data_check */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 08-24-2026 Eclipse ThreadX Initial Version 6.5.0 */ +/* contributors */ +/* */ +/**************************************************************************/ +static UINT _txm_module_manager_page_walk(ALIGN_TYPE first_byte, ALIGN_TYPE last_byte, UINT write_request, UINT expected) +{ + +ALIGN_TYPE first_page; +ALIGN_TYPE last_page; +ALIGN_TYPE page; +ULONG pages; +ULONG index; +UINT matched; + + + /* Reduce the range to the pages it touches. */ + first_page = first_byte & TXM_MODULE_PAGE_BASE_MASK; + last_page = last_byte & TXM_MODULE_PAGE_BASE_MASK; + + /* Count them. Both addresses are page-aligned, so the division is exact. */ + pages = ((ULONG) ((last_page - first_page) / ((ALIGN_TYPE) TXM_MODULE_MEMORY_ALIGNMENT))) + ((ULONG) 1); + + /* Determine if the range is longer than this port is willing to translate. */ + if (pages > ((ULONG) TXM_MODULE_MANAGER_DATA_CHECK_MAX_PAGES)) + { + + /* Refuse rather than spend unbounded time in a kernel request. Refusing is safe + for both callers: neither can then claim the range is inside or outside. */ + matched = TX_FALSE; + } + else + { + + /* Assume every page agrees until one does not. */ + matched = TX_TRUE; + index = (ULONG) 0; + + /* Translate each page in turn, stopping as soon as the answer is settled. The + address is rebuilt from the index so that the walk cannot wrap past the top + page of the address space. */ + while ((index < pages) && (matched == TX_TRUE)) + { + + /* Build the address of this page. */ + page = first_page + (((ALIGN_TYPE) index) * ((ALIGN_TYPE) TXM_MODULE_MEMORY_ALIGNMENT)); + + /* Ask the MMU whether the module may reach this page with the requested access. */ + if (_txm_module_manager_address_probe((ULONG) page, write_request) != expected) + { + + /* This page disagrees, so the range as a whole does. */ + matched = TX_FALSE; + } + + /* Move to the next page. */ + index++; + } + } + + /* Return whether the whole range answered as expected. */ + return(matched); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txm_module_manager_inside_data_check Cortex-A7/MMU/GNU */ +/* 6.5.0 */ +/* AUTHOR */ +/* */ +/* Eclipse ThreadX contributors */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function determines whether every byte of a caller-supplied */ +/* range lies inside the module's data or shared memory and is */ +/* reachable by the module with the requested access. The module's own */ +/* data region is answered from the manager's own records, which are */ +/* exact. Anything else is answered by translating every page the */ +/* range touches, because this port keeps no record of the shared and */ +/* external regions the application maps into the module. */ +/* */ +/* INPUT */ +/* */ +/* module_instance Pointer to module instance */ +/* obj_ptr Address of the first byte */ +/* obj_size Size of the range in bytes */ +/* write_request TXM_MODULE_MANAGER_ACCESS_READ or */ +/* TXM_MODULE_MANAGER_ACCESS_WRITE */ +/* */ +/* OUTPUT */ +/* */ +/* TX_TRUE if the whole range is reachable with that access */ +/* */ +/* CALLS */ +/* */ +/* _txm_module_manager_range_end_get */ +/* _txm_module_manager_current_asid_get */ +/* _txm_module_manager_data_window_classify */ +/* _txm_module_manager_page_walk */ +/* */ +/* CALLED BY */ +/* */ +/* TXM_MODULE_MANAGER_CHECK_INSIDE_DATA_READ */ +/* TXM_MODULE_MANAGER_CHECK_INSIDE_DATA_WRITE */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 08-24-2026 Eclipse ThreadX Initial Version 6.5.0 */ +/* contributors */ +/* */ +/**************************************************************************/ +UINT _txm_module_manager_inside_data_check(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE obj_ptr, ULONG obj_size, UINT write_request) +{ + +ALIGN_TYPE last_byte; +UINT window; +UINT status; + + + /* Assume the range is not usable until every condition is met. */ + status = TX_FALSE; + + /* A range can only belong to a module that exists. */ + if (module_instance != TX_NULL) + { + + /* Determine the last byte, rejecting empty and wrapping ranges. */ + if (_txm_module_manager_range_end_get(obj_ptr, obj_size, &last_byte) == TX_TRUE) + { + + /* Address translation answers for whichever context is loaded, so it can only + be trusted while the requesting module's context is the loaded one. */ + if (_txm_module_manager_current_asid_get() == (module_instance -> txm_module_instance_asid)) + { + + /* Place the range relative to the module's own data region. */ + window = _txm_module_manager_data_window_classify(module_instance, obj_ptr, last_byte); + + if (window == ((UINT) TXM_MODULE_DATA_WINDOW_CONTAINED)) + { + + /* The module's data region is mapped for unprivileged reading and + writing, so both intents are satisfied without translating. */ + status = TX_TRUE; + } + else if (window == ((UINT) TXM_MODULE_DATA_WINDOW_OUTSIDE)) + { + + /* Shared or external memory: every page must grant the access. */ + status = _txm_module_manager_page_walk(obj_ptr, last_byte, write_request, TX_TRUE); + } + else + { + + /* The range leaves the module's data partway through. */ + status = TX_FALSE; + } + } + } + } + + /* Return the completion status. */ + return(status); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txm_module_manager_outside_data_check Cortex-A7/MMU/GNU */ +/* 6.5.0 */ +/* AUTHOR */ +/* */ +/* Eclipse ThreadX contributors */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function determines whether no byte of a caller-supplied range */ +/* is reachable by the module. It is deliberately not the negation of */ +/* the inside check: a range that reaches into the module's memory */ +/* only partway is inside neither answer, and reporting it as outside */ +/* would let it pass as a kernel object. */ +/* */ +/* INPUT */ +/* */ +/* module_instance Pointer to module instance */ +/* obj_ptr Address of the first byte */ +/* obj_size Size of the range in bytes */ +/* */ +/* OUTPUT */ +/* */ +/* TX_TRUE if no byte of the range is reachable by the module */ +/* */ +/* CALLS */ +/* */ +/* _txm_module_manager_range_end_get */ +/* _txm_module_manager_current_asid_get */ +/* _txm_module_manager_data_window_classify */ +/* _txm_module_manager_page_walk */ +/* */ +/* CALLED BY */ +/* */ +/* TXM_MODULE_MANAGER_CHECK_OUTSIDE_DATA */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 08-24-2026 Eclipse ThreadX Initial Version 6.5.0 */ +/* contributors */ +/* */ +/**************************************************************************/ +UINT _txm_module_manager_outside_data_check(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE obj_ptr, ULONG obj_size) +{ + +ALIGN_TYPE last_byte; +UINT window; +UINT status; + + + /* Assume the range is not provably outside the module. */ + status = TX_FALSE; + + /* A range can only be placed against a module that exists. */ + if (module_instance != TX_NULL) + { + + /* Determine the last byte, rejecting empty and wrapping ranges. */ + if (_txm_module_manager_range_end_get(obj_ptr, obj_size, &last_byte) == TX_TRUE) + { + + /* Address translation answers for whichever context is loaded, so it can only + be trusted while the requesting module's context is the loaded one. */ + if (_txm_module_manager_current_asid_get() == (module_instance -> txm_module_instance_asid)) + { + + /* Place the range relative to the module's own data region. */ + window = _txm_module_manager_data_window_classify(module_instance, obj_ptr, last_byte); + + if (window == ((UINT) TXM_MODULE_DATA_WINDOW_OUTSIDE)) + { + + /* Clear of the module's data region, so the remaining question is + whether any page of it is shared or external memory. */ + status = _txm_module_manager_page_walk(obj_ptr, last_byte, TXM_MODULE_MANAGER_ACCESS_READ, TX_FALSE); + } + else + { + + /* The range touches the module's data region. */ + status = TX_FALSE; + } + } + } + } + + /* Return the completion status. */ + return(status); +} diff --git a/ports_module/cortex_a7/gnu/module_manager/src/txm_module_manager_mm_register_setup.c b/ports_module/cortex_a7/gnu/module_manager/src/txm_module_manager_mm_register_setup.c index 602029709..b2161fde0 100644 --- a/ports_module/cortex_a7/gnu/module_manager/src/txm_module_manager_mm_register_setup.c +++ b/ports_module/cortex_a7/gnu/module_manager/src/txm_module_manager_mm_register_setup.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Claude Code (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -35,24 +37,34 @@ extern ULONG _txm_ttbr1_page_table[TXM_MAXIMUM_MODULES][TXM_MASTER_PAGE_TABLE_EN /* */ /* FUNCTION RELEASE */ /* */ -/* _txm_module_manager_inside_data_check Cortex-A7/MMU/GNU */ -/* 6.2.1 */ +/* _txm_module_manager_address_probe Cortex-A7/MMU/GNU */ +/* 6.5.0 */ /* AUTHOR */ /* */ /* Scott Larson, Microsoft Corporation */ +/* Eclipse ThreadX contributors */ /* */ /* DESCRIPTION */ /* */ -/* This function determines if pointer is within the module's data or */ -/* shared memory. */ +/* This function asks the MMU whether unprivileged code running in the */ +/* currently loaded translation context may reach one address with the */ +/* requested access. Reading and writing are asked separately, because */ +/* a module's code and its read-only shared memory translate for */ +/* reading while a kernel service writing to them would fault or, */ +/* worse, succeed from privileged mode. */ +/* */ +/* This answers for one address only. Callers that hold a range must */ +/* ask about every page the range touches. */ /* */ /* INPUT */ /* */ -/* pointer Data pointer */ +/* address Address to translate */ +/* write_request TXM_MODULE_MANAGER_ACCESS_READ or */ +/* TXM_MODULE_MANAGER_ACCESS_WRITE */ /* */ /* OUTPUT */ /* */ -/* Completion Status */ +/* TX_TRUE if the translation granted the requested access */ /* */ /* CALLS */ /* */ @@ -60,18 +72,41 @@ extern ULONG _txm_ttbr1_page_table[TXM_MAXIMUM_MODULES][TXM_MASTER_PAGE_TABLE_EN /* */ /* CALLED BY */ /* */ -/* TXM_MODULE_MANAGER_DATA_POINTER_CHECK */ +/* _txm_module_manager_page_walk */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 03-08-2023 Scott Larson Initial Version 6.2.1 */ +/* 08-24-2026 Eclipse ThreadX Added the write intent and */ +/* contributors moved range handling to */ +/* the caller, resulting in */ +/* version 6.5.0 */ /* */ /**************************************************************************/ -UINT _txm_module_manager_inside_data_check(ULONG pointer) +UINT _txm_module_manager_address_probe(ULONG address, UINT write_request) { -ULONG translation; +ULONG translation; + + + /* Determine which unprivileged access the caller needs. */ + if (write_request == ((UINT) TXM_MODULE_MANAGER_ACCESS_WRITE)) + { + + /* ATS1CUW operation on address supplied in address, Stage 1 unprivileged write. */ + __asm volatile ("MCR p15, 0, %0, c7, c8, 3" : : "r"(address) : ); + } + else + { + + /* ATS1CUR operation on address supplied in address, Stage 1 unprivileged read. */ + __asm volatile ("MCR p15, 0, %0, c7, c8, 2" : : "r"(address) : ); + } - /* ATS1CUR operation on address supplied in pointer, Stage 1 unprivileged read. */ - __asm volatile ("MCR p15, 0, %0, c7, c8, 2" : : "r"(pointer) : ); __asm volatile ("ISB"); /* Ensure completion of the MCR write to CP15. */ - __asm volatile ("MRC p15, 0, %0, c7, c4, 0" : "=r"(translation) : : ); /* Read result from 32-bit PAR into translation. */ + __asm volatile ("MRC p15, 0, %0, c7, c4, 0" : "=r"(translation) : : ); /* Read result from 32-bit PAR into translation. */ if (translation & TXM_ADDRESS_TRANSLATION_FAULT_BIT) { @@ -82,6 +117,62 @@ ULONG translation; } +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txm_module_manager_current_asid_get Cortex-A7/MMU/GNU */ +/* 6.5.0 */ +/* AUTHOR */ +/* */ +/* Eclipse ThreadX contributors */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns the ASID of the translation context that is */ +/* currently loaded. Address translation always answers for that */ +/* context, so a caller validating a pointer on behalf of a module */ +/* must confirm that the loaded context is that module's before it */ +/* believes the answer. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* ASID of the currently loaded translation context */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _txm_module_manager_inside_data_check */ +/* _txm_module_manager_outside_data_check */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 08-24-2026 Eclipse ThreadX Initial Version 6.5.0 */ +/* contributors */ +/* */ +/**************************************************************************/ +ULONG _txm_module_manager_current_asid_get(VOID) +{ + +ULONG contextidr; + + + /* Read CONTEXTIDR, whose low byte holds the ASID in the short-descriptor format. */ + __asm volatile ("MRC p15, 0, %0, c13, c0, 1" : "=r"(contextidr) : : ); + + return(contextidr & TXM_CONTEXTIDR_ASID_MASK); +} + + /**************************************************************************/ /* */ /* FUNCTION RELEASE */ diff --git a/ports_module/cortex_a7/iar/example_build/tx.ewp b/ports_module/cortex_a7/iar/example_build/tx.ewp index 9d4862186..97f9ffe7f 100644 --- a/ports_module/cortex_a7/iar/example_build/tx.ewp +++ b/ports_module/cortex_a7/iar/example_build/tx.ewp @@ -2832,6 +2832,9 @@ $PROJ_DIR$\..\module_manager\src\txm_module_manager_mm_initialize.c + + $PROJ_DIR$\..\module_manager\src\txm_module_manager_inside_data_check.c + $PROJ_DIR$\..\module_manager\src\txm_module_manager_mm_register_setup.c diff --git a/ports_module/cortex_a7/iar/inc/txm_module_port.h b/ports_module/cortex_a7/iar/inc/txm_module_port.h index 247868ea3..dbaf7e175 100644 --- a/ports_module/cortex_a7/iar/inc/txm_module_port.h +++ b/ports_module/cortex_a7/iar/inc/txm_module_port.h @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Claude Code (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -251,6 +253,22 @@ The following extensions must also be defined in tx_port.h: #define TXM_ADDRESS_TRANSLATION_FAULT_BIT 1 +/* Mask selecting the ASID field of CONTEXTIDR in the short-descriptor format. */ +#define TXM_CONTEXTIDR_ASID_MASK 0x000000FF + +/* Access intents understood by the module data range check. */ +#define TXM_MODULE_MANAGER_ACCESS_READ 0 +#define TXM_MODULE_MANAGER_ACCESS_WRITE 1 + +/* Define the largest number of MMU pages a single caller-supplied range may span before + the data range check rejects it. This bounds the worst-case, module-controlled cost of + validating one kernel request, which keeps the check deterministic. The default permits + a 4 MB range. Applications that hand larger shared-memory ranges to kernel services can + define a larger value. */ +#ifndef TXM_MODULE_MANAGER_DATA_CHECK_MAX_PAGES +#define TXM_MODULE_MANAGER_DATA_CHECK_MAX_PAGES 1024 +#endif + #define TXM_ASID_RESERVED 0xFFFFFFFF #define TXM_MODULE_ASID_ERROR 0xF6 @@ -386,9 +404,26 @@ typedef struct TXM_MODULE_MANAGER_MEMORY_FAULT_INFO_STRUCT /* Define the macros to perform port-specific checks when passing pointers to the kernel. */ -/* Define macro to make sure object is inside the module's data or shared memory. */ +/* Define macros to make sure a whole object is inside the module's data or shared memory. + The MMU is the authority for shared and external memory, so the check translates every + page the range touches with the requested unprivileged access. Passing the size and the + access intent through is what keeps the check honest: translating only the first address, + and only for reading, would accept a range that leaves the module's mapping partway + through, or a read-only range used as a kernel write destination. */ +#define TXM_MODULE_MANAGER_CHECK_INSIDE_DATA_READ(module_instance, obj_ptr, obj_size) \ + _txm_module_manager_inside_data_check(module_instance, (ALIGN_TYPE) (obj_ptr), (ULONG) (obj_size), TXM_MODULE_MANAGER_ACCESS_READ) + +#define TXM_MODULE_MANAGER_CHECK_INSIDE_DATA_WRITE(module_instance, obj_ptr, obj_size) \ + _txm_module_manager_inside_data_check(module_instance, (ALIGN_TYPE) (obj_ptr), (ULONG) (obj_size), TXM_MODULE_MANAGER_ACCESS_WRITE) + +/* The unqualified check keeps its historical name and takes the stricter write intent. */ #define TXM_MODULE_MANAGER_CHECK_INSIDE_DATA(module_instance, obj_ptr, obj_size) \ - _txm_module_manager_inside_data_check((ULONG) obj_ptr) + TXM_MODULE_MANAGER_CHECK_INSIDE_DATA_WRITE(module_instance, obj_ptr, obj_size) + +/* Negating the inside check would report a range that only partly reaches into the module + as being outside it, so the outside direction gets its own check. */ +#define TXM_MODULE_MANAGER_CHECK_OUTSIDE_DATA(module_instance, obj_ptr, obj_size) \ + _txm_module_manager_outside_data_check(module_instance, (ALIGN_TYPE) (obj_ptr), (ULONG) (obj_size)) /* Define some internal prototypes to this module port. */ @@ -408,7 +443,10 @@ UINT _txm_module_manager_mm_initialize(VOID); VOID _txm_module_manager_mm_register_setup(TXM_MODULE_INSTANCE *module_instance); \ VOID _txm_level2_page_clear(TXM_MODULE_INSTANCE *module_instance); \ VOID _txm_module_manager_remove_asid(TXM_MODULE_INSTANCE *module_instance); \ -UINT _txm_module_manager_inside_data_check(ULONG pointer); +UINT _txm_module_manager_inside_data_check(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE obj_ptr, ULONG obj_size, UINT write_request); \ +UINT _txm_module_manager_outside_data_check(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE obj_ptr, ULONG obj_size); \ +UINT _txm_module_manager_address_probe(ULONG address, UINT write_request); \ +ULONG _txm_module_manager_current_asid_get(VOID); #define TXM_MODULE_MANAGER_VERSION_ID \ CHAR _txm_module_manager_version_id[] = \ diff --git a/ports_module/cortex_a7/iar/module_manager/src/txm_module_manager_inside_data_check.c b/ports_module/cortex_a7/iar/module_manager/src/txm_module_manager_inside_data_check.c new file mode 100644 index 000000000..972cae84d --- /dev/null +++ b/ports_module/cortex_a7/iar/module_manager/src/txm_module_manager_inside_data_check.c @@ -0,0 +1,538 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Component */ +/** */ +/** Module Manager */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +#define TX_SOURCE_CODE + +#include "tx_api.h" +#include "txm_module.h" + + +/* Define the ways a caller-supplied range can sit relative to the module's data region. */ + +#define TXM_MODULE_DATA_WINDOW_OUTSIDE 0 /* No byte touches the data mapping. */ +#define TXM_MODULE_DATA_WINDOW_CONTAINED 1 /* Every byte is recorded module data. */ +#define TXM_MODULE_DATA_WINDOW_PARTIAL 2 /* Some, but not all, bytes are. */ + + +/* Define the page mask derived from the smallest MMU page this port maps. */ + +#define TXM_MODULE_PAGE_OFFSET_MASK ((ALIGN_TYPE) (TXM_MODULE_MEMORY_ALIGNMENT - 1)) +#define TXM_MODULE_PAGE_BASE_MASK (~TXM_MODULE_PAGE_OFFSET_MASK) + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txm_module_manager_range_end_get Cortex-A7/MMU/IAR */ +/* 6.5.0 */ +/* AUTHOR */ +/* */ +/* Eclipse ThreadX contributors */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function derives the inclusive address of the last byte of a */ +/* caller-supplied range. An empty range is rejected, matching the */ +/* portable check macros, and so is a range whose last byte is not */ +/* representable, so that no caller ever works from a wrapped address. */ +/* */ +/* INPUT */ +/* */ +/* obj_ptr Address of the first byte */ +/* obj_size Size of the range in bytes */ +/* last_byte Destination for the last address */ +/* */ +/* OUTPUT */ +/* */ +/* TX_TRUE if the range is non-empty and does not wrap */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _txm_module_manager_inside_data_check */ +/* _txm_module_manager_outside_data_check */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 08-24-2026 Eclipse ThreadX Initial Version 6.5.0 */ +/* contributors */ +/* */ +/**************************************************************************/ +static UINT _txm_module_manager_range_end_get(ALIGN_TYPE obj_ptr, ULONG obj_size, ALIGN_TYPE *last_byte) +{ + +ALIGN_TYPE span; +ALIGN_TYPE highest; +UINT status; + + + /* Assume the range cannot be used until proven otherwise. */ + status = TX_FALSE; + + /* An empty range has no last byte and is rejected, just as the portable macros do. */ + if (obj_size != ((ULONG) 0)) + { + + /* Work with the inclusive span so that a range reaching the top of the address + space stays representable. */ + span = ((ALIGN_TYPE) obj_size) - ((ALIGN_TYPE) 1); + + /* Determine the highest first byte this span can start from. */ + highest = (~((ALIGN_TYPE) 0)) - span; + + /* Determine if the range would run past the end of the address space. */ + if (obj_ptr <= highest) + { + + /* Record the last byte of the range. */ + *last_byte = obj_ptr + span; + + /* The range is usable. */ + status = TX_TRUE; + } + } + + /* Return the completion status. */ + return(status); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txm_module_manager_data_window_classify Cortex-A7/MMU/IAR */ +/* 6.5.0 */ +/* AUTHOR */ +/* */ +/* Eclipse ThreadX contributors */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function reports how a range sits relative to the module's own */ +/* data region. The module manager records that region exactly, while */ +/* the MMU can only map it a page at a time, so the mapping may reach */ +/* past the recorded end. The recorded region therefore stays the */ +/* authority for the whole mapped window: a range that leaves the */ +/* recorded region but still lands in the window is reported as */ +/* partial, and its caller rejects it rather than asking the MMU, */ +/* which would accept the rounding slack. */ +/* */ +/* INPUT */ +/* */ +/* module_instance Pointer to module instance */ +/* first_byte Address of the first byte */ +/* last_byte Address of the last byte */ +/* */ +/* OUTPUT */ +/* */ +/* One of the TXM_MODULE_DATA_WINDOW_* classifications */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _txm_module_manager_inside_data_check */ +/* _txm_module_manager_outside_data_check */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 08-24-2026 Eclipse ThreadX Initial Version 6.5.0 */ +/* contributors */ +/* */ +/**************************************************************************/ +static UINT _txm_module_manager_data_window_classify(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE first_byte, ALIGN_TYPE last_byte) +{ + +ALIGN_TYPE data_start; +ALIGN_TYPE data_end; +ALIGN_TYPE window_start; +ALIGN_TYPE window_end; +UINT window; + + + /* Pick up the recorded data region. The end address is inclusive. */ + data_start = (ALIGN_TYPE) module_instance -> txm_module_instance_data_start; + data_end = (ALIGN_TYPE) module_instance -> txm_module_instance_data_end; + + /* Determine if the module has a usable data region at all. */ + if (data_start > data_end) + { + + /* An unset or inverted region owns nothing. */ + window = TXM_MODULE_DATA_WINDOW_OUTSIDE; + } + else + { + + /* Widen the region to the pages the MMU actually maps for it. */ + window_start = data_start & TXM_MODULE_PAGE_BASE_MASK; + window_end = data_end | TXM_MODULE_PAGE_OFFSET_MASK; + + /* Determine if every byte is recorded module data. */ + if ((first_byte >= data_start) && (last_byte <= data_end)) + { + + /* The whole range belongs to the module. */ + window = TXM_MODULE_DATA_WINDOW_CONTAINED; + } + else if ((first_byte <= window_end) && (last_byte >= window_start)) + { + + /* The range overlaps the mapped window without being contained by the + recorded region, so it leaves the module's data partway through. */ + window = TXM_MODULE_DATA_WINDOW_PARTIAL; + } + else + { + + /* The range lies elsewhere, so only the MMU can speak for it. */ + window = TXM_MODULE_DATA_WINDOW_OUTSIDE; + } + } + + /* Return the classification. */ + return(window); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txm_module_manager_page_walk Cortex-A7/MMU/IAR */ +/* 6.5.0 */ +/* AUTHOR */ +/* */ +/* Eclipse ThreadX contributors */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function translates every page a range touches and reports */ +/* whether all of them answered as expected. The walk stops at the */ +/* first page that disagrees, and a range spanning more pages than */ +/* the configured maximum is refused so that one kernel request can */ +/* never impose unbounded work. */ +/* */ +/* INPUT */ +/* */ +/* first_byte Address of the first byte */ +/* last_byte Address of the last byte */ +/* write_request Access intent to translate for */ +/* expected Result every page must return */ +/* */ +/* OUTPUT */ +/* */ +/* TX_TRUE if every page answered as expected */ +/* */ +/* CALLS */ +/* */ +/* _txm_module_manager_address_probe */ +/* */ +/* CALLED BY */ +/* */ +/* _txm_module_manager_inside_data_check */ +/* _txm_module_manager_outside_data_check */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 08-24-2026 Eclipse ThreadX Initial Version 6.5.0 */ +/* contributors */ +/* */ +/**************************************************************************/ +static UINT _txm_module_manager_page_walk(ALIGN_TYPE first_byte, ALIGN_TYPE last_byte, UINT write_request, UINT expected) +{ + +ALIGN_TYPE first_page; +ALIGN_TYPE last_page; +ALIGN_TYPE page; +ULONG pages; +ULONG index; +UINT matched; + + + /* Reduce the range to the pages it touches. */ + first_page = first_byte & TXM_MODULE_PAGE_BASE_MASK; + last_page = last_byte & TXM_MODULE_PAGE_BASE_MASK; + + /* Count them. Both addresses are page-aligned, so the division is exact. */ + pages = ((ULONG) ((last_page - first_page) / ((ALIGN_TYPE) TXM_MODULE_MEMORY_ALIGNMENT))) + ((ULONG) 1); + + /* Determine if the range is longer than this port is willing to translate. */ + if (pages > ((ULONG) TXM_MODULE_MANAGER_DATA_CHECK_MAX_PAGES)) + { + + /* Refuse rather than spend unbounded time in a kernel request. Refusing is safe + for both callers: neither can then claim the range is inside or outside. */ + matched = TX_FALSE; + } + else + { + + /* Assume every page agrees until one does not. */ + matched = TX_TRUE; + index = (ULONG) 0; + + /* Translate each page in turn, stopping as soon as the answer is settled. The + address is rebuilt from the index so that the walk cannot wrap past the top + page of the address space. */ + while ((index < pages) && (matched == TX_TRUE)) + { + + /* Build the address of this page. */ + page = first_page + (((ALIGN_TYPE) index) * ((ALIGN_TYPE) TXM_MODULE_MEMORY_ALIGNMENT)); + + /* Ask the MMU whether the module may reach this page with the requested access. */ + if (_txm_module_manager_address_probe((ULONG) page, write_request) != expected) + { + + /* This page disagrees, so the range as a whole does. */ + matched = TX_FALSE; + } + + /* Move to the next page. */ + index++; + } + } + + /* Return whether the whole range answered as expected. */ + return(matched); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txm_module_manager_inside_data_check Cortex-A7/MMU/IAR */ +/* 6.5.0 */ +/* AUTHOR */ +/* */ +/* Eclipse ThreadX contributors */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function determines whether every byte of a caller-supplied */ +/* range lies inside the module's data or shared memory and is */ +/* reachable by the module with the requested access. The module's own */ +/* data region is answered from the manager's own records, which are */ +/* exact. Anything else is answered by translating every page the */ +/* range touches, because this port keeps no record of the shared and */ +/* external regions the application maps into the module. */ +/* */ +/* INPUT */ +/* */ +/* module_instance Pointer to module instance */ +/* obj_ptr Address of the first byte */ +/* obj_size Size of the range in bytes */ +/* write_request TXM_MODULE_MANAGER_ACCESS_READ or */ +/* TXM_MODULE_MANAGER_ACCESS_WRITE */ +/* */ +/* OUTPUT */ +/* */ +/* TX_TRUE if the whole range is reachable with that access */ +/* */ +/* CALLS */ +/* */ +/* _txm_module_manager_range_end_get */ +/* _txm_module_manager_current_asid_get */ +/* _txm_module_manager_data_window_classify */ +/* _txm_module_manager_page_walk */ +/* */ +/* CALLED BY */ +/* */ +/* TXM_MODULE_MANAGER_CHECK_INSIDE_DATA_READ */ +/* TXM_MODULE_MANAGER_CHECK_INSIDE_DATA_WRITE */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 08-24-2026 Eclipse ThreadX Initial Version 6.5.0 */ +/* contributors */ +/* */ +/**************************************************************************/ +UINT _txm_module_manager_inside_data_check(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE obj_ptr, ULONG obj_size, UINT write_request) +{ + +ALIGN_TYPE last_byte; +UINT window; +UINT status; + + + /* Assume the range is not usable until every condition is met. */ + status = TX_FALSE; + + /* A range can only belong to a module that exists. */ + if (module_instance != TX_NULL) + { + + /* Determine the last byte, rejecting empty and wrapping ranges. */ + if (_txm_module_manager_range_end_get(obj_ptr, obj_size, &last_byte) == TX_TRUE) + { + + /* Address translation answers for whichever context is loaded, so it can only + be trusted while the requesting module's context is the loaded one. */ + if (_txm_module_manager_current_asid_get() == (module_instance -> txm_module_instance_asid)) + { + + /* Place the range relative to the module's own data region. */ + window = _txm_module_manager_data_window_classify(module_instance, obj_ptr, last_byte); + + if (window == ((UINT) TXM_MODULE_DATA_WINDOW_CONTAINED)) + { + + /* The module's data region is mapped for unprivileged reading and + writing, so both intents are satisfied without translating. */ + status = TX_TRUE; + } + else if (window == ((UINT) TXM_MODULE_DATA_WINDOW_OUTSIDE)) + { + + /* Shared or external memory: every page must grant the access. */ + status = _txm_module_manager_page_walk(obj_ptr, last_byte, write_request, TX_TRUE); + } + else + { + + /* The range leaves the module's data partway through. */ + status = TX_FALSE; + } + } + } + } + + /* Return the completion status. */ + return(status); +} + + +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txm_module_manager_outside_data_check Cortex-A7/MMU/IAR */ +/* 6.5.0 */ +/* AUTHOR */ +/* */ +/* Eclipse ThreadX contributors */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function determines whether no byte of a caller-supplied range */ +/* is reachable by the module. It is deliberately not the negation of */ +/* the inside check: a range that reaches into the module's memory */ +/* only partway is inside neither answer, and reporting it as outside */ +/* would let it pass as a kernel object. */ +/* */ +/* INPUT */ +/* */ +/* module_instance Pointer to module instance */ +/* obj_ptr Address of the first byte */ +/* obj_size Size of the range in bytes */ +/* */ +/* OUTPUT */ +/* */ +/* TX_TRUE if no byte of the range is reachable by the module */ +/* */ +/* CALLS */ +/* */ +/* _txm_module_manager_range_end_get */ +/* _txm_module_manager_current_asid_get */ +/* _txm_module_manager_data_window_classify */ +/* _txm_module_manager_page_walk */ +/* */ +/* CALLED BY */ +/* */ +/* TXM_MODULE_MANAGER_CHECK_OUTSIDE_DATA */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 08-24-2026 Eclipse ThreadX Initial Version 6.5.0 */ +/* contributors */ +/* */ +/**************************************************************************/ +UINT _txm_module_manager_outside_data_check(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE obj_ptr, ULONG obj_size) +{ + +ALIGN_TYPE last_byte; +UINT window; +UINT status; + + + /* Assume the range is not provably outside the module. */ + status = TX_FALSE; + + /* A range can only be placed against a module that exists. */ + if (module_instance != TX_NULL) + { + + /* Determine the last byte, rejecting empty and wrapping ranges. */ + if (_txm_module_manager_range_end_get(obj_ptr, obj_size, &last_byte) == TX_TRUE) + { + + /* Address translation answers for whichever context is loaded, so it can only + be trusted while the requesting module's context is the loaded one. */ + if (_txm_module_manager_current_asid_get() == (module_instance -> txm_module_instance_asid)) + { + + /* Place the range relative to the module's own data region. */ + window = _txm_module_manager_data_window_classify(module_instance, obj_ptr, last_byte); + + if (window == ((UINT) TXM_MODULE_DATA_WINDOW_OUTSIDE)) + { + + /* Clear of the module's data region, so the remaining question is + whether any page of it is shared or external memory. */ + status = _txm_module_manager_page_walk(obj_ptr, last_byte, TXM_MODULE_MANAGER_ACCESS_READ, TX_FALSE); + } + else + { + + /* The range touches the module's data region. */ + status = TX_FALSE; + } + } + } + } + + /* Return the completion status. */ + return(status); +} diff --git a/ports_module/cortex_a7/iar/module_manager/src/txm_module_manager_mm_register_setup.c b/ports_module/cortex_a7/iar/module_manager/src/txm_module_manager_mm_register_setup.c index 3d477a4a5..3adc61c38 100644 --- a/ports_module/cortex_a7/iar/module_manager/src/txm_module_manager_mm_register_setup.c +++ b/ports_module/cortex_a7/iar/module_manager/src/txm_module_manager_mm_register_setup.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Some portions generated by Claude Code (Opus 5). + /**************************************************************************/ /**************************************************************************/ @@ -35,24 +37,34 @@ extern ULONG _txm_ttbr1_page_table[TXM_MAXIMUM_MODULES][TXM_MASTER_PAGE_TABLE_EN /* */ /* FUNCTION RELEASE */ /* */ -/* _txm_module_manager_inside_data_check Cortex-A7/MMU/IAR */ -/* 6.1 */ +/* _txm_module_manager_address_probe Cortex-A7/MMU/IAR */ +/* 6.5.0 */ /* AUTHOR */ /* */ /* Scott Larson, Microsoft Corporation */ +/* Eclipse ThreadX contributors */ /* */ /* DESCRIPTION */ /* */ -/* This function determines if pointer is within the module's data or */ -/* shared memory. */ +/* This function asks the MMU whether unprivileged code running in the */ +/* currently loaded translation context may reach one address with the */ +/* requested access. Reading and writing are asked separately, because */ +/* a module's code and its read-only shared memory translate for */ +/* reading while a kernel service writing to them would fault or, */ +/* worse, succeed from privileged mode. */ +/* */ +/* This answers for one address only. Callers that hold a range must */ +/* ask about every page the range touches. */ /* */ /* INPUT */ /* */ -/* pointer Data pointer */ +/* address Address to translate */ +/* write_request TXM_MODULE_MANAGER_ACCESS_READ or */ +/* TXM_MODULE_MANAGER_ACCESS_WRITE */ /* */ /* OUTPUT */ /* */ -/* Completion Status */ +/* TX_TRUE if the translation granted the requested access */ /* */ /* CALLS */ /* */ @@ -60,17 +72,40 @@ extern ULONG _txm_ttbr1_page_table[TXM_MAXIMUM_MODULES][TXM_MASTER_PAGE_TABLE_EN /* */ /* CALLED BY */ /* */ -/* TXM_MODULE_MANAGER_DATA_POINTER_CHECK */ +/* _txm_module_manager_page_walk */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 03-08-2023 Scott Larson Initial Version 6.2.1 */ +/* 08-24-2026 Eclipse ThreadX Added the write intent and */ +/* contributors moved range handling to */ +/* the caller, resulting in */ +/* version 6.5.0 */ /* */ /**************************************************************************/ -UINT _txm_module_manager_inside_data_check(ULONG pointer) +UINT _txm_module_manager_address_probe(ULONG address, UINT write_request) { -ULONG translation; +ULONG translation; + + + /* Determine which unprivileged access the caller needs. */ + if (write_request == ((UINT) TXM_MODULE_MANAGER_ACCESS_WRITE)) + { + + /* ATS1CUW operation on address supplied in address, Stage 1 unprivileged write. */ + asm("MCR p15, 0, %0, c7, c8, 3" : : "r"(address) : ); + } + else + { + + /* ATS1CUR operation on address supplied in address, Stage 1 unprivileged read. */ + asm("MCR p15, 0, %0, c7, c8, 2" : : "r"(address) : ); + } - /* ATS1CUR operation on address supplied in pointer, Stage 1 unprivileged read. */ - asm("MCR p15, 0, %0, c7, c8, 2" : : "r"(pointer) : ); - asm("ISB"); /* Ensure completion of the MCR write to CP15. */ + asm("ISB"); /* Ensure completion of the MCR write to CP15. */ asm("MRC p15, 0, %0, c7, c4, 0" : "=r"(translation) : : ); /* Read result from 32-bit PAR into translation. */ if (translation & TXM_ADDRESS_TRANSLATION_FAULT_BIT) @@ -82,6 +117,62 @@ ULONG translation; } +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _txm_module_manager_current_asid_get Cortex-A7/MMU/IAR */ +/* 6.5.0 */ +/* AUTHOR */ +/* */ +/* Eclipse ThreadX contributors */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function returns the ASID of the translation context that is */ +/* currently loaded. Address translation always answers for that */ +/* context, so a caller validating a pointer on behalf of a module */ +/* must confirm that the loaded context is that module's before it */ +/* believes the answer. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* ASID of the currently loaded translation context */ +/* */ +/* CALLS */ +/* */ +/* None */ +/* */ +/* CALLED BY */ +/* */ +/* _txm_module_manager_inside_data_check */ +/* _txm_module_manager_outside_data_check */ +/* */ +/* RELEASE HISTORY */ +/* */ +/* DATE NAME DESCRIPTION */ +/* */ +/* 08-24-2026 Eclipse ThreadX Initial Version 6.5.0 */ +/* contributors */ +/* */ +/**************************************************************************/ +ULONG _txm_module_manager_current_asid_get(VOID) +{ + +ULONG contextidr; + + + /* Read CONTEXTIDR, whose low byte holds the ASID in the short-descriptor format. */ + asm("MRC p15, 0, %0, c13, c0, 1" : "=r"(contextidr) : : ); + + return(contextidr & TXM_CONTEXTIDR_ASID_MASK); +} + + /**************************************************************************/ /* */ /* FUNCTION RELEASE */ diff --git a/scripts/check_module_mmu_a7.sh b/scripts/check_module_mmu_a7.sh new file mode 100755 index 000000000..593edb316 --- /dev/null +++ b/scripts/check_module_mmu_a7.sh @@ -0,0 +1,120 @@ +#!/bin/bash +############################################################################## +# 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. +# +# AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +# The AI-generated portions may be considered public domain (CC0-1.0) +# and not subject to the project's licence. The human contributor has +# reviewed and verified that the code is correct. +# +# SPDX-License-Identifier: MIT and CC0-1.0 +############################################################################## + +# Runs the Cortex-A7 module range check against a live MMU. +# +# The host test for that check stands a simulated page map behind the port's +# CP15 primitive, so it never executes an address translation. An encoding that +# named the wrong operation, or a PAR fault bit read the wrong way round, would +# pass it. This check builds a bare-metal image that turns the MMU on and drives +# the real check through the real translations, then runs it under an emulator. +# +# scripts/check_module_mmu_a7.sh +# +# Environment: +# CROSS_CC arm-none-eabi C compiler; defaults to arm-none-eabi-gcc. +# QEMU Arm system emulator; defaults to qemu-system-arm. +# +# Exit status is 0 when the image runs and every expectation holds, 1 when an +# expectation fails, and 0 with a notice when the tools are absent, so that a +# machine without a cross toolchain does not fail the build. + +set -u + +CC="${CROSS_CC:-arm-none-eabi-gcc}" +QEMU_BIN="${QEMU:-qemu-system-arm}" + +ROOT="$(cd "$(dirname "$0")/.." && pwd)" +SRC="$ROOT/test/tx/module_manager/threadx_module_manager_cortex_a7_mmu_test.c" +PORT="$ROOT/ports_module/cortex_a7/gnu/module_manager/src/txm_module_manager_inside_data_check.c" + +for tool in "$CC" "$QEMU_BIN"; do + if ! command -v "$tool" >/dev/null 2>&1 && [ ! -x "$tool" ]; then + echo "Skipping: $tool not found." + echo " Needs an arm-none-eabi toolchain and qemu-system-arm." + exit 0 + fi +done + +# The port supplies the two architecture primitives from its register setup +# file, which cannot be compiled here because it also builds the module page +# tables. They are provided by the image itself, copied from that file, so what +# runs is the same instruction sequence the port issues. +work="$(mktemp -d)" +trap 'rm -rf "$work"' EXIT + +cat > "$work/primitives.c" <<'PRIMITIVES' +#define TX_SOURCE_CODE +#include "tx_api.h" +#include "txm_module.h" + +UINT _txm_module_manager_address_probe(ULONG address, UINT write_request) +{ +ULONG translation; + + if (write_request == ((UINT) TXM_MODULE_MANAGER_ACCESS_WRITE)) + { + __asm volatile ("MCR p15, 0, %0, c7, c8, 3" : : "r"(address) : ); + } + else + { + __asm volatile ("MCR p15, 0, %0, c7, c8, 2" : : "r"(address) : ); + } + + __asm volatile ("ISB"); + __asm volatile ("MRC p15, 0, %0, c7, c4, 0" : "=r"(translation) : : ); + + if (translation & TXM_ADDRESS_TRANSLATION_FAULT_BIT) + { + return(TX_FALSE); + } + + return(TX_TRUE); +} + +ULONG _txm_module_manager_current_asid_get(VOID) +{ +ULONG contextidr; + + __asm volatile ("MRC p15, 0, %0, c13, c0, 1" : "=r"(contextidr) : : ); + + return(contextidr & TXM_CONTEXTIDR_ASID_MASK); +} +PRIMITIVES + +"$CC" -mcpu=cortex-a7 -marm -O1 -std=gnu99 -Wall -Wextra -Werror \ + --specs=rdimon.specs \ + -I"$ROOT/ports_module/cortex_a7/gnu/inc" \ + -I"$ROOT/common/inc" \ + -I"$ROOT/common_modules/inc" \ + -I"$ROOT/common_modules/module_manager/inc" \ + -o "$work/mmu_test.elf" "$SRC" "$PORT" "$work/primitives.c" || { + echo "FAIL: the Cortex-A7 MMU test image did not build." + exit 1 +} + +output="$("$QEMU_BIN" -M realview-pb-a8 -cpu cortex-a7 -m 128 -nographic \ + -semihosting -kernel "$work/mmu_test.elf" 2>/dev/null)" +status=$? + +echo "$output" + +if [ $status -ne 0 ] || ! echo "$output" | grep -q "SUCCESS!"; then + echo "FAIL: the Cortex-A7 MMU test did not report success." + exit 1 +fi + +exit 0 diff --git a/test/tx/cmake/module_manager/CMakeLists.txt b/test/tx/cmake/module_manager/CMakeLists.txt index 2ebd9684a..17511fd59 100644 --- a/test/tx/cmake/module_manager/CMakeLists.txt +++ b/test/tx/cmake/module_manager/CMakeLists.txt @@ -236,3 +236,19 @@ target_compile_options( add_test(${CMAKE_BUILD_TYPE}::threadx_module_manager_queue_message_range_test threadx_module_manager_queue_message_range_test) + +add_executable( + threadx_module_manager_cortex_a7_range_check_test + ${SOURCE_DIR}/threadx_module_manager_cortex_a7_range_check_test.c + ${cortex_a7_module_dir}/module_manager/src/txm_module_manager_inside_data_check.c) + +target_include_directories( + threadx_module_manager_cortex_a7_range_check_test + PRIVATE ${REPO_ROOT}/common/inc + ${REPO_ROOT}/ports/cortex_a7/gnu/inc + ${REPO_ROOT}/common_modules/inc + ${REPO_ROOT}/common_modules/module_manager/inc + ${cortex_a7_module_dir}/inc) + +add_test(${CMAKE_BUILD_TYPE}::threadx_module_manager_cortex_a7_range_check_test + threadx_module_manager_cortex_a7_range_check_test) diff --git a/test/tx/module_manager/threadx_module_manager_cortex_a7_mmu_test.c b/test/tx/module_manager/threadx_module_manager_cortex_a7_mmu_test.c new file mode 100644 index 000000000..8cc08108d --- /dev/null +++ b/test/tx/module_manager/threadx_module_manager_cortex_a7_mmu_test.c @@ -0,0 +1,205 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Test */ +/** */ +/** Module Manager Cortex-A7 range validation, against a live MMU */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +/* The host test for this check stands a simulated page map behind the port's + one architecture primitive, which lets it run everywhere but leaves the CP15 + address translation itself unexercised: an encoding that named the wrong + operation, or a PAR fault bit read the wrong way round, would pass it. + + This test closes that gap. It builds a short-descriptor translation table, + turns the MMU on, and drives the real check through the real translation + operations on a real Cortex-A7 translation regime. It is a bare-metal image, + built and run by scripts/check_module_mmu_a7.sh under an emulator. + + The sections below are mapped for their access permissions only; nothing is + dereferenced through them, and none of the addresses name a real target. */ + +#include + +#define TX_SOURCE_CODE + +#include "tx_api.h" +#include "txm_module.h" + + +/* Short-descriptor section entry fields. AP[2:0] selects the access + permissions: 011 is unprivileged read/write, 010 is unprivileged read only, + 001 leaves the section privileged-only. */ + +#define TEST_SECTION_TYPE 0x00000002 +#define TEST_AP_LOW(value) (((ULONG) (value)) << 10) +#define TEST_AP_USER_RW TEST_AP_LOW(3) +#define TEST_AP_USER_RO TEST_AP_LOW(2) +#define TEST_AP_PRIVILEGED_ONLY TEST_AP_LOW(1) + +#define TEST_LEVEL1_ENTRIES 4096 +#define TEST_SECTION_SIZE 0x00100000 + +/* One section of each kind the check has to tell apart, plus an unmapped + section immediately after the read-only one so a range can be made to leave + its mapping partway through. */ + +#define TEST_SHARED_RW 0x40000000 +#define TEST_SHARED_RO 0x40100000 +#define TEST_GUARD 0x40200000 +#define TEST_MODULE_DATA 0x41000000 +#define TEST_MODULE_DATA_SIZE 0x00001000 +#define TEST_KERNEL_ONLY 0x30000000 + +static ULONG test_level1_table[TEST_LEVEL1_ENTRIES] __attribute__((aligned(16384))); +static UINT test_failures = 0; + + +/* Reproduce the behaviour this check replaced: one translation of the first + address, for reading, with the size discarded. Kept so the boundary cases + can show both answers against the same live MMU. */ +static UINT test_first_address_only_check(ALIGN_TYPE obj_ptr) +{ + return(_txm_module_manager_address_probe((ULONG) obj_ptr, TXM_MODULE_MANAGER_ACCESS_READ)); +} + + +/* Build a flat translation table, then enable the MMU. */ +static VOID test_mmu_enable(VOID) +{ + +ULONG index; +ULONG sctlr; +ULONG zero = 0; +ULONG dacr = 1; /* Domain 0 as a client, so AP is checked. */ + + + /* Everything is privileged-only until a section below says otherwise. */ + for (index = 0; index < TEST_LEVEL1_ENTRIES; index++) + { + test_level1_table[index] = (index * TEST_SECTION_SIZE) | TEST_SECTION_TYPE | TEST_AP_PRIVILEGED_ONLY; + } + + test_level1_table[TEST_SHARED_RW / TEST_SECTION_SIZE] = + TEST_SHARED_RW | TEST_SECTION_TYPE | TEST_AP_USER_RW; + test_level1_table[TEST_SHARED_RO / TEST_SECTION_SIZE] = + TEST_SHARED_RO | TEST_SECTION_TYPE | TEST_AP_USER_RO; + test_level1_table[TEST_MODULE_DATA / TEST_SECTION_SIZE] = + TEST_MODULE_DATA | TEST_SECTION_TYPE | TEST_AP_USER_RW; + + /* Leave the guard section faulting. */ + test_level1_table[TEST_GUARD / TEST_SECTION_SIZE] = 0; + + __asm volatile ("MCR p15, 0, %0, c2, c0, 2" : : "r"(zero)); /* TTBCR */ + __asm volatile ("MCR p15, 0, %0, c2, c0, 0" : : "r"((ULONG) test_level1_table)); /* TTBR0 */ + __asm volatile ("MCR p15, 0, %0, c3, c0, 0" : : "r"(dacr)); /* DACR */ + __asm volatile ("MCR p15, 0, %0, c13, c0, 1" : : "r"(zero)); /* CONTEXTIDR */ + __asm volatile ("MCR p15, 0, %0, c8, c7, 0" : : "r"(zero)); /* TLBIALL */ + __asm volatile ("DSB"); + __asm volatile ("ISB"); + + __asm volatile ("MRC p15, 0, %0, c1, c0, 0" : "=r"(sctlr)); + sctlr = sctlr | ((ULONG) 1); /* SCTLR.M */ + __asm volatile ("MCR p15, 0, %0, c1, c0, 0" : : "r"(sctlr)); + __asm volatile ("ISB"); +} + + +static VOID test_expect(const char *description, UINT actual, UINT expected) +{ + if (actual != expected) + { + printf(" FAIL: %s (expected %u, got %u)\n", description, expected, actual); + test_failures++; + } +} + + +int main(VOID) +{ + +TXM_MODULE_INSTANCE module; +TXM_MODULE_INSTANCE *module_instance; +ALIGN_TYPE straddle; + + + printf("Cortex-A7 module range validation against a live MMU................... "); + + test_mmu_enable(); + + module_instance = &module; + module_instance -> txm_module_instance_id = TXM_MODULE_ID; + module_instance -> txm_module_instance_data_start = (VOID *) TEST_MODULE_DATA; + module_instance -> txm_module_instance_data_end = (VOID *) (TEST_MODULE_DATA + TEST_MODULE_DATA_SIZE - 1); + module_instance -> txm_module_instance_code_start = (VOID *) 0; + module_instance -> txm_module_instance_code_end = (VOID *) 0; + module_instance -> txm_module_instance_asid = 0; + + /* The module's own data is answered from the manager's records. */ + test_expect("recorded module data is writable", + _txm_module_manager_inside_data_check(module_instance, (ALIGN_TYPE) TEST_MODULE_DATA, 4, + TXM_MODULE_MANAGER_ACCESS_WRITE), TX_TRUE); + test_expect("a range crossing the recorded data end is rejected", + _txm_module_manager_inside_data_check(module_instance, + (ALIGN_TYPE) (TEST_MODULE_DATA + TEST_MODULE_DATA_SIZE - 2), 4, + TXM_MODULE_MANAGER_ACCESS_WRITE), TX_FALSE); + + /* Shared memory is answered by the MMU, one page at a time. */ + test_expect("shared read/write memory is writable", + _txm_module_manager_inside_data_check(module_instance, (ALIGN_TYPE) TEST_SHARED_RW, 4, + TXM_MODULE_MANAGER_ACCESS_WRITE), TX_TRUE); + test_expect("shared read-only memory is readable", + _txm_module_manager_inside_data_check(module_instance, (ALIGN_TYPE) TEST_SHARED_RO, 4, + TXM_MODULE_MANAGER_ACCESS_READ), TX_TRUE); + + /* The write intent is the reason the port asks for two translations rather + than one; a read-only mapping must not serve as a kernel destination. */ + test_expect("shared read-only memory is not writable", + _txm_module_manager_inside_data_check(module_instance, (ALIGN_TYPE) TEST_SHARED_RO, 4, + TXM_MODULE_MANAGER_ACCESS_WRITE), TX_FALSE); + + /* A range that leaves its mapping partway through. This is the case the + replaced check accepted, and the reason this test exists. */ + straddle = (ALIGN_TYPE) (TEST_GUARD - 2); + test_expect("a range crossing into the guard section is rejected", + _txm_module_manager_inside_data_check(module_instance, straddle, 4, + TXM_MODULE_MANAGER_ACCESS_READ), TX_FALSE); + test_expect("...and translating only its first address would have accepted it", + test_first_address_only_check(straddle), TX_TRUE); + + /* Privileged memory is reachable by neither intent, and is outside the module. */ + test_expect("privileged-only memory is not readable", + _txm_module_manager_inside_data_check(module_instance, (ALIGN_TYPE) TEST_KERNEL_ONLY, 4, + TXM_MODULE_MANAGER_ACCESS_READ), TX_FALSE); + test_expect("privileged-only memory is outside the module", + _txm_module_manager_outside_data_check(module_instance, (ALIGN_TYPE) TEST_KERNEL_ONLY, 64), TX_TRUE); + test_expect("shared memory is not outside the module", + _txm_module_manager_outside_data_check(module_instance, (ALIGN_TYPE) TEST_SHARED_RW, 64), TX_FALSE); + + if (test_failures == 0) + { + printf("SUCCESS!\n"); + return(0); + } + + printf("ERROR: %u expectation(s) failed\n", test_failures); + return(1); +} diff --git a/test/tx/module_manager/threadx_module_manager_cortex_a7_range_check_test.c b/test/tx/module_manager/threadx_module_manager_cortex_a7_range_check_test.c new file mode 100644 index 000000000..a0cca868e --- /dev/null +++ b/test/tx/module_manager/threadx_module_manager_cortex_a7_range_check_test.c @@ -0,0 +1,443 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + + +/**************************************************************************/ +/**************************************************************************/ +/** */ +/** ThreadX Test */ +/** */ +/** Module Manager Cortex-A7 data range validation */ +/** */ +/**************************************************************************/ +/**************************************************************************/ + +/* This test exercises the Cortex-A7 module data range check through the same + macros the module dispatchers use. The check normally asks the MMU about one + page at a time, so the test stands a simulated page map behind that one + architecture primitive and drives every outcome from the host build. + + No address in this test is dereferenced and none of them name a real target. + They are labels in a table that the stubbed primitive answers questions about, + which is what lets the test describe a range that leaves a module's mapping + without ever building something that could read past one. */ + +#include + +#define TX_SOURCE_CODE + +#include "tx_api.h" +#include "txm_module.h" +#include "txm_module_manager_util.h" + + +/* Define the simulated address space. + + The module's recorded data region deliberately ends partway through its last + page, because that is what the module manager's page-granular mapping does in + practice: the mapping reaches to the end of the page while the recorded region + does not. The bytes in between are the rounding slack, and the check must not + hand them out. */ + +#define TEST_PAGE_SIZE 4096 + +#define TEST_DATA_START 0x20001000UL +#define TEST_DATA_END 0x200027FFUL /* Ends mid-page: slack follows. */ +#define TEST_DATA_WINDOW_END 0x20002FFFUL /* Last byte the MMU maps for it. */ + +#define TEST_CODE_START 0x10001000UL +#define TEST_CODE_END 0x10001FFFUL + +#define TEST_SHARED_RW_START 0x20010000UL /* Two contiguous read/write pages. */ +#define TEST_SHARED_RW_END 0x20011FFFUL +#define TEST_GUARD_PAGE 0x20012000UL /* Unmapped, directly after them. */ + +#define TEST_SPLIT_FIRST_PAGE 0x20030000UL /* Mapped. */ +#define TEST_SPLIT_MIDDLE_PAGE 0x20031000UL /* Unmapped. */ +#define TEST_SPLIT_LAST_PAGE 0x20032000UL /* Mapped. */ + +#define TEST_SHARED_RO_START 0x20020000UL /* Readable, not writable. */ +#define TEST_SHARED_RO_END 0x20020FFFUL + +#define TEST_KERNEL_OBJECT 0x30000000UL /* Unmapped for the module. */ + +#define TEST_MODULE_ASID 5UL +#define TEST_OTHER_MODULE_ASID 6UL + + +/* Define one entry of the simulated page map. */ + +typedef struct TEST_PAGE_STRUCT +{ + ULONG test_page_base; + UINT test_page_readable; + UINT test_page_writable; +} TEST_PAGE; + + +static TEST_PAGE test_page_map[] = +{ + /* The module's own data pages, mapped read/write to the end of the page. */ + {TEST_DATA_START, TX_TRUE, TX_TRUE}, + {TEST_DATA_START + TEST_PAGE_SIZE, TX_TRUE, TX_TRUE}, + + /* The module's code, readable but never writable from unprivileged mode. */ + {TEST_CODE_START, TX_TRUE, TX_FALSE}, + + /* Read/write shared memory, followed by an unmapped guard page. */ + {TEST_SHARED_RW_START, TX_TRUE, TX_TRUE}, + {TEST_SHARED_RW_START + TEST_PAGE_SIZE, TX_TRUE, TX_TRUE}, + + /* Read-only shared memory. */ + {TEST_SHARED_RO_START, TX_TRUE, TX_FALSE}, + + /* Two mapped pages with an unmapped page between them. */ + {TEST_SPLIT_FIRST_PAGE, TX_TRUE, TX_TRUE}, + {TEST_SPLIT_LAST_PAGE, TX_TRUE, TX_TRUE} +}; + +#define TEST_PAGE_MAP_ENTRIES (sizeof(test_page_map) / sizeof(test_page_map[0])) + + +/* Define the state the stubbed architecture primitives answer from. */ + +static ULONG test_current_asid = TEST_MODULE_ASID; +static ULONG test_probe_count = 0UL; +static UINT test_failures = 0U; + + +/* Stand in for the CP15 address translation the real port performs. */ +UINT _txm_module_manager_address_probe(ULONG address, UINT write_request) +{ + +ULONG page_base; +ULONG index; +UINT granted; + + + test_probe_count++; + + page_base = address & (~((ULONG) (TEST_PAGE_SIZE - 1))); + granted = TX_FALSE; + + for (index = 0UL; index < (ULONG) TEST_PAGE_MAP_ENTRIES; index++) + { + if (test_page_map[index].test_page_base == page_base) + { + if (write_request == TXM_MODULE_MANAGER_ACCESS_WRITE) + { + granted = test_page_map[index].test_page_writable; + } + else + { + granted = test_page_map[index].test_page_readable; + } + } + } + + return(granted); +} + + +/* Stand in for the CONTEXTIDR read the real port performs. */ +ULONG _txm_module_manager_current_asid_get(VOID) +{ + return(test_current_asid); +} + + +/* Model the implementation this test guards against. It translated the first + address of the range and nothing else, and it only ever asked about reading. + Keeping it here lets each boundary case show both answers side by side. */ +static UINT test_first_address_only_check(ALIGN_TYPE obj_ptr) +{ + return(_txm_module_manager_address_probe((ULONG) obj_ptr, TXM_MODULE_MANAGER_ACCESS_READ)); +} + + +/* Record the outcome of one expectation. */ +static VOID test_expect(const char *description, UINT actual, UINT expected) +{ + if (actual != expected) + { + printf("FAIL: %s (expected %u, got %u)\n", description, expected, actual); + test_failures++; + } +} + + +/* Build a module instance describing the simulated module. */ +static VOID test_module_build(TXM_MODULE_INSTANCE *module_instance) +{ + module_instance -> txm_module_instance_id = TXM_MODULE_ID; + module_instance -> txm_module_instance_data_start = (VOID *) TEST_DATA_START; + module_instance -> txm_module_instance_data_end = (VOID *) TEST_DATA_END; + module_instance -> txm_module_instance_code_start = (VOID *) TEST_CODE_START; + module_instance -> txm_module_instance_code_end = (VOID *) TEST_CODE_END; + module_instance -> txm_module_instance_asid = TEST_MODULE_ASID; +} + + +int main(void) +{ + +TXM_MODULE_INSTANCE module; +TXM_MODULE_INSTANCE *module_instance; +ALIGN_TYPE address; +ULONG probes_before; +ULONG huge_size; + + + printf("Cortex-A7 module data range validation test............................ "); + + module_instance = &module; + test_module_build(module_instance); + + /**********************************************************************/ + /* Normal valid behaviour. */ + /**********************************************************************/ + + test_expect("one byte inside module data is writable", + TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, (ALIGN_TYPE) TEST_DATA_START, 1UL), TX_TRUE); + + test_expect("one word inside module data is writable", + TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, (ALIGN_TYPE) TEST_DATA_START, (ULONG) sizeof(ULONG)), TX_TRUE); + + test_expect("one word inside module data is readable", + TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_READ(module_instance, (ALIGN_TYPE) TEST_DATA_START, (ULONG) sizeof(ULONG)), TX_TRUE); + + test_expect("a range spanning both module data pages is writable", + TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, (ALIGN_TYPE) TEST_DATA_START, 0x1800UL), TX_TRUE); + + /* The module's own data is answered from the manager's records, so it costs + no translations at all. This is what keeps the common case deterministic. */ + probes_before = test_probe_count; + (VOID) TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, (ALIGN_TYPE) TEST_DATA_START, 0x1800UL); + test_expect("module data is answered without translating", + (UINT) (test_probe_count == probes_before), TX_TRUE); + + /**********************************************************************/ + /* Null and invalid parameters. */ + /**********************************************************************/ + + /* A null buffer is how the dispatchers say "not supplied", and the macros + accept it. Only the range check below it must reject a null module. */ + test_expect("a null buffer pointer is accepted by the buffer macros", + TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, (ALIGN_TYPE) 0, (ULONG) sizeof(ULONG)), TX_TRUE); + + test_expect("a null module instance is rejected", + _txm_module_manager_inside_data_check(TX_NULL, (ALIGN_TYPE) TEST_DATA_START, (ULONG) sizeof(ULONG), TXM_MODULE_MANAGER_ACCESS_WRITE), TX_FALSE); + + test_expect("a null module instance is not outside anything either", + _txm_module_manager_outside_data_check(TX_NULL, (ALIGN_TYPE) TEST_KERNEL_OBJECT, (ULONG) sizeof(ULONG)), TX_FALSE); + + /* A module torn down to an empty data region owns nothing, and the address + range must then be settled by the MMU rather than by stale records. */ + module.txm_module_instance_data_start = (VOID *) TEST_DATA_END; + module.txm_module_instance_data_end = (VOID *) TEST_DATA_START; + test_expect("an inverted data region grants nothing from records", + _txm_module_manager_inside_data_check(module_instance, (ALIGN_TYPE) TEST_KERNEL_OBJECT, (ULONG) sizeof(ULONG), TXM_MODULE_MANAGER_ACCESS_WRITE), TX_FALSE); + test_module_build(module_instance); + + /**********************************************************************/ + /* Exact boundaries, and the one byte past each of them. */ + /**********************************************************************/ + + test_expect("a range starting exactly at data start is accepted", + TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, (ALIGN_TYPE) TEST_DATA_START, 4UL), TX_TRUE); + + test_expect("a range starting one byte before data start is rejected", + TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, (ALIGN_TYPE) (TEST_DATA_START - 1UL), 4UL), TX_FALSE); + + test_expect("a range ending exactly at data end is accepted", + TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, (ALIGN_TYPE) (TEST_DATA_END - 3UL), 4UL), TX_TRUE); + + test_expect("the last byte of data on its own is accepted", + TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, (ALIGN_TYPE) TEST_DATA_END, 1UL), TX_TRUE); + + /* One byte further is the rounding slack: mapped, but not the module's. */ + address = (ALIGN_TYPE) (TEST_DATA_END - 3UL); + test_expect("a range ending one byte past data end is rejected", + TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, address, 5UL), TX_FALSE); + test_expect("...and the first-address-only check would have accepted it", + test_first_address_only_check(address), TX_TRUE); + + test_expect("the one-past-the-end byte is rejected on its own", + TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, (ALIGN_TYPE) (TEST_DATA_END + 1UL), 1UL), TX_FALSE); + + test_expect("the whole rounding slack is rejected", + TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, (ALIGN_TYPE) (TEST_DATA_END + 1UL), (ULONG) (TEST_DATA_WINDOW_END - TEST_DATA_END)), TX_FALSE); + + /* A word that straddles the recorded end crosses it by one word. */ + address = (ALIGN_TYPE) (TEST_DATA_END - 1UL); + test_expect("a word straddling data end is rejected", + TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, address, (ULONG) sizeof(ULONG)), TX_FALSE); + test_expect("...and the first-address-only check would have accepted it", + test_first_address_only_check(address), TX_TRUE); + + /**********************************************************************/ + /* Integer overflow and underflow. */ + /**********************************************************************/ + + test_expect("a zero-length range is rejected", + TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, (ALIGN_TYPE) TEST_DATA_START, 0UL), TX_FALSE); + + /* A range whose end wraps must be refused before anything is computed from + the wrapped address. */ + probes_before = test_probe_count; + test_expect("a range whose end wraps past the top of memory is rejected", + TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, (ALIGN_TYPE) TEST_DATA_START, 0xFFFFFFFFUL), TX_FALSE); + test_expect("...without translating the wrapped address", + (UINT) (test_probe_count == probes_before), TX_TRUE); + + test_expect("a range starting at the very top of memory with size two is rejected", + TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, (ALIGN_TYPE) 0xFFFFFFFFUL, 2UL), TX_FALSE); + + test_expect("a one-byte range at the very top of memory does not wrap, and is simply unmapped", + TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, (ALIGN_TYPE) 0xFFFFFFFFUL, 1UL), TX_FALSE); + + test_expect("a zero-length range is not outside the module either", + _txm_module_manager_outside_data_check(module_instance, (ALIGN_TYPE) TEST_KERNEL_OBJECT, 0UL), TX_FALSE); + + /**********************************************************************/ + /* Shared memory, guard pages, and holes. */ + /**********************************************************************/ + + test_expect("a range inside read/write shared memory is writable", + TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, (ALIGN_TYPE) TEST_SHARED_RW_START, (ULONG) sizeof(ULONG)), TX_TRUE); + + test_expect("a range spanning two shared pages is writable", + TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, (ALIGN_TYPE) TEST_SHARED_RW_START, 0x1800UL), TX_TRUE); + + test_expect("a range ending exactly at the end of shared memory is accepted", + TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, (ALIGN_TYPE) (TEST_SHARED_RW_END - 3UL), 4UL), TX_TRUE); + + /* One byte more crosses into the guard page. */ + address = (ALIGN_TYPE) (TEST_SHARED_RW_END - 3UL); + test_expect("a range crossing one byte into the guard page is rejected", + TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, address, 5UL), TX_FALSE); + test_expect("...and the first-address-only check would have accepted it", + test_first_address_only_check(address), TX_TRUE); + + test_expect("a three-page range with an unmapped middle page is rejected", + TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, (ALIGN_TYPE) TEST_SPLIT_FIRST_PAGE, (ULONG) ((TEST_SPLIT_LAST_PAGE + 4UL) - TEST_SPLIT_FIRST_PAGE)), TX_FALSE); + + test_expect("the first page of that range on its own is still accepted", + TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, (ALIGN_TYPE) TEST_SPLIT_FIRST_PAGE, 4UL), TX_TRUE); + + /**********************************************************************/ + /* Read intent versus write intent. */ + /**********************************************************************/ + + test_expect("read-only shared memory can be read from", + TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_READ(module_instance, (ALIGN_TYPE) TEST_SHARED_RO_START, (ULONG) sizeof(ULONG)), TX_TRUE); + + test_expect("read-only shared memory cannot be written to", + TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, (ALIGN_TYPE) TEST_SHARED_RO_START, (ULONG) sizeof(ULONG)), TX_FALSE); + + test_expect("a read-only shared range crossing its own end is rejected for reading too", + TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_READ(module_instance, (ALIGN_TYPE) (TEST_SHARED_RO_END - 3UL), 5UL), TX_FALSE); + + test_expect("module code can be read from", + TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_READ(module_instance, (ALIGN_TYPE) TEST_CODE_START, (ULONG) sizeof(ULONG)), TX_TRUE); + + test_expect("module code cannot be used as a kernel write destination", + TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, (ALIGN_TYPE) TEST_CODE_START, (ULONG) sizeof(ULONG)), TX_FALSE); + + test_expect("a string may be dereferenced out of module code", + TXM_MODULE_MANAGER_PARAM_CHECK_DEREFERENCE_STRING(module_instance, (ALIGN_TYPE) TEST_CODE_START), TX_TRUE); + + test_expect("a range running off the end of module code is rejected", + TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_READ(module_instance, (ALIGN_TYPE) (TEST_CODE_END - 3UL), 5UL), TX_FALSE); + + /**********************************************************************/ + /* The outside direction. */ + /**********************************************************************/ + + test_expect("a kernel object clear of the module is outside it", + TXM_MODULE_MANAGER_ENSURE_OUTSIDE_MODULE(module_instance, (ALIGN_TYPE) TEST_KERNEL_OBJECT, 64UL), TX_TRUE); + + test_expect("the module's own data is not outside it", + TXM_MODULE_MANAGER_ENSURE_OUTSIDE_MODULE(module_instance, (ALIGN_TYPE) TEST_DATA_START, 64UL), TX_FALSE); + + test_expect("shared memory is not outside the module", + TXM_MODULE_MANAGER_ENSURE_OUTSIDE_MODULE(module_instance, (ALIGN_TYPE) TEST_SHARED_RW_START, 64UL), TX_FALSE); + + test_expect("module code is not outside the module", + TXM_MODULE_MANAGER_ENSURE_OUTSIDE_MODULE(module_instance, (ALIGN_TYPE) TEST_CODE_START, 64UL), TX_FALSE); + + /* A range that reaches into the module only partway is inside neither answer. + Reporting it as outside would let it pass as a kernel object, which is the + mirror image of the defect this test guards against. */ + test_expect("a range straddling the end of module data is not outside it", + TXM_MODULE_MANAGER_ENSURE_OUTSIDE_MODULE(module_instance, (ALIGN_TYPE) (TEST_DATA_END - 3UL), 16UL), TX_FALSE); + + test_expect("a range straddling the guard page after shared memory is not outside the module", + TXM_MODULE_MANAGER_ENSURE_OUTSIDE_MODULE(module_instance, (ALIGN_TYPE) (TEST_SHARED_RW_END - 3UL), 16UL), TX_FALSE); + + /**********************************************************************/ + /* Cross-module and application-owned memory. */ + /**********************************************************************/ + + /* Translation answers for whichever context is loaded. If another module's + context is loaded, this module's records and the MMU disagree, so neither + check may answer at all. */ + test_current_asid = TEST_OTHER_MODULE_ASID; + + test_expect("nothing is inside the module while another context is loaded", + TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, (ALIGN_TYPE) TEST_DATA_START, (ULONG) sizeof(ULONG)), TX_FALSE); + + test_expect("nothing is provably outside it either", + TXM_MODULE_MANAGER_ENSURE_OUTSIDE_MODULE(module_instance, (ALIGN_TYPE) TEST_KERNEL_OBJECT, 64UL), TX_FALSE); + + test_current_asid = TEST_MODULE_ASID; + + test_expect("the module is served again once its own context is loaded", + TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, (ALIGN_TYPE) TEST_DATA_START, (ULONG) sizeof(ULONG)), TX_TRUE); + + /**********************************************************************/ + /* The bound on how much work one request may ask for. */ + /**********************************************************************/ + + huge_size = ((ULONG) TXM_MODULE_MANAGER_DATA_CHECK_MAX_PAGES) * ((ULONG) TEST_PAGE_SIZE); + + probes_before = test_probe_count; + test_expect("a range one page longer than the maximum is rejected", + TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, (ALIGN_TYPE) TEST_SHARED_RW_START, huge_size + 1UL), TX_FALSE); + test_expect("...without translating any of it", + (UINT) (test_probe_count == probes_before), TX_TRUE); + + test_expect("an over-long range is not outside the module either", + _txm_module_manager_outside_data_check(module_instance, (ALIGN_TYPE) TEST_KERNEL_OBJECT, huge_size + 1UL), TX_FALSE); + + /* A range at exactly the maximum is still walked, and the walk stops at the + first page that fails rather than translating all of it. */ + probes_before = test_probe_count; + test_expect("a range of exactly the maximum length is walked and rejected here", + TXM_MODULE_MANAGER_PARAM_CHECK_BUFFER_WRITE(module_instance, (ALIGN_TYPE) TEST_SHARED_RW_START, huge_size), TX_FALSE); + test_expect("...stopping at the first page that fails", + (UINT) ((test_probe_count - probes_before) == 3UL), TX_TRUE); + + /**********************************************************************/ + + if (test_failures == 0U) + { + printf("SUCCESS!\n"); + return(0); + } + + printf("ERROR: %u expectation(s) failed\n", test_failures); + return(1); +} diff --git a/test/tx/module_manager/threadx_module_manager_delete_ownership_test.c b/test/tx/module_manager/threadx_module_manager_delete_ownership_test.c index a84772533..95a85ddc5 100644 --- a/test/tx/module_manager/threadx_module_manager_delete_ownership_test.c +++ b/test/tx/module_manager/threadx_module_manager_delete_ownership_test.c @@ -347,17 +347,56 @@ UINT _txe_mutex_put(TX_MUTEX *mutex_ptr) /* Stand in for the module port's data range check. */ -UINT _txm_module_manager_inside_data_check(ULONG obj_ptr) +UINT _txm_module_manager_inside_data_check(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE obj_ptr, + ULONG obj_size, UINT write_request) { ULONG data_start; ULONG data_end; + (VOID) module_instance; + (VOID) write_request; + + data_start = (ULONG) (ALIGN_TYPE) test_module_data.test_data_bytes; + data_end = data_start + ((ULONG) TEST_MODULE_MEMORY_BYTES); + + /* The whole range has to lie inside the module's data, not just its first + address, and the subtraction is done on the end rather than the start so that + a size which would carry the range past the top of the address space cannot + wrap into an accepting answer. */ + if (((ULONG) obj_ptr >= data_start) && (obj_size <= (data_end - (ULONG) obj_ptr))) + { + return(TX_TRUE); + } + + return(TX_FALSE); +} + + +/* Outside is not the negation of inside: a range that only partly reaches into the + module's data is neither. It has to end before that data begins or begin after it + ends, and a size that would carry the end past the top of the address space is + refused rather than allowed to compare as though it had not. */ +UINT _txm_module_manager_outside_data_check(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE obj_ptr, + ULONG obj_size) +{ + +ULONG data_start; +ULONG data_end; + + + (VOID) module_instance; + data_start = (ULONG) (ALIGN_TYPE) test_module_data.test_data_bytes; data_end = data_start + ((ULONG) TEST_MODULE_MEMORY_BYTES); - if ((obj_ptr >= data_start) && (obj_ptr < data_end)) + if (obj_size > (~((ULONG) 0) - (ULONG) obj_ptr)) + { + return(TX_FALSE); + } + + if ((((ULONG) obj_ptr + obj_size) <= data_start) || ((ULONG) obj_ptr >= data_end)) { return(TX_TRUE); } diff --git a/test/tx/module_manager/threadx_module_manager_live_object_deallocation_test.c b/test/tx/module_manager/threadx_module_manager_live_object_deallocation_test.c index 3eaf95c67..a351ce3b4 100644 --- a/test/tx/module_manager/threadx_module_manager_live_object_deallocation_test.c +++ b/test/tx/module_manager/threadx_module_manager_live_object_deallocation_test.c @@ -318,17 +318,56 @@ UINT _txe_mutex_put(TX_MUTEX *mutex_ptr) /* Stand in for the module port's data range check. */ -UINT _txm_module_manager_inside_data_check(ULONG obj_ptr) +UINT _txm_module_manager_inside_data_check(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE obj_ptr, + ULONG obj_size, UINT write_request) { ULONG data_start; ULONG data_end; + (VOID) module_instance; + (VOID) write_request; + + data_start = (ULONG) (ALIGN_TYPE) test_module_data.test_data_bytes; + data_end = data_start + ((ULONG) TEST_MODULE_MEMORY_BYTES); + + /* The whole range has to lie inside the module's data, not just its first + address, and the subtraction is done on the end rather than the start so that + a size which would carry the range past the top of the address space cannot + wrap into an accepting answer. */ + if (((ULONG) obj_ptr >= data_start) && (obj_size <= (data_end - (ULONG) obj_ptr))) + { + return(TX_TRUE); + } + + return(TX_FALSE); +} + + +/* Outside is not the negation of inside: a range that only partly reaches into the + module's data is neither. It has to end before that data begins or begin after it + ends, and a size that would carry the end past the top of the address space is + refused rather than allowed to compare as though it had not. */ +UINT _txm_module_manager_outside_data_check(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE obj_ptr, + ULONG obj_size) +{ + +ULONG data_start; +ULONG data_end; + + + (VOID) module_instance; + data_start = (ULONG) (ALIGN_TYPE) test_module_data.test_data_bytes; data_end = data_start + ((ULONG) TEST_MODULE_MEMORY_BYTES); - if ((obj_ptr >= data_start) && (obj_ptr < data_end)) + if (obj_size > (~((ULONG) 0) - (ULONG) obj_ptr)) + { + return(TX_FALSE); + } + + if ((((ULONG) obj_ptr + obj_size) <= data_start) || ((ULONG) obj_ptr >= data_end)) { return(TX_TRUE); } diff --git a/test/tx/module_manager/threadx_module_manager_object_allocate_overflow_test.c b/test/tx/module_manager/threadx_module_manager_object_allocate_overflow_test.c index 5989ca48f..38314ba47 100644 --- a/test/tx/module_manager/threadx_module_manager_object_allocate_overflow_test.c +++ b/test/tx/module_manager/threadx_module_manager_object_allocate_overflow_test.c @@ -148,14 +148,30 @@ ULONG _tx_timer_created_count; /* This test models no module memory of its own, so no address is ever inside the calling module's data. */ -UINT _txm_module_manager_inside_data_check(ULONG obj_ptr) +UINT _txm_module_manager_inside_data_check(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE obj_ptr, + ULONG obj_size, UINT write_request) { + (VOID) module_instance; (VOID) obj_ptr; + (VOID) obj_size; + (VOID) write_request; return(TX_FALSE); } +/* No module data is modelled here, so every range lies outside it. */ +UINT _txm_module_manager_outside_data_check(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE obj_ptr, + ULONG obj_size) +{ + (VOID) module_instance; + (VOID) obj_ptr; + (VOID) obj_size; + + return(TX_TRUE); +} + + /* Not reached from the allocation path under test. */ VOID _txm_module_manager_alignment_adjust(TXM_MODULE_PREAMBLE *module_preamble, ULONG *code_size, ULONG *code_alignment, ULONG *data_size, ULONG *data_alignment) diff --git a/test/tx/module_manager/threadx_module_manager_object_authentication_test.c b/test/tx/module_manager/threadx_module_manager_object_authentication_test.c index 6c79efaec..396f57f2d 100644 --- a/test/tx/module_manager/threadx_module_manager_object_authentication_test.c +++ b/test/tx/module_manager/threadx_module_manager_object_authentication_test.c @@ -330,17 +330,56 @@ UINT _txe_mutex_put(TX_MUTEX *mutex_ptr) /* Stand in for the module port's data range check, which the portable outside-the-module test is built on. */ -UINT _txm_module_manager_inside_data_check(ULONG obj_ptr) +UINT _txm_module_manager_inside_data_check(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE obj_ptr, + ULONG obj_size, UINT write_request) { ULONG data_start; ULONG data_end; + (VOID) module_instance; + (VOID) write_request; + + data_start = (ULONG) (ALIGN_TYPE) test_module_data.test_data_bytes; + data_end = data_start + ((ULONG) TEST_MODULE_MEMORY_BYTES); + + /* The whole range has to lie inside the module's data, not just its first + address, and the subtraction is done on the end rather than the start so that + a size which would carry the range past the top of the address space cannot + wrap into an accepting answer. */ + if (((ULONG) obj_ptr >= data_start) && (obj_size <= (data_end - (ULONG) obj_ptr))) + { + return(TX_TRUE); + } + + return(TX_FALSE); +} + + +/* Outside is not the negation of inside: a range that only partly reaches into the + module's data is neither. It has to end before that data begins or begin after it + ends, and a size that would carry the end past the top of the address space is + refused rather than allowed to compare as though it had not. */ +UINT _txm_module_manager_outside_data_check(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE obj_ptr, + ULONG obj_size) +{ + +ULONG data_start; +ULONG data_end; + + + (VOID) module_instance; + data_start = (ULONG) (ALIGN_TYPE) test_module_data.test_data_bytes; data_end = data_start + ((ULONG) TEST_MODULE_MEMORY_BYTES); - if ((obj_ptr >= data_start) && (obj_ptr < data_end)) + if (obj_size > (~((ULONG) 0) - (ULONG) obj_ptr)) + { + return(TX_FALSE); + } + + if ((((ULONG) obj_ptr + obj_size) <= data_start) || ((ULONG) obj_ptr >= data_end)) { return(TX_TRUE); } diff --git a/test/tx/module_manager/threadx_module_manager_thread_kernel_stack_test.c b/test/tx/module_manager/threadx_module_manager_thread_kernel_stack_test.c index e971b1599..1ab911451 100644 --- a/test/tx/module_manager/threadx_module_manager_thread_kernel_stack_test.c +++ b/test/tx/module_manager/threadx_module_manager_thread_kernel_stack_test.c @@ -252,15 +252,30 @@ ULONG index; /* Stand in for the module port's data-range check. Nothing here is inside a module's own data, so every address the manager asks about is outside it. */ -UINT _txm_module_manager_inside_data_check(ULONG obj_ptr) +UINT _txm_module_manager_inside_data_check(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE obj_ptr, + ULONG obj_size, UINT write_request) { - + (VOID) module_instance; (VOID) obj_ptr; + (VOID) obj_size; + (VOID) write_request; return(TX_FALSE); } +/* No module data is modelled here, so every range lies outside it. */ +UINT _txm_module_manager_outside_data_check(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE obj_ptr, + ULONG obj_size) +{ + (VOID) module_instance; + (VOID) obj_ptr; + (VOID) obj_size; + + return(TX_TRUE); +} + + /* Stand in for the module port's alignment adjustment. It is referenced by a loading path this test does not drive, and is never reached from here. */ VOID _txm_module_manager_alignment_adjust(TXM_MODULE_PREAMBLE *module_preamble, ULONG *code_size, From 47a5259002b0e51e7fbce1807f05a6987fe0ccd1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 28 Sep 2026 12:42:20 -0400 Subject: [PATCH 161/181] Stopped the SMP Linux port losing a mutex wake-up to a suspend signal (#753) The SMP Linux port suspends a thread with a signal whose handler calls sigsuspend and does not return until the thread is resumed. That signal can arrive while the thread is parked in pthread_mutex_lock on _tx_linux_mutex; the port knows it can, because _tx_linux_mutex_obtain sets tx_thread_linux_mutex_access around the lock call for exactly this case, and nothing anywhere reads that flag. glibc waits for a contended mutex in a loop that re-arms the futex wait after a signal, and this handler never returns to it. The next release hands its wake-up to that thread, which will not act on it, and any other thread parked on the mutex is never woken, leaving the mutex free with waiters on it. That deadlocks the process: the only thread that can resume the suspended one is the scheduler, and the scheduler takes this mutex on every pass. _tx_linux_mutex_obtain now waits with pthread_mutex_timedlock and retries, so the wait is re-armed every TX_LINUX_MUTEX_RETRY_NSEC and a lost wake-up costs one retry period instead of the process. The period is one millisecond, half the scheduler's own idle period. Nothing else changes. Four hung processes captured untraced, across three tests, show the same state: a thread in sigsuspend on top of pthread_mutex_lock, the scheduler blocked in pthread_mutex_lock, and the mutex reading free. Standalone, threadx_smp_random_resume_suspend_exclusion_test hung 3 times in 100 runs and 2 in 55 before the change and 0 in 400 after it. Assisted-by: Claude Code (Opus 5) --- ports_smp/linux/gnu/inc/tx_port.h | 10 +++++ ports_smp/linux/gnu/src/tx_thread_schedule.c | 41 +++++++++++++++++++- 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/ports_smp/linux/gnu/inc/tx_port.h b/ports_smp/linux/gnu/inc/tx_port.h index dc1aeade2..53a4dc03f 100644 --- a/ports_smp/linux/gnu/inc/tx_port.h +++ b/ports_smp/linux/gnu/inc/tx_port.h @@ -513,6 +513,16 @@ typedef struct } TX_LINUX_MUTEX; +/* Define how long a thread waits on the Linux mutex before retrying. A thread + parked on the mutex can be suspended by the port's signal handler and so never + act on the wake-up the next release sends it, which leaves the wake-up lost + and every other waiter parked on a mutex that is free. */ + +#ifndef TX_LINUX_MUTEX_RETRY_NSEC +#define TX_LINUX_MUTEX_RETRY_NSEC 1000000 +#endif + + /* Define Linux-specific critical section APIs. */ void _tx_linux_mutex_obtain(TX_LINUX_MUTEX *mutex); diff --git a/ports_smp/linux/gnu/src/tx_thread_schedule.c b/ports_smp/linux/gnu/src/tx_thread_schedule.c index 0c3e8e326..0b6eba259 100644 --- a/ports_smp/linux/gnu/src/tx_thread_schedule.c +++ b/ports_smp/linux/gnu/src/tx_thread_schedule.c @@ -292,6 +292,8 @@ void _tx_linux_mutex_obtain(TX_LINUX_MUTEX *mutex) TX_THREAD *thread_ptr; pthread_t current_thread_id; UINT i; +INT linux_status; +struct timespec ts; /* Pickup the current thread ID. */ current_thread_id = pthread_self(); @@ -343,8 +345,43 @@ UINT i; thread_ptr -> tx_thread_linux_mutex_access = TX_TRUE; } - /* Get the Linux mutex. */ - pthread_mutex_lock(&mutex -> tx_linux_mutex); + /* Get the Linux mutex. The wait is timed and retried rather than left + to pthread_mutex_lock, because a thread can be signalled into the + port's suspend handler while it is parked on this mutex. That handler + does not return until the thread is resumed, so the wake-up the next + release sends is delivered to a thread that never retries and is lost. + Any other thread parked on the mutex then waits on a mutex that is + free, which on this port deadlocks the whole process: the thread that + can resume the suspended one is the scheduler, and the scheduler takes + this mutex on every pass. Retrying on a timeout costs nothing when + the mutex is handed over normally, and turns that lost wake-up into a + delay of at most the retry period. */ + do + { + + /* Set the deadline for this attempt. */ + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_nsec = ts.tv_nsec + TX_LINUX_MUTEX_RETRY_NSEC; + if (ts.tv_nsec >= 1000000000) + { + + ts.tv_nsec = ts.tv_nsec - 1000000000; + ts.tv_sec++; + } + + linux_status = pthread_mutex_timedlock(&mutex -> tx_linux_mutex, &ts); + + /* Anything but the deadline expiring is a real failure to obtain the + mutex, so stop retrying and record it. */ + if ((linux_status != 0) && (linux_status != ETIMEDOUT)) + { + + /* Increment the system error counter. */ + _tx_linux_system_error++; + break; + } + + } while (linux_status != 0); /* At this point we have the mutex. */ From b567428f2a826fa24e78fc82f6a5dd46a87b079c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 28 Sep 2026 12:42:48 -0400 Subject: [PATCH 162/181] Stopped the Linux port losing a mutex wake-up to a suspend signal (#754) This is the ThreadX half of the defect fixed for ThreadX SMP in an earlier pull request. The Linux port suspends a thread with a signal whose handler calls sigsuspend and does not return until the thread is resumed, and it takes its critical section with a bare pthread_mutex_lock through tx_linux_mutex_lock. A thread can therefore be signalled while it is parked on _tx_linux_mutex. glibc waits for a contended mutex in a loop that re-arms the futex wait after a signal, and this handler never returns to it. The next unlock hands its wake-up to that thread, which will not act on it, and any other thread parked on the mutex is never woken, leaving the mutex free with waiters on it. tx_linux_mutex_lock now calls a helper that waits with pthread_mutex_timedlock and retries, so the wait is re-armed every TX_LINUX_MUTEX_RETRY_NSEC and a lost wake-up costs one retry period instead of the process. The period is one millisecond. pthread_mutex_timedlock needs _GNU_SOURCE under -std=c99, which both of this port's build systems already define. These are the only two ports affected: a sigsuspend-based suspend handler exists in the Linux and SMP Linux ports and nowhere else, and those two are also the only ports taking a critical section with pthread_mutex_lock. Unlike the SMP port, this one has never been observed to deadlock, which is consistent with one emulated core and far less suspend and resume traffic. The fix is by inspection, and verified as breaking nothing: all seven configurations pass with retries disabled, 105/105 in five and 100/100 in two. Assisted-by: Claude Code (Opus 5) --- ports/linux/gnu/inc/tx_port.h | 13 ++++++- ports/linux/gnu/src/tx_thread_schedule.c | 45 ++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/ports/linux/gnu/inc/tx_port.h b/ports/linux/gnu/inc/tx_port.h index 1f7e25f39..db837e4f9 100644 --- a/ports/linux/gnu/inc/tx_port.h +++ b/ports/linux/gnu/inc/tx_port.h @@ -511,7 +511,7 @@ VOID _tx_thread_interrupt_restore(UINT previous_posture); #define TX_RESTORE _tx_linux_debug_entry_insert("RESTORE", __FILE__, __LINE__); \ _tx_thread_interrupt_restore(tx_saved_posture); #endif /* TX_LINUX_DEBUG_ENABLE */ -#define tx_linux_mutex_lock(p) pthread_mutex_lock(&p) +#define tx_linux_mutex_lock(p) _tx_linux_mutex_lock_retry(&p) #define tx_linux_mutex_unlock(p) pthread_mutex_unlock(&p) #define tx_linux_mutex_recursive_unlock(p) {\ int _recursive_count = (int)tx_linux_mutex_recursive_count;\ @@ -552,6 +552,17 @@ extern CHAR _tx_version_id[]; /* Define externals for the Linux port of ThreadX. */ extern pthread_mutex_t _tx_linux_mutex; + +/* Define how long a thread waits on the Linux mutex before retrying. A thread + parked on the mutex can be suspended by the port's signal handler and so never + act on the wake-up the next unlock sends it, which leaves the wake-up lost and + every other waiter parked on a mutex that is free. */ + +#ifndef TX_LINUX_MUTEX_RETRY_NSEC +#define TX_LINUX_MUTEX_RETRY_NSEC 1000000 +#endif + +void _tx_linux_mutex_lock_retry(pthread_mutex_t *mutex); extern sem_t _tx_linux_semaphore; extern sem_t _tx_linux_semaphore_no_idle; extern ULONG _tx_linux_global_int_disabled_flag; diff --git a/ports/linux/gnu/src/tx_thread_schedule.c b/ports/linux/gnu/src/tx_thread_schedule.c index eeff680fc..405ef4b87 100644 --- a/ports/linux/gnu/src/tx_thread_schedule.c +++ b/ports/linux/gnu/src/tx_thread_schedule.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. + /**************************************************************************/ /**************************************************************************/ @@ -201,6 +203,49 @@ struct timespec ts; } } +/* Define the ThreadX Linux mutex lock function. The wait is timed and retried + rather than left to pthread_mutex_lock, because a thread can be signalled into + the port's suspend handler while it is parked on this mutex. That handler does + not return until the thread is resumed, so the wake-up the next unlock sends is + delivered to a thread that never retries and is lost. Any other thread parked + on the mutex then waits on a mutex that is free. Retrying on a timeout costs + nothing when the mutex is handed over normally, and turns that lost wake-up into + a delay of at most the retry period. */ + +void _tx_linux_mutex_lock_retry(pthread_mutex_t *mutex) +{ + +INT linux_status; +struct timespec ts; + + + do + { + + /* Set the deadline for this attempt. */ + clock_gettime(CLOCK_REALTIME, &ts); + ts.tv_nsec = ts.tv_nsec + TX_LINUX_MUTEX_RETRY_NSEC; + if (ts.tv_nsec >= 1000000000) + { + + ts.tv_nsec = ts.tv_nsec - 1000000000; + ts.tv_sec++; + } + + linux_status = pthread_mutex_timedlock(mutex, &ts); + + /* Anything but the deadline expiring is a real failure to obtain the + mutex, so stop retrying. */ + if ((linux_status != 0) && (linux_status != ETIMEDOUT)) + { + + break; + } + + } while (linux_status != 0); +} + + void _tx_thread_delete_port_completion(TX_THREAD *thread_ptr, UINT tx_saved_posture) { INT linux_status; From e3ed79dbab40396ea037aa2f68a5fbdcd6314e2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 28 Sep 2026 12:43:18 -0400 Subject: [PATCH 163/181] Stopped tx_thread_relinquish discarding the rebalance it requests (#758) _tx_thread_relinquish walks the ready list at the relinquishing thread's priority for a thread to hand its core to. When the walk reaches one it cannot place, carrying preemption-threshold or excluded from that thread's mapped core, it sets the rebalance flag and breaks. That exit falls into the block concluding no other thread is ready, which is not what the walk found, and that block sets the finished flag. The rebalance at the end of the function is guarded on that flag, so it never runs. Every rebalance requested from inside the walk is discarded, because that exit always reaches the block first. A ready thread behind the obstacle then never reaches a core while the others hold them and relinquish to each other. The tick keeps arriving, so it is a livelock rather than a deadlock. The early return now applies only when no rebalance was requested, which lets control reach the rebalance path the other three request sites already use. threadx_smp_relinquish_rebalance_test fills the cores with threads of one priority relinquishing in a loop, places a thread excluded from every core behind them and a runnable thread behind that, and fails if the runnable one has not run within 100 ticks. It fails 3 of 3 before this change and passes 5 of 5 after. Instrumenting a passing run of threadx_thread_relinquish_test counted 12 rebalance requests from the walk against 4 performed, all 4 from sites outside it. 109/109 in all eight configurations, twice from clean. Assisted-by: Claude Code (Opus 5) --- common_smp/src/tx_thread_relinquish.c | 8 +- test/smp/cmake/regression/CMakeLists.txt | 1 + .../threadx_smp_relinquish_rebalance_test.c | 250 ++++++++++++++++++ 3 files changed, 257 insertions(+), 2 deletions(-) create mode 100644 test/smp/regression/threadx_smp_relinquish_rebalance_test.c diff --git a/common_smp/src/tx_thread_relinquish.c b/common_smp/src/tx_thread_relinquish.c index 10982b264..f07d2b56d 100644 --- a/common_smp/src/tx_thread_relinquish.c +++ b/common_smp/src/tx_thread_relinquish.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. + /**************************************************************************/ /**************************************************************************/ @@ -290,8 +292,10 @@ UINT finished; } } while ((next_thread != thread_ptr) && (finished == TX_FALSE)); - /* Determine if we are finished. */ - if (finished == TX_FALSE) + /* Determine if we are finished. A rebalance request means the loop stopped + at a thread it could not place rather than running out of threads, so the + execute list still has to be rebuilt and this is not that case. */ + if ((finished == TX_FALSE) && (rebalance == TX_FALSE)) { /* No other thread is ready at this priority... simply return. */ diff --git a/test/smp/cmake/regression/CMakeLists.txt b/test/smp/cmake/regression/CMakeLists.txt index 771fb44dd..cdf0c5859 100644 --- a/test/smp/cmake/regression/CMakeLists.txt +++ b/test/smp/cmake/regression/CMakeLists.txt @@ -86,6 +86,7 @@ set(regression_test_cases ${SOURCE_DIR}/threadx_smp_random_resume_suspend_exclusion_test.c ${SOURCE_DIR}/threadx_smp_random_resume_suspend_test.c ${SOURCE_DIR}/threadx_smp_rebalance_exclusion_test.c + ${SOURCE_DIR}/threadx_smp_relinquish_rebalance_test.c ${SOURCE_DIR}/threadx_smp_relinquish_test.c ${SOURCE_DIR}/threadx_smp_resume_suspend_ascending_order_test.c ${SOURCE_DIR}/threadx_smp_resume_suspend_descending_order_test.c diff --git a/test/smp/regression/threadx_smp_relinquish_rebalance_test.c b/test/smp/regression/threadx_smp_relinquish_rebalance_test.c new file mode 100644 index 000000000..68a887f97 --- /dev/null +++ b/test/smp/regression/threadx_smp_relinquish_rebalance_test.c @@ -0,0 +1,250 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/* Define the ThreadX SMP relinquish rebalance test. This test fills every core with + threads of one priority that relinquish in a loop, and places two more threads of the + same priority behind them in the ready list: one that no core may run, and one that any + core may run. Walking the ready list, a relinquish reaches the unrunnable thread first + and cannot schedule it, so the execute list has to be rebalanced for the runnable thread + to reach a core. The runnable thread never running is the failure this test detects. */ + +#include +#include "tx_api.h" + + +/* Fill the four cores, so a thread behind these in the ready list only reaches a core + through the execute list being rebalanced. */ + +#define SPIN_THREADS 4 + + +/* The spinning threads keep their cores whatever else happens, so they carry the deadline. + One second is three orders of magnitude more than the handful of relinquishes a healthy + system needs, and the tick advances independently of which threads are scheduled. */ + +#define DEADLINE_TICKS 100 + + +static TX_THREAD thread_control; +static TX_THREAD thread_spin[SPIN_THREADS]; +static TX_THREAD thread_blocked; +static TX_THREAD thread_starved; + +static ULONG spin_counter[SPIN_THREADS]; +static ULONG starved_counter; +static ULONG blocked_counter; +static ULONG reported; + + +/* Define thread prototypes. */ + +static void thread_control_entry(ULONG thread_input); +static void thread_spin_entry(ULONG thread_input); +static void thread_blocked_entry(ULONG thread_input); +static void thread_starved_entry(ULONG thread_input); + + +/* Prototype for test control return. */ + +void test_control_return(UINT status); + + +/* Define what the initial system looks like. */ + +#ifdef CTEST +void test_application_define(void *first_unused_memory) +#else +void threadx_smp_relinquish_rebalance_test(void *first_unused_memory) +#endif +{ + +UINT status; +CHAR *pointer; +UINT i; + + + /* Put first available memory address into a character pointer. */ + pointer = (CHAR *) first_unused_memory; + + /* Create the control thread, which only resumes the others and then completes. */ + status = tx_thread_create(&thread_control, "control thread", thread_control_entry, 0, + pointer, TEST_STACK_SIZE_PRINTF, + 0, 0, TX_NO_TIME_SLICE, TX_AUTO_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + status += tx_thread_smp_core_exclude(&thread_control, 0xE); /* Core 0 only! */ + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running SMP Relinquish Rebalance Test............................... ERROR #1\n"); + test_control_return(1); + } + + /* Create one spinning thread per core. */ + for (i = 0; i < SPIN_THREADS; i++) + { + + status = tx_thread_create(&thread_spin[i], "spin thread", thread_spin_entry, i, + pointer, TEST_STACK_SIZE_PRINTF, + 20, 20, TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running SMP Relinquish Rebalance Test............................... ERROR #2\n"); + test_control_return(1); + } + } + + /* Create the thread no core may run. Excluding every core leaves it ready and + permanently unmapped, which is what makes it a stable obstacle in the ready list + rather than a thread that eventually gets a turn. */ + status = tx_thread_create(&thread_blocked, "blocked thread", thread_blocked_entry, 0, + pointer, TEST_STACK_SIZE_PRINTF, + 20, 20, TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + status += tx_thread_smp_core_exclude(&thread_blocked, 0xF); /* No core at all! */ + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running SMP Relinquish Rebalance Test............................... ERROR #3\n"); + test_control_return(1); + } + + /* Create the thread that any core may run. It is resumed last so that it sits behind + the blocked thread in the ready list at this priority. */ + status = tx_thread_create(&thread_starved, "starved thread", thread_starved_entry, 0, + pointer, TEST_STACK_SIZE_PRINTF, + 20, 20, TX_NO_TIME_SLICE, TX_DONT_START); + pointer = pointer + TEST_STACK_SIZE_PRINTF; + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running SMP Relinquish Rebalance Test............................... ERROR #4\n"); + test_control_return(1); + } +} + + +/* Resume the others in ready list order and complete, so core 0 is released. */ + +static void thread_control_entry(ULONG thread_input) +{ + +UINT status; +UINT i; + + + status = TX_SUCCESS; + + /* Fill the cores first. */ + for (i = 0; i < SPIN_THREADS; i++) + { + + status += tx_thread_resume(&thread_spin[i]); + } + + /* Then the obstacle, then the thread behind it. */ + status += tx_thread_resume(&thread_blocked); + status += tx_thread_resume(&thread_starved); + + /* Check status. */ + if (status != TX_SUCCESS) + { + + printf("Running SMP Relinquish Rebalance Test............................... ERROR #5\n"); + test_control_return(1); + } +} + + +/* Hold a core and relinquish. These threads keep running whatever the scheduler does with + the rest, so they are the ones that can enforce a deadline on the starved thread. */ + +static void thread_spin_entry(ULONG thread_input) +{ + +ULONG start; + + + start = tx_time_get(); + + while (starved_counter == 0) + { + + spin_counter[thread_input]++; + + /* The tick advances whether or not any thread is being scheduled, so this bounds + the test even when nothing is. */ + if ((tx_time_get() - start) > DEADLINE_TICKS) + { + + if (reported == 0) + { + + reported = 1; + printf("Running SMP Relinquish Rebalance Test............................... ERROR #6\n"); + test_control_return(1); + } + + return; + } + + tx_thread_relinquish(); + } +} + + +/* Never runs: every core is excluded for this thread. */ + +static void thread_blocked_entry(ULONG thread_input) +{ + + blocked_counter++; +} + + +/* Reaching a core at all is the pass condition. */ + +static void thread_starved_entry(ULONG thread_input) +{ + + starved_counter++; + + if (reported == 0) + { + + reported = 1; + + /* The blocked thread must not have run, or the obstacle was not an obstacle and + the test proved nothing. */ + if (blocked_counter != 0) + { + + printf("Running SMP Relinquish Rebalance Test............................... ERROR #7\n"); + test_control_return(1); + } + + printf("Running SMP Relinquish Rebalance Test............................... SUCCESS!\n"); + test_control_return(0); + } +} From 2886bdff6fe502a9e1a64d46856a2e9433da33f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 28 Sep 2026 12:43:42 -0400 Subject: [PATCH 164/181] Stopped the SMP Linux port leaking a critical section on unprotect (#759) _tx_thread_smp_unprotect takes the Linux mutex on entry and releases it twice when the protection structure names this core, but only once when it does not, while the matching _tx_thread_smp_protect took it once either way. _tx_thread_system_return clears the protection outright, so an unprotect can find it no longer naming its core and return having released one level fewer than were taken. A thread that later reaches _tx_linux_mutex_release_all drains that level. The timer interrupt thread has none on its tick path unless a thread was preempted on core 0, so a level leaked there while core 0 is idle is never recovered: the nesting count never reaches zero, the mutex is never handed back to Linux, and every other thread waits on it for the life of the process while the tick keeps arriving. The release of the level the matching protect took now happens whether or not the protection still names this core. Protection bookkeeping and scheduling are unchanged, and releasing beyond what a thread holds was already a no-op. Two hung processes captured untraced, in different tests, show the timer thread owning the mutex with a nesting count of one while parked in its tick wait, the scheduler blocked in pthread_mutex_timedlock, and the clock advancing 99 ticks a second across a ten second sample while nothing else changes. On a healthy run that path is taken 0 times in 26,546 unprotect calls. Forcing it on the timer thread leaks one level before this change and balances after it. Assisted-by: Claude Code (Opus 5) --- ports_smp/linux/gnu/src/tx_thread_smp_unprotect.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/ports_smp/linux/gnu/src/tx_thread_smp_unprotect.c b/ports_smp/linux/gnu/src/tx_thread_smp_unprotect.c index 7428666fc..2e0e7f1ef 100644 --- a/ports_smp/linux/gnu/src/tx_thread_smp_unprotect.c +++ b/ports_smp/linux/gnu/src/tx_thread_smp_unprotect.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. + /**************************************************************************/ /**************************************************************************/ @@ -124,11 +126,18 @@ pthread_t current_thread_id; _tx_linux_debug_entry_insert("UNPROTECT-nested", __FILE__, __LINE__); } - /* Only release the critical section. */ - _tx_linux_mutex_release(&_tx_linux_mutex); } - /* Release the critical section. */ + /* Release the critical section taken by the matching _tx_thread_smp_protect. + The protection and the critical section are separate counts, and this + release is owed whether or not the protection still names this core: the + protection can be cleared by another core while this one holds the + critical section it took. The critical section is only handed back to + Linux when its nesting count reaches zero, so a release skipped here is + never made up and the mutex stays locked for the life of the process. */ + _tx_linux_mutex_release(&_tx_linux_mutex); + + /* Release the critical section taken on entry. */ _tx_linux_mutex_release(&_tx_linux_mutex); } From c3bf5e6db5f245e51fae24041d68d061378131b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 28 Sep 2026 12:44:18 -0400 Subject: [PATCH 165/181] Made the SMP pt test's randomised phase set preemption thresholds (#760) The randomised phase of threadx_smp_random_resume_suspend_exclusion_pt_test guards its preemption-threshold setup with tx_thread_priority > 40, but the test creates its 1024 source threads with priority = i reset whenever it reaches TX_MAX_PRIORITIES, which is 32 on the Linux port the regression suite runs. The guard is therefore never true. The one thing that distinguishes this test from its non-pt twin in that phase never executes, so the randomised phase exercises no preemption threshold at all and the test duplicates its twin there. The threshold the earlier rebalance section sets is unaffected. Both the guard and the threshold gap are now derived from TX_MAX_PRIORITIES, so the phase sets a threshold whatever the port's priority count is. On a 32-priority port that is priority > 16 with a threshold eight levels better, which keeps the original shape of a threshold set on the worse half of the priority range. Verified under gdb that the block is now reached, at priority 26 with a threshold of 18, and that thread_entry's preemption-threshold invariant is entered for a randomised-phase thread; neither happened before the change. 40/40 passes, 20 runs each in disable_notify_callbacks_build and stack_checking_build. Assisted-by: Claude Code (Opus 5) --- .../threadx_smp_random_resume_suspend_exclusion_pt_test.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/test/smp/regression/threadx_smp_random_resume_suspend_exclusion_pt_test.c b/test/smp/regression/threadx_smp_random_resume_suspend_exclusion_pt_test.c index ed5874181..d5fe04369 100644 --- a/test/smp/regression/threadx_smp_random_resume_suspend_exclusion_pt_test.c +++ b/test/smp/regression/threadx_smp_random_resume_suspend_exclusion_pt_test.c @@ -2312,12 +2312,14 @@ UINT status; exclusions = (ULONG) (rand()%15); tx_thread_smp_core_exclude(thread_ptr, exclusions); - /* See if we should setup a preemption-threshold. */ - if ((thread_ptr -> tx_thread_priority > 40) && + /* See if we should setup a preemption-threshold. The thresholds are + derived from TX_MAX_PRIORITIES so that the randomised phase sets one + whatever the port's priority count is. */ + if ((thread_ptr -> tx_thread_priority > (TX_MAX_PRIORITIES/2)) && (exclusions & 1)) { /* Change preemption-threshold to enable it. */ - tx_thread_preemption_change(thread_ptr, thread_ptr -> tx_thread_priority - 20, &original_threshold); + tx_thread_preemption_change(thread_ptr, thread_ptr -> tx_thread_priority - (TX_MAX_PRIORITIES/4), &original_threshold); } /* Save the thread pointer. */ From 990faf670d67d730a569b3838a89b35bc27bbb61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 28 Sep 2026 12:45:09 -0400 Subject: [PATCH 166/181] Enabled execution profiling for Cortex-R5 (#766) The Cortex-R5 assembly guarded its execution-profile hooks with only the legacy TX_ENABLE_EXECUTION_CHANGE_NOTIFY symbol. The documented TX_EXECUTION_PROFILE_ENABLE configuration initialized profiling without recording thread or interrupt transitions. I made all AC5, AC6, GNU, Green Hills, and IAR hooks accept both symbols. I also extended the port consistency and GNU/LLVM feature checks to cover the current configuration. All 849 base assembly files and all 219 TX_EXECUTION_PROFILE_ENABLE files passed with GCC 14.2.1 and clang 22.1.0. A CMake/Ninja Cortex-R5 profile build emitted all seven expected hook relocations. Proprietary toolchains were not run. Assisted-by: Codex (GPT-5) --- .../ac5/src/tx_thread_context_restore.s | 7 +++--- .../ac5/src/tx_thread_context_save.s | 11 ++++---- .../ac5/src/tx_thread_fiq_context_restore.s | 7 +++--- .../ac5/src/tx_thread_fiq_context_save.s | 11 ++++---- ports/cortex_r5/ac5/src/tx_thread_schedule.s | 7 +++--- .../ac5/src/tx_thread_system_return.s | 7 +++--- .../ac5/src/tx_thread_vectored_context_save.s | 11 ++++---- .../ac6/src/tx_thread_context_restore.S | 5 ++-- .../ac6/src/tx_thread_context_save.S | 9 ++++--- .../ac6/src/tx_thread_fiq_context_restore.S | 5 ++-- .../ac6/src/tx_thread_fiq_context_save.S | 9 ++++--- ports/cortex_r5/ac6/src/tx_thread_schedule.S | 5 ++-- .../ac6/src/tx_thread_system_return.S | 5 ++-- .../ac6/src/tx_thread_vectored_context_save.S | 9 ++++--- .../ghs/src/tx_thread_context_restore.arm | 5 ++-- .../ghs/src/tx_thread_context_save.arm | 9 ++++--- .../ghs/src/tx_thread_fiq_context_restore.arm | 5 ++-- .../ghs/src/tx_thread_fiq_context_save.arm | 9 ++++--- .../cortex_r5/ghs/src/tx_thread_schedule.arm | 5 ++-- .../ghs/src/tx_thread_system_return.arm | 5 ++-- .../src/tx_thread_vectored_context_save.arm | 9 ++++--- .../gnu/src/tx_thread_context_restore.S | 5 ++-- .../gnu/src/tx_thread_context_save.S | 9 ++++--- .../gnu/src/tx_thread_fiq_context_restore.S | 5 ++-- .../gnu/src/tx_thread_fiq_context_save.S | 9 ++++--- ports/cortex_r5/gnu/src/tx_thread_schedule.S | 5 ++-- .../gnu/src/tx_thread_system_return.S | 5 ++-- .../gnu/src/tx_thread_vectored_context_save.S | 9 ++++--- .../iar/src/tx_thread_context_restore.s | 5 ++-- .../iar/src/tx_thread_context_save.s | 9 ++++--- ports/cortex_r5/iar/src/tx_thread_schedule.s | 5 ++-- .../iar/src/tx_thread_system_return.s | 5 ++-- .../iar/src/tx_thread_vectored_context_save.s | 9 ++++--- scripts/check_clang.sh | 2 +- scripts/check_gcc.sh | 2 +- scripts/check_ports.sh | 25 ++++++++++++++++++- 36 files changed, 160 insertions(+), 104 deletions(-) diff --git a/ports/cortex_r5/ac5/src/tx_thread_context_restore.s b/ports/cortex_r5/ac5/src/tx_thread_context_restore.s index 1d070d89c..0063a5237 100644 --- a/ports/cortex_r5/ac5/src/tx_thread_context_restore.s +++ b/ports/cortex_r5/ac5/src/tx_thread_context_restore.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * 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 @@ -7,6 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ +; Portions of this file were generated with AI assistance. ; ; ;/**************************************************************************/ @@ -47,7 +49,7 @@ SVC_MODE EQU 0x93 ; SVC mode IMPORT _tx_timer_time_slice IMPORT _tx_thread_schedule IMPORT _tx_thread_preempt_disable - IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY + IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY :LOR: :DEF:TX_EXECUTION_PROFILE_ENABLE IMPORT _tx_execution_isr_exit ENDIF ; @@ -101,7 +103,7 @@ _tx_thread_context_restore CPSID i ; Disable IRQ interrupts ENDIF - IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY + IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY :LOR: :DEF:TX_EXECUTION_PROFILE_ENABLE ; ; /* Call the ISR exit function to indicate an ISR is complete. */ ; @@ -245,4 +247,3 @@ __tx_thread_idle_system_restore ;} ; END - diff --git a/ports/cortex_r5/ac5/src/tx_thread_context_save.s b/ports/cortex_r5/ac5/src/tx_thread_context_save.s index 043fbdeb4..05961bf7c 100644 --- a/ports/cortex_r5/ac5/src/tx_thread_context_save.s +++ b/ports/cortex_r5/ac5/src/tx_thread_context_save.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * 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 @@ -7,6 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ +; Portions of this file were generated with AI assistance. ; ; ;/**************************************************************************/ @@ -32,7 +34,7 @@ IMPORT _tx_thread_system_state IMPORT _tx_thread_current_ptr IMPORT __tx_irq_processing_return - IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY + IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY :LOR: :DEF:TX_EXECUTION_PROFILE_ENABLE IMPORT _tx_execution_isr_enter ENDIF ; @@ -109,7 +111,7 @@ _tx_thread_context_save ; MOV r10, #0 ; Clear stack limit - IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY + IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY :LOR: :DEF:TX_EXECUTION_PROFILE_ENABLE ; ; /* Call the ISR enter function to indicate an ISR is executing. */ ; @@ -149,7 +151,7 @@ __tx_thread_not_nested_save ; MOV r10, #0 ; Clear stack limit - IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY + IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY :LOR: :DEF:TX_EXECUTION_PROFILE_ENABLE ; ; /* Call the ISR enter function to indicate an ISR is executing. */ ; @@ -173,7 +175,7 @@ __tx_thread_idle_system_save ; MOV r10, #0 ; Clear stack limit - IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY + IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY :LOR: :DEF:TX_EXECUTION_PROFILE_ENABLE ; ; /* Call the ISR enter function to indicate an ISR is executing. */ ; @@ -189,4 +191,3 @@ __tx_thread_idle_system_save ;} ; END - diff --git a/ports/cortex_r5/ac5/src/tx_thread_fiq_context_restore.s b/ports/cortex_r5/ac5/src/tx_thread_fiq_context_restore.s index f58456b99..3f5ae6822 100644 --- a/ports/cortex_r5/ac5/src/tx_thread_fiq_context_restore.s +++ b/ports/cortex_r5/ac5/src/tx_thread_fiq_context_restore.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * 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 @@ -7,6 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ +; Portions of this file were generated with AI assistance. ; ; ;/**************************************************************************/ @@ -43,7 +45,7 @@ IRQ_MODE_BITS EQU 0x12 ; IRQ mode bits IMPORT _tx_timer_time_slice IMPORT _tx_thread_schedule IMPORT _tx_thread_preempt_disable - IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY + IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY :LOR: :DEF:TX_EXECUTION_PROFILE_ENABLE IMPORT _tx_execution_isr_exit ENDIF ; @@ -93,7 +95,7 @@ _tx_thread_fiq_context_restore ; CPSID if ; Disable IRQ and FIQ interrupts - IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY + IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY :LOR: :DEF:TX_EXECUTION_PROFILE_ENABLE ; ; /* Call the ISR exit function to indicate an ISR is complete. */ ; @@ -235,4 +237,3 @@ __tx_thread_fiq_idle_system_restore ;} ; END - diff --git a/ports/cortex_r5/ac5/src/tx_thread_fiq_context_save.s b/ports/cortex_r5/ac5/src/tx_thread_fiq_context_save.s index 67bc6290f..eb8f4e2e6 100644 --- a/ports/cortex_r5/ac5/src/tx_thread_fiq_context_save.s +++ b/ports/cortex_r5/ac5/src/tx_thread_fiq_context_save.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * 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 @@ -7,6 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ +; Portions of this file were generated with AI assistance. ; ; ;/**************************************************************************/ @@ -32,7 +34,7 @@ IMPORT _tx_thread_system_state IMPORT _tx_thread_current_ptr IMPORT __tx_fiq_processing_return - IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY + IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY :LOR: :DEF:TX_EXECUTION_PROFILE_ENABLE IMPORT _tx_execution_isr_enter ENDIF ; @@ -106,7 +108,7 @@ _tx_thread_fiq_context_save ; MOV r10, #0 ; Clear stack limit - IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY + IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY :LOR: :DEF:TX_EXECUTION_PROFILE_ENABLE ; ; /* Call the ISR enter function to indicate an ISR is executing. */ ; @@ -150,7 +152,7 @@ __tx_thread_fiq_not_nested_save ; MOV r10, #0 ; Clear stack limit - IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY + IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY :LOR: :DEF:TX_EXECUTION_PROFILE_ENABLE ; ; /* Call the ISR enter function to indicate an ISR is executing. */ ; @@ -169,7 +171,7 @@ __tx_thread_fiq_idle_system_save ; ; /* Interrupt occurred in the scheduling loop. */ ; - IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY + IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY :LOR: :DEF:TX_EXECUTION_PROFILE_ENABLE ; ; /* Call the ISR enter function to indicate an ISR is executing. */ ; @@ -193,4 +195,3 @@ __tx_thread_fiq_idle_system_save ;} ; END - diff --git a/ports/cortex_r5/ac5/src/tx_thread_schedule.s b/ports/cortex_r5/ac5/src/tx_thread_schedule.s index b50d0614b..47bdc9717 100644 --- a/ports/cortex_r5/ac5/src/tx_thread_schedule.s +++ b/ports/cortex_r5/ac5/src/tx_thread_schedule.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * 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 @@ -7,6 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ +; Portions of this file were generated with AI assistance. ; ; ;/**************************************************************************/ @@ -33,7 +35,7 @@ IMPORT _tx_thread_execute_ptr IMPORT _tx_thread_current_ptr IMPORT _tx_timer_time_slice - IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY + IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY :LOR: :DEF:TX_EXECUTION_PROFILE_ENABLE IMPORT _tx_execution_thread_enter ENDIF ; @@ -136,7 +138,7 @@ __tx_thread_schedule_loop ; /* Switch to the thread's stack. */ ; sp = _tx_thread_execute_ptr -> tx_thread_stack_ptr; ; - IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY + IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY :LOR: :DEF:TX_EXECUTION_PROFILE_ENABLE ; ; /* Call the thread entry function to indicate the thread is executing. */ ; @@ -223,4 +225,3 @@ __tx_no_thread_to_disable ENDIF END - diff --git a/ports/cortex_r5/ac5/src/tx_thread_system_return.s b/ports/cortex_r5/ac5/src/tx_thread_system_return.s index ac35c95f5..5680174b7 100644 --- a/ports/cortex_r5/ac5/src/tx_thread_system_return.s +++ b/ports/cortex_r5/ac5/src/tx_thread_system_return.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * 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 @@ -7,6 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ +; Portions of this file were generated with AI assistance. ; ; ;/**************************************************************************/ @@ -32,7 +34,7 @@ IMPORT _tx_thread_current_ptr IMPORT _tx_timer_time_slice IMPORT _tx_thread_schedule - IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY + IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY :LOR: :DEF:TX_EXECUTION_PROFILE_ENABLE IMPORT _tx_execution_thread_exit ENDIF ; @@ -106,7 +108,7 @@ _tx_skip_solicited_vfp_save STMDB sp!, {r0-r1} ; Save type and CPSR ; ; - IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY + IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY :LOR: :DEF:TX_EXECUTION_PROFILE_ENABLE ; ; /* Call the thread exit function to indicate the thread is no longer executing. */ ; @@ -148,4 +150,3 @@ __tx_thread_dont_save_ts ; ;} END - diff --git a/ports/cortex_r5/ac5/src/tx_thread_vectored_context_save.s b/ports/cortex_r5/ac5/src/tx_thread_vectored_context_save.s index b1918801a..02394cb59 100644 --- a/ports/cortex_r5/ac5/src/tx_thread_vectored_context_save.s +++ b/ports/cortex_r5/ac5/src/tx_thread_vectored_context_save.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * 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 @@ -7,6 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ +; Portions of this file were generated with AI assistance. ; ; ;/**************************************************************************/ @@ -31,7 +33,7 @@ ; IMPORT _tx_thread_system_state IMPORT _tx_thread_current_ptr - IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY + IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY :LOR: :DEF:TX_EXECUTION_PROFILE_ENABLE IMPORT _tx_execution_isr_enter ENDIF ; @@ -102,7 +104,7 @@ _tx_thread_vectored_context_save ; MOV r10, #0 ; Clear stack limit - IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY + IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY :LOR: :DEF:TX_EXECUTION_PROFILE_ENABLE ; ; /* Call the ISR enter function to indicate an ISR is executing. */ ; @@ -142,7 +144,7 @@ __tx_thread_not_nested_save ; MOV r10, #0 ; Clear stack limit - IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY + IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY :LOR: :DEF:TX_EXECUTION_PROFILE_ENABLE ; ; /* Call the ISR enter function to indicate an ISR is executing. */ ; @@ -170,7 +172,7 @@ __tx_thread_idle_system_save ; MOV r10, #0 ; Clear stack limit - IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY + IF :DEF:TX_ENABLE_EXECUTION_CHANGE_NOTIFY :LOR: :DEF:TX_EXECUTION_PROFILE_ENABLE ; ; /* Call the ISR enter function to indicate an ISR is executing. */ ; @@ -190,4 +192,3 @@ __tx_thread_idle_system_save ;} ; END - diff --git a/ports/cortex_r5/ac6/src/tx_thread_context_restore.S b/ports/cortex_r5/ac6/src/tx_thread_context_restore.S index da9ae44fb..7ddcc173d 100644 --- a/ports/cortex_r5/ac6/src/tx_thread_context_restore.S +++ b/ports/cortex_r5/ac6/src/tx_thread_context_restore.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * 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 @@ -7,6 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ @@ -101,7 +103,7 @@ _tx_thread_context_restore: CPSID i @ Disable IRQ interrupts #endif -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) @ @ /* Call the ISR exit function to indicate an ISR is complete. */ @ @@ -245,4 +247,3 @@ __tx_thread_idle_system_restore: @} - diff --git a/ports/cortex_r5/ac6/src/tx_thread_context_save.S b/ports/cortex_r5/ac6/src/tx_thread_context_save.S index f0324d69f..95a7a1b22 100644 --- a/ports/cortex_r5/ac6/src/tx_thread_context_save.S +++ b/ports/cortex_r5/ac6/src/tx_thread_context_save.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * 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 @@ -7,6 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ @@ -112,7 +114,7 @@ _tx_thread_context_save: @ MOV r10, #0 @ Clear stack limit -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) @ @ /* Call the ISR enter function to indicate an ISR is executing. */ @ @@ -152,7 +154,7 @@ __tx_thread_not_nested_save: @ MOV r10, #0 @ Clear stack limit -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) @ @ /* Call the ISR enter function to indicate an ISR is executing. */ @ @@ -176,7 +178,7 @@ __tx_thread_idle_system_save: @ MOV r10, #0 @ Clear stack limit -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) @ @ /* Call the ISR enter function to indicate an ISR is executing. */ @ @@ -192,4 +194,3 @@ __tx_thread_idle_system_save: @} - diff --git a/ports/cortex_r5/ac6/src/tx_thread_fiq_context_restore.S b/ports/cortex_r5/ac6/src/tx_thread_fiq_context_restore.S index 51fe146b3..a5290aacd 100644 --- a/ports/cortex_r5/ac6/src/tx_thread_fiq_context_restore.S +++ b/ports/cortex_r5/ac6/src/tx_thread_fiq_context_restore.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * 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 @@ -7,6 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ @@ -96,7 +98,7 @@ _tx_thread_fiq_context_restore: @ CPSID if @ Disable IRQ and FIQ interrupts -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) @ @ /* Call the ISR exit function to indicate an ISR is complete. */ @ @@ -236,4 +238,3 @@ __tx_thread_fiq_idle_system_restore: B _tx_thread_schedule @ Return to scheduler @ @} - diff --git a/ports/cortex_r5/ac6/src/tx_thread_fiq_context_save.S b/ports/cortex_r5/ac6/src/tx_thread_fiq_context_save.S index 153037406..7e794e574 100644 --- a/ports/cortex_r5/ac6/src/tx_thread_fiq_context_save.S +++ b/ports/cortex_r5/ac6/src/tx_thread_fiq_context_save.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * 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 @@ -7,6 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ @@ -108,7 +110,7 @@ _tx_thread_fiq_context_save: @ MOV r10, #0 @ Clear stack limit -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) @ @ /* Call the ISR enter function to indicate an ISR is executing. */ @ @@ -152,7 +154,7 @@ __tx_thread_fiq_not_nested_save: @ MOV r10, #0 @ Clear stack limit -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) @ @ /* Call the ISR enter function to indicate an ISR is executing. */ @ @@ -171,7 +173,7 @@ __tx_thread_fiq_idle_system_save: @ @ /* Interrupt occurred in the scheduling loop. */ @ -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) @ @ /* Call the ISR enter function to indicate an ISR is executing. */ @ @@ -193,4 +195,3 @@ __tx_thread_fiq_idle_system_save: @ @ } @} - diff --git a/ports/cortex_r5/ac6/src/tx_thread_schedule.S b/ports/cortex_r5/ac6/src/tx_thread_schedule.S index dc014e831..6ddf6d602 100644 --- a/ports/cortex_r5/ac6/src/tx_thread_schedule.S +++ b/ports/cortex_r5/ac6/src/tx_thread_schedule.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * 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 @@ -7,6 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ @@ -152,7 +154,7 @@ __tx_thread_schedule_loop: @ /* Switch to the thread's stack. */ @ sp = _tx_thread_execute_ptr -> tx_thread_stack_ptr; @ -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) @ @ /* Call the thread entry function to indicate the thread is executing. */ @ @@ -239,4 +241,3 @@ __tx_no_thread_to_disable: MSR CPSR_cxsf, r2 @ Recover CPSR BX LR @ Return to caller #endif - diff --git a/ports/cortex_r5/ac6/src/tx_thread_system_return.S b/ports/cortex_r5/ac6/src/tx_thread_system_return.S index 50e5d2e20..abe096c34 100644 --- a/ports/cortex_r5/ac6/src/tx_thread_system_return.S +++ b/ports/cortex_r5/ac6/src/tx_thread_system_return.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * 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 @@ -7,6 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ @@ -125,7 +127,7 @@ _tx_skip_solicited_vfp_save: STMDB sp!, {r0-r1} @ Save type and CPSR @ @ -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) @ @ /* Call the thread exit function to indicate the thread is no longer executing. */ @ @@ -166,4 +168,3 @@ __tx_thread_dont_save_ts: B _tx_thread_schedule @ Jump to scheduler! @ @} - diff --git a/ports/cortex_r5/ac6/src/tx_thread_vectored_context_save.S b/ports/cortex_r5/ac6/src/tx_thread_vectored_context_save.S index b79d87927..dffa3ff10 100644 --- a/ports/cortex_r5/ac6/src/tx_thread_vectored_context_save.S +++ b/ports/cortex_r5/ac6/src/tx_thread_vectored_context_save.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * 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 @@ -7,6 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ @@ -105,7 +107,7 @@ _tx_thread_vectored_context_save: @ MOV r10, #0 @ Clear stack limit -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) @ @ /* Call the ISR enter function to indicate an ISR is executing. */ @ @@ -141,7 +143,7 @@ __tx_thread_not_nested_save: @ MOV r10, #0 @ Clear stack limit -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) @ @ /* Call the ISR enter function to indicate an ISR is executing. */ @ @@ -165,7 +167,7 @@ __tx_thread_idle_system_save: @ MOV r10, #0 @ Clear stack limit -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) @ @ /* Call the ISR enter function to indicate an ISR is executing. */ @ @@ -179,4 +181,3 @@ __tx_thread_idle_system_save: @ @ } @} - diff --git a/ports/cortex_r5/ghs/src/tx_thread_context_restore.arm b/ports/cortex_r5/ghs/src/tx_thread_context_restore.arm index b103b804c..414e0de09 100644 --- a/ports/cortex_r5/ghs/src/tx_thread_context_restore.arm +++ b/ports/cortex_r5/ghs/src/tx_thread_context_restore.arm @@ -1,5 +1,6 @@ /*************************************************************************** * Copyright (c) 2024 Microsoft Corporation + * 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 @@ -8,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ @@ -99,7 +101,7 @@ _tx_thread_context_restore: #endif #endif -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) /* Call the ISR exit function to indicate an ISR is complete. */ @@ -254,4 +256,3 @@ __tx_thread_idle_system_restore: .size _tx_thread_context_restore,.-_tx_thread_context_restore /* } */ - diff --git a/ports/cortex_r5/ghs/src/tx_thread_context_save.arm b/ports/cortex_r5/ghs/src/tx_thread_context_save.arm index 29a95aaeb..c33f47bf6 100644 --- a/ports/cortex_r5/ghs/src/tx_thread_context_save.arm +++ b/ports/cortex_r5/ghs/src/tx_thread_context_save.arm @@ -1,5 +1,6 @@ /*************************************************************************** * Copyright (c) 2024 Microsoft Corporation + * 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 @@ -8,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ @@ -122,7 +124,7 @@ _tx_thread_context_save: MOV r10, 0 # Clear stack limit -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) /* Call the ISR enter function to indicate an ISR is executing. */ @@ -162,7 +164,7 @@ __tx_thread_not_nested_save: MOV r10, 0 # Clear stack limit -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) /* Call the ISR enter function to indicate an ISR is executing. */ @@ -186,7 +188,7 @@ __tx_thread_idle_system_save: MOV r10, 0 # Clear stack limit -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) /* Call the ISR enter function to indicate an ISR is executing. */ @@ -203,4 +205,3 @@ __tx_thread_idle_system_save: /* } } */ - diff --git a/ports/cortex_r5/ghs/src/tx_thread_fiq_context_restore.arm b/ports/cortex_r5/ghs/src/tx_thread_fiq_context_restore.arm index 4287f779e..ec9cbb8ee 100644 --- a/ports/cortex_r5/ghs/src/tx_thread_fiq_context_restore.arm +++ b/ports/cortex_r5/ghs/src/tx_thread_fiq_context_restore.arm @@ -1,5 +1,6 @@ /*************************************************************************** * Copyright (c) 2024 Microsoft Corporation + * 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 @@ -8,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ @@ -96,7 +98,7 @@ _tx_thread_fiq_context_restore: CPSID if # Disable IRQ and FIQ interrupts #endif -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) /* Call the ISR exit function to indicate an ISR is complete. */ @@ -259,4 +261,3 @@ __tx_thread_fiq_idle_system_restore: .size _tx_thread_fiq_context_restore,.-_tx_thread_fiq_context_restore /* } */ - diff --git a/ports/cortex_r5/ghs/src/tx_thread_fiq_context_save.arm b/ports/cortex_r5/ghs/src/tx_thread_fiq_context_save.arm index 28725995d..475048437 100644 --- a/ports/cortex_r5/ghs/src/tx_thread_fiq_context_save.arm +++ b/ports/cortex_r5/ghs/src/tx_thread_fiq_context_save.arm @@ -1,5 +1,6 @@ /*************************************************************************** * Copyright (c) 2024 Microsoft Corporation + * 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 @@ -8,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ @@ -105,7 +107,7 @@ _tx_thread_fiq_context_save: MOV r10, 0 # Clear stack limit -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) /* Call the ISR enter function to indicate an ISR is executing. */ @@ -149,7 +151,7 @@ __tx_thread_fiq_not_nested_save: MOV r10, 0 # Clear stack limit -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) /* Call the ISR enter function to indicate an ISR is executing. */ @@ -168,7 +170,7 @@ __tx_thread_fiq_idle_system_save: /* Interrupt occurred in the scheduling loop. */ -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) /* Call the ISR enter function to indicate an ISR is executing. */ @@ -193,4 +195,3 @@ __tx_thread_fiq_idle_system_save: /* } } */ - diff --git a/ports/cortex_r5/ghs/src/tx_thread_schedule.arm b/ports/cortex_r5/ghs/src/tx_thread_schedule.arm index e0548e7f9..9383ac315 100644 --- a/ports/cortex_r5/ghs/src/tx_thread_schedule.arm +++ b/ports/cortex_r5/ghs/src/tx_thread_schedule.arm @@ -1,5 +1,6 @@ /*************************************************************************** * Copyright (c) 2024 Microsoft Corporation + * 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 @@ -8,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ @@ -152,7 +154,7 @@ __tx_thread_schedule_loop: LDR sp, [r0, 8] # Switch stack pointers STR r3, [r2] # Setup time-slice -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) /* Call the thread entry function to indicate the thread is executing. */ @@ -248,4 +250,3 @@ __tx_no_thread_to_disable: /* } */ - diff --git a/ports/cortex_r5/ghs/src/tx_thread_system_return.arm b/ports/cortex_r5/ghs/src/tx_thread_system_return.arm index 488b93631..630f2378d 100644 --- a/ports/cortex_r5/ghs/src/tx_thread_system_return.arm +++ b/ports/cortex_r5/ghs/src/tx_thread_system_return.arm @@ -1,5 +1,6 @@ /*************************************************************************** * Copyright (c) 2024 Microsoft Corporation + * 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 @@ -8,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ @@ -117,7 +119,7 @@ _tx_skip_solicited_vfp_save: #endif #endif -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) /* Call the thread exit function to indicate the thread is no longer executing. */ @@ -162,4 +164,3 @@ __tx_thread_dont_save_ts: .type _tx_thread_system_return,$function .size _tx_thread_system_return,.-_tx_thread_system_return /* } */ - diff --git a/ports/cortex_r5/ghs/src/tx_thread_vectored_context_save.arm b/ports/cortex_r5/ghs/src/tx_thread_vectored_context_save.arm index 11bca1b99..3db25b086 100644 --- a/ports/cortex_r5/ghs/src/tx_thread_vectored_context_save.arm +++ b/ports/cortex_r5/ghs/src/tx_thread_vectored_context_save.arm @@ -1,5 +1,6 @@ /*************************************************************************** * Copyright (c) 2024 Microsoft Corporation + * 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 @@ -8,6 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ @@ -115,7 +117,7 @@ _tx_thread_vectored_context_save: MOV r10, 0 # Clear stack limit -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) /* Call the ISR enter function to indicate an ISR is executing. */ @@ -151,7 +153,7 @@ __tx_thread_not_nested_save: MOV r10, 0 # Clear stack limit -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) /* Call the ISR enter function to indicate an ISR is executing. */ @@ -175,7 +177,7 @@ __tx_thread_idle_system_save: MOV r10, 0 # Clear stack limit -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) /* Call the ISR enter function to indicate an ISR is executing. */ @@ -192,4 +194,3 @@ __tx_thread_idle_system_save: /* } } */ - diff --git a/ports/cortex_r5/gnu/src/tx_thread_context_restore.S b/ports/cortex_r5/gnu/src/tx_thread_context_restore.S index c8c28acb7..296c12c20 100644 --- a/ports/cortex_r5/gnu/src/tx_thread_context_restore.S +++ b/ports/cortex_r5/gnu/src/tx_thread_context_restore.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * 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 @@ -7,6 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ @@ -95,7 +97,7 @@ _tx_thread_context_restore: CPSID i @ Disable IRQ interrupts #endif -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) @ @ /* Call the ISR exit function to indicate an ISR is complete. */ @ @@ -239,4 +241,3 @@ __tx_thread_idle_system_restore: @} - diff --git a/ports/cortex_r5/gnu/src/tx_thread_context_save.S b/ports/cortex_r5/gnu/src/tx_thread_context_save.S index 124341860..655a8c9d9 100644 --- a/ports/cortex_r5/gnu/src/tx_thread_context_save.S +++ b/ports/cortex_r5/gnu/src/tx_thread_context_save.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * 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 @@ -7,6 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ @@ -105,7 +107,7 @@ _tx_thread_context_save: @ MOV r10, #0 @ Clear stack limit -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) @ @ /* Call the ISR enter function to indicate an ISR is executing. */ @ @@ -145,7 +147,7 @@ __tx_thread_not_nested_save: @ MOV r10, #0 @ Clear stack limit -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) @ @ /* Call the ISR enter function to indicate an ISR is executing. */ @ @@ -169,7 +171,7 @@ __tx_thread_idle_system_save: @ MOV r10, #0 @ Clear stack limit -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) @ @ /* Call the ISR enter function to indicate an ISR is executing. */ @ @@ -185,4 +187,3 @@ __tx_thread_idle_system_save: @} - diff --git a/ports/cortex_r5/gnu/src/tx_thread_fiq_context_restore.S b/ports/cortex_r5/gnu/src/tx_thread_fiq_context_restore.S index 5ebe4ac44..dc6326f46 100644 --- a/ports/cortex_r5/gnu/src/tx_thread_fiq_context_restore.S +++ b/ports/cortex_r5/gnu/src/tx_thread_fiq_context_restore.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * 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 @@ -7,6 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ @@ -89,7 +91,7 @@ _tx_thread_fiq_context_restore: @ CPSID if @ Disable IRQ and FIQ interrupts -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) @ @ /* Call the ISR exit function to indicate an ISR is complete. */ @ @@ -229,4 +231,3 @@ __tx_thread_fiq_idle_system_restore: B _tx_thread_schedule @ Return to scheduler @ @} - diff --git a/ports/cortex_r5/gnu/src/tx_thread_fiq_context_save.S b/ports/cortex_r5/gnu/src/tx_thread_fiq_context_save.S index ccd30f3de..1161b21c5 100644 --- a/ports/cortex_r5/gnu/src/tx_thread_fiq_context_save.S +++ b/ports/cortex_r5/gnu/src/tx_thread_fiq_context_save.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * 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 @@ -7,6 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ @@ -102,7 +104,7 @@ _tx_thread_fiq_context_save: @ MOV r10, #0 @ Clear stack limit -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) @ @ /* Call the ISR enter function to indicate an ISR is executing. */ @ @@ -146,7 +148,7 @@ __tx_thread_fiq_not_nested_save: @ MOV r10, #0 @ Clear stack limit -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) @ @ /* Call the ISR enter function to indicate an ISR is executing. */ @ @@ -165,7 +167,7 @@ __tx_thread_fiq_idle_system_save: @ @ /* Interrupt occurred in the scheduling loop. */ @ -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) @ @ /* Call the ISR enter function to indicate an ISR is executing. */ @ @@ -187,4 +189,3 @@ __tx_thread_fiq_idle_system_save: @ @ } @} - diff --git a/ports/cortex_r5/gnu/src/tx_thread_schedule.S b/ports/cortex_r5/gnu/src/tx_thread_schedule.S index e19265f5d..0b3a4ff1e 100644 --- a/ports/cortex_r5/gnu/src/tx_thread_schedule.S +++ b/ports/cortex_r5/gnu/src/tx_thread_schedule.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * 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 @@ -7,6 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ @@ -145,7 +147,7 @@ __tx_thread_schedule_loop: @ /* Switch to the thread's stack. */ @ sp = _tx_thread_execute_ptr -> tx_thread_stack_ptr; @ -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) @ @ /* Call the thread entry function to indicate the thread is executing. */ @ @@ -232,4 +234,3 @@ __tx_no_thread_to_disable: MSR CPSR_cxsf, r2 @ Recover CPSR BX LR @ Return to caller #endif - diff --git a/ports/cortex_r5/gnu/src/tx_thread_system_return.S b/ports/cortex_r5/gnu/src/tx_thread_system_return.S index 0144b037c..6237c15ae 100644 --- a/ports/cortex_r5/gnu/src/tx_thread_system_return.S +++ b/ports/cortex_r5/gnu/src/tx_thread_system_return.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * 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 @@ -7,6 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ @@ -120,7 +122,7 @@ _tx_skip_solicited_vfp_save: STMDB sp!, {r0-r1} @ Save type and CPSR @ @ -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) @ @ /* Call the thread exit function to indicate the thread is no longer executing. */ @ @@ -161,4 +163,3 @@ __tx_thread_dont_save_ts: B _tx_thread_schedule @ Jump to scheduler! @ @} - diff --git a/ports/cortex_r5/gnu/src/tx_thread_vectored_context_save.S b/ports/cortex_r5/gnu/src/tx_thread_vectored_context_save.S index e985f24f4..8c0364450 100644 --- a/ports/cortex_r5/gnu/src/tx_thread_vectored_context_save.S +++ b/ports/cortex_r5/gnu/src/tx_thread_vectored_context_save.S @@ -1,5 +1,6 @@ @/*************************************************************************** @ * Copyright (c) 2024 Microsoft Corporation +@ * 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 @@ -7,6 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ @@ -99,7 +101,7 @@ _tx_thread_vectored_context_save: @ MOV r10, #0 @ Clear stack limit -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) @ @ /* Call the ISR enter function to indicate an ISR is executing. */ @ @@ -135,7 +137,7 @@ __tx_thread_not_nested_save: @ MOV r10, #0 @ Clear stack limit -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) @ @ /* Call the ISR enter function to indicate an ISR is executing. */ @ @@ -159,7 +161,7 @@ __tx_thread_idle_system_save: @ MOV r10, #0 @ Clear stack limit -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) @ @ /* Call the ISR enter function to indicate an ISR is executing. */ @ @@ -173,4 +175,3 @@ __tx_thread_idle_system_save: @ @ } @} - diff --git a/ports/cortex_r5/iar/src/tx_thread_context_restore.s b/ports/cortex_r5/iar/src/tx_thread_context_restore.s index a035dc5e8..4746914bb 100644 --- a/ports/cortex_r5/iar/src/tx_thread_context_restore.s +++ b/ports/cortex_r5/iar/src/tx_thread_context_restore.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * 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 @@ -7,6 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ +; Portions of this file were generated with AI assistance. ; ; ;/**************************************************************************/ @@ -92,7 +94,7 @@ _tx_thread_context_restore ; CPSID i ; Disable IRQ interrupts -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) ; ; /* Call the ISR exit function to indicate an ISR is complete. */ ; @@ -237,4 +239,3 @@ __tx_thread_idle_system_restore ; ; END - diff --git a/ports/cortex_r5/iar/src/tx_thread_context_save.s b/ports/cortex_r5/iar/src/tx_thread_context_save.s index acd05d0a4..cf495ba4b 100644 --- a/ports/cortex_r5/iar/src/tx_thread_context_save.s +++ b/ports/cortex_r5/iar/src/tx_thread_context_save.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * 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 @@ -7,6 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ +; Portions of this file were generated with AI assistance. ; ; ;/**************************************************************************/ @@ -105,7 +107,7 @@ _tx_thread_context_save ; MOV r10, #0 ; Clear stack limit -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) ; ; /* Call the ISR enter function to indicate an ISR is executing. */ ; @@ -145,7 +147,7 @@ __tx_thread_not_nested_save ; MOV r10, #0 ; Clear stack limit -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) ; ; /* Call the ISR enter function to indicate an ISR is executing. */ ; @@ -169,7 +171,7 @@ __tx_thread_idle_system_save ; MOV r10, #0 ; Clear stack limit -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) ; ; /* Call the ISR enter function to indicate an ISR is executing. */ ; @@ -188,4 +190,3 @@ __tx_thread_idle_system_save ; ; END - diff --git a/ports/cortex_r5/iar/src/tx_thread_schedule.s b/ports/cortex_r5/iar/src/tx_thread_schedule.s index 4152a2cbf..f3f806192 100644 --- a/ports/cortex_r5/iar/src/tx_thread_schedule.s +++ b/ports/cortex_r5/iar/src/tx_thread_schedule.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * 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 @@ -7,6 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ +; Portions of this file were generated with AI assistance. ; ; ;/**************************************************************************/ @@ -129,7 +131,7 @@ __tx_thread_schedule_loop ; /* Switch to the thread's stack. */ ; sp = _tx_thread_execute_ptr -> tx_thread_stack_ptr; ; -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) ; ; /* Call the thread entry function to indicate the thread is executing. */ ; @@ -210,4 +212,3 @@ __tx_no_thread_to_disable: #endif END - diff --git a/ports/cortex_r5/iar/src/tx_thread_system_return.s b/ports/cortex_r5/iar/src/tx_thread_system_return.s index 6ceabc46b..83ec0fea8 100644 --- a/ports/cortex_r5/iar/src/tx_thread_system_return.s +++ b/ports/cortex_r5/iar/src/tx_thread_system_return.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * 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 @@ -7,6 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ +; Portions of this file were generated with AI assistance. ; ; ;/**************************************************************************/ @@ -103,7 +105,7 @@ _tx_skip_solicited_vfp_save: STMDB sp!, {r0-r1} ; Save type and CPSR ; ; -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) ; ; /* Call the thread exit function to indicate the thread is no longer executing. */ ; @@ -145,4 +147,3 @@ __tx_thread_dont_save_ts ; ;} END - diff --git a/ports/cortex_r5/iar/src/tx_thread_vectored_context_save.s b/ports/cortex_r5/iar/src/tx_thread_vectored_context_save.s index 3a5ed54a1..044f7ea0d 100644 --- a/ports/cortex_r5/iar/src/tx_thread_vectored_context_save.s +++ b/ports/cortex_r5/iar/src/tx_thread_vectored_context_save.s @@ -1,5 +1,6 @@ ;/*************************************************************************** ; * Copyright (c) 2024 Microsoft Corporation +; * 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 @@ -7,6 +8,7 @@ ; * ; * SPDX-License-Identifier: MIT ; **************************************************************************/ +; Portions of this file were generated with AI assistance. ; ; ;/**************************************************************************/ @@ -99,7 +101,7 @@ _tx_thread_vectored_context_save ; MOV r10, #0 ; Clear stack limit -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) ; ; /* Call the ISR enter function to indicate an ISR is executing. */ ; @@ -135,7 +137,7 @@ __tx_thread_not_nested_save ; MOV r10, #0 ; Clear stack limit -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) ; ; /* Call the ISR enter function to indicate an ISR is executing. */ ; @@ -159,7 +161,7 @@ __tx_thread_idle_system_save ; MOV r10, #0 ; Clear stack limit -#ifdef TX_ENABLE_EXECUTION_CHANGE_NOTIFY +#if defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY) || defined(TX_EXECUTION_PROFILE_ENABLE) ; ; /* Call the ISR enter function to indicate an ISR is executing. */ ; @@ -174,4 +176,3 @@ __tx_thread_idle_system_save ; } ;} END - diff --git a/scripts/check_clang.sh b/scripts/check_clang.sh index 57c4d63af..8956404be 100755 --- a/scripts/check_clang.sh +++ b/scripts/check_clang.sh @@ -152,7 +152,7 @@ declare -A PORT_TARGET=( # Baseline, where the 16-bit POP takes r0-r7 and pc only, and rejected by GNU as # well as by LLVM. Turning the feature on had never once been tried. FEATURE_MACROS="TX_ENABLE_VFP_SUPPORT TX_ENABLE_FIQ_SUPPORT TX_LOW_POWER - TX_ENABLE_EXECUTION_CHANGE_NOTIFY" + TX_ENABLE_EXECUTION_CHANGE_NOTIFY TX_EXECUTION_PROFILE_ENABLE" # TX_ENABLE_IRQ_NESTING and TX_ENABLE_FIQ_NESTING are deliberately not here. # They guard no assembly in the trees this script walks: the nesting start and end diff --git a/scripts/check_gcc.sh b/scripts/check_gcc.sh index e714a5c13..b8b2d794c 100755 --- a/scripts/check_gcc.sh +++ b/scripts/check_gcc.sh @@ -242,7 +242,7 @@ declare -A PORT_TARGET=( # months after the identical fix landed in its non-module sibling, because no # glob in either script reached ports_module until #672. FEATURE_MACROS="TX_ENABLE_VFP_SUPPORT TX_ENABLE_FIQ_SUPPORT TX_LOW_POWER - TX_ENABLE_EXECUTION_CHANGE_NOTIFY" + TX_ENABLE_EXECUTION_CHANGE_NOTIFY TX_EXECUTION_PROFILE_ENABLE" # TX_ENABLE_IRQ_NESTING and TX_ENABLE_FIQ_NESTING are deliberately not here. # They guard no assembly in the trees this script walks: the nesting start and diff --git a/scripts/check_ports.sh b/scripts/check_ports.sh index 19b350cae..4da7bc632 100755 --- a/scripts/check_ports.sh +++ b/scripts/check_ports.sh @@ -251,7 +251,30 @@ done < <(find ports ports_arch ports_module ports_smp -name "*.s" -type f \ [ "$lowercase" -eq 0 ] && say " ok: no .s file under a gnu tree uses the preprocessor" # -------------------------------------------------------------------------- -# 5. Report only: families with no copy script. +# 5. Cortex-R5 execution-profile guards accept both configuration names. +# -------------------------------------------------------------------------- +# Profiling storage uses TX_EXECUTION_PROFILE_ENABLE, while +# TX_ENABLE_EXECUTION_CHANGE_NOTIFY remains a supported compatibility symbol. +# Every Cortex-R5 profiling hook must recognize both symbols. +say "" +say "== Cortex-R5 execution-profile guards accept both symbols ==" + +profile_guards_missing=0 +while IFS=: read -r file line text; do + case "$text" in + *TX_EXECUTION_PROFILE_ENABLE*) ;; + *) + fail "$file:$line accepts the legacy execution-profile symbol only" + profile_guards_missing=$((profile_guards_missing + 1)) + ;; + esac +done < <(grep -Rn "TX_ENABLE_EXECUTION_CHANGE_NOTIFY" ports/cortex_r5/*/src 2>/dev/null) + +[ "$profile_guards_missing" -eq 0 ] && \ + say " ok: every Cortex-R5 profiling hook accepts both symbols" + +# -------------------------------------------------------------------------- +# 6. Report only: families with no copy script. # -------------------------------------------------------------------------- # These are maintained by hand, so a fix applied to one toolchain can silently # miss the others. Nothing here fails the run; it is a prompt to look. From 6098ce67d9c6a9a332e8054104acde60832a1c16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 28 Sep 2026 12:46:17 -0400 Subject: [PATCH 167/181] Added a blame ignore list for the mechanical header and version passes (#763) Running git blame on a file header returns a tree-wide copyright, disclosure or version-constant pass rather than the commit that last touched the code. There have been 11 such passes in this repository since 2024, and every header line in the tree now points at one of them. Added .git-blame-ignore-revs listing those commits. GitHub applies the file to its blame view automatically; locally it takes one git config command, which the file documents in its own header. Additive. No source file is touched, and every listed commit was verified to be an ancestor of dev. Assisted-by: Claude Code (Opus 5) --- .git-blame-ignore-revs | 54 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) create mode 100644 .git-blame-ignore-revs diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 000000000..cf90f4143 --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,54 @@ +# Commits that changed file headers, copyright lines or version constants across +# the whole tree. They carry no behavioural change, so `git blame` should look +# through them to the commit that last touched the code itself. +# +# GitHub applies this file automatically. To use it locally, run once: +# +# git config blame.ignoreRevsFile .git-blame-ignore-revs +# +# Add a commit here only when it is mechanical and repository-wide. A commit +# that changes behaviour does not belong in this file, however large it is. + +# 2023-10-23 Update release version to 6.3.0 and date to 10-31-2023 (#308) +# 1366 files +13b700fd3ed763cedcba7dbd17b859077a01aa9c + +# 2024-01-29 Update copyright. +# 3618 files +8276bcf71142197e09551e29f1779299fa591ec7 + +# 2024-01-30 Update version id string. +# 1048 files +3e1da1f0b0973e6b833b08b10fb27c7c718835b3 + +# 2024-02-23 Update the copyright for all assembly files. +# 798 files +039a3463974f922f6dd6bfb8afb7ee2895eaebcf + +# 2024-02-27 Update version number to 6.4.1 +# 237 files +27f0ce9ca2334b975c298fd00eac1bc05ecec1f7 + +# 2025-02-24 Updated ports version to v6.4.2. +# 235 files +376e26be292f7d579091650a70b5670195240539 + +# 2026-03-05 Updated copyright headers and version number constants (#509) +# 5970 files +c3259a216026372e3833dd8996a68f77e8595fbd + +# 2026-06-03 Release 6.5.1.202602 preparation (#543) +# 204 files +de1c6e9bbe13e2db480e4e0ed2d3589ebdd5db27 + +# 2026-06-06 Added copyright headers to files missing them +# 581 files +730b61874bc5cf40768987605ae5187fde0fa1e2 + +# 2026-06-08 Release 6.5.1.202602a preparation (#547) +# 207 files +df30b8b96e4c0c6d72e0bb80d2a2ec31666e5afe + +# 2026-09-15 Normalized the AI disclosure comment to one fixed line per file (#740) +# 455 files +9e4c57138dfa004cd512b60259c1c5047a8b3dd1 From c805d9d3dfdebf55566649b4c67c8ea09980a440 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 28 Sep 2026 12:46:55 -0400 Subject: [PATCH 168/181] Linked ThreadX readers to published documentation (#774) The ThreadX README sent readers to archived Markdown documentation. I linked the overview, Modules, and SMP guides to published HTML pages. The general documentation entry now follows the latest release. All replacement URLs returned HTTP 200; git diff --check passed. Assisted-by: Codex (gpt-6-astra) --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 260a77a30..256162ae4 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ Eclipse ThreadX has been integrated to the semiconductor's SDKs and development We also provide [getting started guide](https://github.com/eclipse-threadx/getting-started) and [samples](https://github.com/eclipse-threadx/samples) using development boards from semiconductors you can build and test with. -See [Overview of Eclipse ThreadX RTOS](https://github.com/eclipse-threadx/rtos-docs/blob/main/rtos-docs/threadx/overview-threadx.md) for the high-level overview. +See [Overview of Eclipse ThreadX RTOS](https://threadx.io/releases/6.5.1/threadx/main/overview-threadx.html) for the high-level overview. ## Repository Structure and Usage ### Directory layout @@ -118,7 +118,7 @@ xtensa cortex_a65ae ``` ### ThreadX Modules -[Eclipse ThreadX Modules](https://github.com/eclipse-threadx/rtos-docs/blob/main/rtos-docs/threadx-modules/chapter1.md) component provides an infrastructure for applications to dynamically load modules that are built separately from the resident portion of the application. +[Eclipse ThreadX Modules](https://threadx.io/releases/6.5.1/threadx-modules/main/chapter1.html) component provides an infrastructure for applications to dynamically load modules that are built separately from the resident portion of the application. ``` cortex_a35 cortex_a35_smp @@ -134,7 +134,7 @@ rxv2 ``` ### ThreadX SMP -[Eclipse ThreadX SMP](https://github.com/eclipse-threadx/rtos-docs/blob/main/rtos-docs/threadx/threadx-smp/chapter1.md) is a high-performance real-time SMP kernel designed specifically for embedded applications. +[Eclipse ThreadX SMP](https://threadx.io/releases/6.5.1/threadx/main/threadx-smp/chapter1.html) is a high-performance real-time SMP kernel designed specifically for embedded applications. ``` arc_hs_smp cortex_a34_smp @@ -210,7 +210,7 @@ License terms for using Eclipse ThreadX are defined in the LICENSE.txt file of t The following are references to additional ThreadX RTOS resources: -- **Product introduction**: https://github.com/eclipse-threadx/rtos-docs +- **Product introduction**: https://threadx.io/releases/latest - **Product issues and bugs, or feature requests**: https://github.com/eclipse-threadx/threadx/issues - **TraceX Installer**: https://aka.ms/azrtos-tracex-installer From f65727f58529c4ff6b235a0c169e6daa9937c633 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 28 Sep 2026 12:47:25 -0400 Subject: [PATCH 169/181] Added a script that counts Assisted-by attributions completely (#775) Git reads trailers only from a block at the very end of a commit message. A squash merge concatenates the branch's messages, so every trailer but the last ends up mid-message, and an indented trailer is skipped as well. Both forms are real attributions and both are invisible to the trailer parser, which is what the project has been using to answer which agents touched a file. The script reads whole commit bodies instead. It groups by value, or lists one line per commit with --list, and takes a revision and a path the way git log does. On dev it reports 163 attributions where the trailer parser reports 122, so a quarter of the record was unreachable. The difference is entirely squashed and indented trailers, not new commits. Assisted-by: Claude Code (Opus 5) --- scripts/count_assisted_by.sh | 79 ++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100755 scripts/count_assisted_by.sh diff --git a/scripts/count_assisted_by.sh b/scripts/count_assisted_by.sh new file mode 100755 index 000000000..57cdf65d2 --- /dev/null +++ b/scripts/count_assisted_by.sh @@ -0,0 +1,79 @@ +#!/bin/bash +############################################################################## +# 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. +# +# AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +# The AI-generated portions may be considered public domain (CC0-1.0) +# and not subject to the project's licence. The human contributor has +# reviewed and verified that the code is correct. +# +# SPDX-License-Identifier: MIT and CC0-1.0 +############################################################################## + +# Report the Assisted-by attributions in a repository's history. +# +# scripts/count_assisted_by.sh # HEAD, grouped by value +# scripts/count_assisted_by.sh origin/dev # a branch +# scripts/count_assisted_by.sh origin/dev -- ports # a path +# scripts/count_assisted_by.sh --list origin/dev # one line per commit +# +# Why not git's own trailer parser: git reads trailers only from a block at the +# very end of a message. A squash merge concatenates the branch's commit +# messages, which leaves every trailer but the last one buried mid-message, and +# an indented trailer is skipped as well. Both forms are real attributions and +# both are invisible to --format='%(trailers:key=Assisted-by)'. This reads whole +# commit bodies instead, so the count is complete. + +set -u + +list=0 +if [ "${1:-}" = "--list" ]; then + list=1 + shift +fi + +rev="${1:-}" +if [ -n "$rev" ] && [ "$rev" != "--" ]; then + shift +else + rev="HEAD" +fi + +if [ "${1:-}" = "--" ]; then + shift +fi + +# %x02 opens a record and %x01 separates the hash from the body, so bodies +# containing blank lines survive the pass through awk. +git log "$rev" --format='%x02%H%x01%B' ${1+"$@"} \ + | tr '\n' '\003' | tr '\002' '\n' \ + | awk -F'\001' -v list="$list" ' + NF >= 2 { + body = $2 + gsub(/\003/, "\n", body) + n = split(body, line, "\n") + for (i = 1; i <= n; i++) { + if (line[i] ~ /^[[:space:]]*Assisted-by:[[:space:]]*/) { + value = line[i] + sub(/^[[:space:]]*Assisted-by:[[:space:]]*/, "", value) + sub(/[[:space:]]+$/, "", value) + if (value == "") + continue + if (list) + print substr($1, 1, 8) " " value + else + count[value]++ + } + } + } + END { + if (list) + exit + for (value in count) + printf "%6d %s\n", count[value], value + }' \ + | { if [ "$list" -eq 1 ]; then cat; else sort -rn; fi; } From 9bf9978e9507bfef4fbffa283d36aaedc0ac7508 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 28 Sep 2026 14:02:49 -0400 Subject: [PATCH 170/181] Silenced the SMP MISRA shim's implicit conversions (#751) common_smp/src/tx_misra.c performs four implicit conversions that its monoprocessor twin makes explicit, and ignores a parameter the twin casts to void. Built with the warning set common_smp uses, the file reports five diagnostics that common/src/tx_misra.c does not: tx_misra.c:49 conversion to 'int' from 'UINT' may change the sign of the result tx_misra.c:93 conversion to 'ULONG' from 'int' may change the sign of the result tx_misra.c:151 the same tx_misra.c:221 the same tx_misra.c:624 unused parameter 'status' The two files are otherwise the same shim, so this is drift rather than a deliberate difference: common/src already carries (INT) on the memset value, (ULONG) on the three pointer differences, and (VOID)status. That the shim is the file reporting them is the reason to fix it. It exists to route the kernel's pointer conversions through functions a MISRA analysis can account for, and an implicit signed-to-unsigned conversion inside it is the class of construct it was written to remove. The test trees hide it. test/tx builds the kernel with -Werror, so the monoprocessor copy could never have regressed this way; test/smp has -Werror commented out, so the SMP copy warns and builds. Applying the monoprocessor form to all five sites. Object code is byte identical before and after, compared with --strip-debug at -m32 -std=c99 with TX_MISRA_ENABLE defined, so this changes diagnostics and nothing else. Assisted-by: Claude Code (Opus 5) --- common_smp/src/tx_misra.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/common_smp/src/tx_misra.c b/common_smp/src/tx_misra.c index f5dd5f53d..f37cebaac 100644 --- a/common_smp/src/tx_misra.c +++ b/common_smp/src/tx_misra.c @@ -47,7 +47,7 @@ /**************************************************************************/ VOID _tx_misra_memset(VOID *ptr, UINT value, UINT size) { - memset(ptr, value, size); + memset(ptr, (INT)value, size); } @@ -91,7 +91,7 @@ ULONG _tx_misra_uchar_pointer_dif(UCHAR *ptr1, UCHAR *ptr2) ULONG value; - value = ptr1 - ptr2; + value = (ULONG)(ptr1 - ptr2); return(value); } @@ -149,7 +149,7 @@ ULONG _tx_misra_ulong_pointer_dif(ULONG *ptr1, ULONG *ptr2) { ULONG value; - value = ptr1 - ptr2; + value = (ULONG)(ptr1 - ptr2); return(value); } @@ -219,7 +219,7 @@ ULONG _tx_misra_timer_pointer_dif(TX_TIMER_INTERNAL **ptr1, TX_TIMER_INTERNAL * ULONG value; - value = ptr1 - ptr2; + value = (ULONG)(ptr1 - ptr2); return(value); } @@ -625,6 +625,8 @@ TX_MUTEX *_tx_misra_void_to_mutex_pointer_convert(VOID *pointer) UINT _tx_misra_status_get(UINT status) { + (VOID)status; + /* Return a successful status. */ return(TX_SUCCESS); } From a752784c65b4288d08c0272ad95242b8c4bf0f0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 28 Sep 2026 14:03:25 -0400 Subject: [PATCH 171/181] Updated ThreadX contribution guide for current workflows (#776) * Updated ThreadX contribution guide for current workflows The existing guide left contributors without current build, test, and submission guidance. The guide now covers the shared project process and ThreadX-specific C99, port, simulator, CI, attribution, and release practices. Documentation links resolve and git diff --check passed. Build tests were not run for this documentation change. Assisted-by: Codex (gpt-6-sol) * Added visible spacing between contributor setup steps The ECA and Git setup items had no visible gap in GitHub Markdown. An indented line break now separates them while preserving list numbering. GitHub Markdown rendered the items in one list with the visible gap, and git diff --check passed. Assisted-by: Codex (gpt-6-sol) --- CONTRIBUTING.md | 384 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 340 insertions(+), 44 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7dfafcacc..e340d3d75 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -4,69 +4,365 @@ Thanks for your interest in this project. ## Project description -Eclipse ThreadX provides a vendor-neutral, open source, safety certified OS for -real-time applications published on under a permissive license. The Eclipse -ThreadX suite encompasses: -* ThreadX - advanced real-time operating system (RTOS) designed specifically for deeply embedded applications -* NetX Duo - advanced, industrial-grade TCP/IP network stack designed specifically for deeply embedded real-time and IoT applications -* FileX - high-performance, FAT-compatible file system that’s fully integrated with ThreadX kernel -* GUIX - provides a complete, embedded graphical user interface (GUI) library -* USBX - high-performance USB host, device, and on-the-go (OTG) embedded stack, that is fully integrated with ThreadX kernel -* LevelX - Flash Wear Leveling for FileX and stand-alone purposes -* GuiX Studio - design environment, facilitating the creation and maintenance of all graphical elements for GUIX -* TraceX - analysis tool that provides a graphical view of real-time system events to better understand the behavior of real-time systems - -Project site: https://projects.eclipse.org/projects/iot.threadx +Eclipse ThreadX provides a vendor-neutral, open source, safety-certified OS for real-time applications, published under a permissive license. The Eclipse ThreadX suite encompasses: + +* **ThreadX** - advanced real-time operating system (RTOS) designed specifically for deeply embedded applications +* **NetX Duo** - advanced, industrial-grade TCP/IP network stack designed specifically for deeply embedded real-time and IoT applications +* **FileX** - high-performance, FAT-compatible file system that is fully integrated with the ThreadX kernel +* **GUIX** - complete, embedded graphical user interface (GUI) library +* **GUIX Studio** - design environment, facilitating the creation and maintenance of all graphical elements for GUIX +* **USBX** - high-performance USB host, device, and on-the-go (OTG) embedded stack, fully integrated with the ThreadX kernel +* **LevelX** - flash wear levelling for FileX and stand-alone purposes +* **TraceX** - analysis tool that provides a graphical view of real-time system events to better understand the behaviour of real-time systems +* **ZoneX** - deterministic partitioning hypervisor for mixed-criticality embedded systems +* **SampleX** - samples and demos for the components above + +Project websites: + +* https://threadx.io +* https://projects.eclipse.org/projects/iot.threadx + +This file describes how to contribute to **ThreadX**. General contribution conventions are shared across the Eclipse ThreadX repositories; build and test instructions differ by component. ## Terms of Use -This repository is subject to the Terms of Use of the Eclipse Foundation -https://www.eclipse.org/legal/termsofuse.php +This repository is subject to the Terms of Use of the Eclipse Foundation: https://www.eclipse.org/legal/termsofuse.php -## Developer resources +## New contributors -Information regarding source code management, builds, coding standards, and more. -https://projects.eclipse.org/projects/iot.threadx/developer +Welcome. Here is the shortest path from zero to a merged pull request. -The project maintains the following source code repositories +1. **Create an Eclipse Foundation account.** https://accounts.eclipse.org/user/register -* https://github.com/eclipse-threadx/.github -* https://github.com/eclipse-threadx/cmsis-packs -* https://github.com/eclipse-threadx/filex -* https://github.com/eclipse-threadx/getting-started -* https://github.com/eclipse-threadx/guix -* https://github.com/eclipse-threadx/levelx -* https://github.com/eclipse-threadx/netxduo -* https://github.com/eclipse-threadx/rtos-docs -* https://github.com/eclipse-threadx/samples -* https://github.com/eclipse-threadx/threadx -* https://github.com/eclipse-threadx/threadx-learn-samples -* https://github.com/eclipse-threadx/tracex -* https://github.com/eclipse-threadx/usbx + The email address on that account matters: it must be the same address you use as the `Author` of your Git commits. If the two do not match, the ECA check on your pull request will fail. + +2. **Sign the Eclipse Contributor Agreement (ECA).** See the section below. This is a one-time step and covers every Eclipse Foundation project. + +
+ +3. **Configure Git accordingly.** + + ``` + git config user.name "Your Name" + git config user.email "the-address-on-your-eclipse-account@example.org" + ``` + +4. **Pick something to work on.** Open issues are fair game, including ones nobody has assigned. Please leave a comment on the issue saying you intend to work on it, so two people do not solve the same problem twice. If an issue carries a `good first issue` label, it is a reasonable starting point. + +5. **Have an idea for a new feature? Discuss it first.** Open a thread in [GitHub Discussions](https://github.com/orgs/eclipse-threadx/discussions) or raise it on the [developer mailing list](https://accounts.eclipse.org/mailing-list/threadx-dev) before writing code. Kernel APIs and port changes can affect many applications, so discuss the shape of a feature before submitting a finished implementation. + +Bug fixes and documentation corrections need no prior discussion. Send them straight in. ## Eclipse Development Process -This Eclipse Foundation open project is governed by the Eclipse Foundation -Development Process and operates under the terms of the Eclipse IP Policy. +This Eclipse Foundation open project is governed by the Eclipse Foundation Development Process and operates under the terms of the Eclipse IP Policy. * https://eclipse.org/projects/dev_process * https://www.eclipse.org/org/documents/Eclipse_IP_Policy.pdf ## Eclipse Contributor Agreement -In order to be able to contribute to Eclipse Foundation projects you must electronically sign the Eclipse Contributor Agreement (ECA). -https://www.eclipse.org/legal/ECA.php +In order to be able to contribute to Eclipse Foundation projects you must electronically sign the Eclipse Contributor Agreement (ECA): https://www.eclipse.org/legal/ECA.php + +The ECA provides the Eclipse Foundation with a permanent record that you agree that each of your contributions will comply with the commitments documented in the Developer Certificate of Origin (DCO). Having an ECA on file associated with the email address matching the "Author" field of your contribution's Git commits fulfills the DCO's requirement that you sign-off on your contributions. + +For more information, please see the Eclipse Committer Handbook: https://www.eclipse.org/projects/handbook/#resources-commit + +## Required tooling + +Build and test ThreadX with CMake and Ninja. The Windows simulator uses MSVC from the Visual Studio Build Tools; a full Visual Studio installation is not required. + +| Tool | Requirement | +| ---- | ----------- | +| CMake | 3.13 or later (the minimum declared by the root build) | +| Ninja | any recent release | +| Git | any recent release | +| Python | 3.x, with `gcovr` 8.6 for coverage reports | + +The reference host compiler is GCC 14 on Linux and MSVC on Windows. Arm port CI pins Arm GNU Toolchain **14.3.rel1** (`arm-none-eabi` and `aarch64-none-elf`) and Arm Toolchain for Embedded **22.1.0**. Use GCC syntax for assembly built with GNU toolchains. Other ports may require their own vendor toolchain; check the port's build files. + +ThreadX code is C99-compatible. The kernel, SMP, and FreeRTOS compatibility test projects declare C99 explicitly. + +## Building and testing + +The scripts below are thin entry points to the CMake and CTest projects under `test/`. On Ubuntu, `scripts/install.sh` installs the dependencies used by the host regression jobs. + +| Scripts | What they cover | +| ------- | --------------- | +| `scripts/build_tx.sh`, `scripts/test_tx.sh` | The single-core kernel regression suite across its build configurations. | +| `scripts/build_smp.sh`, `scripts/test_smp.sh` | The SMP kernel regression suite across its build configurations. | +| `scripts/build_freertos.sh`, `scripts/test_freertos.sh` | The FreeRTOS compatibility layer. | +| `scripts/build_tx_riscv.sh`, `scripts/test_tx_riscv.sh` | The RISC-V kernel port; install its toolchain with `scripts/install_riscv.sh`. | +| `scripts/build_posix.sh`, `scripts/test_posix.sh` | The POSIX compatibility layer on RISC-V. | +| `scripts/build_tx.ps1`, `scripts/test_tx.ps1` | The Windows single-core simulator (`win32` or `win64`). | +| `scripts/build_smp.ps1`, `scripts/test_smp.ps1` | The Windows SMP simulator (`win64`). | + +For the Linux suites, run the matching build script before its test script. The test scripts use CTest and run the timing-sensitive simulator tests serially. The Windows scripts also configure CMake with Ninja; run them from a PowerShell environment with the Visual Studio Build Tools installed. + +For Arm port changes, `scripts/check_gcc.sh` and `scripts/check_clang.sh` assemble and compile the supported port sources and link examples; they do not execute target code. `scripts/check_ports.sh` checks generated-port reproducibility and other port-tree rules. The Cortex-R52 FVP workflow executes images on the Armv8-R AEM FVP when the model is configured. Build-only checks cannot establish that a port runs correctly, so report target execution separately. + +The kernel and SMP CI jobs instrument all five host build configurations and merge their coverage. They currently enforce a **99% line coverage floor** on each merged report. The project goal is 100% test coverage, and new behaviour needs regression tests. The existing CI floor does not establish full coverage: it does not gate branch coverage, and the FreeRTOS and RISC-V jobs do not collect coverage. Explain any gap relevant to your change in the pull request. + +Describe what you ran and what passed. A successful build alone does not verify runtime behaviour. + +## Continuous integration + +ThreadX has six directly triggered GitHub Actions workflows and one reusable regression workflow. They do not all have the same triggers: some run for pushes and pull requests to `dev` and `master`, while others run only for pull requests. Most build and port checks have path filters; `regression_test.yml` is unfiltered. + +| Workflow | What it checks | +| -------- | -------------- | +| `regression_test.yml` | Single-core kernel, SMP, FreeRTOS compatibility, and RISC-V regression suites through `regression_template.yml`; kernel and SMP merged line coverage floors. | +| `gcc_check.yml` | Arm port assembly, C compilation, example links, and invalid Cortex-R52 option combinations with Arm GNU Toolchain. | +| `clang_check.yml` | Arm port assembly, C compilation, and example links with Arm Toolchain for Embedded. | +| `ci_cortex_m.yml` | CMake and Ninja cross-builds for selected Cortex-M ports. | +| `ports_arch_check.yml` | Generated-port consistency and port-tree checks. | +| `r52_fvp.yml` | Cortex-R52 builds and FVP execution when the model is configured. | + +The Armv8-R AEM FVP is distributed behind a click-through licence. If the `FVP_AEMV8R_URL` repository variable is unset, the Cortex-R52 workflow builds the images but reports that it did not execute them. A green build in that state is not a runtime test. + +## Pull request acceptance criteria + +**Pull requests must target the `dev` branch.** `master` holds the latest release; see [Release model and support](#release-model-and-support) below. A pull request opened against `master` will be asked to retarget. + +Before requesting a review, check your contribution against this list. + +**Process** + +* The branch is a feature branch based on `dev`. Never commit directly to `master` or `dev`. +* Your ECA is signed and the commit `Author` email matches your Eclipse account. +* The pull request is one logical change. Unrelated fixes belong in separate pull requests. +* Commit subject lines start with a past-tense verb, for example `Fixed the memory allocator`. +* The pull request explains what changed and why, and how you verified it. + +**Code** + +* The code is C99-compatible. +* It follows the coding style of the surrounding code. +* New functions and structures are documented in comments, as in existing code. +* MISRA C rules are followed as closely as practical, taking MISRA C 2004, 2012 and 2023 into account. Any deviation is explicit, names the rule being circumvented, and justifies it in a comment. +* `goto` is not used. +* No new external dependencies. This is a hard rule. +* When implementing an industry standard, code is not copied from an existing implementation. Existing implementations may inform your work, but you must identify those sources clearly. +* Code is written with ThreadX's priorities in mind: runtime speed and small code size. +* New C and assembly files, and edited C and assembly files, carry the appropriate header and attribution (see below). + +**Verification** + +* All applicable CI checks are green. +* The change builds without new warnings on the reference toolchains. +* Regression tests covering the change are added or updated. The project targets 100% test coverage; a pull request that lowers coverage needs a stated reason. The current host CI floor is 99% merged line coverage for each kernel suite. +* API or behaviour changes come with a matching documentation pull request against [rtos-docs-asciidoc](https://github.com/eclipse-threadx/rtos-docs-asciidoc). + +**Security** + +If you discover a security issue while working on a change, do not describe it in a public pull request. Follow [SECURITY.md](SECURITY.md) instead. + +## AI-assisted contributions + +**AI-assisted contributions are welcome**, provided they are attributed. + +Two things are non-negotiable: + +1. **Attribution.** Mark AI-assisted C and assembly files as described below, and identify the tool and model in the commit message. +2. **Human responsibility.** The human contributor submitting the pull request is responsible for the contribution - technically and legally. Signing the ECA means *you* certify the contribution's provenance. An AI tool cannot sign the ECA and cannot hold that responsibility. Review what the tool produced, understand it, and verify that it is correct and that you have the right to contribute it. "The model wrote it" is not a defence. + +This is consistent with the Eclipse Foundation's [Generative AI Usage Guidelines](https://www.eclipse.org/projects/guidelines/genai/) and the [Eclipse Project Handbook](https://www.eclipse.org/projects/handbook/#genai). Please read them before submitting AI-assisted work. + +### Using a coding agent + +Give a coding agent this contribution guide and the build instructions for the area it changes. Review its output against the same acceptance criteria as any other contribution. In particular, check C99 compatibility, surrounding style, test coverage, and the correct port or simulator for runtime verification. + +### Header for new files + +Add this header when creating a new C or assembly (`.S`) file: + +```c +/*************************************************************************** + * Copyright (c) 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. + * + * AI Disclosure: This file was largely AI-generated by (). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ +``` + +Substitute the current year, product name, and model and version. If a file was written without AI assistance, omit the AI Disclosure paragraph and use `SPDX-License-Identifier: MIT`. + +### Header for existing files + +When editing an existing C or assembly file whose copyright is from 2025 or earlier, and which does not already mention Eclipse ThreadX contributors, add this line to the header: + +```c + * Copyright (c) Eclipse ThreadX contributors +``` + +It goes *below* the older copyright. All copyright lines must stay in chronological order. For example: + +```c +/*************************************************************************** + * Copyright (c) 2024 Microsoft Corporation + * 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 + **************************************************************************/ +``` + +If the edit was AI-assisted and the file does not already carry an AI disclosure line, add this line just under the header: + +```c +// Portions of this file were generated with AI assistance. +``` -The ECA provides the Eclipse Foundation with a permanent record that you agree -that each of your contributions will comply with the commitments documented in -the Developer Certificate of Origin (DCO). Having an ECA on file associated with -the email address matching the "Author" field of your contribution's Git commits -fulfills the DCO's requirement that you sign-off on your contributions. +Use the comment marker already used by the file. Keep an existing disclosure line unchanged and never add a second one. If you copy an existing file to get started on a new one, treat the result as a new file: use the new-file header, do not carry the old one over. -For more information, please see the Eclipse Committer Handbook: -https://www.eclipse.org/projects/handbook/#resources-commit +### Commit attribution + +Attribute AI assistance with an `Assisted-by` trailer in each commit that contains AI-assisted changes: + +```text +Fixed the thread resume status + +A suspended thread could report an out-of-date status after resuming. + +The resume path now returns the status set by the operation that woke it. + +The single-core regression suite passed all tests. + +Assisted-by: () +``` + +Use the product's accepted name (`Claude Code`, `Copilot`, `Codex`, or `Gemini`) and the model string reported by the tool. Do not use `Co-Authored-By` for AI attribution. Commit subjects and pull request titles start with a past-tense verb and stay within 72 characters. The message body states the cause, fix, and test result in that order; wrap commit bodies at 88 characters. Pull request descriptions use one line per paragraph. + +## Release model and support + +This section summarises the project's [Release Model and Support Policy](https://github.com/eclipse-threadx/rtos-docs-asciidoc/blob/main/rtos-docs/home/modules/ROOT/pages/releases-and-support.adoc), which is the authoritative version. + +### Version numbers + +Eclipse ThreadX releases generally follow [Semantic Versioning](https://semver.org/). Given a version number **X.Y.Z.Bh**, for example `6.5.0.202601a`: + +* **X** increases for a *milestone release*. Components currently stay at version 6. +* **Y** increases for a *feature release* adding a major feature. +* **Z** increases for a *maintenance release* of minor fixes and improvements. +* **B** is a *build number* identifying the quarter of publication - `202601` is Q1 2026. +* **h** denotes a *hotfix release*, identified by a letter. Hotfix releases are component-specific. + +### Release cadence + +The project adopted a predictable quarterly release model in September 2025 and has published a release every quarter since. + +Quarterly releases ship new versions of every component, whether or not that component saw code changes, so that version numbers do not drift apart between components. A release shipping no code changes for a component says so in its release notes. + +Urgent fixes between quarterly releases ship as *hotfix* releases. Those contain only security fixes, or fixes for serious problems that prevent building or testing applications. + +### Branches + +The project runs a time-based release train on trunk-based development. There are no long-term support branches and no backports to older releases. + +* `master` always contains the latest quarterly or hotfix release. +* `dev` is the integration branch. Pull requests are merged there during the quarter. Track `dev` if you want to test new features and fixes ahead of a release. +* A quarterly release is performed by merging `dev` into `master`. + +### Support policy + +Issues in the codebase are fixed on a best-effort basis, and pull requests fixing existing or new issues are gladly accepted. + +Security vulnerabilities disclosed confidentially are handled under the [Eclipse Foundation's security policy](https://www.eclipse.org/security/policy/). Once a candidate vulnerability is confirmed, the team works to deliver a fix as soon as possible, shipping it in the next quarterly release or as a hotfix depending on timing. Resolved vulnerabilities are disclosed immediately after a release containing the fix becomes available. The team aims to resolve newly confirmed vulnerabilities within three months; that period may be extended by the Project Leadership Chain together with the Eclipse Foundation Security team where appropriate. + +See [SECURITY.md](SECURITY.md) for how to report a vulnerability. + +### Roadmap + +The project team plans its work on a [public GitHub project board](https://github.com/orgs/eclipse-threadx/projects/2/views/2). + +### A note on older releases + +Microsoft contributed only the Azure RTOS codebase v6.x to the Eclipse Foundation. Older ThreadX releases (v5.x and lower) sold by Express Logic were never made open source, and Microsoft has discontinued sales and support for them. Users of ThreadX 5.x and lower should upgrade to the latest release of Eclipse ThreadX as soon as possible. + +## Documentation + +The documentation is published at **https://threadx.io**. PDF manuals for every component, in A4 and US Letter formats, are attached as assets to each GitHub release. + +### The stack + +Documentation is written in [AsciiDoc](https://asciidoc.org/) and built with [Antora](https://antora.org/). PDF manuals are produced by the [Antora Assembler](https://docs.antora.org/assembler/latest/) with `asciidoctor-pdf`. + +### The workflow + +1. The single source of truth is [rtos-docs-asciidoc](https://github.com/eclipse-threadx/rtos-docs-asciidoc). All documentation changes are made there, as pull requests, following the same branch rules as the code repositories. +2. At release time the site is generated from that source into [rtos-docs-html](https://github.com/eclipse-threadx/rtos-docs-html), which holds the rendered HTML and exists solely for website integration. Do not edit it by hand - your changes will be overwritten by the next build. +3. The website then serves the generated content from `rtos-docs-html`. + +The older `rtos-docs` repository, which held the documentation in Markdown, is archived and superseded by `rtos-docs-asciidoc`. Do not send changes there. + +If your contribution adds or changes an API or a feature, open a matching pull request against `rtos-docs-asciidoc`. + +## Developer resources + +Information regarding source code management, builds, coding standards, and more: https://projects.eclipse.org/projects/iot.threadx/developer + +The project maintains the following repositories: + +**Components** + +* https://github.com/eclipse-threadx/threadx +* https://github.com/eclipse-threadx/netxduo +* https://github.com/eclipse-threadx/filex +* https://github.com/eclipse-threadx/guix +* https://github.com/eclipse-threadx/usbx +* https://github.com/eclipse-threadx/levelx +* https://github.com/eclipse-threadx/tracex +* https://github.com/eclipse-threadx/zonex + +**Samples and platforms** + +* https://github.com/eclipse-threadx/samplex +* https://github.com/eclipse-threadx/supported-platforms + +**Documentation** + +* https://github.com/eclipse-threadx/rtos-docs-asciidoc +* https://github.com/eclipse-threadx/rtos-docs-html + +**Community and process** + +* https://github.com/eclipse-threadx/discussions +* https://github.com/eclipse-threadx/trustedx +* https://github.com/eclipse-threadx/.github ## Contact -Contact the project developers via the project's "dev" list. +### GitHub Discussions + +https://github.com/orgs/eclipse-threadx/discussions + +Q&A, feedback, and announcements. Decisions taken by the project team are documented here as well. This is usually the fastest way to reach both the team and other users. + +### Main ThreadX mailing list + +https://accounts.eclipse.org/mailing-list/threadx + +News and updates about the ThreadX project and the ThreadX Alliance. + +### Developer mailing list + https://accounts.eclipse.org/mailing-list/threadx-dev + +Project team conversations. Feel free to jump in and ask non-technical questions there. + +### User mailing list + +https://accounts.eclipse.org/mailing-list/threadx-users + +Ask your technical questions and discuss issues here. From 83361990cb4d03da8851e30030688ed3abb4d840 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 28 Sep 2026 14:03:53 -0400 Subject: [PATCH 172/181] Normalized the AI disclosure comment and added a check that keeps it so (#762) * Normalized the AI disclosure line across every tracked file type The repository-wide pass covered source files only, so build files, CMake toolchain files, shell scripts and the GDB and manifest files kept the older per-edit form of the disclosure comment, which names a product and a model version. The Cortex-R52 module manager port then merged after that pass and brought the old form back into the sources as well. Replaced it with the fixed text in all of them, using the comment character each file already uses. Comment-only. 143 files, one line each. The repository now holds 601 files carrying exactly one disclosure line, none carrying the old form, and none carrying more than one. Assisted-by: Claude Code (Opus 5) * Added a check that keeps the AI disclosure comment in its one accepted form Nothing enforced the disclosure convention, so the drift it exists to prevent returned twice: once when a port merged after the normalisation pass carrying the older per-edit form, and once because that pass had covered source files only, leaving build files and scripts untouched for months. Added scripts/check_ai_disclosure.sh, which rejects the superseded per-edit form, a doubled comment marker, more than one disclosure line in a file, and any spelling of the line that is not exact. It runs from repo_checks.yml, a workflow with no path filter, because a source-path filter is what hid the build files the first time. The check passes on this branch. Each of its four rules was confirmed to fail on a tree with that defect reintroduced, and to pass once it was removed. Assisted-by: Claude Code (Opus 5) * Normalised the disclosure lines that landed after this branch Thirteen files reached dev after this branch was written, each carrying the superseded per-edit form. txm_module_manager_dispatch.h reached it with six stacked copies, naming the same product and the same model every time -- the accumulation the fixed text exists to prevent. Each of those files now carries one disclosure line in the accepted form. Where the accepted line was already present, the superseded ones are deleted rather than converted, so no file gains a second. check_ai_disclosure.sh reported eighteen hits across thirteen files before the pass and passes after it. Assisted-by: Claude Code (Opus 5) * Exempted Markdown from the near-miss disclosure check The near-miss rule flags any line carrying the phrase "AI assistance" that is not the accepted text, which is right for source but wrong for documentation. The contribution guide has to quote the accepted line and say when it applies, so the check reports two paragraphs of prose as drift and fails the build. Markdown is now exempt from that rule alone. The three rules that matter for a documentation file -- superseded form, doubled comment marker, duplicate line -- still scan it, so a stale disclosure in a Markdown file is still caught. The check passes against a tree carrying the rewritten contribution guide, and still fails when a near miss is planted in a source file. Assisted-by: Claude Code (Opus 5) * Corrected the trailer command named in the disclosure check The header comment points a reader at git's own trailer parser to find out which agents have touched a file. That parser reads trailers only from a block at the very end of a message, so a squash merge -- which concatenates a branch's messages -- buries every trailer but the last one mid-message, and an indented trailer is skipped outright. On dev it finds 122 attributions where 163 exist. The comment now names count_assisted_by.sh, which reads whole bodies. Assisted-by: Claude Code (Opus 5) --- .github/workflows/repo_checks.yml | 63 +++++++++ cmake/aarch64-none-elf.cmake | 2 +- cmake/arm11.cmake | 2 +- cmake/arm9.cmake | 2 +- cmake/cortex_a12.cmake | 2 +- cmake/cortex_a15.cmake | 2 +- cmake/cortex_a17.cmake | 2 +- cmake/cortex_a34.cmake | 2 +- cmake/cortex_a35.cmake | 2 +- cmake/cortex_a5.cmake | 2 +- cmake/cortex_a53.cmake | 2 +- cmake/cortex_a55.cmake | 2 +- cmake/cortex_a57.cmake | 2 +- cmake/cortex_a5x.cmake | 2 +- cmake/cortex_a65.cmake | 2 +- cmake/cortex_a65ae.cmake | 2 +- cmake/cortex_a7.cmake | 2 +- cmake/cortex_a72.cmake | 2 +- cmake/cortex_a73.cmake | 2 +- cmake/cortex_a75.cmake | 2 +- cmake/cortex_a76.cmake | 2 +- cmake/cortex_a76ae.cmake | 2 +- cmake/cortex_a77.cmake | 2 +- cmake/cortex_a78.cmake | 2 +- cmake/cortex_a8.cmake | 2 +- cmake/cortex_m23.cmake | 2 +- cmake/cortex_m33.cmake | 2 +- cmake/cortex_m52.cmake | 2 +- cmake/cortex_m55.cmake | 2 +- cmake/cortex_m85.cmake | 2 +- cmake/cortex_r4.cmake | 2 +- cmake/cortex_r5.cmake | 2 +- cmake/cortex_r52.cmake | 2 +- cmake/cortex_r52_clang.cmake | 2 +- .../src/txm_module_object_deallocate.c | 2 +- .../inc/txm_module_manager_dispatch.h | 12 -- .../inc/txm_module_manager_util.h | 2 +- .../src/txm_module_manager_object_allocate.c | 2 +- .../txm_module_manager_object_deallocate.c | 2 +- .../src/txm_module_manager_thread_reset.c | 2 +- .../src/txm_module_manager_util.c | 2 +- ports/arm11/gnu/CMakeLists.txt | 2 +- .../arm11/gnu/example_build/build_threadx.sh | 2 +- .../gnu/example_build/build_threadx_sample.sh | 2 +- ports/arm9/gnu/CMakeLists.txt | 2 +- ports/arm9/gnu/example_build/build_threadx.sh | 2 +- .../gnu/example_build/build_threadx_sample.sh | 2 +- ports/cortex_a12/gnu/CMakeLists.txt | 2 +- .../gnu/example_build/build_threadx.sh | 2 +- .../gnu/example_build/build_threadx_sample.sh | 2 +- ports/cortex_a15/gnu/CMakeLists.txt | 2 +- .../gnu/example_build/build_threadx.sh | 2 +- .../gnu/example_build/build_threadx_sample.sh | 2 +- ports/cortex_a17/gnu/CMakeLists.txt | 2 +- .../gnu/example_build/build_threadx.sh | 2 +- .../gnu/example_build/build_threadx_sample.sh | 2 +- ports/cortex_a34/gnu/CMakeLists.txt | 2 +- ports/cortex_a35/gnu/CMakeLists.txt | 2 +- ports/cortex_a5/gnu/CMakeLists.txt | 2 +- .../gnu/example_build/build_threadx.sh | 2 +- .../gnu/example_build/build_threadx_sample.sh | 2 +- ports/cortex_a53/gnu/CMakeLists.txt | 2 +- ports/cortex_a55/gnu/CMakeLists.txt | 2 +- ports/cortex_a57/gnu/CMakeLists.txt | 2 +- ports/cortex_a65/gnu/CMakeLists.txt | 2 +- ports/cortex_a65ae/gnu/CMakeLists.txt | 2 +- ports/cortex_a7/gnu/CMakeLists.txt | 2 +- .../gnu/example_build/build_threadx.sh | 2 +- .../gnu/example_build/build_threadx_sample.sh | 2 +- ports/cortex_a72/gnu/CMakeLists.txt | 2 +- ports/cortex_a73/gnu/CMakeLists.txt | 2 +- ports/cortex_a75/gnu/CMakeLists.txt | 2 +- ports/cortex_a76/gnu/CMakeLists.txt | 2 +- ports/cortex_a76ae/gnu/CMakeLists.txt | 2 +- ports/cortex_a77/gnu/CMakeLists.txt | 2 +- ports/cortex_a8/gnu/CMakeLists.txt | 2 +- .../gnu/example_build/build_threadx.sh | 2 +- .../gnu/example_build/build_threadx_sample.sh | 2 +- ports/cortex_a9/gnu/CMakeLists.txt | 2 +- .../gnu/example_build/build_threadx.sh | 2 +- .../gnu/example_build/build_threadx_sample.sh | 2 +- .../gnu/example_build/build_threadx.sh | 2 +- .../gnu/example_build/build_threadx_sample.sh | 2 +- ports/cortex_m23/gnu/CMakeLists.txt | 2 +- .../gnu/example_build/build_threadx.sh | 2 +- .../gnu/example_build/build_threadx_sample.sh | 2 +- .../example_build/tx_initialize_low_level.arm | 2 +- .../gnu/example_build/build_threadx.sh | 2 +- .../gnu/example_build/build_threadx_sample.sh | 2 +- .../gnu/example_build/build_threadx.sh | 2 +- .../gnu/example_build/build_threadx_sample.sh | 2 +- .../example_build/tx_initialize_low_level.arm | 2 +- .../gnu/example_build/build_threadx.sh | 2 +- .../gnu/example_build/build_threadx_sample.sh | 2 +- .../gnu/example_build/build_threadx.sh | 2 +- .../gnu/example_build/build_threadx_sample.sh | 2 +- .../example_build/tx_initialize_low_level.arm | 2 +- .../gnu/example_build/build_threadx.sh | 2 +- .../gnu/example_build/build_threadx_sample.sh | 2 +- .../gnu/example_build/build_threadx.sh | 2 +- .../gnu/example_build/build_threadx_sample.sh | 2 +- ports/cortex_r4/gnu/CMakeLists.txt | 2 +- .../gnu/example_build/build_threadx.sh | 2 +- .../gnu/example_build/build_threadx_sample.sh | 2 +- ports/cortex_r5/gnu/CMakeLists.txt | 2 +- .../gnu/example_build/build_threadx.sh | 2 +- .../gnu/example_build/build_threadx_sample.sh | 2 +- ports/cortex_r52/gnu/CMakeLists.txt | 2 +- .../fvp_baser_aemv8r/CMakeLists.txt | 2 +- .../fvp_baser_aemv8r/test/run_fvp_test.py | 2 +- .../example_build/s32z280_evb/CMakeLists.txt | 2 +- .../s32z280_evb/tools/read_identity.gdb | 2 +- .../ARMv7-A/threadx/ports/gnu/CMakeLists.txt | 2 +- .../example_build/tx_initialize_low_level.arm | 2 +- .../ARMv8-A/threadx/ports/gnu/CMakeLists.txt | 2 +- .../threadx_smp/ports/gnu/CMakeLists.txt | 2 +- .../cortex_a7/ac5/inc/txm_module_port.h | 2 +- .../txm_module_manager_mm_register_setup.c | 2 +- .../cortex_a7/gnu/inc/txm_module_port.h | 2 +- .../txm_module_manager_mm_register_setup.c | 2 +- .../cortex_a7/iar/inc/txm_module_port.h | 2 +- .../txm_module_manager_mm_register_setup.c | 2 +- .../s32z280_evb/tools/diagnose_module.gdb | 2 +- .../s32z280_evb/tools/run_module_demo.gdb | 2 +- .../s32z280_evb/tools/run_module_demo.sh | 2 +- ports_module/cortex_r52/gnu/inc/tx_port.h | 2 +- .../cortex_r52/gnu/inc/txm_module_port.h | 2 +- .../src/tx_thread_context_restore.S | 2 +- .../src/tx_thread_context_save.S | 2 +- .../module_manager/src/tx_thread_schedule.S | 2 +- .../src/tx_thread_stack_build.S | 2 +- .../src/tx_thread_system_return.S | 2 +- .../src/txm_module_manager_alignment_adjust.c | 2 +- ...xm_module_manager_external_memory_enable.c | 2 +- .../txm_module_manager_memory_fault_handler.c | 2 +- .../txm_module_manager_thread_stack_build.S | 2 +- ports_smp/cortex_a34_smp/gnu/CMakeLists.txt | 2 +- ports_smp/cortex_a35_smp/gnu/CMakeLists.txt | 2 +- ports_smp/cortex_a53_smp/gnu/CMakeLists.txt | 2 +- ports_smp/cortex_a55_smp/gnu/CMakeLists.txt | 2 +- ports_smp/cortex_a57_smp/gnu/CMakeLists.txt | 2 +- ports_smp/cortex_a5_smp/gnu/CMakeLists.txt | 2 +- ports_smp/cortex_a5x_smp/gnu/CMakeLists.txt | 2 +- .../green/src/tx_thread_smp_time_get.a64 | 2 +- ports_smp/cortex_a65_smp/gnu/CMakeLists.txt | 2 +- ports_smp/cortex_a65ae_smp/gnu/CMakeLists.txt | 2 +- ports_smp/cortex_a72_smp/gnu/CMakeLists.txt | 2 +- ports_smp/cortex_a73_smp/gnu/CMakeLists.txt | 2 +- ports_smp/cortex_a75_smp/gnu/CMakeLists.txt | 2 +- ports_smp/cortex_a76_smp/gnu/CMakeLists.txt | 2 +- ports_smp/cortex_a76ae_smp/gnu/CMakeLists.txt | 2 +- ports_smp/cortex_a77_smp/gnu/CMakeLists.txt | 2 +- ports_smp/cortex_a78_smp/gnu/CMakeLists.txt | 2 +- ports_smp/cortex_a7_smp/gnu/CMakeLists.txt | 2 +- ports_smp/linux/gnu/CMakeLists.txt | 2 +- .../mips32_interaptiv_smp/gnu/CMakeLists.txt | 2 +- scripts/check_ai_disclosure.sh | 129 ++++++++++++++++++ .../tx/cmake/thread_transition/CMakeLists.txt | 2 +- 158 files changed, 347 insertions(+), 167 deletions(-) create mode 100644 .github/workflows/repo_checks.yml create mode 100755 scripts/check_ai_disclosure.sh diff --git a/.github/workflows/repo_checks.yml b/.github/workflows/repo_checks.yml new file mode 100644 index 000000000..955e6ddd1 --- /dev/null +++ b/.github/workflows/repo_checks.yml @@ -0,0 +1,63 @@ +############################################################################### +# 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. +# +# AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +# The AI-generated portions may be considered public domain (CC0-1.0) +# and not subject to the project's licence. The human contributor has +# reviewed and verified that the code is correct. +# +# SPDX-License-Identifier: MIT and CC0-1.0 +############################################################################### + +name: repo_checks + +# Repository-wide text checks. +# +# THIS LIVES IN ITS OWN WORKFLOW BECAUSE IT MUST NOT BE PATH-FILTERED, and a +# path filter is a property of a workflow rather than of a job. The check +# selects its input with `git ls-files` and scans every tracked file, so any +# file at all can carry a finding. +# +# That is not hypothetical here. The pass that introduced the fixed +# disclosure line covered source files only, and the drift it was meant to end +# survived for months afterwards in CMake files, toolchain files, shell and +# PowerShell scripts, a GDB script and a Visual Studio manifest -- precisely +# the files a source-path filter would have skipped. A workflow that gates no +# pull request anybody opens is worse than no workflow, because it looks like +# coverage. +# +# Cheap enough that running it on everything costs nothing worth measuring: it +# is grep over a repository this size, with no toolchain, no build and no +# cache. + +on: + # No `paths:` on either trigger, deliberately. See above. + push: + branches: [ dev, master ] + pull_request: + branches: [ dev, master ] + +# A second push to the same branch makes the first answer irrelevant. +concurrency: + group: repo-checks-${{ github.ref }} + cancel-in-progress: true + +permissions: + contents: read + +jobs: + checks: + runs-on: ubuntu-24.04 + steps: + # Actions are pinned to a commit SHA with the version in the trailing + # comment. A tag can be moved; a SHA cannot, which is what makes "which + # code ran in our CI" answerable from the repository. + - name: Check out the repository + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + + - name: Check the AI disclosure comments + run: scripts/check_ai_disclosure.sh diff --git a/cmake/aarch64-none-elf.cmake b/cmake/aarch64-none-elf.cmake index be2034251..dada9fec1 100644 --- a/cmake/aarch64-none-elf.cmake +++ b/cmake/aarch64-none-elf.cmake @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # Shared settings for the AArch64 bare metal ports, the counterpart of # arm-none-eabi.cmake beside it. The two differ by more than the tool prefix: diff --git a/cmake/arm11.cmake b/cmake/arm11.cmake index cd28e9458..957e1f053 100644 --- a/cmake/arm11.cmake +++ b/cmake/arm11.cmake @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # Toolchain file for ARM11 using GNU tools. The port readme identifies the # target as ARM1136J-S, which is what -mcpu selects. diff --git a/cmake/arm9.cmake b/cmake/arm9.cmake index 5bf113758..436d232e5 100644 --- a/cmake/arm9.cmake +++ b/cmake/arm9.cmake @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # Toolchain file for ARM9 using GNU tools. This is the oldest core in the # CMake build; the port readme names ARM9 itself. diff --git a/cmake/cortex_a12.cmake b/cmake/cortex_a12.cmake index 54658771c..4c5a603e2 100644 --- a/cmake/cortex_a12.cmake +++ b/cmake/cortex_a12.cmake @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # Toolchain file for Arm Cortex-A12 using GNU tools. diff --git a/cmake/cortex_a15.cmake b/cmake/cortex_a15.cmake index 84f85702f..30ab71d2a 100644 --- a/cmake/cortex_a15.cmake +++ b/cmake/cortex_a15.cmake @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # Toolchain file for Arm Cortex-A15 using GNU tools. diff --git a/cmake/cortex_a17.cmake b/cmake/cortex_a17.cmake index 594ee96f7..c0f7e86be 100644 --- a/cmake/cortex_a17.cmake +++ b/cmake/cortex_a17.cmake @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # Toolchain file for Arm Cortex-A17 using GNU tools. diff --git a/cmake/cortex_a34.cmake b/cmake/cortex_a34.cmake index 36d855e38..14d244ea3 100644 --- a/cmake/cortex_a34.cmake +++ b/cmake/cortex_a34.cmake @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # Toolchain file for Arm Cortex-A34 using GNU tools. diff --git a/cmake/cortex_a35.cmake b/cmake/cortex_a35.cmake index ed3d187b5..60107e31e 100644 --- a/cmake/cortex_a35.cmake +++ b/cmake/cortex_a35.cmake @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # Toolchain file for Arm Cortex-A35 using GNU tools. diff --git a/cmake/cortex_a5.cmake b/cmake/cortex_a5.cmake index c87577846..501695db1 100644 --- a/cmake/cortex_a5.cmake +++ b/cmake/cortex_a5.cmake @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # Toolchain file for Arm Cortex-A5 using GNU tools. diff --git a/cmake/cortex_a53.cmake b/cmake/cortex_a53.cmake index d5011d27b..975808575 100644 --- a/cmake/cortex_a53.cmake +++ b/cmake/cortex_a53.cmake @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # Toolchain file for Arm Cortex-A53 using GNU tools. diff --git a/cmake/cortex_a55.cmake b/cmake/cortex_a55.cmake index 8c32ac039..fd13fd276 100644 --- a/cmake/cortex_a55.cmake +++ b/cmake/cortex_a55.cmake @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # Toolchain file for Arm Cortex-A55 using GNU tools. diff --git a/cmake/cortex_a57.cmake b/cmake/cortex_a57.cmake index 9a5b64221..ca2a1902e 100644 --- a/cmake/cortex_a57.cmake +++ b/cmake/cortex_a57.cmake @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # Toolchain file for Arm Cortex-A57 using GNU tools. diff --git a/cmake/cortex_a5x.cmake b/cmake/cortex_a5x.cmake index 0fe6730e7..b212cb877 100644 --- a/cmake/cortex_a5x.cmake +++ b/cmake/cortex_a5x.cmake @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # Toolchain file for the Arm Cortex-A5x SMP port using GNU tools. That port # targets the family rather than one core: its readme and example name A53, diff --git a/cmake/cortex_a65.cmake b/cmake/cortex_a65.cmake index 389605aa2..6011522cb 100644 --- a/cmake/cortex_a65.cmake +++ b/cmake/cortex_a65.cmake @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # Toolchain file for Arm Cortex-A65 using GNU tools. diff --git a/cmake/cortex_a65ae.cmake b/cmake/cortex_a65ae.cmake index 717ce0c47..d0bf1d50b 100644 --- a/cmake/cortex_a65ae.cmake +++ b/cmake/cortex_a65ae.cmake @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # Toolchain file for Arm Cortex-A65ae using GNU tools. diff --git a/cmake/cortex_a7.cmake b/cmake/cortex_a7.cmake index 5e3f4a9cb..2f0fb5c8d 100644 --- a/cmake/cortex_a7.cmake +++ b/cmake/cortex_a7.cmake @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # Toolchain file for Arm Cortex-A7 using GNU tools. diff --git a/cmake/cortex_a72.cmake b/cmake/cortex_a72.cmake index 24a65cf98..3e07e47d5 100644 --- a/cmake/cortex_a72.cmake +++ b/cmake/cortex_a72.cmake @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # Toolchain file for Arm Cortex-A72 using GNU tools. diff --git a/cmake/cortex_a73.cmake b/cmake/cortex_a73.cmake index b5bb0c7d7..eb95c4f12 100644 --- a/cmake/cortex_a73.cmake +++ b/cmake/cortex_a73.cmake @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # Toolchain file for Arm Cortex-A73 using GNU tools. diff --git a/cmake/cortex_a75.cmake b/cmake/cortex_a75.cmake index 8b4694df2..851a6f909 100644 --- a/cmake/cortex_a75.cmake +++ b/cmake/cortex_a75.cmake @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # Toolchain file for Arm Cortex-A75 using GNU tools. diff --git a/cmake/cortex_a76.cmake b/cmake/cortex_a76.cmake index 8a4718b6a..1d3766e9d 100644 --- a/cmake/cortex_a76.cmake +++ b/cmake/cortex_a76.cmake @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # Toolchain file for Arm Cortex-A76 using GNU tools. diff --git a/cmake/cortex_a76ae.cmake b/cmake/cortex_a76ae.cmake index 66c9cd403..99e4de80c 100644 --- a/cmake/cortex_a76ae.cmake +++ b/cmake/cortex_a76ae.cmake @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # Toolchain file for Arm Cortex-A76ae using GNU tools. diff --git a/cmake/cortex_a77.cmake b/cmake/cortex_a77.cmake index ba61d0e24..2df67ddd0 100644 --- a/cmake/cortex_a77.cmake +++ b/cmake/cortex_a77.cmake @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # Toolchain file for Arm Cortex-A77 using GNU tools. diff --git a/cmake/cortex_a78.cmake b/cmake/cortex_a78.cmake index b5523913e..fdd8324b5 100644 --- a/cmake/cortex_a78.cmake +++ b/cmake/cortex_a78.cmake @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # Toolchain file for Arm Cortex-A78 using GNU tools. diff --git a/cmake/cortex_a8.cmake b/cmake/cortex_a8.cmake index 8fd839e94..92db6228e 100644 --- a/cmake/cortex_a8.cmake +++ b/cmake/cortex_a8.cmake @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # Toolchain file for Arm Cortex-A8 using GNU tools. diff --git a/cmake/cortex_m23.cmake b/cmake/cortex_m23.cmake index 22ba78a45..a8ed71257 100644 --- a/cmake/cortex_m23.cmake +++ b/cmake/cortex_m23.cmake @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # Toolchain file for Arm Cortex-M23 using GNU tools. Armv8-M Baseline is # Thumb only, hence -mthumb with no Arm state alternative. diff --git a/cmake/cortex_m33.cmake b/cmake/cortex_m33.cmake index 6acab09d7..c7dff48ae 100644 --- a/cmake/cortex_m33.cmake +++ b/cmake/cortex_m33.cmake @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # Toolchain file for Arm Cortex-M33 using GNU tools. diff --git a/cmake/cortex_m52.cmake b/cmake/cortex_m52.cmake index 4ba987d6d..21a7d4877 100644 --- a/cmake/cortex_m52.cmake +++ b/cmake/cortex_m52.cmake @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # Toolchain file for Arm Cortex-M52 using GNU tools. # diff --git a/cmake/cortex_m55.cmake b/cmake/cortex_m55.cmake index 3a35c8bd1..abdf3264c 100644 --- a/cmake/cortex_m55.cmake +++ b/cmake/cortex_m55.cmake @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # Toolchain file for Arm Cortex-M55 using GNU tools. # diff --git a/cmake/cortex_m85.cmake b/cmake/cortex_m85.cmake index 82b44a736..e8eb7c290 100644 --- a/cmake/cortex_m85.cmake +++ b/cmake/cortex_m85.cmake @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # Toolchain file for Arm Cortex-M85 using GNU tools. # diff --git a/cmake/cortex_r4.cmake b/cmake/cortex_r4.cmake index 4b09e076b..88b5ce9e6 100644 --- a/cmake/cortex_r4.cmake +++ b/cmake/cortex_r4.cmake @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # Toolchain file for Arm Cortex-R4 using GNU tools. diff --git a/cmake/cortex_r5.cmake b/cmake/cortex_r5.cmake index 8c93a0016..6050a4c9a 100644 --- a/cmake/cortex_r5.cmake +++ b/cmake/cortex_r5.cmake @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # Toolchain file for Arm Cortex-R5 using GNU tools. diff --git a/cmake/cortex_r52.cmake b/cmake/cortex_r52.cmake index a9e7aee61..183782c9a 100644 --- a/cmake/cortex_r52.cmake +++ b/cmake/cortex_r52.cmake @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # Toolchain file for Arm Cortex-R52 (Armv8-R, AArch32) using GNU tools. diff --git a/cmake/cortex_r52_clang.cmake b/cmake/cortex_r52_clang.cmake index 2105ecbe2..f5669efa7 100644 --- a/cmake/cortex_r52_clang.cmake +++ b/cmake/cortex_r52_clang.cmake @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # Toolchain file for Arm Cortex-R52 (Armv8-R, AArch32) using Arm Toolchain for # Embedded, which is LLVM based and is the successor to Arm Compiler 6. diff --git a/common_modules/module_lib/src/txm_module_object_deallocate.c b/common_modules/module_lib/src/txm_module_object_deallocate.c index e0c0d6c48..fa5ebe85c 100644 --- a/common_modules/module_lib/src/txm_module_object_deallocate.c +++ b/common_modules/module_lib/src/txm_module_object_deallocate.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Claude Code (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/common_modules/module_manager/inc/txm_module_manager_dispatch.h b/common_modules/module_manager/inc/txm_module_manager_dispatch.h index 2df1491b0..9210c9893 100644 --- a/common_modules/module_manager/inc/txm_module_manager_dispatch.h +++ b/common_modules/module_manager/inc/txm_module_manager_dispatch.h @@ -11,18 +11,6 @@ **************************************************************************/ // Portions of this file were generated with AI assistance. -// Some portions generated by Claude Code (Opus 5). - -// Some portions generated by Claude Code (Opus 5). - -// Some portions generated by Claude Code (Opus 5). - -// Some portions generated by Claude Code (Opus 5). - -// Some portions generated by Claude Code (Opus 5). - -// Some portions generated by Claude Code (Opus 5). - /**************************************************************************/ /**************************************************************************/ diff --git a/common_modules/module_manager/inc/txm_module_manager_util.h b/common_modules/module_manager/inc/txm_module_manager_util.h index 7feb0f3e8..6b9e5b762 100644 --- a/common_modules/module_manager/inc/txm_module_manager_util.h +++ b/common_modules/module_manager/inc/txm_module_manager_util.h @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Claude Code (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/common_modules/module_manager/src/txm_module_manager_object_allocate.c b/common_modules/module_manager/src/txm_module_manager_object_allocate.c index 7729ad322..8e452b44f 100644 --- a/common_modules/module_manager/src/txm_module_manager_object_allocate.c +++ b/common_modules/module_manager/src/txm_module_manager_object_allocate.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Claude Code (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/common_modules/module_manager/src/txm_module_manager_object_deallocate.c b/common_modules/module_manager/src/txm_module_manager_object_deallocate.c index dd4c105db..c9a9ed4ff 100644 --- a/common_modules/module_manager/src/txm_module_manager_object_deallocate.c +++ b/common_modules/module_manager/src/txm_module_manager_object_deallocate.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Claude Code (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/common_modules/module_manager/src/txm_module_manager_thread_reset.c b/common_modules/module_manager/src/txm_module_manager_thread_reset.c index 1a33964e4..334070bf2 100644 --- a/common_modules/module_manager/src/txm_module_manager_thread_reset.c +++ b/common_modules/module_manager/src/txm_module_manager_thread_reset.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Claude Code (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/common_modules/module_manager/src/txm_module_manager_util.c b/common_modules/module_manager/src/txm_module_manager_util.c index 756120fa4..93516ab22 100644 --- a/common_modules/module_manager/src/txm_module_manager_util.c +++ b/common_modules/module_manager/src/txm_module_manager_util.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Claude Code (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/arm11/gnu/CMakeLists.txt b/ports/arm11/gnu/CMakeLists.txt index 83d7e0fa8..b8166b4d1 100644 --- a/ports/arm11/gnu/CMakeLists.txt +++ b/ports/arm11/gnu/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # ThreadX port sources for arm11, GNU tools. diff --git a/ports/arm11/gnu/example_build/build_threadx.sh b/ports/arm11/gnu/example_build/build_threadx.sh index 693b44ce8..f7253cf16 100755 --- a/ports/arm11/gnu/example_build/build_threadx.sh +++ b/ports/arm11/gnu/example_build/build_threadx.sh @@ -10,7 +10,7 @@ # SPDX-License-Identifier: MIT # # AI Disclosure: This file was largely AI-generated by Copilot (Claude Sonnet 4.6). -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # The AI-generated portions may be considered public domain (CC0-1.0) # and not subject to the project's licence. The human contributor has # reviewed and verified that the code is correct. diff --git a/ports/arm11/gnu/example_build/build_threadx_sample.sh b/ports/arm11/gnu/example_build/build_threadx_sample.sh index 93287d531..97a3a1c56 100755 --- a/ports/arm11/gnu/example_build/build_threadx_sample.sh +++ b/ports/arm11/gnu/example_build/build_threadx_sample.sh @@ -10,7 +10,7 @@ # SPDX-License-Identifier: MIT # # AI Disclosure: This file was largely AI-generated by Copilot (Claude Sonnet 4.6). -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # The AI-generated portions may be considered public domain (CC0-1.0) # and not subject to the project's licence. The human contributor has # reviewed and verified that the code is correct. diff --git a/ports/arm9/gnu/CMakeLists.txt b/ports/arm9/gnu/CMakeLists.txt index 6d071937c..f98d2556d 100644 --- a/ports/arm9/gnu/CMakeLists.txt +++ b/ports/arm9/gnu/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # ThreadX port sources for arm9, GNU tools. diff --git a/ports/arm9/gnu/example_build/build_threadx.sh b/ports/arm9/gnu/example_build/build_threadx.sh index ad8a3357d..d8de5055a 100755 --- a/ports/arm9/gnu/example_build/build_threadx.sh +++ b/ports/arm9/gnu/example_build/build_threadx.sh @@ -10,7 +10,7 @@ # SPDX-License-Identifier: MIT # # AI Disclosure: This file was largely AI-generated by Copilot (Claude Sonnet 4.6). -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # The AI-generated portions may be considered public domain (CC0-1.0) # and not subject to the project's licence. The human contributor has # reviewed and verified that the code is correct. diff --git a/ports/arm9/gnu/example_build/build_threadx_sample.sh b/ports/arm9/gnu/example_build/build_threadx_sample.sh index 78b3ac7fa..d9339bc07 100755 --- a/ports/arm9/gnu/example_build/build_threadx_sample.sh +++ b/ports/arm9/gnu/example_build/build_threadx_sample.sh @@ -10,7 +10,7 @@ # SPDX-License-Identifier: MIT # # AI Disclosure: This file was largely AI-generated by Copilot (Claude Sonnet 4.6). -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # The AI-generated portions may be considered public domain (CC0-1.0) # and not subject to the project's licence. The human contributor has # reviewed and verified that the code is correct. diff --git a/ports/cortex_a12/gnu/CMakeLists.txt b/ports/cortex_a12/gnu/CMakeLists.txt index d03910d1d..fc2158767 100644 --- a/ports/cortex_a12/gnu/CMakeLists.txt +++ b/ports/cortex_a12/gnu/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # ThreadX port sources for the ARMv7-A cores, GNU tools. # Copied into every ARMv7-A gnu port by update.sh, so edit it here. diff --git a/ports/cortex_a12/gnu/example_build/build_threadx.sh b/ports/cortex_a12/gnu/example_build/build_threadx.sh index ec3cd8279..af9b02a83 100755 --- a/ports/cortex_a12/gnu/example_build/build_threadx.sh +++ b/ports/cortex_a12/gnu/example_build/build_threadx.sh @@ -10,7 +10,7 @@ # SPDX-License-Identifier: MIT # # AI Disclosure: This file was largely AI-generated by Copilot (Claude Sonnet 4.6). -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # The AI-generated portions may be considered public domain (CC0-1.0) # and not subject to the project's licence. The human contributor has # reviewed and verified that the code is correct. diff --git a/ports/cortex_a12/gnu/example_build/build_threadx_sample.sh b/ports/cortex_a12/gnu/example_build/build_threadx_sample.sh index 0d2fdf5b4..43b0882e6 100755 --- a/ports/cortex_a12/gnu/example_build/build_threadx_sample.sh +++ b/ports/cortex_a12/gnu/example_build/build_threadx_sample.sh @@ -10,7 +10,7 @@ # SPDX-License-Identifier: MIT # # AI Disclosure: This file was largely AI-generated by Copilot (Claude Sonnet 4.6). -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # The AI-generated portions may be considered public domain (CC0-1.0) # and not subject to the project's licence. The human contributor has # reviewed and verified that the code is correct. diff --git a/ports/cortex_a15/gnu/CMakeLists.txt b/ports/cortex_a15/gnu/CMakeLists.txt index d03910d1d..fc2158767 100644 --- a/ports/cortex_a15/gnu/CMakeLists.txt +++ b/ports/cortex_a15/gnu/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # ThreadX port sources for the ARMv7-A cores, GNU tools. # Copied into every ARMv7-A gnu port by update.sh, so edit it here. diff --git a/ports/cortex_a15/gnu/example_build/build_threadx.sh b/ports/cortex_a15/gnu/example_build/build_threadx.sh index 74e7fe8af..4cfb4531d 100755 --- a/ports/cortex_a15/gnu/example_build/build_threadx.sh +++ b/ports/cortex_a15/gnu/example_build/build_threadx.sh @@ -10,7 +10,7 @@ # SPDX-License-Identifier: MIT # # AI Disclosure: This file was largely AI-generated by Copilot (Claude Sonnet 4.6). -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # The AI-generated portions may be considered public domain (CC0-1.0) # and not subject to the project's licence. The human contributor has # reviewed and verified that the code is correct. diff --git a/ports/cortex_a15/gnu/example_build/build_threadx_sample.sh b/ports/cortex_a15/gnu/example_build/build_threadx_sample.sh index dcda93622..e34e74108 100755 --- a/ports/cortex_a15/gnu/example_build/build_threadx_sample.sh +++ b/ports/cortex_a15/gnu/example_build/build_threadx_sample.sh @@ -10,7 +10,7 @@ # SPDX-License-Identifier: MIT # # AI Disclosure: This file was largely AI-generated by Copilot (Claude Sonnet 4.6). -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # The AI-generated portions may be considered public domain (CC0-1.0) # and not subject to the project's licence. The human contributor has # reviewed and verified that the code is correct. diff --git a/ports/cortex_a17/gnu/CMakeLists.txt b/ports/cortex_a17/gnu/CMakeLists.txt index d03910d1d..fc2158767 100644 --- a/ports/cortex_a17/gnu/CMakeLists.txt +++ b/ports/cortex_a17/gnu/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # ThreadX port sources for the ARMv7-A cores, GNU tools. # Copied into every ARMv7-A gnu port by update.sh, so edit it here. diff --git a/ports/cortex_a17/gnu/example_build/build_threadx.sh b/ports/cortex_a17/gnu/example_build/build_threadx.sh index 6616b2d27..31f1ee346 100755 --- a/ports/cortex_a17/gnu/example_build/build_threadx.sh +++ b/ports/cortex_a17/gnu/example_build/build_threadx.sh @@ -10,7 +10,7 @@ # SPDX-License-Identifier: MIT # # AI Disclosure: This file was largely AI-generated by Copilot (Claude Sonnet 4.6). -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # The AI-generated portions may be considered public domain (CC0-1.0) # and not subject to the project's licence. The human contributor has # reviewed and verified that the code is correct. diff --git a/ports/cortex_a17/gnu/example_build/build_threadx_sample.sh b/ports/cortex_a17/gnu/example_build/build_threadx_sample.sh index e200d473b..ef776a9bf 100755 --- a/ports/cortex_a17/gnu/example_build/build_threadx_sample.sh +++ b/ports/cortex_a17/gnu/example_build/build_threadx_sample.sh @@ -10,7 +10,7 @@ # SPDX-License-Identifier: MIT # # AI Disclosure: This file was largely AI-generated by Copilot (Claude Sonnet 4.6). -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # The AI-generated portions may be considered public domain (CC0-1.0) # and not subject to the project's licence. The human contributor has # reviewed and verified that the code is correct. diff --git a/ports/cortex_a34/gnu/CMakeLists.txt b/ports/cortex_a34/gnu/CMakeLists.txt index 12a58cbeb..972c10f18 100644 --- a/ports/cortex_a34/gnu/CMakeLists.txt +++ b/ports/cortex_a34/gnu/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # ThreadX port sources for the AArch64 cores, GNU tools. # Copied into every AArch64 gnu port by update.sh, so edit it here. diff --git a/ports/cortex_a35/gnu/CMakeLists.txt b/ports/cortex_a35/gnu/CMakeLists.txt index 12a58cbeb..972c10f18 100644 --- a/ports/cortex_a35/gnu/CMakeLists.txt +++ b/ports/cortex_a35/gnu/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # ThreadX port sources for the AArch64 cores, GNU tools. # Copied into every AArch64 gnu port by update.sh, so edit it here. diff --git a/ports/cortex_a5/gnu/CMakeLists.txt b/ports/cortex_a5/gnu/CMakeLists.txt index d03910d1d..fc2158767 100644 --- a/ports/cortex_a5/gnu/CMakeLists.txt +++ b/ports/cortex_a5/gnu/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # ThreadX port sources for the ARMv7-A cores, GNU tools. # Copied into every ARMv7-A gnu port by update.sh, so edit it here. diff --git a/ports/cortex_a5/gnu/example_build/build_threadx.sh b/ports/cortex_a5/gnu/example_build/build_threadx.sh index c19003962..212fccc90 100755 --- a/ports/cortex_a5/gnu/example_build/build_threadx.sh +++ b/ports/cortex_a5/gnu/example_build/build_threadx.sh @@ -10,7 +10,7 @@ # SPDX-License-Identifier: MIT # # AI Disclosure: This file was largely AI-generated by Copilot (Claude Sonnet 4.6). -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # The AI-generated portions may be considered public domain (CC0-1.0) # and not subject to the project's licence. The human contributor has # reviewed and verified that the code is correct. diff --git a/ports/cortex_a5/gnu/example_build/build_threadx_sample.sh b/ports/cortex_a5/gnu/example_build/build_threadx_sample.sh index 4422f95f9..c65b831a5 100755 --- a/ports/cortex_a5/gnu/example_build/build_threadx_sample.sh +++ b/ports/cortex_a5/gnu/example_build/build_threadx_sample.sh @@ -10,7 +10,7 @@ # SPDX-License-Identifier: MIT # # AI Disclosure: This file was largely AI-generated by Copilot (Claude Sonnet 4.6). -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # The AI-generated portions may be considered public domain (CC0-1.0) # and not subject to the project's licence. The human contributor has # reviewed and verified that the code is correct. diff --git a/ports/cortex_a53/gnu/CMakeLists.txt b/ports/cortex_a53/gnu/CMakeLists.txt index 12a58cbeb..972c10f18 100644 --- a/ports/cortex_a53/gnu/CMakeLists.txt +++ b/ports/cortex_a53/gnu/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # ThreadX port sources for the AArch64 cores, GNU tools. # Copied into every AArch64 gnu port by update.sh, so edit it here. diff --git a/ports/cortex_a55/gnu/CMakeLists.txt b/ports/cortex_a55/gnu/CMakeLists.txt index 12a58cbeb..972c10f18 100644 --- a/ports/cortex_a55/gnu/CMakeLists.txt +++ b/ports/cortex_a55/gnu/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # ThreadX port sources for the AArch64 cores, GNU tools. # Copied into every AArch64 gnu port by update.sh, so edit it here. diff --git a/ports/cortex_a57/gnu/CMakeLists.txt b/ports/cortex_a57/gnu/CMakeLists.txt index 12a58cbeb..972c10f18 100644 --- a/ports/cortex_a57/gnu/CMakeLists.txt +++ b/ports/cortex_a57/gnu/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # ThreadX port sources for the AArch64 cores, GNU tools. # Copied into every AArch64 gnu port by update.sh, so edit it here. diff --git a/ports/cortex_a65/gnu/CMakeLists.txt b/ports/cortex_a65/gnu/CMakeLists.txt index 12a58cbeb..972c10f18 100644 --- a/ports/cortex_a65/gnu/CMakeLists.txt +++ b/ports/cortex_a65/gnu/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # ThreadX port sources for the AArch64 cores, GNU tools. # Copied into every AArch64 gnu port by update.sh, so edit it here. diff --git a/ports/cortex_a65ae/gnu/CMakeLists.txt b/ports/cortex_a65ae/gnu/CMakeLists.txt index 12a58cbeb..972c10f18 100644 --- a/ports/cortex_a65ae/gnu/CMakeLists.txt +++ b/ports/cortex_a65ae/gnu/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # ThreadX port sources for the AArch64 cores, GNU tools. # Copied into every AArch64 gnu port by update.sh, so edit it here. diff --git a/ports/cortex_a7/gnu/CMakeLists.txt b/ports/cortex_a7/gnu/CMakeLists.txt index d03910d1d..fc2158767 100644 --- a/ports/cortex_a7/gnu/CMakeLists.txt +++ b/ports/cortex_a7/gnu/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # ThreadX port sources for the ARMv7-A cores, GNU tools. # Copied into every ARMv7-A gnu port by update.sh, so edit it here. diff --git a/ports/cortex_a7/gnu/example_build/build_threadx.sh b/ports/cortex_a7/gnu/example_build/build_threadx.sh index 223f72cfe..e7e0408aa 100755 --- a/ports/cortex_a7/gnu/example_build/build_threadx.sh +++ b/ports/cortex_a7/gnu/example_build/build_threadx.sh @@ -10,7 +10,7 @@ # SPDX-License-Identifier: MIT # # AI Disclosure: This file was largely AI-generated by Copilot (Claude Sonnet 4.6). -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # The AI-generated portions may be considered public domain (CC0-1.0) # and not subject to the project's licence. The human contributor has # reviewed and verified that the code is correct. diff --git a/ports/cortex_a7/gnu/example_build/build_threadx_sample.sh b/ports/cortex_a7/gnu/example_build/build_threadx_sample.sh index a59e9139d..8526340c8 100755 --- a/ports/cortex_a7/gnu/example_build/build_threadx_sample.sh +++ b/ports/cortex_a7/gnu/example_build/build_threadx_sample.sh @@ -10,7 +10,7 @@ # SPDX-License-Identifier: MIT # # AI Disclosure: This file was largely AI-generated by Copilot (Claude Sonnet 4.6). -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # The AI-generated portions may be considered public domain (CC0-1.0) # and not subject to the project's licence. The human contributor has # reviewed and verified that the code is correct. diff --git a/ports/cortex_a72/gnu/CMakeLists.txt b/ports/cortex_a72/gnu/CMakeLists.txt index 12a58cbeb..972c10f18 100644 --- a/ports/cortex_a72/gnu/CMakeLists.txt +++ b/ports/cortex_a72/gnu/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # ThreadX port sources for the AArch64 cores, GNU tools. # Copied into every AArch64 gnu port by update.sh, so edit it here. diff --git a/ports/cortex_a73/gnu/CMakeLists.txt b/ports/cortex_a73/gnu/CMakeLists.txt index 12a58cbeb..972c10f18 100644 --- a/ports/cortex_a73/gnu/CMakeLists.txt +++ b/ports/cortex_a73/gnu/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # ThreadX port sources for the AArch64 cores, GNU tools. # Copied into every AArch64 gnu port by update.sh, so edit it here. diff --git a/ports/cortex_a75/gnu/CMakeLists.txt b/ports/cortex_a75/gnu/CMakeLists.txt index 12a58cbeb..972c10f18 100644 --- a/ports/cortex_a75/gnu/CMakeLists.txt +++ b/ports/cortex_a75/gnu/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # ThreadX port sources for the AArch64 cores, GNU tools. # Copied into every AArch64 gnu port by update.sh, so edit it here. diff --git a/ports/cortex_a76/gnu/CMakeLists.txt b/ports/cortex_a76/gnu/CMakeLists.txt index 12a58cbeb..972c10f18 100644 --- a/ports/cortex_a76/gnu/CMakeLists.txt +++ b/ports/cortex_a76/gnu/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # ThreadX port sources for the AArch64 cores, GNU tools. # Copied into every AArch64 gnu port by update.sh, so edit it here. diff --git a/ports/cortex_a76ae/gnu/CMakeLists.txt b/ports/cortex_a76ae/gnu/CMakeLists.txt index 12a58cbeb..972c10f18 100644 --- a/ports/cortex_a76ae/gnu/CMakeLists.txt +++ b/ports/cortex_a76ae/gnu/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # ThreadX port sources for the AArch64 cores, GNU tools. # Copied into every AArch64 gnu port by update.sh, so edit it here. diff --git a/ports/cortex_a77/gnu/CMakeLists.txt b/ports/cortex_a77/gnu/CMakeLists.txt index 12a58cbeb..972c10f18 100644 --- a/ports/cortex_a77/gnu/CMakeLists.txt +++ b/ports/cortex_a77/gnu/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # ThreadX port sources for the AArch64 cores, GNU tools. # Copied into every AArch64 gnu port by update.sh, so edit it here. diff --git a/ports/cortex_a8/gnu/CMakeLists.txt b/ports/cortex_a8/gnu/CMakeLists.txt index d03910d1d..fc2158767 100644 --- a/ports/cortex_a8/gnu/CMakeLists.txt +++ b/ports/cortex_a8/gnu/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # ThreadX port sources for the ARMv7-A cores, GNU tools. # Copied into every ARMv7-A gnu port by update.sh, so edit it here. diff --git a/ports/cortex_a8/gnu/example_build/build_threadx.sh b/ports/cortex_a8/gnu/example_build/build_threadx.sh index ab7ba54f0..2678ab15f 100755 --- a/ports/cortex_a8/gnu/example_build/build_threadx.sh +++ b/ports/cortex_a8/gnu/example_build/build_threadx.sh @@ -10,7 +10,7 @@ # SPDX-License-Identifier: MIT # # AI Disclosure: This file was largely AI-generated by Copilot (Claude Sonnet 4.6). -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # The AI-generated portions may be considered public domain (CC0-1.0) # and not subject to the project's licence. The human contributor has # reviewed and verified that the code is correct. diff --git a/ports/cortex_a8/gnu/example_build/build_threadx_sample.sh b/ports/cortex_a8/gnu/example_build/build_threadx_sample.sh index 88e7ed553..78deda53f 100755 --- a/ports/cortex_a8/gnu/example_build/build_threadx_sample.sh +++ b/ports/cortex_a8/gnu/example_build/build_threadx_sample.sh @@ -10,7 +10,7 @@ # SPDX-License-Identifier: MIT # # AI Disclosure: This file was largely AI-generated by Copilot (Claude Sonnet 4.6). -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # The AI-generated portions may be considered public domain (CC0-1.0) # and not subject to the project's licence. The human contributor has # reviewed and verified that the code is correct. diff --git a/ports/cortex_a9/gnu/CMakeLists.txt b/ports/cortex_a9/gnu/CMakeLists.txt index d03910d1d..fc2158767 100644 --- a/ports/cortex_a9/gnu/CMakeLists.txt +++ b/ports/cortex_a9/gnu/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # ThreadX port sources for the ARMv7-A cores, GNU tools. # Copied into every ARMv7-A gnu port by update.sh, so edit it here. diff --git a/ports/cortex_a9/gnu/example_build/build_threadx.sh b/ports/cortex_a9/gnu/example_build/build_threadx.sh index ede743654..920b8b7fb 100755 --- a/ports/cortex_a9/gnu/example_build/build_threadx.sh +++ b/ports/cortex_a9/gnu/example_build/build_threadx.sh @@ -10,7 +10,7 @@ # SPDX-License-Identifier: MIT # # AI Disclosure: This file was largely AI-generated by Copilot (Claude Sonnet 4.6). -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # The AI-generated portions may be considered public domain (CC0-1.0) # and not subject to the project's licence. The human contributor has # reviewed and verified that the code is correct. diff --git a/ports/cortex_a9/gnu/example_build/build_threadx_sample.sh b/ports/cortex_a9/gnu/example_build/build_threadx_sample.sh index ea3178cb3..d7fdce06e 100755 --- a/ports/cortex_a9/gnu/example_build/build_threadx_sample.sh +++ b/ports/cortex_a9/gnu/example_build/build_threadx_sample.sh @@ -10,7 +10,7 @@ # SPDX-License-Identifier: MIT # # AI Disclosure: This file was largely AI-generated by Copilot (Claude Sonnet 4.6). -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # The AI-generated portions may be considered public domain (CC0-1.0) # and not subject to the project's licence. The human contributor has # reviewed and verified that the code is correct. diff --git a/ports/cortex_m0/gnu/example_build/build_threadx.sh b/ports/cortex_m0/gnu/example_build/build_threadx.sh index 88e2bd473..3ef038454 100755 --- a/ports/cortex_m0/gnu/example_build/build_threadx.sh +++ b/ports/cortex_m0/gnu/example_build/build_threadx.sh @@ -10,7 +10,7 @@ # SPDX-License-Identifier: MIT # # AI Disclosure: This file was largely AI-generated by Copilot (Claude Sonnet 4.6). -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # The AI-generated portions may be considered public domain (CC0-1.0) # and not subject to the project's licence. The human contributor has # reviewed and verified that the code is correct. diff --git a/ports/cortex_m0/gnu/example_build/build_threadx_sample.sh b/ports/cortex_m0/gnu/example_build/build_threadx_sample.sh index b9de126fe..772813df7 100755 --- a/ports/cortex_m0/gnu/example_build/build_threadx_sample.sh +++ b/ports/cortex_m0/gnu/example_build/build_threadx_sample.sh @@ -10,7 +10,7 @@ # SPDX-License-Identifier: MIT # # AI Disclosure: This file was largely AI-generated by Copilot (Claude Sonnet 4.6). -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # The AI-generated portions may be considered public domain (CC0-1.0) # and not subject to the project's licence. The human contributor has # reviewed and verified that the code is correct. diff --git a/ports/cortex_m23/gnu/CMakeLists.txt b/ports/cortex_m23/gnu/CMakeLists.txt index e7c71e07d..a16300c1a 100644 --- a/ports/cortex_m23/gnu/CMakeLists.txt +++ b/ports/cortex_m23/gnu/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # ThreadX port sources for cortex_m23, GNU tools. diff --git a/ports/cortex_m23/gnu/example_build/build_threadx.sh b/ports/cortex_m23/gnu/example_build/build_threadx.sh index b5c97e53e..16a424387 100755 --- a/ports/cortex_m23/gnu/example_build/build_threadx.sh +++ b/ports/cortex_m23/gnu/example_build/build_threadx.sh @@ -10,7 +10,7 @@ # SPDX-License-Identifier: MIT # # AI Disclosure: This file was largely AI-generated by Copilot (Claude Sonnet 4.6). -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # The AI-generated portions may be considered public domain (CC0-1.0) # and not subject to the project's licence. The human contributor has # reviewed and verified that the code is correct. diff --git a/ports/cortex_m23/gnu/example_build/build_threadx_sample.sh b/ports/cortex_m23/gnu/example_build/build_threadx_sample.sh index b359e160e..7aa425616 100755 --- a/ports/cortex_m23/gnu/example_build/build_threadx_sample.sh +++ b/ports/cortex_m23/gnu/example_build/build_threadx_sample.sh @@ -10,7 +10,7 @@ # SPDX-License-Identifier: MIT # # AI Disclosure: This file was largely AI-generated by Copilot (Claude Sonnet 4.6). -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # The AI-generated portions may be considered public domain (CC0-1.0) # and not subject to the project's licence. The human contributor has # reviewed and verified that the code is correct. diff --git a/ports/cortex_m3/ghs/example_build/tx_initialize_low_level.arm b/ports/cortex_m3/ghs/example_build/tx_initialize_low_level.arm index 47beffbc2..b9f622fe4 100644 --- a/ports/cortex_m3/ghs/example_build/tx_initialize_low_level.arm +++ b/ports/cortex_m3/ghs/example_build/tx_initialize_low_level.arm @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -; Some portions generated by Copilot (Opus 5). +; Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m3/gnu/example_build/build_threadx.sh b/ports/cortex_m3/gnu/example_build/build_threadx.sh index 9c924d41f..b938bb2f0 100755 --- a/ports/cortex_m3/gnu/example_build/build_threadx.sh +++ b/ports/cortex_m3/gnu/example_build/build_threadx.sh @@ -10,7 +10,7 @@ # SPDX-License-Identifier: MIT # # AI Disclosure: This file was largely AI-generated by Copilot (Claude Sonnet 4.6). -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # The AI-generated portions may be considered public domain (CC0-1.0) # and not subject to the project's licence. The human contributor has # reviewed and verified that the code is correct. diff --git a/ports/cortex_m3/gnu/example_build/build_threadx_sample.sh b/ports/cortex_m3/gnu/example_build/build_threadx_sample.sh index 1b6b7f7ca..472e8ebd3 100755 --- a/ports/cortex_m3/gnu/example_build/build_threadx_sample.sh +++ b/ports/cortex_m3/gnu/example_build/build_threadx_sample.sh @@ -10,7 +10,7 @@ # SPDX-License-Identifier: MIT # # AI Disclosure: This file was largely AI-generated by Copilot (Claude Sonnet 4.6). -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # The AI-generated portions may be considered public domain (CC0-1.0) # and not subject to the project's licence. The human contributor has # reviewed and verified that the code is correct. diff --git a/ports/cortex_m33/gnu/example_build/build_threadx.sh b/ports/cortex_m33/gnu/example_build/build_threadx.sh index b97e7b2a4..00fd41407 100755 --- a/ports/cortex_m33/gnu/example_build/build_threadx.sh +++ b/ports/cortex_m33/gnu/example_build/build_threadx.sh @@ -10,7 +10,7 @@ # SPDX-License-Identifier: MIT # # AI Disclosure: This file was largely AI-generated by Copilot (Claude Sonnet 4.6). -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # The AI-generated portions may be considered public domain (CC0-1.0) # and not subject to the project's licence. The human contributor has # reviewed and verified that the code is correct. diff --git a/ports/cortex_m33/gnu/example_build/build_threadx_sample.sh b/ports/cortex_m33/gnu/example_build/build_threadx_sample.sh index 6cf086ed9..5bd1c8dff 100755 --- a/ports/cortex_m33/gnu/example_build/build_threadx_sample.sh +++ b/ports/cortex_m33/gnu/example_build/build_threadx_sample.sh @@ -10,7 +10,7 @@ # SPDX-License-Identifier: MIT # # AI Disclosure: This file was largely AI-generated by Copilot (Claude Sonnet 4.6). -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # The AI-generated portions may be considered public domain (CC0-1.0) # and not subject to the project's licence. The human contributor has # reviewed and verified that the code is correct. diff --git a/ports/cortex_m4/ghs/example_build/tx_initialize_low_level.arm b/ports/cortex_m4/ghs/example_build/tx_initialize_low_level.arm index 1de645edd..ee3bc56ff 100644 --- a/ports/cortex_m4/ghs/example_build/tx_initialize_low_level.arm +++ b/ports/cortex_m4/ghs/example_build/tx_initialize_low_level.arm @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -; Some portions generated by Copilot (Opus 5). +; Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m4/gnu/example_build/build_threadx.sh b/ports/cortex_m4/gnu/example_build/build_threadx.sh index 69a951789..d6971e300 100755 --- a/ports/cortex_m4/gnu/example_build/build_threadx.sh +++ b/ports/cortex_m4/gnu/example_build/build_threadx.sh @@ -10,7 +10,7 @@ # SPDX-License-Identifier: MIT # # AI Disclosure: This file was largely AI-generated by Copilot (Claude Sonnet 4.6). -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # The AI-generated portions may be considered public domain (CC0-1.0) # and not subject to the project's licence. The human contributor has # reviewed and verified that the code is correct. diff --git a/ports/cortex_m4/gnu/example_build/build_threadx_sample.sh b/ports/cortex_m4/gnu/example_build/build_threadx_sample.sh index 39fef2036..34c60bf17 100755 --- a/ports/cortex_m4/gnu/example_build/build_threadx_sample.sh +++ b/ports/cortex_m4/gnu/example_build/build_threadx_sample.sh @@ -10,7 +10,7 @@ # SPDX-License-Identifier: MIT # # AI Disclosure: This file was largely AI-generated by Copilot (Claude Sonnet 4.6). -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # The AI-generated portions may be considered public domain (CC0-1.0) # and not subject to the project's licence. The human contributor has # reviewed and verified that the code is correct. diff --git a/ports/cortex_m55/gnu/example_build/build_threadx.sh b/ports/cortex_m55/gnu/example_build/build_threadx.sh index 67220aae3..dc0d75bc3 100755 --- a/ports/cortex_m55/gnu/example_build/build_threadx.sh +++ b/ports/cortex_m55/gnu/example_build/build_threadx.sh @@ -10,7 +10,7 @@ # SPDX-License-Identifier: MIT # # AI Disclosure: This file was largely AI-generated by Copilot (Claude Sonnet 4.6). -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # The AI-generated portions may be considered public domain (CC0-1.0) # and not subject to the project's licence. The human contributor has # reviewed and verified that the code is correct. diff --git a/ports/cortex_m55/gnu/example_build/build_threadx_sample.sh b/ports/cortex_m55/gnu/example_build/build_threadx_sample.sh index b297995ab..0131c4085 100755 --- a/ports/cortex_m55/gnu/example_build/build_threadx_sample.sh +++ b/ports/cortex_m55/gnu/example_build/build_threadx_sample.sh @@ -10,7 +10,7 @@ # SPDX-License-Identifier: MIT # # AI Disclosure: This file was largely AI-generated by Copilot (Claude Sonnet 4.6). -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # The AI-generated portions may be considered public domain (CC0-1.0) # and not subject to the project's licence. The human contributor has # reviewed and verified that the code is correct. diff --git a/ports/cortex_m7/ghs/example_build/tx_initialize_low_level.arm b/ports/cortex_m7/ghs/example_build/tx_initialize_low_level.arm index b98fa9745..7c2b80ab3 100644 --- a/ports/cortex_m7/ghs/example_build/tx_initialize_low_level.arm +++ b/ports/cortex_m7/ghs/example_build/tx_initialize_low_level.arm @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -; Some portions generated by Copilot (Opus 5). +; Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports/cortex_m7/gnu/example_build/build_threadx.sh b/ports/cortex_m7/gnu/example_build/build_threadx.sh index d7875b4a4..1aea1938a 100755 --- a/ports/cortex_m7/gnu/example_build/build_threadx.sh +++ b/ports/cortex_m7/gnu/example_build/build_threadx.sh @@ -10,7 +10,7 @@ # SPDX-License-Identifier: MIT # # AI Disclosure: This file was largely AI-generated by Copilot (Claude Sonnet 4.6). -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # The AI-generated portions may be considered public domain (CC0-1.0) # and not subject to the project's licence. The human contributor has # reviewed and verified that the code is correct. diff --git a/ports/cortex_m7/gnu/example_build/build_threadx_sample.sh b/ports/cortex_m7/gnu/example_build/build_threadx_sample.sh index 3b6a6c012..9a59e93c6 100755 --- a/ports/cortex_m7/gnu/example_build/build_threadx_sample.sh +++ b/ports/cortex_m7/gnu/example_build/build_threadx_sample.sh @@ -10,7 +10,7 @@ # SPDX-License-Identifier: MIT # # AI Disclosure: This file was largely AI-generated by Copilot (Claude Sonnet 4.6). -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # The AI-generated portions may be considered public domain (CC0-1.0) # and not subject to the project's licence. The human contributor has # reviewed and verified that the code is correct. diff --git a/ports/cortex_m85/gnu/example_build/build_threadx.sh b/ports/cortex_m85/gnu/example_build/build_threadx.sh index b579685ef..cc87ce572 100755 --- a/ports/cortex_m85/gnu/example_build/build_threadx.sh +++ b/ports/cortex_m85/gnu/example_build/build_threadx.sh @@ -10,7 +10,7 @@ # SPDX-License-Identifier: MIT # # AI Disclosure: This file was largely AI-generated by Copilot (Claude Sonnet 4.6). -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # The AI-generated portions may be considered public domain (CC0-1.0) # and not subject to the project's licence. The human contributor has # reviewed and verified that the code is correct. diff --git a/ports/cortex_m85/gnu/example_build/build_threadx_sample.sh b/ports/cortex_m85/gnu/example_build/build_threadx_sample.sh index 0bddbbf61..795d94009 100755 --- a/ports/cortex_m85/gnu/example_build/build_threadx_sample.sh +++ b/ports/cortex_m85/gnu/example_build/build_threadx_sample.sh @@ -10,7 +10,7 @@ # SPDX-License-Identifier: MIT # # AI Disclosure: This file was largely AI-generated by Copilot (Claude Sonnet 4.6). -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # The AI-generated portions may be considered public domain (CC0-1.0) # and not subject to the project's licence. The human contributor has # reviewed and verified that the code is correct. diff --git a/ports/cortex_r4/gnu/CMakeLists.txt b/ports/cortex_r4/gnu/CMakeLists.txt index b40b5b998..328020d09 100644 --- a/ports/cortex_r4/gnu/CMakeLists.txt +++ b/ports/cortex_r4/gnu/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # ThreadX port sources for cortex_r4, GNU tools. diff --git a/ports/cortex_r4/gnu/example_build/build_threadx.sh b/ports/cortex_r4/gnu/example_build/build_threadx.sh index bd03369fe..9d55743b8 100755 --- a/ports/cortex_r4/gnu/example_build/build_threadx.sh +++ b/ports/cortex_r4/gnu/example_build/build_threadx.sh @@ -10,7 +10,7 @@ # SPDX-License-Identifier: MIT # # AI Disclosure: This file was largely AI-generated by Copilot (Claude Sonnet 4.6). -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # The AI-generated portions may be considered public domain (CC0-1.0) # and not subject to the project's licence. The human contributor has # reviewed and verified that the code is correct. diff --git a/ports/cortex_r4/gnu/example_build/build_threadx_sample.sh b/ports/cortex_r4/gnu/example_build/build_threadx_sample.sh index 1f0e2709e..7871bae4c 100755 --- a/ports/cortex_r4/gnu/example_build/build_threadx_sample.sh +++ b/ports/cortex_r4/gnu/example_build/build_threadx_sample.sh @@ -10,7 +10,7 @@ # SPDX-License-Identifier: MIT # # AI Disclosure: This file was largely AI-generated by Copilot (Claude Sonnet 4.6). -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # The AI-generated portions may be considered public domain (CC0-1.0) # and not subject to the project's licence. The human contributor has # reviewed and verified that the code is correct. diff --git a/ports/cortex_r5/gnu/CMakeLists.txt b/ports/cortex_r5/gnu/CMakeLists.txt index 46d1dadb7..3e5421edb 100644 --- a/ports/cortex_r5/gnu/CMakeLists.txt +++ b/ports/cortex_r5/gnu/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # ThreadX port sources for cortex_r5, GNU tools. diff --git a/ports/cortex_r5/gnu/example_build/build_threadx.sh b/ports/cortex_r5/gnu/example_build/build_threadx.sh index a71eb5cb8..0108d1c8d 100755 --- a/ports/cortex_r5/gnu/example_build/build_threadx.sh +++ b/ports/cortex_r5/gnu/example_build/build_threadx.sh @@ -10,7 +10,7 @@ # SPDX-License-Identifier: MIT # # AI Disclosure: This file was largely AI-generated by Copilot (Claude Sonnet 4.6). -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # The AI-generated portions may be considered public domain (CC0-1.0) # and not subject to the project's licence. The human contributor has # reviewed and verified that the code is correct. diff --git a/ports/cortex_r5/gnu/example_build/build_threadx_sample.sh b/ports/cortex_r5/gnu/example_build/build_threadx_sample.sh index 2b3e4d551..53eb59025 100755 --- a/ports/cortex_r5/gnu/example_build/build_threadx_sample.sh +++ b/ports/cortex_r5/gnu/example_build/build_threadx_sample.sh @@ -10,7 +10,7 @@ # SPDX-License-Identifier: MIT # # AI Disclosure: This file was largely AI-generated by Copilot (Claude Sonnet 4.6). -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # The AI-generated portions may be considered public domain (CC0-1.0) # and not subject to the project's licence. The human contributor has # reviewed and verified that the code is correct. diff --git a/ports/cortex_r52/gnu/CMakeLists.txt b/ports/cortex_r52/gnu/CMakeLists.txt index 957e2cbed..6444a0632 100644 --- a/ports/cortex_r52/gnu/CMakeLists.txt +++ b/ports/cortex_r52/gnu/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. target_sources(${PROJECT_NAME} PRIVATE diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/CMakeLists.txt b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/CMakeLists.txt index c7e15ec37..ee01eb3e5 100644 --- a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/CMakeLists.txt +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # Example builds for Cortex-R52 on the Armv8-R AEM FVP (FVP_BaseR_AEMv8R). diff --git a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/test/run_fvp_test.py b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/test/run_fvp_test.py index 356a6a102..37aa0adcf 100644 --- a/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/test/run_fvp_test.py +++ b/ports/cortex_r52/gnu/example_build/fvp_baser_aemv8r/test/run_fvp_test.py @@ -2,7 +2,7 @@ # # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # """Run a Cortex-R52 image on the Armv8-R AEM FVP and assert its result. diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/CMakeLists.txt b/ports/cortex_r52/gnu/example_build/s32z280_evb/CMakeLists.txt index ae0a8b73f..85dd29d65 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/CMakeLists.txt +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # Example build for Cortex-R52 on the NXP S32Z280-594EVB, RTU0 core 0. # diff --git a/ports/cortex_r52/gnu/example_build/s32z280_evb/tools/read_identity.gdb b/ports/cortex_r52/gnu/example_build/s32z280_evb/tools/read_identity.gdb index e409f8f3f..1bb0890ea 100644 --- a/ports/cortex_r52/gnu/example_build/s32z280_evb/tools/read_identity.gdb +++ b/ports/cortex_r52/gnu/example_build/s32z280_evb/tools/read_identity.gdb @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # Load s32z280_boot.elf onto the S32Z280-594EVB, run it, and report what the # core said about itself. diff --git a/ports_arch/ARMv7-A/threadx/ports/gnu/CMakeLists.txt b/ports_arch/ARMv7-A/threadx/ports/gnu/CMakeLists.txt index d03910d1d..fc2158767 100644 --- a/ports_arch/ARMv7-A/threadx/ports/gnu/CMakeLists.txt +++ b/ports_arch/ARMv7-A/threadx/ports/gnu/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # ThreadX port sources for the ARMv7-A cores, GNU tools. # Copied into every ARMv7-A gnu port by update.sh, so edit it here. diff --git a/ports_arch/ARMv7-M/threadx/ghs/example_build/tx_initialize_low_level.arm b/ports_arch/ARMv7-M/threadx/ghs/example_build/tx_initialize_low_level.arm index b98fa9745..7c2b80ab3 100644 --- a/ports_arch/ARMv7-M/threadx/ghs/example_build/tx_initialize_low_level.arm +++ b/ports_arch/ARMv7-M/threadx/ghs/example_build/tx_initialize_low_level.arm @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -; Some portions generated by Copilot (Opus 5). +; Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_arch/ARMv8-A/threadx/ports/gnu/CMakeLists.txt b/ports_arch/ARMv8-A/threadx/ports/gnu/CMakeLists.txt index 12a58cbeb..972c10f18 100644 --- a/ports_arch/ARMv8-A/threadx/ports/gnu/CMakeLists.txt +++ b/ports_arch/ARMv8-A/threadx/ports/gnu/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # ThreadX port sources for the AArch64 cores, GNU tools. # Copied into every AArch64 gnu port by update.sh, so edit it here. diff --git a/ports_arch/ARMv8-A/threadx_smp/ports/gnu/CMakeLists.txt b/ports_arch/ARMv8-A/threadx_smp/ports/gnu/CMakeLists.txt index b4758a855..36f7492b7 100644 --- a/ports_arch/ARMv8-A/threadx_smp/ports/gnu/CMakeLists.txt +++ b/ports_arch/ARMv8-A/threadx_smp/ports/gnu/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # ThreadX SMP port sources for the AArch64 cores, GNU tools. # Copied into every AArch64 gnu SMP port by update.sh, so edit it here. diff --git a/ports_module/cortex_a7/ac5/inc/txm_module_port.h b/ports_module/cortex_a7/ac5/inc/txm_module_port.h index 126be1e82..8953710f7 100644 --- a/ports_module/cortex_a7/ac5/inc/txm_module_port.h +++ b/ports_module/cortex_a7/ac5/inc/txm_module_port.h @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Claude Code (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_a7/ac5/module_manager/src/txm_module_manager_mm_register_setup.c b/ports_module/cortex_a7/ac5/module_manager/src/txm_module_manager_mm_register_setup.c index a86cfbe49..b5166df3d 100644 --- a/ports_module/cortex_a7/ac5/module_manager/src/txm_module_manager_mm_register_setup.c +++ b/ports_module/cortex_a7/ac5/module_manager/src/txm_module_manager_mm_register_setup.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Claude Code (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_a7/gnu/inc/txm_module_port.h b/ports_module/cortex_a7/gnu/inc/txm_module_port.h index 119479922..bfb04475c 100644 --- a/ports_module/cortex_a7/gnu/inc/txm_module_port.h +++ b/ports_module/cortex_a7/gnu/inc/txm_module_port.h @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Claude Code (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_a7/gnu/module_manager/src/txm_module_manager_mm_register_setup.c b/ports_module/cortex_a7/gnu/module_manager/src/txm_module_manager_mm_register_setup.c index b2161fde0..5be181360 100644 --- a/ports_module/cortex_a7/gnu/module_manager/src/txm_module_manager_mm_register_setup.c +++ b/ports_module/cortex_a7/gnu/module_manager/src/txm_module_manager_mm_register_setup.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Claude Code (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_a7/iar/inc/txm_module_port.h b/ports_module/cortex_a7/iar/inc/txm_module_port.h index dbaf7e175..aafa8d43f 100644 --- a/ports_module/cortex_a7/iar/inc/txm_module_port.h +++ b/ports_module/cortex_a7/iar/inc/txm_module_port.h @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Claude Code (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_a7/iar/module_manager/src/txm_module_manager_mm_register_setup.c b/ports_module/cortex_a7/iar/module_manager/src/txm_module_manager_mm_register_setup.c index 3adc61c38..08c83dc71 100644 --- a/ports_module/cortex_a7/iar/module_manager/src/txm_module_manager_mm_register_setup.c +++ b/ports_module/cortex_a7/iar/module_manager/src/txm_module_manager_mm_register_setup.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Claude Code (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_r52/gnu/example_build/s32z280_evb/tools/diagnose_module.gdb b/ports_module/cortex_r52/gnu/example_build/s32z280_evb/tools/diagnose_module.gdb index 235cd6e48..d1a1a489a 100644 --- a/ports_module/cortex_r52/gnu/example_build/s32z280_evb/tools/diagnose_module.gdb +++ b/ports_module/cortex_r52/gnu/example_build/s32z280_evb/tools/diagnose_module.gdb @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # Diagnostic run for the S32Z280 module manager demonstration. Same attach and # load as run_module_demo.gdb, but instead of judging the result it dumps the diff --git a/ports_module/cortex_r52/gnu/example_build/s32z280_evb/tools/run_module_demo.gdb b/ports_module/cortex_r52/gnu/example_build/s32z280_evb/tools/run_module_demo.gdb index b95eb8265..9c2fe3b50 100644 --- a/ports_module/cortex_r52/gnu/example_build/s32z280_evb/tools/run_module_demo.gdb +++ b/ports_module/cortex_r52/gnu/example_build/s32z280_evb/tools/run_module_demo.gdb @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # Load s32z280_module.elf onto the S32Z280-594EVB, run it, and report what the # protection boundary did. diff --git a/ports_module/cortex_r52/gnu/example_build/s32z280_evb/tools/run_module_demo.sh b/ports_module/cortex_r52/gnu/example_build/s32z280_evb/tools/run_module_demo.sh index c37d5a969..bbbdee436 100755 --- a/ports_module/cortex_r52/gnu/example_build/s32z280_evb/tools/run_module_demo.sh +++ b/ports_module/cortex_r52/gnu/example_build/s32z280_evb/tools/run_module_demo.sh @@ -1,7 +1,7 @@ #!/bin/bash # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # Run the ThreadX module manager demonstration on the S32Z280-594EVB and capture # the evidence: the console log and the fault registers. diff --git a/ports_module/cortex_r52/gnu/inc/tx_port.h b/ports_module/cortex_r52/gnu/inc/tx_port.h index d3013b1f0..9f6e8e3da 100644 --- a/ports_module/cortex_r52/gnu/inc/tx_port.h +++ b/ports_module/cortex_r52/gnu/inc/tx_port.h @@ -8,7 +8,7 @@ * * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Claude Code (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_r52/gnu/inc/txm_module_port.h b/ports_module/cortex_r52/gnu/inc/txm_module_port.h index 33a994d93..1d71d40a6 100644 --- a/ports_module/cortex_r52/gnu/inc/txm_module_port.h +++ b/ports_module/cortex_r52/gnu/inc/txm_module_port.h @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Claude Code (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_r52/gnu/module_manager/src/tx_thread_context_restore.S b/ports_module/cortex_r52/gnu/module_manager/src/tx_thread_context_restore.S index 90865906b..d6d7f63f2 100644 --- a/ports_module/cortex_r52/gnu/module_manager/src/tx_thread_context_restore.S +++ b/ports_module/cortex_r52/gnu/module_manager/src/tx_thread_context_restore.S @@ -8,7 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ -@ Some portions generated by Claude Code (Opus 5). +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ diff --git a/ports_module/cortex_r52/gnu/module_manager/src/tx_thread_context_save.S b/ports_module/cortex_r52/gnu/module_manager/src/tx_thread_context_save.S index 9b61077e4..26443700a 100644 --- a/ports_module/cortex_r52/gnu/module_manager/src/tx_thread_context_save.S +++ b/ports_module/cortex_r52/gnu/module_manager/src/tx_thread_context_save.S @@ -8,7 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ -@ Some portions generated by Claude Code (Opus 5). +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ diff --git a/ports_module/cortex_r52/gnu/module_manager/src/tx_thread_schedule.S b/ports_module/cortex_r52/gnu/module_manager/src/tx_thread_schedule.S index ad92ea7ed..e10d7c23a 100644 --- a/ports_module/cortex_r52/gnu/module_manager/src/tx_thread_schedule.S +++ b/ports_module/cortex_r52/gnu/module_manager/src/tx_thread_schedule.S @@ -8,7 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ -@ Some portions generated by Claude Code (Opus 5). +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ diff --git a/ports_module/cortex_r52/gnu/module_manager/src/tx_thread_stack_build.S b/ports_module/cortex_r52/gnu/module_manager/src/tx_thread_stack_build.S index 935b321ad..e45805f76 100644 --- a/ports_module/cortex_r52/gnu/module_manager/src/tx_thread_stack_build.S +++ b/ports_module/cortex_r52/gnu/module_manager/src/tx_thread_stack_build.S @@ -8,7 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ -@ Some portions generated by Claude Code (Opus 5). +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ diff --git a/ports_module/cortex_r52/gnu/module_manager/src/tx_thread_system_return.S b/ports_module/cortex_r52/gnu/module_manager/src/tx_thread_system_return.S index c0ab615b4..ae0eac7d3 100644 --- a/ports_module/cortex_r52/gnu/module_manager/src/tx_thread_system_return.S +++ b/ports_module/cortex_r52/gnu/module_manager/src/tx_thread_system_return.S @@ -8,7 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ -@ Some portions generated by Claude Code (Opus 5). +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ diff --git a/ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_alignment_adjust.c b/ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_alignment_adjust.c index 6850fe558..e06225f62 100644 --- a/ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_alignment_adjust.c +++ b/ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_alignment_adjust.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Claude Code (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_external_memory_enable.c b/ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_external_memory_enable.c index c5b9adcf5..f60f1ad74 100644 --- a/ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_external_memory_enable.c +++ b/ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_external_memory_enable.c @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Claude Code (Opus 5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ diff --git a/ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_memory_fault_handler.c b/ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_memory_fault_handler.c index cac30d2fb..62f287e09 100644 --- a/ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_memory_fault_handler.c +++ b/ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_memory_fault_handler.c @@ -20,7 +20,7 @@ /**************************************************************************/ /**************************************************************************/ -// Some portions generated by Claude Code (Opus 5). +// Portions of this file were generated with AI assistance. #define TX_SOURCE_CODE diff --git a/ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_thread_stack_build.S b/ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_thread_stack_build.S index 69916ff08..1d1d711a1 100644 --- a/ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_thread_stack_build.S +++ b/ports_module/cortex_r52/gnu/module_manager/src/txm_module_manager_thread_stack_build.S @@ -8,7 +8,7 @@ @ * @ * SPDX-License-Identifier: MIT @ **************************************************************************/ -@ Some portions generated by Claude Code (Opus 5). +@ Portions of this file were generated with AI assistance. @ @ @/**************************************************************************/ diff --git a/ports_smp/cortex_a34_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a34_smp/gnu/CMakeLists.txt index b4758a855..36f7492b7 100644 --- a/ports_smp/cortex_a34_smp/gnu/CMakeLists.txt +++ b/ports_smp/cortex_a34_smp/gnu/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # ThreadX SMP port sources for the AArch64 cores, GNU tools. # Copied into every AArch64 gnu SMP port by update.sh, so edit it here. diff --git a/ports_smp/cortex_a35_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a35_smp/gnu/CMakeLists.txt index b4758a855..36f7492b7 100644 --- a/ports_smp/cortex_a35_smp/gnu/CMakeLists.txt +++ b/ports_smp/cortex_a35_smp/gnu/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # ThreadX SMP port sources for the AArch64 cores, GNU tools. # Copied into every AArch64 gnu SMP port by update.sh, so edit it here. diff --git a/ports_smp/cortex_a53_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a53_smp/gnu/CMakeLists.txt index b4758a855..36f7492b7 100644 --- a/ports_smp/cortex_a53_smp/gnu/CMakeLists.txt +++ b/ports_smp/cortex_a53_smp/gnu/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # ThreadX SMP port sources for the AArch64 cores, GNU tools. # Copied into every AArch64 gnu SMP port by update.sh, so edit it here. diff --git a/ports_smp/cortex_a55_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a55_smp/gnu/CMakeLists.txt index b4758a855..36f7492b7 100644 --- a/ports_smp/cortex_a55_smp/gnu/CMakeLists.txt +++ b/ports_smp/cortex_a55_smp/gnu/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # ThreadX SMP port sources for the AArch64 cores, GNU tools. # Copied into every AArch64 gnu SMP port by update.sh, so edit it here. diff --git a/ports_smp/cortex_a57_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a57_smp/gnu/CMakeLists.txt index b4758a855..36f7492b7 100644 --- a/ports_smp/cortex_a57_smp/gnu/CMakeLists.txt +++ b/ports_smp/cortex_a57_smp/gnu/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # ThreadX SMP port sources for the AArch64 cores, GNU tools. # Copied into every AArch64 gnu SMP port by update.sh, so edit it here. diff --git a/ports_smp/cortex_a5_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a5_smp/gnu/CMakeLists.txt index d3b42149c..28c41af5e 100644 --- a/ports_smp/cortex_a5_smp/gnu/CMakeLists.txt +++ b/ports_smp/cortex_a5_smp/gnu/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # ThreadX port sources for cortex_a5_smp, GNU tools. diff --git a/ports_smp/cortex_a5x_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a5x_smp/gnu/CMakeLists.txt index dfbd61b30..08db4117e 100644 --- a/ports_smp/cortex_a5x_smp/gnu/CMakeLists.txt +++ b/ports_smp/cortex_a5x_smp/gnu/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # ThreadX port sources for cortex_a5x_smp, GNU tools. diff --git a/ports_smp/cortex_a5x_smp/green/src/tx_thread_smp_time_get.a64 b/ports_smp/cortex_a5x_smp/green/src/tx_thread_smp_time_get.a64 index b3501d5a0..37514c26a 100644 --- a/ports_smp/cortex_a5x_smp/green/src/tx_thread_smp_time_get.a64 +++ b/ports_smp/cortex_a5x_smp/green/src/tx_thread_smp_time_get.a64 @@ -9,7 +9,7 @@ * SPDX-License-Identifier: MIT **************************************************************************/ -// Some portions generated by Codex (GPT-5). +// Portions of this file were generated with AI assistance. /**************************************************************************/ /**************************************************************************/ diff --git a/ports_smp/cortex_a65_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a65_smp/gnu/CMakeLists.txt index b4758a855..36f7492b7 100644 --- a/ports_smp/cortex_a65_smp/gnu/CMakeLists.txt +++ b/ports_smp/cortex_a65_smp/gnu/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # ThreadX SMP port sources for the AArch64 cores, GNU tools. # Copied into every AArch64 gnu SMP port by update.sh, so edit it here. diff --git a/ports_smp/cortex_a65ae_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a65ae_smp/gnu/CMakeLists.txt index b4758a855..36f7492b7 100644 --- a/ports_smp/cortex_a65ae_smp/gnu/CMakeLists.txt +++ b/ports_smp/cortex_a65ae_smp/gnu/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # ThreadX SMP port sources for the AArch64 cores, GNU tools. # Copied into every AArch64 gnu SMP port by update.sh, so edit it here. diff --git a/ports_smp/cortex_a72_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a72_smp/gnu/CMakeLists.txt index b4758a855..36f7492b7 100644 --- a/ports_smp/cortex_a72_smp/gnu/CMakeLists.txt +++ b/ports_smp/cortex_a72_smp/gnu/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # ThreadX SMP port sources for the AArch64 cores, GNU tools. # Copied into every AArch64 gnu SMP port by update.sh, so edit it here. diff --git a/ports_smp/cortex_a73_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a73_smp/gnu/CMakeLists.txt index b4758a855..36f7492b7 100644 --- a/ports_smp/cortex_a73_smp/gnu/CMakeLists.txt +++ b/ports_smp/cortex_a73_smp/gnu/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # ThreadX SMP port sources for the AArch64 cores, GNU tools. # Copied into every AArch64 gnu SMP port by update.sh, so edit it here. diff --git a/ports_smp/cortex_a75_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a75_smp/gnu/CMakeLists.txt index b4758a855..36f7492b7 100644 --- a/ports_smp/cortex_a75_smp/gnu/CMakeLists.txt +++ b/ports_smp/cortex_a75_smp/gnu/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # ThreadX SMP port sources for the AArch64 cores, GNU tools. # Copied into every AArch64 gnu SMP port by update.sh, so edit it here. diff --git a/ports_smp/cortex_a76_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a76_smp/gnu/CMakeLists.txt index b4758a855..36f7492b7 100644 --- a/ports_smp/cortex_a76_smp/gnu/CMakeLists.txt +++ b/ports_smp/cortex_a76_smp/gnu/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # ThreadX SMP port sources for the AArch64 cores, GNU tools. # Copied into every AArch64 gnu SMP port by update.sh, so edit it here. diff --git a/ports_smp/cortex_a76ae_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a76ae_smp/gnu/CMakeLists.txt index b4758a855..36f7492b7 100644 --- a/ports_smp/cortex_a76ae_smp/gnu/CMakeLists.txt +++ b/ports_smp/cortex_a76ae_smp/gnu/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # ThreadX SMP port sources for the AArch64 cores, GNU tools. # Copied into every AArch64 gnu SMP port by update.sh, so edit it here. diff --git a/ports_smp/cortex_a77_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a77_smp/gnu/CMakeLists.txt index b4758a855..36f7492b7 100644 --- a/ports_smp/cortex_a77_smp/gnu/CMakeLists.txt +++ b/ports_smp/cortex_a77_smp/gnu/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # ThreadX SMP port sources for the AArch64 cores, GNU tools. # Copied into every AArch64 gnu SMP port by update.sh, so edit it here. diff --git a/ports_smp/cortex_a78_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a78_smp/gnu/CMakeLists.txt index b4758a855..36f7492b7 100644 --- a/ports_smp/cortex_a78_smp/gnu/CMakeLists.txt +++ b/ports_smp/cortex_a78_smp/gnu/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # ThreadX SMP port sources for the AArch64 cores, GNU tools. # Copied into every AArch64 gnu SMP port by update.sh, so edit it here. diff --git a/ports_smp/cortex_a7_smp/gnu/CMakeLists.txt b/ports_smp/cortex_a7_smp/gnu/CMakeLists.txt index ef6be36c9..d4094f4d8 100644 --- a/ports_smp/cortex_a7_smp/gnu/CMakeLists.txt +++ b/ports_smp/cortex_a7_smp/gnu/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # ThreadX port sources for cortex_a7_smp, GNU tools. diff --git a/ports_smp/linux/gnu/CMakeLists.txt b/ports_smp/linux/gnu/CMakeLists.txt index 23d4a1a58..7ff9e0a5c 100644 --- a/ports_smp/linux/gnu/CMakeLists.txt +++ b/ports_smp/linux/gnu/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # ThreadX port sources for linux, GNU tools. diff --git a/ports_smp/mips32_interaptiv_smp/gnu/CMakeLists.txt b/ports_smp/mips32_interaptiv_smp/gnu/CMakeLists.txt index 6f8133312..c54890aaf 100644 --- a/ports_smp/mips32_interaptiv_smp/gnu/CMakeLists.txt +++ b/ports_smp/mips32_interaptiv_smp/gnu/CMakeLists.txt @@ -1,6 +1,6 @@ # Copyright (c) 2026 Eclipse ThreadX contributors # SPDX-License-Identifier: MIT -# Some portions generated by Claude Code (Opus 5). +# Portions of this file were generated with AI assistance. # # ThreadX port sources for mips32_interaptiv_smp, GNU tools. diff --git a/scripts/check_ai_disclosure.sh b/scripts/check_ai_disclosure.sh new file mode 100755 index 000000000..5a08a44c3 --- /dev/null +++ b/scripts/check_ai_disclosure.sh @@ -0,0 +1,129 @@ +#!/bin/bash +############################################################################### +# 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. +# +# AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5). +# The AI-generated portions may be considered public domain (CC0-1.0) +# and not subject to the project's licence. The human contributor has +# reviewed and verified that the code is correct. +# +# SPDX-License-Identifier: MIT and CC0-1.0 +############################################################################### +# +# Fail the build if a file's AI disclosure comment has drifted from the one +# accepted form. +# +# A file that was edited with AI assistance carries exactly one line: +# +# Portions of this file were generated with AI assistance. +# +# written with the comment character that file already uses. It names no +# product, no model and no version, and a file carries at most one of it, ever. +# +# The text is fixed for a reason that is easy to miss. An earlier convention +# named the product and the model -- "Some portions generated by +# ()" -- and the result was not attribution but accumulation: each tool +# that touched a file failed to recognise the line another tool had left, and +# appended its own. Files reached three stacked lines, and one product ended +# up spelled four different ways across the tree, which made the record +# unusable for the one question it was meant to answer. +# +# Precise attribution lives on the commit instead, where the Assisted-by +# trailer is dated and attached to the diff it describes: +# +# scripts/count_assisted_by.sh --list -- +# +# A file-level flag answers WHETHER; the history answers WHO. A header line +# cannot hold the second honestly, because the code it names gets rewritten +# and the line stays. +# +# The AI Disclosure paragraph in a new file's copyright header is different and +# is not checked here: it keeps its product and model version, because a file +# is created once and that record cannot grow. +# +# This script is excluded from its own scan. It has to spell the rejected +# forms in order to look for them. + +set -euo pipefail + +readonly ROOT="$(cd "$(dirname "$(realpath "$0")")/.." && pwd)" +readonly SELF='scripts/check_ai_disclosure.sh' +readonly FIXED='Portions of this file were generated with AI assistance.' + +cd "${ROOT}" + +# Tracked files only. A build tree is not this repository's text to police, +# and scanning one would make the check depend on whether somebody had built. +mapfile -d '' -t FILES < <(git ls-files -z | grep -zZv "^${SELF}$") + +status=0 + +report() { + printf '%s\n\n' "$1" >&2 + printf '%s\n\n' "$2" >&2 + status=1 +} + +# 1. The superseded per-edit form, which names a product and a model. +hits="$(grep -nI 'Some portions generated by' -- "${FILES[@]}" 2>/dev/null || true)" +if [ -n "${hits}" ]; then + report "AI disclosure check FAILED: superseded per-edit form. + +Replace each of these with the fixed line, keeping the file's comment +character: + + ${FIXED}" "${hits}" +fi + +# 2. A doubled comment marker, such as '; //' or '@ //'. Assembly dialects +# differ -- armasm and IAR use ';', GNU as uses '@' or '//' -- and writing +# both is a symptom of a tool guessing rather than reading the file. +hits="$(grep -nIE '(//|[;@#])[[:space:]]*//[[:space:]]*Portions of this file were generated' \ + -- "${FILES[@]}" 2>/dev/null || true)" +if [ -n "${hits}" ]; then + report "AI disclosure check FAILED: doubled comment marker. + +Use the single comment character the rest of the file uses." "${hits}" +fi + +# 3. More than one disclosure line in a file. This is the failure the fixed +# text exists to prevent, so it is worth catching directly rather than +# inferring it from the form. +hits="$(grep -cIF "${FIXED}" -- "${FILES[@]}" 2>/dev/null | awk -F: '$NF > 1' || true)" +if [ -n "${hits}" ]; then + report "AI disclosure check FAILED: more than one disclosure line. + +A file carries at most one, ever. Keep the first and delete the rest; the +commit trailer, not the header, records which agents have touched the file." "${hits}" +fi + +# 4. A near miss. A line that is clearly meant to be the disclosure but is +# not spelled exactly right defeats every deduplication that follows it. +# +# Markdown is exempt from this one check. The contribution guide has to +# quote the accepted text and explain when it applies, so matching the bare +# phrase there reports prose rather than drift. A superseded form in a +# Markdown file is still caught by check 1. +mapfile -d '' -t SOURCES < <(printf '%s\0' "${FILES[@]}" | grep -zZv '\.md$' || true) +hits='' +if [ "${#SOURCES[@]}" -gt 0 ]; then + hits="$(grep -nIF 'AI assistance' -- "${SOURCES[@]}" 2>/dev/null \ + | grep -vF "${FIXED}" || true)" +fi +if [ -n "${hits}" ]; then + report "AI disclosure check FAILED: the text is not spelled exactly. + +The accepted text, character for character, is: + + ${FIXED}" "${hits}" +fi + +if [ "${status}" -eq 0 ]; then + echo "AI disclosure check passed." +fi + +exit "${status}" diff --git a/test/tx/cmake/thread_transition/CMakeLists.txt b/test/tx/cmake/thread_transition/CMakeLists.txt index a56592382..342ca839c 100644 --- a/test/tx/cmake/thread_transition/CMakeLists.txt +++ b/test/tx/cmake/thread_transition/CMakeLists.txt @@ -1,4 +1,4 @@ -# Some portions generated by Codex (gpt-5.6-sol). +# Portions of this file were generated with AI assistance. cmake_minimum_required(VERSION 3.13 FATAL_ERROR) cmake_policy(SET CMP0057 NEW) From cf577c713719a2f1603624d7974ea55beb370d30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 28 Sep 2026 14:08:13 -0400 Subject: [PATCH 173/181] Made ThreadX object names const-qualifiable behind an option (#761) Fixes #61 Object names are exposed as writable pointers throughout the kernel API, which rejects string literals in C++ and lets a caller modify a name an object still holds. Information services return those names through writable double pointers. Create services, control blocks, information services, the module manager and trace registration now preserve const qualification, behind TX_ENABLE_CONST_NAMES. The option defaults to off, so a build that says nothing gets exactly the types it got before. It is opt-in rather than opt-out because it changes the type of a public struct field: application code that copies a name into a writable CHAR * stops compiling, which is a reasonable thing to ask of a minor release and not of a patch one. Issue #780 tracks making it the default in 6.6. Two things the option reaches that its own call sites do not. TX_CHAR_TO_UCHAR_POINTER_CONVERT has exactly two users, both of them reading an object name in _tx_trace_object_register, and every form of that macro but the MISRA one casts the qualifier away without saying so; the conversion is now const in and const out, so nothing launders const to make the build pass. The FreeRTOS adapter holds the name pcTaskGetName retrieves in a TX_NAME_CONST pointer so that it tracks whichever declaration tx_thread_info_get has, and keeps its writable return type through an explicit MISRA C:2012 Rule 11.8 cast, because that signature is part of the FreeRTOS API. Default build: all seven host configurations and all five SMP configurations build with zero warnings and pass -- 113/113 on five host configurations, 100/100 on the two MISRA builds, 118/118 on SMP, 3/3 FreeRTOS. With TX_ENABLE_CONST_NAMES set, the host default and both MISRA configurations, the SMP trace configuration and the FreeRTOS adapter build with zero warnings and pass. Co-authored-by: Tilen Majerle Assisted-by: Codex (gpt-6-astra) Assisted-by: Claude Code (Opus 5) --- common/inc/tx_api.h | 133 ++++++++++-------- common/inc/tx_trace.h | 4 +- common/inc/tx_user_sample.h | 9 +- common/src/tx_block_pool_create.c | 4 +- common/src/tx_block_pool_info_get.c | 4 +- common/src/tx_byte_pool_create.c | 4 +- common/src/tx_byte_pool_info_get.c | 4 +- common/src/tx_event_flags_create.c | 4 +- common/src/tx_event_flags_info_get.c | 4 +- common/src/tx_misra.c | 20 ++- common/src/tx_mutex_create.c | 4 +- common/src/tx_mutex_info_get.c | 4 +- common/src/tx_queue_create.c | 4 +- common/src/tx_queue_info_get.c | 4 +- common/src/tx_semaphore_create.c | 4 +- common/src/tx_semaphore_info_get.c | 4 +- common/src/tx_thread_create.c | 2 +- common/src/tx_thread_info_get.c | 4 +- common/src/tx_timer_create.c | 4 +- common/src/tx_timer_info_get.c | 4 +- common/src/tx_trace_object_register.c | 19 +-- common/src/txe_block_pool_create.c | 4 +- common/src/txe_block_pool_info_get.c | 4 +- common/src/txe_byte_pool_create.c | 4 +- common/src/txe_byte_pool_info_get.c | 4 +- common/src/txe_event_flags_create.c | 4 +- common/src/txe_event_flags_info_get.c | 4 +- common/src/txe_mutex_create.c | 4 +- common/src/txe_mutex_info_get.c | 4 +- common/src/txe_queue_create.c | 4 +- common/src/txe_queue_info_get.c | 4 +- common/src/txe_semaphore_create.c | 4 +- common/src/txe_semaphore_info_get.c | 4 +- common/src/txe_thread_create.c | 4 +- common/src/txe_thread_info_get.c | 4 +- common/src/txe_timer_create.c | 4 +- common/src/txe_timer_info_get.c | 4 +- common_modules/inc/txm_module.h | 2 +- .../module_lib/src/txm_block_pool_create.c | 4 +- .../module_lib/src/txm_block_pool_info_get.c | 4 +- .../module_lib/src/txm_byte_pool_create.c | 4 +- .../module_lib/src/txm_byte_pool_info_get.c | 4 +- .../module_lib/src/txm_event_flags_create.c | 4 +- .../module_lib/src/txm_event_flags_info_get.c | 4 +- .../module_lib/src/txm_mutex_create.c | 4 +- .../module_lib/src/txm_mutex_info_get.c | 4 +- .../module_lib/src/txm_queue_create.c | 4 +- .../module_lib/src/txm_queue_info_get.c | 4 +- .../module_lib/src/txm_semaphore_create.c | 4 +- .../module_lib/src/txm_semaphore_info_get.c | 4 +- .../module_lib/src/txm_thread_create.c | 4 +- .../module_lib/src/txm_thread_info_get.c | 4 +- .../module_lib/src/txm_timer_create.c | 4 +- .../module_lib/src/txm_timer_info_get.c | 4 +- .../inc/txm_module_manager_dispatch.h | 64 ++++----- .../inc/txm_module_manager_util.h | 2 +- .../src/txm_module_manager_thread_create.c | 3 +- .../src/txm_module_manager_util.c | 2 +- common_smp/inc/tx_api.h | 101 +++++++------ common_smp/inc/tx_trace.h | 6 +- common_smp/inc/tx_user_sample.h | 9 +- common_smp/src/tx_block_pool_create.c | 4 +- common_smp/src/tx_block_pool_info_get.c | 4 +- common_smp/src/tx_byte_pool_create.c | 4 +- common_smp/src/tx_byte_pool_info_get.c | 4 +- common_smp/src/tx_event_flags_create.c | 4 +- common_smp/src/tx_event_flags_info_get.c | 4 +- common_smp/src/tx_misra.c | 20 ++- common_smp/src/tx_mutex_create.c | 4 +- common_smp/src/tx_mutex_info_get.c | 4 +- common_smp/src/tx_queue_create.c | 4 +- common_smp/src/tx_queue_info_get.c | 4 +- common_smp/src/tx_semaphore_create.c | 4 +- common_smp/src/tx_semaphore_info_get.c | 4 +- common_smp/src/tx_thread_create.c | 2 +- common_smp/src/tx_thread_info_get.c | 4 +- common_smp/src/tx_timer_create.c | 4 +- common_smp/src/tx_timer_info_get.c | 4 +- common_smp/src/tx_trace_object_register.c | 19 +-- common_smp/src/txe_block_pool_create.c | 4 +- common_smp/src/txe_block_pool_info_get.c | 4 +- common_smp/src/txe_byte_pool_create.c | 4 +- common_smp/src/txe_byte_pool_info_get.c | 4 +- common_smp/src/txe_event_flags_create.c | 4 +- common_smp/src/txe_event_flags_info_get.c | 4 +- common_smp/src/txe_mutex_create.c | 4 +- common_smp/src/txe_mutex_info_get.c | 4 +- common_smp/src/txe_queue_create.c | 4 +- common_smp/src/txe_queue_info_get.c | 4 +- common_smp/src/txe_semaphore_create.c | 4 +- common_smp/src/txe_semaphore_info_get.c | 4 +- common_smp/src/txe_thread_create.c | 4 +- common_smp/src/txe_thread_info_get.c | 4 +- common_smp/src/txe_timer_create.c | 4 +- common_smp/src/txe_timer_info_get.c | 4 +- test/freertos/regression/txfr_test_harness.c | 20 +-- .../threadx_block_memory_basic_test.c | 4 +- ...hreadx_block_memory_error_detection_test.c | 4 +- .../threadx_block_memory_information_test.c | 8 +- .../threadx_byte_memory_basic_test.c | 4 +- .../threadx_byte_memory_information_test.c | 6 +- .../threadx_byte_memory_long_search_test.c | 4 +- .../threadx_event_flag_basic_test.c | 4 +- .../threadx_event_flag_information_test.c | 6 +- .../smp/regression/threadx_mutex_basic_test.c | 4 +- .../threadx_mutex_information_test.c | 6 +- .../threadx_queue_basic_one_word_test.c | 4 +- .../threadx_queue_information_test.c | 6 +- .../regression/threadx_semaphore_basic_test.c | 4 +- .../threadx_semaphore_information_test.c | 6 +- .../threadx_thread_basic_execution_test.c | 4 +- .../threadx_thread_information_test.c | 6 +- .../threadx_timer_information_test.c | 6 +- .../regression/threadx_timer_simple_test.c | 4 +- .../smp/regression/threadx_trace_basic_test.c | 4 +- ...odule_manager_block_pool_parameters_test.c | 6 +- .../threadx_block_memory_basic_test.c | 4 +- ...hreadx_block_memory_error_detection_test.c | 4 +- .../threadx_block_memory_information_test.c | 8 +- .../threadx_byte_memory_basic_test.c | 4 +- .../threadx_byte_memory_information_test.c | 6 +- .../threadx_event_flag_basic_test.c | 4 +- .../threadx_event_flag_information_test.c | 6 +- test/tx/regression/threadx_mutex_basic_test.c | 4 +- .../threadx_mutex_information_test.c | 6 +- .../threadx_queue_basic_one_word_test.c | 4 +- .../threadx_queue_information_test.c | 6 +- .../regression/threadx_semaphore_basic_test.c | 4 +- .../threadx_semaphore_information_test.c | 6 +- .../threadx_thread_basic_execution_test.c | 2 +- .../threadx_thread_information_test.c | 6 +- .../threadx_timer_information_test.c | 6 +- .../tx/regression/threadx_timer_simple_test.c | 4 +- test/tx/regression/threadx_trace_basic_test.c | 2 +- .../FreeRTOS/tx_freertos.c | 5 +- 135 files changed, 622 insertions(+), 318 deletions(-) diff --git a/common/inc/tx_api.h b/common/inc/tx_api.h index bf9de8565..bac617e5d 100644 --- a/common/inc/tx_api.h +++ b/common/inc/tx_api.h @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -64,6 +66,17 @@ extern "C" { #include "tx_port.h" +/* Define the qualifier applied to object name strings. Opting in makes every + object name a pointer to const, which the kernel and its tests are written + for. It is off by default because it changes the type of a public struct + field, and application code that copies a name into a writable pointer stops + compiling. */ +#ifdef TX_ENABLE_CONST_NAMES +#define TX_NAME_CONST const +#else +#define TX_NAME_CONST +#endif + #if (defined(TX_EXECUTION_PROFILE_ENABLE) && !defined(TX_ENABLE_EXECUTION_CHANGE_NOTIFY)) #include "tx_execution_profile.h" #endif @@ -368,7 +381,7 @@ typedef struct TX_TIMER_STRUCT ULONG tx_timer_id; /* Define the timer's name. */ - CHAR *tx_timer_name; + TX_NAME_CONST CHAR *tx_timer_name; /* Define the actual contents of the timer. This is the block that is used in the actual timer expiration processing. */ @@ -434,7 +447,7 @@ typedef struct TX_THREAD_STRUCT is typically defined to whitespace or a pointer type in tx_port.h. */ TX_THREAD_EXTENSION_0 - CHAR *tx_thread_name; /* Pointer to thread's name */ + TX_NAME_CONST CHAR *tx_thread_name; /* Pointer to thread's name */ UINT tx_thread_priority; /* Priority of thread (0-1023) */ UINT tx_thread_state; /* Thread's execution state */ UINT tx_thread_delayed_suspend; /* Delayed suspend flag */ @@ -595,7 +608,7 @@ typedef struct TX_BLOCK_POOL_STRUCT ULONG tx_block_pool_id; /* Define the block pool's name. */ - CHAR *tx_block_pool_name; + TX_NAME_CONST CHAR *tx_block_pool_name; /* Define the number of available memory blocks in the pool. */ UINT tx_block_pool_available; @@ -673,7 +686,7 @@ typedef struct TX_BYTE_POOL_STRUCT ULONG tx_byte_pool_id; /* Define the byte pool's name. */ - CHAR *tx_byte_pool_name; + TX_NAME_CONST CHAR *tx_byte_pool_name; /* Define the number of available bytes in the pool. */ ULONG tx_byte_pool_available; @@ -752,7 +765,7 @@ typedef struct TX_EVENT_FLAGS_GROUP_STRUCT ULONG tx_event_flags_group_id; /* Define the event flags group's name. */ - CHAR *tx_event_flags_group_name; + TX_NAME_CONST CHAR *tx_event_flags_group_name; /* Define the actual current event flags in this group. A zero in a particular bit indicates the event flag is not set. */ @@ -838,7 +851,7 @@ typedef struct TX_MUTEX_STRUCT ULONG tx_mutex_id; /* Define the mutex's name. */ - CHAR *tx_mutex_name; + TX_NAME_CONST CHAR *tx_mutex_name; /* Define the mutex ownership count. */ UINT tx_mutex_ownership_count; @@ -911,7 +924,7 @@ typedef struct TX_QUEUE_STRUCT ULONG tx_queue_id; /* Define the queue's name. */ - CHAR *tx_queue_name; + TX_NAME_CONST CHAR *tx_queue_name; /* Define the message size that was specified in queue creation. */ UINT tx_queue_message_size; @@ -990,7 +1003,7 @@ typedef struct TX_SEMAPHORE_STRUCT ULONG tx_semaphore_id; /* Define the semaphore's name. */ - CHAR *tx_semaphore_name; + TX_NAME_CONST CHAR *tx_semaphore_name; /* Define the actual semaphore count. A zero means that no semaphore instance is available. */ @@ -1417,10 +1430,10 @@ VOID tx_application_define(VOID *first_unused_memory); /* Define block memory pool management function prototypes. */ UINT _tx_block_allocate(TX_BLOCK_POOL *pool_ptr, VOID **block_ptr, ULONG wait_option); -UINT _tx_block_pool_create(TX_BLOCK_POOL *pool_ptr, CHAR *name_ptr, ULONG block_size, +UINT _tx_block_pool_create(TX_BLOCK_POOL *pool_ptr, TX_NAME_CONST CHAR *name_ptr, ULONG block_size, VOID *pool_start, ULONG pool_size); UINT _tx_block_pool_delete(TX_BLOCK_POOL *pool_ptr); -UINT _tx_block_pool_info_get(TX_BLOCK_POOL *pool_ptr, CHAR **name, ULONG *available_blocks, +UINT _tx_block_pool_info_get(TX_BLOCK_POOL *pool_ptr, TX_NAME_CONST CHAR **name, ULONG *available_blocks, ULONG *total_blocks, TX_THREAD **first_suspended, ULONG *suspended_count, TX_BLOCK_POOL **next_pool); UINT _tx_block_pool_performance_info_get(TX_BLOCK_POOL *pool_ptr, ULONG *allocates, ULONG *releases, @@ -1435,20 +1448,20 @@ UINT _tx_block_release(VOID *block_ptr); application. */ UINT _txe_block_allocate(TX_BLOCK_POOL *pool_ptr, VOID **block_ptr, ULONG wait_option); -UINT _txe_block_pool_create(TX_BLOCK_POOL *pool_ptr, CHAR *name_ptr, ULONG block_size, +UINT _txe_block_pool_create(TX_BLOCK_POOL *pool_ptr, TX_NAME_CONST CHAR *name_ptr, ULONG block_size, VOID *pool_start, ULONG pool_size, UINT pool_control_block_size); UINT _txe_block_pool_delete(TX_BLOCK_POOL *pool_ptr); -UINT _txe_block_pool_info_get(TX_BLOCK_POOL *pool_ptr, CHAR **name, ULONG *available_blocks, +UINT _txe_block_pool_info_get(TX_BLOCK_POOL *pool_ptr, TX_NAME_CONST CHAR **name, ULONG *available_blocks, ULONG *total_blocks, TX_THREAD **first_suspended, ULONG *suspended_count, TX_BLOCK_POOL **next_pool); UINT _txe_block_pool_prioritize(TX_BLOCK_POOL *pool_ptr); UINT _txe_block_release(VOID *block_ptr); #ifdef TX_ENABLE_MULTI_ERROR_CHECKING UINT _txr_block_allocate(TX_BLOCK_POOL *pool_ptr, VOID **block_ptr, ULONG wait_option); -UINT _txr_block_pool_create(TX_BLOCK_POOL *pool_ptr, CHAR *name_ptr, ULONG block_size, +UINT _txr_block_pool_create(TX_BLOCK_POOL *pool_ptr, TX_NAME_CONST CHAR *name_ptr, ULONG block_size, VOID *pool_start, ULONG pool_size, UINT pool_control_block_size); UINT _txr_block_pool_delete(TX_BLOCK_POOL *pool_ptr); -UINT _txr_block_pool_info_get(TX_BLOCK_POOL *pool_ptr, CHAR **name, ULONG *available_blocks, +UINT _txr_block_pool_info_get(TX_BLOCK_POOL *pool_ptr, TX_NAME_CONST CHAR **name, ULONG *available_blocks, ULONG *total_blocks, TX_THREAD **first_suspended, ULONG *suspended_count, TX_BLOCK_POOL **next_pool); UINT _txr_block_pool_prioritize(TX_BLOCK_POOL *pool_ptr); @@ -1460,10 +1473,10 @@ UINT _txr_block_release(VOID *block_ptr); UINT _tx_byte_allocate(TX_BYTE_POOL *pool_ptr, VOID **memory_ptr, ULONG memory_size, ULONG wait_option); -UINT _tx_byte_pool_create(TX_BYTE_POOL *pool_ptr, CHAR *name_ptr, VOID *pool_start, +UINT _tx_byte_pool_create(TX_BYTE_POOL *pool_ptr, TX_NAME_CONST CHAR *name_ptr, VOID *pool_start, ULONG pool_size); UINT _tx_byte_pool_delete(TX_BYTE_POOL *pool_ptr); -UINT _tx_byte_pool_info_get(TX_BYTE_POOL *pool_ptr, CHAR **name, ULONG *available_bytes, +UINT _tx_byte_pool_info_get(TX_BYTE_POOL *pool_ptr, TX_NAME_CONST CHAR **name, ULONG *available_bytes, ULONG *fragments, TX_THREAD **first_suspended, ULONG *suspended_count, TX_BYTE_POOL **next_pool); UINT _tx_byte_pool_performance_info_get(TX_BYTE_POOL *pool_ptr, ULONG *allocates, ULONG *releases, @@ -1479,10 +1492,10 @@ UINT _tx_byte_release(VOID *memory_ptr); UINT _txe_byte_allocate(TX_BYTE_POOL *pool_ptr, VOID **memory_ptr, ULONG memory_size, ULONG wait_option); -UINT _txe_byte_pool_create(TX_BYTE_POOL *pool_ptr, CHAR *name_ptr, VOID *pool_start, +UINT _txe_byte_pool_create(TX_BYTE_POOL *pool_ptr, TX_NAME_CONST CHAR *name_ptr, VOID *pool_start, ULONG pool_size, UINT pool_control_block_size); UINT _txe_byte_pool_delete(TX_BYTE_POOL *pool_ptr); -UINT _txe_byte_pool_info_get(TX_BYTE_POOL *pool_ptr, CHAR **name, ULONG *available_bytes, +UINT _txe_byte_pool_info_get(TX_BYTE_POOL *pool_ptr, TX_NAME_CONST CHAR **name, ULONG *available_bytes, ULONG *fragments, TX_THREAD **first_suspended, ULONG *suspended_count, TX_BYTE_POOL **next_pool); UINT _txe_byte_pool_prioritize(TX_BYTE_POOL *pool_ptr); @@ -1490,10 +1503,10 @@ UINT _txe_byte_release(VOID *memory_ptr); #ifdef TX_ENABLE_MULTI_ERROR_CHECKING UINT _txr_byte_allocate(TX_BYTE_POOL *pool_ptr, VOID **memory_ptr, ULONG memory_size, ULONG wait_option); -UINT _txr_byte_pool_create(TX_BYTE_POOL *pool_ptr, CHAR *name_ptr, VOID *pool_start, +UINT _txr_byte_pool_create(TX_BYTE_POOL *pool_ptr, TX_NAME_CONST CHAR *name_ptr, VOID *pool_start, ULONG pool_size, UINT pool_control_block_size); UINT _txr_byte_pool_delete(TX_BYTE_POOL *pool_ptr); -UINT _txr_byte_pool_info_get(TX_BYTE_POOL *pool_ptr, CHAR **name, ULONG *available_bytes, +UINT _txr_byte_pool_info_get(TX_BYTE_POOL *pool_ptr, TX_NAME_CONST CHAR **name, ULONG *available_bytes, ULONG *fragments, TX_THREAD **first_suspended, ULONG *suspended_count, TX_BYTE_POOL **next_pool); UINT _txr_byte_pool_prioritize(TX_BYTE_POOL *pool_ptr); @@ -1503,11 +1516,11 @@ UINT _txr_byte_release(VOID *memory_ptr); /* Define event flags management function prototypes. */ -UINT _tx_event_flags_create(TX_EVENT_FLAGS_GROUP *group_ptr, CHAR *name_ptr); +UINT _tx_event_flags_create(TX_EVENT_FLAGS_GROUP *group_ptr, TX_NAME_CONST CHAR *name_ptr); UINT _tx_event_flags_delete(TX_EVENT_FLAGS_GROUP *group_ptr); UINT _tx_event_flags_get(TX_EVENT_FLAGS_GROUP *group_ptr, ULONG requested_flags, UINT get_option, ULONG *actual_flags_ptr, ULONG wait_option); -UINT _tx_event_flags_info_get(TX_EVENT_FLAGS_GROUP *group_ptr, CHAR **name, ULONG *current_flags, +UINT _tx_event_flags_info_get(TX_EVENT_FLAGS_GROUP *group_ptr, TX_NAME_CONST CHAR **name, ULONG *current_flags, TX_THREAD **first_suspended, ULONG *suspended_count, TX_EVENT_FLAGS_GROUP **next_group); UINT _tx_event_flags_performance_info_get(TX_EVENT_FLAGS_GROUP *group_ptr, ULONG *sets, ULONG *gets, @@ -1522,22 +1535,22 @@ UINT _tx_event_flags_set_notify(TX_EVENT_FLAGS_GROUP *group_ptr, VOID (*e /* Define error checking shells for API services. These are only referenced by the application. */ -UINT _txe_event_flags_create(TX_EVENT_FLAGS_GROUP *group_ptr, CHAR *name_ptr, UINT event_control_block_size); +UINT _txe_event_flags_create(TX_EVENT_FLAGS_GROUP *group_ptr, TX_NAME_CONST CHAR *name_ptr, UINT event_control_block_size); UINT _txe_event_flags_delete(TX_EVENT_FLAGS_GROUP *group_ptr); UINT _txe_event_flags_get(TX_EVENT_FLAGS_GROUP *group_ptr, ULONG requested_flags, UINT get_option, ULONG *actual_flags_ptr, ULONG wait_option); -UINT _txe_event_flags_info_get(TX_EVENT_FLAGS_GROUP *group_ptr, CHAR **name, ULONG *current_flags, +UINT _txe_event_flags_info_get(TX_EVENT_FLAGS_GROUP *group_ptr, TX_NAME_CONST CHAR **name, ULONG *current_flags, TX_THREAD **first_suspended, ULONG *suspended_count, TX_EVENT_FLAGS_GROUP **next_group); UINT _txe_event_flags_set(TX_EVENT_FLAGS_GROUP *group_ptr, ULONG flags_to_set, UINT set_option); UINT _txe_event_flags_set_notify(TX_EVENT_FLAGS_GROUP *group_ptr, VOID (*events_set_notify)(TX_EVENT_FLAGS_GROUP *notify_group_ptr)); #ifdef TX_ENABLE_MULTI_ERROR_CHECKING -UINT _txr_event_flags_create(TX_EVENT_FLAGS_GROUP *group_ptr, CHAR *name_ptr, UINT event_control_block_size); +UINT _txr_event_flags_create(TX_EVENT_FLAGS_GROUP *group_ptr, TX_NAME_CONST CHAR *name_ptr, UINT event_control_block_size); UINT _txr_event_flags_delete(TX_EVENT_FLAGS_GROUP *group_ptr); UINT _txr_event_flags_get(TX_EVENT_FLAGS_GROUP *group_ptr, ULONG requested_flags, UINT get_option, ULONG *actual_flags_ptr, ULONG wait_option); -UINT _txr_event_flags_info_get(TX_EVENT_FLAGS_GROUP *group_ptr, CHAR **name, ULONG *current_flags, +UINT _txr_event_flags_info_get(TX_EVENT_FLAGS_GROUP *group_ptr, TX_NAME_CONST CHAR **name, ULONG *current_flags, TX_THREAD **first_suspended, ULONG *suspended_count, TX_EVENT_FLAGS_GROUP **next_group); UINT _txr_event_flags_set(TX_EVENT_FLAGS_GROUP *group_ptr, ULONG flags_to_set, @@ -1553,10 +1566,10 @@ VOID _tx_initialize_kernel_enter(VOID); /* Define mutex management function prototypes. */ -UINT _tx_mutex_create(TX_MUTEX *mutex_ptr, CHAR *name_ptr, UINT inherit); +UINT _tx_mutex_create(TX_MUTEX *mutex_ptr, TX_NAME_CONST CHAR *name_ptr, UINT inherit); UINT _tx_mutex_delete(TX_MUTEX *mutex_ptr); UINT _tx_mutex_get(TX_MUTEX *mutex_ptr, ULONG wait_option); -UINT _tx_mutex_info_get(TX_MUTEX *mutex_ptr, CHAR **name, ULONG *count, TX_THREAD **owner, +UINT _tx_mutex_info_get(TX_MUTEX *mutex_ptr, TX_NAME_CONST CHAR **name, ULONG *count, TX_THREAD **owner, TX_THREAD **first_suspended, ULONG *suspended_count, TX_MUTEX **next_mutex); UINT _tx_mutex_performance_info_get(TX_MUTEX *mutex_ptr, ULONG *puts, ULONG *gets, @@ -1570,19 +1583,19 @@ UINT _tx_mutex_put(TX_MUTEX *mutex_ptr); /* Define error checking shells for API services. These are only referenced by the application. */ -UINT _txe_mutex_create(TX_MUTEX *mutex_ptr, CHAR *name_ptr, UINT inherit, UINT mutex_control_block_size); +UINT _txe_mutex_create(TX_MUTEX *mutex_ptr, TX_NAME_CONST CHAR *name_ptr, UINT inherit, UINT mutex_control_block_size); UINT _txe_mutex_delete(TX_MUTEX *mutex_ptr); UINT _txe_mutex_get(TX_MUTEX *mutex_ptr, ULONG wait_option); -UINT _txe_mutex_info_get(TX_MUTEX *mutex_ptr, CHAR **name, ULONG *count, TX_THREAD **owner, +UINT _txe_mutex_info_get(TX_MUTEX *mutex_ptr, TX_NAME_CONST CHAR **name, ULONG *count, TX_THREAD **owner, TX_THREAD **first_suspended, ULONG *suspended_count, TX_MUTEX **next_mutex); UINT _txe_mutex_prioritize(TX_MUTEX *mutex_ptr); UINT _txe_mutex_put(TX_MUTEX *mutex_ptr); #ifdef TX_ENABLE_MULTI_ERROR_CHECKING -UINT _txr_mutex_create(TX_MUTEX *mutex_ptr, CHAR *name_ptr, UINT inherit, UINT mutex_control_block_size); +UINT _txr_mutex_create(TX_MUTEX *mutex_ptr, TX_NAME_CONST CHAR *name_ptr, UINT inherit, UINT mutex_control_block_size); UINT _txr_mutex_delete(TX_MUTEX *mutex_ptr); UINT _txr_mutex_get(TX_MUTEX *mutex_ptr, ULONG wait_option); -UINT _txr_mutex_info_get(TX_MUTEX *mutex_ptr, CHAR **name, ULONG *count, TX_THREAD **owner, +UINT _txr_mutex_info_get(TX_MUTEX *mutex_ptr, TX_NAME_CONST CHAR **name, ULONG *count, TX_THREAD **owner, TX_THREAD **first_suspended, ULONG *suspended_count, TX_MUTEX **next_mutex); UINT _txr_mutex_prioritize(TX_MUTEX *mutex_ptr); @@ -1592,11 +1605,11 @@ UINT _txr_mutex_put(TX_MUTEX *mutex_ptr); /* Define queue management function prototypes. */ -UINT _tx_queue_create(TX_QUEUE *queue_ptr, CHAR *name_ptr, UINT message_size, +UINT _tx_queue_create(TX_QUEUE *queue_ptr, TX_NAME_CONST CHAR *name_ptr, UINT message_size, VOID *queue_start, ULONG queue_size); UINT _tx_queue_delete(TX_QUEUE *queue_ptr); UINT _tx_queue_flush(TX_QUEUE *queue_ptr); -UINT _tx_queue_info_get(TX_QUEUE *queue_ptr, CHAR **name, ULONG *enqueued, ULONG *available_storage, +UINT _tx_queue_info_get(TX_QUEUE *queue_ptr, TX_NAME_CONST CHAR **name, ULONG *enqueued, ULONG *available_storage, TX_THREAD **first_suspended, ULONG *suspended_count, TX_QUEUE **next_queue); UINT _tx_queue_performance_info_get(TX_QUEUE *queue_ptr, ULONG *messages_sent, ULONG *messages_received, ULONG *empty_suspensions, ULONG *full_suspensions, ULONG *full_errors, ULONG *timeouts); @@ -1612,11 +1625,11 @@ UINT _tx_queue_front_send(TX_QUEUE *queue_ptr, VOID *source_ptr, ULONG wa /* Define error checking shells for API services. These are only referenced by the application. */ -UINT _txe_queue_create(TX_QUEUE *queue_ptr, CHAR *name_ptr, UINT message_size, +UINT _txe_queue_create(TX_QUEUE *queue_ptr, TX_NAME_CONST CHAR *name_ptr, UINT message_size, VOID *queue_start, ULONG queue_size, UINT queue_control_block_size); UINT _txe_queue_delete(TX_QUEUE *queue_ptr); UINT _txe_queue_flush(TX_QUEUE *queue_ptr); -UINT _txe_queue_info_get(TX_QUEUE *queue_ptr, CHAR **name, ULONG *enqueued, ULONG *available_storage, +UINT _txe_queue_info_get(TX_QUEUE *queue_ptr, TX_NAME_CONST CHAR **name, ULONG *enqueued, ULONG *available_storage, TX_THREAD **first_suspended, ULONG *suspended_count, TX_QUEUE **next_queue); UINT _txe_queue_prioritize(TX_QUEUE *queue_ptr); UINT _txe_queue_receive(TX_QUEUE *queue_ptr, VOID *destination_ptr, ULONG wait_option); @@ -1624,11 +1637,11 @@ UINT _txe_queue_send(TX_QUEUE *queue_ptr, VOID *source_ptr, ULONG wait_op UINT _txe_queue_send_notify(TX_QUEUE *queue_ptr, VOID (*queue_send_notify)(TX_QUEUE *notify_queue_ptr)); UINT _txe_queue_front_send(TX_QUEUE *queue_ptr, VOID *source_ptr, ULONG wait_option); #ifdef TX_ENABLE_MULTI_ERROR_CHECKING -UINT _txr_queue_create(TX_QUEUE *queue_ptr, CHAR *name_ptr, UINT message_size, +UINT _txr_queue_create(TX_QUEUE *queue_ptr, TX_NAME_CONST CHAR *name_ptr, UINT message_size, VOID *queue_start, ULONG queue_size, UINT queue_control_block_size); UINT _txr_queue_delete(TX_QUEUE *queue_ptr); UINT _txr_queue_flush(TX_QUEUE *queue_ptr); -UINT _txr_queue_info_get(TX_QUEUE *queue_ptr, CHAR **name, ULONG *enqueued, ULONG *available_storage, +UINT _txr_queue_info_get(TX_QUEUE *queue_ptr, TX_NAME_CONST CHAR **name, ULONG *enqueued, ULONG *available_storage, TX_THREAD **first_suspended, ULONG *suspended_count, TX_QUEUE **next_queue); UINT _txr_queue_prioritize(TX_QUEUE *queue_ptr); UINT _txr_queue_receive(TX_QUEUE *queue_ptr, VOID *destination_ptr, ULONG wait_option); @@ -1641,10 +1654,10 @@ UINT _txr_queue_front_send(TX_QUEUE *queue_ptr, VOID *source_ptr, ULONG w /* Define semaphore management function prototypes. */ UINT _tx_semaphore_ceiling_put(TX_SEMAPHORE *semaphore_ptr, ULONG ceiling); -UINT _tx_semaphore_create(TX_SEMAPHORE *semaphore_ptr, CHAR *name_ptr, ULONG initial_count); +UINT _tx_semaphore_create(TX_SEMAPHORE *semaphore_ptr, TX_NAME_CONST CHAR *name_ptr, ULONG initial_count); UINT _tx_semaphore_delete(TX_SEMAPHORE *semaphore_ptr); UINT _tx_semaphore_get(TX_SEMAPHORE *semaphore_ptr, ULONG wait_option); -UINT _tx_semaphore_info_get(TX_SEMAPHORE *semaphore_ptr, CHAR **name, ULONG *current_value, +UINT _tx_semaphore_info_get(TX_SEMAPHORE *semaphore_ptr, TX_NAME_CONST CHAR **name, ULONG *current_value, TX_THREAD **first_suspended, ULONG *suspended_count, TX_SEMAPHORE **next_semaphore); UINT _tx_semaphore_performance_info_get(TX_SEMAPHORE *semaphore_ptr, ULONG *puts, ULONG *gets, @@ -1659,10 +1672,10 @@ UINT _tx_semaphore_put_notify(TX_SEMAPHORE *semaphore_ptr, VOID (*semapho application. */ UINT _txe_semaphore_ceiling_put(TX_SEMAPHORE *semaphore_ptr, ULONG ceiling); -UINT _txe_semaphore_create(TX_SEMAPHORE *semaphore_ptr, CHAR *name_ptr, ULONG initial_count, UINT semaphore_control_block_size); +UINT _txe_semaphore_create(TX_SEMAPHORE *semaphore_ptr, TX_NAME_CONST CHAR *name_ptr, ULONG initial_count, UINT semaphore_control_block_size); UINT _txe_semaphore_delete(TX_SEMAPHORE *semaphore_ptr); UINT _txe_semaphore_get(TX_SEMAPHORE *semaphore_ptr, ULONG wait_option); -UINT _txe_semaphore_info_get(TX_SEMAPHORE *semaphore_ptr, CHAR **name, ULONG *current_value, +UINT _txe_semaphore_info_get(TX_SEMAPHORE *semaphore_ptr, TX_NAME_CONST CHAR **name, ULONG *current_value, TX_THREAD **first_suspended, ULONG *suspended_count, TX_SEMAPHORE **next_semaphore); UINT _txe_semaphore_prioritize(TX_SEMAPHORE *semaphore_ptr); @@ -1670,10 +1683,10 @@ UINT _txe_semaphore_put(TX_SEMAPHORE *semaphore_ptr); UINT _txe_semaphore_put_notify(TX_SEMAPHORE *semaphore_ptr, VOID (*semaphore_put_notify)(TX_SEMAPHORE *notify_semaphore_ptr)); #ifdef TX_ENABLE_MULTI_ERROR_CHECKING UINT _txr_semaphore_ceiling_put(TX_SEMAPHORE *semaphore_ptr, ULONG ceiling); -UINT _txr_semaphore_create(TX_SEMAPHORE *semaphore_ptr, CHAR *name_ptr, ULONG initial_count, UINT semaphore_control_block_size); +UINT _txr_semaphore_create(TX_SEMAPHORE *semaphore_ptr, TX_NAME_CONST CHAR *name_ptr, ULONG initial_count, UINT semaphore_control_block_size); UINT _txr_semaphore_delete(TX_SEMAPHORE *semaphore_ptr); UINT _txr_semaphore_get(TX_SEMAPHORE *semaphore_ptr, ULONG wait_option); -UINT _txr_semaphore_info_get(TX_SEMAPHORE *semaphore_ptr, CHAR **name, ULONG *current_value, +UINT _txr_semaphore_info_get(TX_SEMAPHORE *semaphore_ptr, TX_NAME_CONST CHAR **name, ULONG *current_value, TX_THREAD **first_suspended, ULONG *suspended_count, TX_SEMAPHORE **next_semaphore); UINT _txr_semaphore_prioritize(TX_SEMAPHORE *semaphore_ptr); @@ -1686,7 +1699,7 @@ UINT _txr_semaphore_put_notify(TX_SEMAPHORE *semaphore_ptr, VOID (*semaph VOID _tx_thread_context_save(VOID); VOID _tx_thread_context_restore(VOID); -UINT _tx_thread_create(TX_THREAD *thread_ptr, CHAR *name_ptr, +UINT _tx_thread_create(TX_THREAD *thread_ptr, TX_NAME_CONST CHAR *name_ptr, VOID (*entry_function)(ULONG entry_input), ULONG entry_input, VOID *stack_start, ULONG stack_size, UINT priority, UINT preempt_threshold, @@ -1694,7 +1707,7 @@ UINT _tx_thread_create(TX_THREAD *thread_ptr, CHAR *name_ptr, UINT _tx_thread_delete(TX_THREAD *thread_ptr); UINT _tx_thread_entry_exit_notify(TX_THREAD *thread_ptr, VOID (*thread_entry_exit_notify)(TX_THREAD *notify_thread_ptr, UINT type)); TX_THREAD *_tx_thread_identify(VOID); -UINT _tx_thread_info_get(TX_THREAD *thread_ptr, CHAR **name, UINT *state, ULONG *run_count, +UINT _tx_thread_info_get(TX_THREAD *thread_ptr, TX_NAME_CONST CHAR **name, UINT *state, ULONG *run_count, UINT *priority, UINT *preemption_threshold, ULONG *time_slice, TX_THREAD **next_thread, TX_THREAD **next_suspended_thread); UINT _tx_thread_interrupt_control(UINT new_posture); @@ -1723,14 +1736,14 @@ UINT _tx_thread_wait_abort(TX_THREAD *thread_ptr); /* Define error checking shells for API services. These are only referenced by the application. */ -UINT _txe_thread_create(TX_THREAD *thread_ptr, CHAR *name_ptr, +UINT _txe_thread_create(TX_THREAD *thread_ptr, TX_NAME_CONST CHAR *name_ptr, VOID (*entry_function)(ULONG entry_input), ULONG entry_input, VOID *stack_start, ULONG stack_size, UINT priority, UINT preempt_threshold, ULONG time_slice, UINT auto_start, UINT thread_control_block_size); UINT _txe_thread_delete(TX_THREAD *thread_ptr); UINT _txe_thread_entry_exit_notify(TX_THREAD *thread_ptr, VOID (*thread_entry_exit_notify)(TX_THREAD *notify_thread_ptr, UINT type)); -UINT _txe_thread_info_get(TX_THREAD *thread_ptr, CHAR **name, UINT *state, ULONG *run_count, +UINT _txe_thread_info_get(TX_THREAD *thread_ptr, TX_NAME_CONST CHAR **name, UINT *state, ULONG *run_count, UINT *priority, UINT *preemption_threshold, ULONG *time_slice, TX_THREAD **next_thread, TX_THREAD **next_suspended_thread); UINT _txe_thread_preemption_change(TX_THREAD *thread_ptr, UINT new_threshold, @@ -1745,14 +1758,14 @@ UINT _txe_thread_terminate(TX_THREAD *thread_ptr); UINT _txe_thread_time_slice_change(TX_THREAD *thread_ptr, ULONG new_time_slice, ULONG *old_time_slice); UINT _txe_thread_wait_abort(TX_THREAD *thread_ptr); #ifdef TX_ENABLE_MULTI_ERROR_CHECKING -UINT _txr_thread_create(TX_THREAD *thread_ptr, CHAR *name_ptr, +UINT _txr_thread_create(TX_THREAD *thread_ptr, TX_NAME_CONST CHAR *name_ptr, VOID (*entry_function)(ULONG entry_input), ULONG entry_input, VOID *stack_start, ULONG stack_size, UINT priority, UINT preempt_threshold, ULONG time_slice, UINT auto_start, UINT thread_control_block_size); UINT _txr_thread_delete(TX_THREAD *thread_ptr); UINT _txr_thread_entry_exit_notify(TX_THREAD *thread_ptr, VOID (*thread_entry_exit_notify)(TX_THREAD *notify_thread_ptr, UINT type)); -UINT _txr_thread_info_get(TX_THREAD *thread_ptr, CHAR **name, UINT *state, ULONG *run_count, +UINT _txr_thread_info_get(TX_THREAD *thread_ptr, TX_NAME_CONST CHAR **name, UINT *state, ULONG *run_count, UINT *priority, UINT *preemption_threshold, ULONG *time_slice, TX_THREAD **next_thread, TX_THREAD **next_suspended_thread); UINT _txr_thread_preemption_change(TX_THREAD *thread_ptr, UINT new_threshold, @@ -1772,12 +1785,12 @@ UINT _txr_thread_wait_abort(TX_THREAD *thread_ptr); UINT _tx_timer_activate(TX_TIMER *timer_ptr); UINT _tx_timer_change(TX_TIMER *timer_ptr, ULONG initial_ticks, ULONG reschedule_ticks); -UINT _tx_timer_create(TX_TIMER *timer_ptr, CHAR *name_ptr, +UINT _tx_timer_create(TX_TIMER *timer_ptr, TX_NAME_CONST CHAR *name_ptr, VOID (*expiration_function)(ULONG input), ULONG expiration_input, ULONG initial_ticks, ULONG reschedule_ticks, UINT auto_activate); UINT _tx_timer_deactivate(TX_TIMER *timer_ptr); UINT _tx_timer_delete(TX_TIMER *timer_ptr); -UINT _tx_timer_info_get(TX_TIMER *timer_ptr, CHAR **name, UINT *active, ULONG *remaining_ticks, +UINT _tx_timer_info_get(TX_TIMER *timer_ptr, TX_NAME_CONST CHAR **name, UINT *active, ULONG *remaining_ticks, ULONG *reschedule_ticks, TX_TIMER **next_timer); UINT _tx_timer_performance_info_get(TX_TIMER *timer_ptr, ULONG *activates, ULONG *reactivates, ULONG *deactivates, ULONG *expirations, ULONG *expiration_adjusts); @@ -1793,22 +1806,22 @@ VOID _tx_time_set(ULONG new_time); UINT _txe_timer_activate(TX_TIMER *timer_ptr); UINT _txe_timer_change(TX_TIMER *timer_ptr, ULONG initial_ticks, ULONG reschedule_ticks); -UINT _txe_timer_create(TX_TIMER *timer_ptr, CHAR *name_ptr, +UINT _txe_timer_create(TX_TIMER *timer_ptr, TX_NAME_CONST CHAR *name_ptr, VOID (*expiration_function)(ULONG input), ULONG expiration_input, ULONG initial_ticks, ULONG reschedule_ticks, UINT auto_activate, UINT timer_control_block_size); UINT _txe_timer_deactivate(TX_TIMER *timer_ptr); UINT _txe_timer_delete(TX_TIMER *timer_ptr); -UINT _txe_timer_info_get(TX_TIMER *timer_ptr, CHAR **name, UINT *active, ULONG *remaining_ticks, +UINT _txe_timer_info_get(TX_TIMER *timer_ptr, TX_NAME_CONST CHAR **name, UINT *active, ULONG *remaining_ticks, ULONG *reschedule_ticks, TX_TIMER **next_timer); #ifdef TX_ENABLE_MULTI_ERROR_CHECKING UINT _txr_timer_activate(TX_TIMER *timer_ptr); UINT _txr_timer_change(TX_TIMER *timer_ptr, ULONG initial_ticks, ULONG reschedule_ticks); -UINT _txr_timer_create(TX_TIMER *timer_ptr, CHAR *name_ptr, +UINT _txr_timer_create(TX_TIMER *timer_ptr, TX_NAME_CONST CHAR *name_ptr, VOID (*expiration_function)(ULONG input), ULONG expiration_input, ULONG initial_ticks, ULONG reschedule_ticks, UINT auto_activate, UINT timer_control_block_size); UINT _txr_timer_deactivate(TX_TIMER *timer_ptr); UINT _txr_timer_delete(TX_TIMER *timer_ptr); -UINT _txr_timer_info_get(TX_TIMER *timer_ptr, CHAR **name, UINT *active, ULONG *remaining_ticks, +UINT _txr_timer_info_get(TX_TIMER *timer_ptr, TX_NAME_CONST CHAR **name, UINT *active, ULONG *remaining_ticks, ULONG *reschedule_ticks, TX_TIMER **next_timer); #endif @@ -1924,7 +1937,8 @@ TX_THREAD *_tx_misra_ulong_to_thread_pointer_convert(ULONG value); VOID *_tx_misra_timer_indirect_to_void_pointer_convert(TX_TIMER_INTERNAL **pointer); CHAR *_tx_misra_const_char_to_char_pointer_convert(const char *pointer); TX_THREAD *_tx_misra_void_to_thread_pointer_convert(VOID *pointer); -UCHAR *_tx_misra_char_to_uchar_pointer_convert(CHAR *pointer); +const UCHAR *_tx_misra_char_to_uchar_pointer_convert(TX_NAME_CONST CHAR *pointer); +const UCHAR *_tx_misra_const_uchar_pointer_add(const UCHAR *pointer, ULONG amount); VOID _tx_misra_event_flags_group_not_used(TX_EVENT_FLAGS_GROUP *group_ptr); VOID _tx_misra_event_flags_set_notify_not_used(VOID (*events_set_notify)(TX_EVENT_FLAGS_GROUP *notify_group_ptr)); VOID _tx_misra_queue_not_used(TX_QUEUE *queue_ptr); @@ -1936,6 +1950,7 @@ VOID _tx_misra_thread_entry_exit_notify_not_used(VOID (*threa #define TX_MEMSET(a,b,c) _tx_misra_memset((a), (UINT) (b), (UINT) (c)) #define TX_UCHAR_POINTER_ADD(a,b) _tx_misra_uchar_pointer_add((UCHAR *) (a), (ULONG) (b)) +#define TX_CONST_UCHAR_POINTER_ADD(a,b) _tx_misra_const_uchar_pointer_add((const UCHAR *) (a), (ULONG) (b)) #define TX_UCHAR_POINTER_SUB(a,b) _tx_misra_uchar_pointer_sub((UCHAR *) (a), (ULONG) (b)) #define TX_UCHAR_POINTER_DIF(a,b) _tx_misra_uchar_pointer_dif((UCHAR *) (a), (UCHAR *) (b)) #define TX_ULONG_POINTER_ADD(a,b) _tx_misra_ulong_pointer_add((ULONG *) (a), (ULONG) (b)) @@ -1996,6 +2011,7 @@ VOID _tx_misra_thread_entry_exit_notify_not_used(VOID (*threa #endif #define TX_UCHAR_POINTER_ADD(a,b) (((UCHAR *) (a)) + ((UINT) (b))) +#define TX_CONST_UCHAR_POINTER_ADD(a,b) (((const UCHAR *) (a)) + ((UINT) (b))) #define TX_UCHAR_POINTER_SUB(a,b) (((UCHAR *) (a)) - ((UINT) (b))) #define TX_UCHAR_POINTER_DIF(a,b) ((ULONG)(((UCHAR *) (a)) - ((UCHAR *) (b)))) #define TX_ULONG_POINTER_ADD(a,b) (((ULONG *) (a)) + ((UINT) (b))) @@ -2043,7 +2059,7 @@ VOID _tx_misra_thread_entry_exit_notify_not_used(VOID (*threa #endif #define TX_CONST_CHAR_TO_CHAR_POINTER_CONVERT(a) ((CHAR *) ((VOID *) (a))) #define TX_VOID_TO_THREAD_POINTER_CONVERT(a) ((TX_THREAD *) ((VOID *) (a))) -#define TX_CHAR_TO_UCHAR_POINTER_CONVERT(a) ((UCHAR *) ((VOID *) (a))) +#define TX_CHAR_TO_UCHAR_POINTER_CONVERT(a) ((const UCHAR *) ((const VOID *) (a))) #ifndef TX_EVENT_FLAGS_GROUP_NOT_USED #define TX_EVENT_FLAGS_GROUP_NOT_USED(a) ((void)(a)) #endif @@ -2341,4 +2357,3 @@ void __ghs_rnerr(char *errMsg, int stackLevels, int stackTraceDisplay, void *hex #endif #endif - diff --git a/common/inc/tx_trace.h b/common/inc/tx_trace.h index 10b96761e..8f2667cac 100644 --- a/common/inc/tx_trace.h +++ b/common/inc/tx_trace.h @@ -453,7 +453,7 @@ TRACE_DECLARE ULONG _tx_trace_registry_search_start #define TX_TRACE_INITIALIZE _tx_trace_initialize(); -#define TX_TRACE_OBJECT_REGISTER(t,p,n,a,b) _tx_trace_object_register((UCHAR) (t), (VOID *) (p), (CHAR *) (n), (ULONG) (a), (ULONG) (b)); +#define TX_TRACE_OBJECT_REGISTER(t,p,n,a,b) _tx_trace_object_register((UCHAR) (t), (VOID *) (p), (n), (ULONG) (a), (ULONG) (b)); #define TX_TRACE_OBJECT_UNREGISTER(o) _tx_trace_object_unregister((VOID *) (o)); #ifndef TX_TRACE_IN_LINE_INSERT #define TX_TRACE_IN_LINE_INSERT(i,a,b,c,d,e) \ @@ -529,7 +529,7 @@ UCHAR *_tx_misra_entry_to_uchar_pointer_convert(TX_TRACE_BUFFE /* Define internal function prototypes of the trace component, only if compiling ThreadX source code. */ VOID _tx_trace_initialize(VOID); -VOID _tx_trace_object_register(UCHAR object_type, VOID *object_ptr, CHAR *object_name, ULONG parameter_1, ULONG parameter_2); +VOID _tx_trace_object_register(UCHAR object_type, VOID *object_ptr, TX_NAME_CONST CHAR *object_name, ULONG parameter_1, ULONG parameter_2); VOID _tx_trace_object_unregister(VOID *object_ptr); diff --git a/common/inc/tx_user_sample.h b/common/inc/tx_user_sample.h index 0733c16c4..676ff38cd 100644 --- a/common/inc/tx_user_sample.h +++ b/common/inc/tx_user_sample.h @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -107,6 +109,12 @@ #define TX_TIMER_TICKS_PER_SECOND (100UL) */ +/* Define this option to qualify object names as pointers to const. */ + +/* +#define TX_ENABLE_CONST_NAMES +*/ + /* Determine if there is a FileX pointer in the thread control block. By default, the pointer is there for legacy/backwards compatibility. The pointer must also be there for applications using FileX. @@ -295,4 +303,3 @@ */ #endif - diff --git a/common/src/tx_block_pool_create.c b/common/src/tx_block_pool_create.c index 1d2c803cf..8781dc789 100644 --- a/common/src/tx_block_pool_create.c +++ b/common/src/tx_block_pool_create.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -66,7 +68,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _tx_block_pool_create(TX_BLOCK_POOL *pool_ptr, CHAR *name_ptr, ULONG block_size, +UINT _tx_block_pool_create(TX_BLOCK_POOL *pool_ptr, TX_NAME_CONST CHAR *name_ptr, ULONG block_size, VOID *pool_start, ULONG pool_size) { diff --git a/common/src/tx_block_pool_info_get.c b/common/src/tx_block_pool_info_get.c index 5998f1db4..5e1e89fdd 100644 --- a/common/src/tx_block_pool_info_get.c +++ b/common/src/tx_block_pool_info_get.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -69,7 +71,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _tx_block_pool_info_get(TX_BLOCK_POOL *pool_ptr, CHAR **name, ULONG *available_blocks, +UINT _tx_block_pool_info_get(TX_BLOCK_POOL *pool_ptr, TX_NAME_CONST CHAR **name, ULONG *available_blocks, ULONG *total_blocks, TX_THREAD **first_suspended, ULONG *suspended_count, TX_BLOCK_POOL **next_pool) { diff --git a/common/src/tx_byte_pool_create.c b/common/src/tx_byte_pool_create.c index 21abbe356..f5c8460dc 100644 --- a/common/src/tx_byte_pool_create.c +++ b/common/src/tx_byte_pool_create.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -65,7 +67,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _tx_byte_pool_create(TX_BYTE_POOL *pool_ptr, CHAR *name_ptr, VOID *pool_start, ULONG pool_size) +UINT _tx_byte_pool_create(TX_BYTE_POOL *pool_ptr, TX_NAME_CONST CHAR *name_ptr, VOID *pool_start, ULONG pool_size) { TX_INTERRUPT_SAVE_AREA diff --git a/common/src/tx_byte_pool_info_get.c b/common/src/tx_byte_pool_info_get.c index bd0964407..e9e9efa48 100644 --- a/common/src/tx_byte_pool_info_get.c +++ b/common/src/tx_byte_pool_info_get.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -69,7 +71,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _tx_byte_pool_info_get(TX_BYTE_POOL *pool_ptr, CHAR **name, ULONG *available_bytes, +UINT _tx_byte_pool_info_get(TX_BYTE_POOL *pool_ptr, TX_NAME_CONST CHAR **name, ULONG *available_bytes, ULONG *fragments, TX_THREAD **first_suspended, ULONG *suspended_count, TX_BYTE_POOL **next_pool) { diff --git a/common/src/tx_event_flags_create.c b/common/src/tx_event_flags_create.c index 2a9c042d6..361fafa44 100644 --- a/common/src/tx_event_flags_create.c +++ b/common/src/tx_event_flags_create.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -64,7 +66,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _tx_event_flags_create(TX_EVENT_FLAGS_GROUP *group_ptr, CHAR *name_ptr) +UINT _tx_event_flags_create(TX_EVENT_FLAGS_GROUP *group_ptr, TX_NAME_CONST CHAR *name_ptr) { TX_INTERRUPT_SAVE_AREA diff --git a/common/src/tx_event_flags_info_get.c b/common/src/tx_event_flags_info_get.c index 21e85c9a1..51ec345fa 100644 --- a/common/src/tx_event_flags_info_get.c +++ b/common/src/tx_event_flags_info_get.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -71,7 +73,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _tx_event_flags_info_get(TX_EVENT_FLAGS_GROUP *group_ptr, CHAR **name, ULONG *current_flags, +UINT _tx_event_flags_info_get(TX_EVENT_FLAGS_GROUP *group_ptr, TX_NAME_CONST CHAR **name, ULONG *current_flags, TX_THREAD **first_suspended, ULONG *suspended_count, TX_EVENT_FLAGS_GROUP **next_group) { diff --git a/common/src/tx_misra.c b/common/src/tx_misra.c index 9abf12f02..7ac5dc68c 100644 --- a/common/src/tx_misra.c +++ b/common/src/tx_misra.c @@ -820,15 +820,29 @@ UCHAR *_tx_misra_entry_to_uchar_pointer_convert(TX_TRACE_BUFFER_ENTRY *pointer) /***********************************************************************************************/ /***********************************************************************************************/ /** */ -/** UCHAR *_tx_misra_char_to_uchar_pointer_convert(CHAR *pointer); */ +/** const UCHAR *_tx_misra_char_to_uchar_pointer_convert(TX_NAME_CONST CHAR *pointer); */ /** */ /***********************************************************************************************/ /***********************************************************************************************/ -UCHAR *_tx_misra_char_to_uchar_pointer_convert(CHAR *pointer) +const UCHAR *_tx_misra_char_to_uchar_pointer_convert(TX_NAME_CONST CHAR *pointer) { /* Return a UCHAR pointer. */ - return((UCHAR *) ((VOID *) pointer)); + return((const UCHAR *) ((const VOID *) pointer)); +} + + +/***********************************************************************************************/ +/***********************************************************************************************/ +/** */ +/** const UCHAR *_tx_misra_const_uchar_pointer_add(const UCHAR *ptr, ULONG amount); */ +/** */ +/***********************************************************************************************/ +/***********************************************************************************************/ +const UCHAR *_tx_misra_const_uchar_pointer_add(const UCHAR *ptr, ULONG amount) +{ + ptr = ptr + amount; + return(ptr); } diff --git a/common/src/tx_mutex_create.c b/common/src/tx_mutex_create.c index 436c01f50..a1f5eba85 100644 --- a/common/src/tx_mutex_create.c +++ b/common/src/tx_mutex_create.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -65,7 +67,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _tx_mutex_create(TX_MUTEX *mutex_ptr, CHAR *name_ptr, UINT inherit) +UINT _tx_mutex_create(TX_MUTEX *mutex_ptr, TX_NAME_CONST CHAR *name_ptr, UINT inherit) { TX_INTERRUPT_SAVE_AREA diff --git a/common/src/tx_mutex_info_get.c b/common/src/tx_mutex_info_get.c index a24d1e30e..3be2606bb 100644 --- a/common/src/tx_mutex_info_get.c +++ b/common/src/tx_mutex_info_get.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -70,7 +72,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _tx_mutex_info_get(TX_MUTEX *mutex_ptr, CHAR **name, ULONG *count, TX_THREAD **owner, +UINT _tx_mutex_info_get(TX_MUTEX *mutex_ptr, TX_NAME_CONST CHAR **name, ULONG *count, TX_THREAD **owner, TX_THREAD **first_suspended, ULONG *suspended_count, TX_MUTEX **next_mutex) { diff --git a/common/src/tx_queue_create.c b/common/src/tx_queue_create.c index 59ae154e4..afb5648d5 100644 --- a/common/src/tx_queue_create.c +++ b/common/src/tx_queue_create.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -66,7 +68,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _tx_queue_create(TX_QUEUE *queue_ptr, CHAR *name_ptr, UINT message_size, +UINT _tx_queue_create(TX_QUEUE *queue_ptr, TX_NAME_CONST CHAR *name_ptr, UINT message_size, VOID *queue_start, ULONG queue_size) { diff --git a/common/src/tx_queue_info_get.c b/common/src/tx_queue_info_get.c index d0ecb2b65..e25da54ef 100644 --- a/common/src/tx_queue_info_get.c +++ b/common/src/tx_queue_info_get.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -69,7 +71,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _tx_queue_info_get(TX_QUEUE *queue_ptr, CHAR **name, ULONG *enqueued, ULONG *available_storage, +UINT _tx_queue_info_get(TX_QUEUE *queue_ptr, TX_NAME_CONST CHAR **name, ULONG *enqueued, ULONG *available_storage, TX_THREAD **first_suspended, ULONG *suspended_count, TX_QUEUE **next_queue) { diff --git a/common/src/tx_semaphore_create.c b/common/src/tx_semaphore_create.c index 849f5d3b5..14553ca8d 100644 --- a/common/src/tx_semaphore_create.c +++ b/common/src/tx_semaphore_create.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -64,7 +66,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _tx_semaphore_create(TX_SEMAPHORE *semaphore_ptr, CHAR *name_ptr, ULONG initial_count) +UINT _tx_semaphore_create(TX_SEMAPHORE *semaphore_ptr, TX_NAME_CONST CHAR *name_ptr, ULONG initial_count) { TX_INTERRUPT_SAVE_AREA diff --git a/common/src/tx_semaphore_info_get.c b/common/src/tx_semaphore_info_get.c index 89fd94238..2ffad1f7e 100644 --- a/common/src/tx_semaphore_info_get.c +++ b/common/src/tx_semaphore_info_get.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -69,7 +71,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _tx_semaphore_info_get(TX_SEMAPHORE *semaphore_ptr, CHAR **name, ULONG *current_value, +UINT _tx_semaphore_info_get(TX_SEMAPHORE *semaphore_ptr, TX_NAME_CONST CHAR **name, ULONG *current_value, TX_THREAD **first_suspended, ULONG *suspended_count, TX_SEMAPHORE **next_semaphore) { diff --git a/common/src/tx_thread_create.c b/common/src/tx_thread_create.c index 7c9d054c3..cff4db406 100644 --- a/common/src/tx_thread_create.c +++ b/common/src/tx_thread_create.c @@ -78,7 +78,7 @@ /* _tx_timer_initialize Create system timer thread */ /* */ /**************************************************************************/ -UINT _tx_thread_create(TX_THREAD *thread_ptr, CHAR *name_ptr, VOID (*entry_function)(ULONG id), ULONG entry_input, +UINT _tx_thread_create(TX_THREAD *thread_ptr, TX_NAME_CONST CHAR *name_ptr, VOID (*entry_function)(ULONG id), ULONG entry_input, VOID *stack_start, ULONG stack_size, UINT priority, UINT preempt_threshold, ULONG time_slice, UINT auto_start) { diff --git a/common/src/tx_thread_info_get.c b/common/src/tx_thread_info_get.c index 740a3b95d..cd0df6ec8 100644 --- a/common/src/tx_thread_info_get.c +++ b/common/src/tx_thread_info_get.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -72,7 +74,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _tx_thread_info_get(TX_THREAD *thread_ptr, CHAR **name, UINT *state, ULONG *run_count, +UINT _tx_thread_info_get(TX_THREAD *thread_ptr, TX_NAME_CONST CHAR **name, UINT *state, ULONG *run_count, UINT *priority, UINT *preemption_threshold, ULONG *time_slice, TX_THREAD **next_thread, TX_THREAD **next_suspended_thread) { diff --git a/common/src/tx_timer_create.c b/common/src/tx_timer_create.c index 30dd4e11f..15eb866f7 100644 --- a/common/src/tx_timer_create.c +++ b/common/src/tx_timer_create.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -67,7 +69,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _tx_timer_create(TX_TIMER *timer_ptr, CHAR *name_ptr, +UINT _tx_timer_create(TX_TIMER *timer_ptr, TX_NAME_CONST CHAR *name_ptr, VOID (*expiration_function)(ULONG id), ULONG expiration_input, ULONG initial_ticks, ULONG reschedule_ticks, UINT auto_activate) { diff --git a/common/src/tx_timer_info_get.c b/common/src/tx_timer_info_get.c index 31c801f9b..0811b5929 100644 --- a/common/src/tx_timer_info_get.c +++ b/common/src/tx_timer_info_get.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -68,7 +70,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _tx_timer_info_get(TX_TIMER *timer_ptr, CHAR **name, UINT *active, ULONG *remaining_ticks, +UINT _tx_timer_info_get(TX_TIMER *timer_ptr, TX_NAME_CONST CHAR **name, UINT *active, ULONG *remaining_ticks, ULONG *reschedule_ticks, TX_TIMER **next_timer) { diff --git a/common/src/tx_trace_object_register.c b/common/src/tx_trace_object_register.c index 741896a5a..a0d0f4949 100644 --- a/common/src/tx_trace_object_register.c +++ b/common/src/tx_trace_object_register.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -66,7 +68,7 @@ /* Application Code */ /* */ /**************************************************************************/ -VOID _tx_trace_object_register(UCHAR object_type, VOID *object_ptr, CHAR *object_name, ULONG parameter_1, ULONG parameter_2) +VOID _tx_trace_object_register(UCHAR object_type, VOID *object_ptr, TX_NAME_CONST CHAR *object_name, ULONG parameter_1, ULONG parameter_2) { #ifdef TX_ENABLE_EVENT_TRACE @@ -75,6 +77,7 @@ UINT i, entries; UINT found, loop_break; TX_THREAD *thread_ptr; UCHAR *work_ptr; +const UCHAR *name_ptr; TX_TRACE_OBJECT_ENTRY *entry_ptr; @@ -211,21 +214,21 @@ TX_TRACE_OBJECT_ENTRY *entry_ptr; for (i = ((ULONG) 0); i < (((ULONG) TX_TRACE_OBJECT_REGISTRY_NAME)-((ULONG) 1)); i++) { - /* Setup work pointer to the object name character. */ - work_ptr = TX_CHAR_TO_UCHAR_POINTER_CONVERT(object_name); - work_ptr = TX_UCHAR_POINTER_ADD(work_ptr, i); + /* Setup name pointer to the object name character. */ + name_ptr = TX_CHAR_TO_UCHAR_POINTER_CONVERT(object_name); + name_ptr = TX_CONST_UCHAR_POINTER_ADD(name_ptr, i); - /* Determine if object_name (work_ptr) is null. */ - if (work_ptr == TX_NULL) + /* Determine if object_name (name_ptr) is null. */ + if (name_ptr == TX_NULL) { break; } /* Copy a character of the name. */ - entry_ptr -> tx_trace_object_entry_name[i] = (UCHAR) *work_ptr; + entry_ptr -> tx_trace_object_entry_name[i] = (UCHAR) *name_ptr; /* Determine if we are at the end. */ - if (*work_ptr == ((UCHAR) 0)) + if (*name_ptr == ((UCHAR) 0)) { break; } diff --git a/common/src/txe_block_pool_create.c b/common/src/txe_block_pool_create.c index 08ef7e69d..b4c7e13fe 100644 --- a/common/src/txe_block_pool_create.c +++ b/common/src/txe_block_pool_create.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -74,7 +76,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _txe_block_pool_create(TX_BLOCK_POOL *pool_ptr, CHAR *name_ptr, ULONG block_size, +UINT _txe_block_pool_create(TX_BLOCK_POOL *pool_ptr, TX_NAME_CONST CHAR *name_ptr, ULONG block_size, VOID *pool_start, ULONG pool_size, UINT pool_control_block_size) { diff --git a/common/src/txe_block_pool_info_get.c b/common/src/txe_block_pool_info_get.c index f91ca2060..4c6003d75 100644 --- a/common/src/txe_block_pool_info_get.c +++ b/common/src/txe_block_pool_info_get.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -70,7 +72,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _txe_block_pool_info_get(TX_BLOCK_POOL *pool_ptr, CHAR **name, ULONG *available_blocks, +UINT _txe_block_pool_info_get(TX_BLOCK_POOL *pool_ptr, TX_NAME_CONST CHAR **name, ULONG *available_blocks, ULONG *total_blocks, TX_THREAD **first_suspended, ULONG *suspended_count, TX_BLOCK_POOL **next_pool) { diff --git a/common/src/txe_byte_pool_create.c b/common/src/txe_byte_pool_create.c index 99a896981..9ae72ee99 100644 --- a/common/src/txe_byte_pool_create.c +++ b/common/src/txe_byte_pool_create.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -73,7 +75,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _txe_byte_pool_create(TX_BYTE_POOL *pool_ptr, CHAR *name_ptr, VOID *pool_start, ULONG pool_size, UINT pool_control_block_size) +UINT _txe_byte_pool_create(TX_BYTE_POOL *pool_ptr, TX_NAME_CONST CHAR *name_ptr, VOID *pool_start, ULONG pool_size, UINT pool_control_block_size) { TX_INTERRUPT_SAVE_AREA diff --git a/common/src/txe_byte_pool_info_get.c b/common/src/txe_byte_pool_info_get.c index 85e7a233a..a83c907bc 100644 --- a/common/src/txe_byte_pool_info_get.c +++ b/common/src/txe_byte_pool_info_get.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -70,7 +72,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _txe_byte_pool_info_get(TX_BYTE_POOL *pool_ptr, CHAR **name, ULONG *available_bytes, +UINT _txe_byte_pool_info_get(TX_BYTE_POOL *pool_ptr, TX_NAME_CONST CHAR **name, ULONG *available_bytes, ULONG *fragments, TX_THREAD **first_suspended, ULONG *suspended_count, TX_BYTE_POOL **next_pool) { diff --git a/common/src/txe_event_flags_create.c b/common/src/txe_event_flags_create.c index 4e3fed773..209847381 100644 --- a/common/src/txe_event_flags_create.c +++ b/common/src/txe_event_flags_create.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -70,7 +72,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _txe_event_flags_create(TX_EVENT_FLAGS_GROUP *group_ptr, CHAR *name_ptr, UINT event_control_block_size) +UINT _txe_event_flags_create(TX_EVENT_FLAGS_GROUP *group_ptr, TX_NAME_CONST CHAR *name_ptr, UINT event_control_block_size) { TX_INTERRUPT_SAVE_AREA diff --git a/common/src/txe_event_flags_info_get.c b/common/src/txe_event_flags_info_get.c index e551d025c..d7bddca4e 100644 --- a/common/src/txe_event_flags_info_get.c +++ b/common/src/txe_event_flags_info_get.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -72,7 +74,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _txe_event_flags_info_get(TX_EVENT_FLAGS_GROUP *group_ptr, CHAR **name, ULONG *current_flags, +UINT _txe_event_flags_info_get(TX_EVENT_FLAGS_GROUP *group_ptr, TX_NAME_CONST CHAR **name, ULONG *current_flags, TX_THREAD **first_suspended, ULONG *suspended_count, TX_EVENT_FLAGS_GROUP **next_group) { diff --git a/common/src/txe_mutex_create.c b/common/src/txe_mutex_create.c index 392f8b0ed..a04612949 100644 --- a/common/src/txe_mutex_create.c +++ b/common/src/txe_mutex_create.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -71,7 +73,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _txe_mutex_create(TX_MUTEX *mutex_ptr, CHAR *name_ptr, UINT inherit, UINT mutex_control_block_size) +UINT _txe_mutex_create(TX_MUTEX *mutex_ptr, TX_NAME_CONST CHAR *name_ptr, UINT inherit, UINT mutex_control_block_size) { TX_INTERRUPT_SAVE_AREA diff --git a/common/src/txe_mutex_info_get.c b/common/src/txe_mutex_info_get.c index f4ef4168c..93b43f91a 100644 --- a/common/src/txe_mutex_info_get.c +++ b/common/src/txe_mutex_info_get.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -71,7 +73,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _txe_mutex_info_get(TX_MUTEX *mutex_ptr, CHAR **name, ULONG *count, TX_THREAD **owner, +UINT _txe_mutex_info_get(TX_MUTEX *mutex_ptr, TX_NAME_CONST CHAR **name, ULONG *count, TX_THREAD **owner, TX_THREAD **first_suspended, ULONG *suspended_count, TX_MUTEX **next_mutex) { diff --git a/common/src/txe_queue_create.c b/common/src/txe_queue_create.c index 185289fef..79aef4a07 100644 --- a/common/src/txe_queue_create.c +++ b/common/src/txe_queue_create.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -72,7 +74,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _txe_queue_create(TX_QUEUE *queue_ptr, CHAR *name_ptr, UINT message_size, +UINT _txe_queue_create(TX_QUEUE *queue_ptr, TX_NAME_CONST CHAR *name_ptr, UINT message_size, VOID *queue_start, ULONG queue_size, UINT queue_control_block_size) { diff --git a/common/src/txe_queue_info_get.c b/common/src/txe_queue_info_get.c index 78d983924..90fdd4108 100644 --- a/common/src/txe_queue_info_get.c +++ b/common/src/txe_queue_info_get.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -70,7 +72,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _txe_queue_info_get(TX_QUEUE *queue_ptr, CHAR **name, ULONG *enqueued, ULONG *available_storage, +UINT _txe_queue_info_get(TX_QUEUE *queue_ptr, TX_NAME_CONST CHAR **name, ULONG *enqueued, ULONG *available_storage, TX_THREAD **first_suspended, ULONG *suspended_count, TX_QUEUE **next_queue) { diff --git a/common/src/txe_semaphore_create.c b/common/src/txe_semaphore_create.c index a190b03c0..d538f5fe1 100644 --- a/common/src/txe_semaphore_create.c +++ b/common/src/txe_semaphore_create.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -70,7 +72,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _txe_semaphore_create(TX_SEMAPHORE *semaphore_ptr, CHAR *name_ptr, ULONG initial_count, UINT semaphore_control_block_size) +UINT _txe_semaphore_create(TX_SEMAPHORE *semaphore_ptr, TX_NAME_CONST CHAR *name_ptr, ULONG initial_count, UINT semaphore_control_block_size) { TX_INTERRUPT_SAVE_AREA diff --git a/common/src/txe_semaphore_info_get.c b/common/src/txe_semaphore_info_get.c index 7695028e4..85747dc32 100644 --- a/common/src/txe_semaphore_info_get.c +++ b/common/src/txe_semaphore_info_get.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -70,7 +72,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _txe_semaphore_info_get(TX_SEMAPHORE *semaphore_ptr, CHAR **name, ULONG *current_value, +UINT _txe_semaphore_info_get(TX_SEMAPHORE *semaphore_ptr, TX_NAME_CONST CHAR **name, ULONG *current_value, TX_THREAD **first_suspended, ULONG *suspended_count, TX_SEMAPHORE **next_semaphore) { diff --git a/common/src/txe_thread_create.c b/common/src/txe_thread_create.c index d319bc9e2..cc5033b29 100644 --- a/common/src/txe_thread_create.c +++ b/common/src/txe_thread_create.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -79,7 +81,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _txe_thread_create(TX_THREAD *thread_ptr, CHAR *name_ptr, +UINT _txe_thread_create(TX_THREAD *thread_ptr, TX_NAME_CONST CHAR *name_ptr, VOID (*entry_function)(ULONG id), ULONG entry_input, VOID *stack_start, ULONG stack_size, UINT priority, UINT preempt_threshold, diff --git a/common/src/txe_thread_info_get.c b/common/src/txe_thread_info_get.c index ad1db3f7f..19e248ebf 100644 --- a/common/src/txe_thread_info_get.c +++ b/common/src/txe_thread_info_get.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -74,7 +76,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _txe_thread_info_get(TX_THREAD *thread_ptr, CHAR **name, UINT *state, ULONG *run_count, +UINT _txe_thread_info_get(TX_THREAD *thread_ptr, TX_NAME_CONST CHAR **name, UINT *state, ULONG *run_count, UINT *priority, UINT *preemption_threshold, ULONG *time_slice, TX_THREAD **next_thread, TX_THREAD **next_suspended_thread) { diff --git a/common/src/txe_timer_create.c b/common/src/txe_timer_create.c index 02cf7c1aa..8c481bde8 100644 --- a/common/src/txe_timer_create.c +++ b/common/src/txe_timer_create.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -74,7 +76,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _txe_timer_create(TX_TIMER *timer_ptr, CHAR *name_ptr, +UINT _txe_timer_create(TX_TIMER *timer_ptr, TX_NAME_CONST CHAR *name_ptr, VOID (*expiration_function)(ULONG id), ULONG expiration_input, ULONG initial_ticks, ULONG reschedule_ticks, UINT auto_activate, UINT timer_control_block_size) { diff --git a/common/src/txe_timer_info_get.c b/common/src/txe_timer_info_get.c index 16ac5f64a..be2e9a13c 100644 --- a/common/src/txe_timer_info_get.c +++ b/common/src/txe_timer_info_get.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -69,7 +71,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _txe_timer_info_get(TX_TIMER *timer_ptr, CHAR **name, UINT *active, ULONG *remaining_ticks, +UINT _txe_timer_info_get(TX_TIMER *timer_ptr, TX_NAME_CONST CHAR **name, UINT *active, ULONG *remaining_ticks, ULONG *reschedule_ticks, TX_TIMER **next_timer) { diff --git a/common_modules/inc/txm_module.h b/common_modules/inc/txm_module.h index 4e84dcbb0..a823c2c05 100644 --- a/common_modules/inc/txm_module.h +++ b/common_modules/inc/txm_module.h @@ -624,7 +624,7 @@ UINT _txm_module_manager_memory_load(TXM_MODULE_INSTANCE *module_instance, CHAR UINT _txm_module_manager_properties_get(TXM_MODULE_INSTANCE *module_instance, ULONG *module_properties_ptr); UINT _txm_module_manager_start(TXM_MODULE_INSTANCE *module_instance); UINT _txm_module_manager_stop(TXM_MODULE_INSTANCE *module_instance); -UINT _txm_module_manager_thread_create(TX_THREAD *thread_ptr, CHAR *name, VOID (*shell_function)(TX_THREAD *, TXM_MODULE_INSTANCE *), +UINT _txm_module_manager_thread_create(TX_THREAD *thread_ptr, TX_NAME_CONST CHAR *name, VOID (*shell_function)(TX_THREAD *, TXM_MODULE_INSTANCE *), VOID (*entry_function)(ULONG), ULONG entry_input, VOID *stack_start, ULONG stack_size, UINT priority, UINT preempt_threshold, ULONG time_slice, UINT auto_start, UINT thread_control_block_size, TXM_MODULE_INSTANCE *module_instance); diff --git a/common_modules/module_lib/src/txm_block_pool_create.c b/common_modules/module_lib/src/txm_block_pool_create.c index 90838e3b1..aa9a61806 100644 --- a/common_modules/module_lib/src/txm_block_pool_create.c +++ b/common_modules/module_lib/src/txm_block_pool_create.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -64,7 +66,7 @@ /* Module application code */ /* */ /**************************************************************************/ -UINT _txe_block_pool_create(TX_BLOCK_POOL *pool_ptr, CHAR *name_ptr, ULONG block_size, VOID *pool_start, ULONG pool_size, UINT pool_control_block_size) +UINT _txe_block_pool_create(TX_BLOCK_POOL *pool_ptr, TX_NAME_CONST CHAR *name_ptr, ULONG block_size, VOID *pool_start, ULONG pool_size, UINT pool_control_block_size) { UINT return_value; diff --git a/common_modules/module_lib/src/txm_block_pool_info_get.c b/common_modules/module_lib/src/txm_block_pool_info_get.c index fa4ea6861..944281e34 100644 --- a/common_modules/module_lib/src/txm_block_pool_info_get.c +++ b/common_modules/module_lib/src/txm_block_pool_info_get.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -64,7 +66,7 @@ /* Module application code */ /* */ /**************************************************************************/ -UINT _txe_block_pool_info_get(TX_BLOCK_POOL *pool_ptr, CHAR **name, ULONG *available_blocks, ULONG *total_blocks, TX_THREAD **first_suspended, ULONG *suspended_count, TX_BLOCK_POOL **next_pool) +UINT _txe_block_pool_info_get(TX_BLOCK_POOL *pool_ptr, TX_NAME_CONST CHAR **name, ULONG *available_blocks, ULONG *total_blocks, TX_THREAD **first_suspended, ULONG *suspended_count, TX_BLOCK_POOL **next_pool) { UINT return_value; diff --git a/common_modules/module_lib/src/txm_byte_pool_create.c b/common_modules/module_lib/src/txm_byte_pool_create.c index d7775e3f1..d0cc76c6a 100644 --- a/common_modules/module_lib/src/txm_byte_pool_create.c +++ b/common_modules/module_lib/src/txm_byte_pool_create.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -63,7 +65,7 @@ /* Module application code */ /* */ /**************************************************************************/ -UINT _txe_byte_pool_create(TX_BYTE_POOL *pool_ptr, CHAR *name_ptr, VOID *pool_start, ULONG pool_size, UINT pool_control_block_size) +UINT _txe_byte_pool_create(TX_BYTE_POOL *pool_ptr, TX_NAME_CONST CHAR *name_ptr, VOID *pool_start, ULONG pool_size, UINT pool_control_block_size) { UINT return_value; diff --git a/common_modules/module_lib/src/txm_byte_pool_info_get.c b/common_modules/module_lib/src/txm_byte_pool_info_get.c index 1ad38f489..d6b4a3d6a 100644 --- a/common_modules/module_lib/src/txm_byte_pool_info_get.c +++ b/common_modules/module_lib/src/txm_byte_pool_info_get.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -64,7 +66,7 @@ /* Module application code */ /* */ /**************************************************************************/ -UINT _txe_byte_pool_info_get(TX_BYTE_POOL *pool_ptr, CHAR **name, ULONG *available_bytes, ULONG *fragments, TX_THREAD **first_suspended, ULONG *suspended_count, TX_BYTE_POOL **next_pool) +UINT _txe_byte_pool_info_get(TX_BYTE_POOL *pool_ptr, TX_NAME_CONST CHAR **name, ULONG *available_bytes, ULONG *fragments, TX_THREAD **first_suspended, ULONG *suspended_count, TX_BYTE_POOL **next_pool) { UINT return_value; diff --git a/common_modules/module_lib/src/txm_event_flags_create.c b/common_modules/module_lib/src/txm_event_flags_create.c index 76f1fe314..b4e155c1d 100644 --- a/common_modules/module_lib/src/txm_event_flags_create.c +++ b/common_modules/module_lib/src/txm_event_flags_create.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -60,7 +62,7 @@ /* Module application code */ /* */ /**************************************************************************/ -UINT _txe_event_flags_create(TX_EVENT_FLAGS_GROUP *group_ptr, CHAR *name_ptr, UINT event_control_block_size) +UINT _txe_event_flags_create(TX_EVENT_FLAGS_GROUP *group_ptr, TX_NAME_CONST CHAR *name_ptr, UINT event_control_block_size) { UINT return_value; diff --git a/common_modules/module_lib/src/txm_event_flags_info_get.c b/common_modules/module_lib/src/txm_event_flags_info_get.c index eedcce1f1..ebcee339d 100644 --- a/common_modules/module_lib/src/txm_event_flags_info_get.c +++ b/common_modules/module_lib/src/txm_event_flags_info_get.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -65,7 +67,7 @@ /* Module application code */ /* */ /**************************************************************************/ -UINT _txe_event_flags_info_get(TX_EVENT_FLAGS_GROUP *group_ptr, CHAR **name, ULONG *current_flags, TX_THREAD **first_suspended, ULONG *suspended_count, TX_EVENT_FLAGS_GROUP **next_group) +UINT _txe_event_flags_info_get(TX_EVENT_FLAGS_GROUP *group_ptr, TX_NAME_CONST CHAR **name, ULONG *current_flags, TX_THREAD **first_suspended, ULONG *suspended_count, TX_EVENT_FLAGS_GROUP **next_group) { UINT return_value; diff --git a/common_modules/module_lib/src/txm_mutex_create.c b/common_modules/module_lib/src/txm_mutex_create.c index f50fd52f2..5dc53dd9c 100644 --- a/common_modules/module_lib/src/txm_mutex_create.c +++ b/common_modules/module_lib/src/txm_mutex_create.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -61,7 +63,7 @@ /* Module application code */ /* */ /**************************************************************************/ -UINT _txe_mutex_create(TX_MUTEX *mutex_ptr, CHAR *name_ptr, UINT inherit, UINT mutex_control_block_size) +UINT _txe_mutex_create(TX_MUTEX *mutex_ptr, TX_NAME_CONST CHAR *name_ptr, UINT inherit, UINT mutex_control_block_size) { UINT return_value; diff --git a/common_modules/module_lib/src/txm_mutex_info_get.c b/common_modules/module_lib/src/txm_mutex_info_get.c index 8e63c779b..534e110ef 100644 --- a/common_modules/module_lib/src/txm_mutex_info_get.c +++ b/common_modules/module_lib/src/txm_mutex_info_get.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -65,7 +67,7 @@ /* Module application code */ /* */ /**************************************************************************/ -UINT _txe_mutex_info_get(TX_MUTEX *mutex_ptr, CHAR **name, ULONG *count, TX_THREAD **owner, TX_THREAD **first_suspended, ULONG *suspended_count, TX_MUTEX **next_mutex) +UINT _txe_mutex_info_get(TX_MUTEX *mutex_ptr, TX_NAME_CONST CHAR **name, ULONG *count, TX_THREAD **owner, TX_THREAD **first_suspended, ULONG *suspended_count, TX_MUTEX **next_mutex) { UINT return_value; diff --git a/common_modules/module_lib/src/txm_queue_create.c b/common_modules/module_lib/src/txm_queue_create.c index a18b9f85d..982c3587c 100644 --- a/common_modules/module_lib/src/txm_queue_create.c +++ b/common_modules/module_lib/src/txm_queue_create.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -62,7 +64,7 @@ /* Module application code */ /* */ /**************************************************************************/ -UINT _txe_queue_create(TX_QUEUE *queue_ptr, CHAR *name_ptr, UINT message_size, VOID *queue_start, ULONG queue_size, UINT queue_control_block_size) +UINT _txe_queue_create(TX_QUEUE *queue_ptr, TX_NAME_CONST CHAR *name_ptr, UINT message_size, VOID *queue_start, ULONG queue_size, UINT queue_control_block_size) { UINT return_value; diff --git a/common_modules/module_lib/src/txm_queue_info_get.c b/common_modules/module_lib/src/txm_queue_info_get.c index c66a3d7e0..8627a45aa 100644 --- a/common_modules/module_lib/src/txm_queue_info_get.c +++ b/common_modules/module_lib/src/txm_queue_info_get.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -64,7 +66,7 @@ /* Module application code */ /* */ /**************************************************************************/ -UINT _txe_queue_info_get(TX_QUEUE *queue_ptr, CHAR **name, ULONG *enqueued, ULONG *available_storage, TX_THREAD **first_suspended, ULONG *suspended_count, TX_QUEUE **next_queue) +UINT _txe_queue_info_get(TX_QUEUE *queue_ptr, TX_NAME_CONST CHAR **name, ULONG *enqueued, ULONG *available_storage, TX_THREAD **first_suspended, ULONG *suspended_count, TX_QUEUE **next_queue) { UINT return_value; diff --git a/common_modules/module_lib/src/txm_semaphore_create.c b/common_modules/module_lib/src/txm_semaphore_create.c index 229b46cd8..fbce2d54e 100644 --- a/common_modules/module_lib/src/txm_semaphore_create.c +++ b/common_modules/module_lib/src/txm_semaphore_create.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -60,7 +62,7 @@ /* Module application code */ /* */ /**************************************************************************/ -UINT _txe_semaphore_create(TX_SEMAPHORE *semaphore_ptr, CHAR *name_ptr, ULONG initial_count, UINT semaphore_control_block_size) +UINT _txe_semaphore_create(TX_SEMAPHORE *semaphore_ptr, TX_NAME_CONST CHAR *name_ptr, ULONG initial_count, UINT semaphore_control_block_size) { UINT return_value; diff --git a/common_modules/module_lib/src/txm_semaphore_info_get.c b/common_modules/module_lib/src/txm_semaphore_info_get.c index 2bdfa2c00..128afae7f 100644 --- a/common_modules/module_lib/src/txm_semaphore_info_get.c +++ b/common_modules/module_lib/src/txm_semaphore_info_get.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -64,7 +66,7 @@ /* Module application code */ /* */ /**************************************************************************/ -UINT _txe_semaphore_info_get(TX_SEMAPHORE *semaphore_ptr, CHAR **name, ULONG *current_value, TX_THREAD **first_suspended, ULONG *suspended_count, TX_SEMAPHORE **next_semaphore) +UINT _txe_semaphore_info_get(TX_SEMAPHORE *semaphore_ptr, TX_NAME_CONST CHAR **name, ULONG *current_value, TX_THREAD **first_suspended, ULONG *suspended_count, TX_SEMAPHORE **next_semaphore) { UINT return_value; diff --git a/common_modules/module_lib/src/txm_thread_create.c b/common_modules/module_lib/src/txm_thread_create.c index 8b1bc3677..f17a01859 100644 --- a/common_modules/module_lib/src/txm_thread_create.c +++ b/common_modules/module_lib/src/txm_thread_create.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -70,7 +72,7 @@ /* Module application code */ /* */ /**************************************************************************/ -UINT _txe_thread_create(TX_THREAD *thread_ptr, CHAR *name_ptr, VOID (*entry_function)(ULONG entry_input), ULONG entry_input, VOID *stack_start, ULONG stack_size, UINT priority, UINT preempt_threshold, ULONG time_slice, UINT auto_start, UINT thread_control_block_size) +UINT _txe_thread_create(TX_THREAD *thread_ptr, TX_NAME_CONST CHAR *name_ptr, VOID (*entry_function)(ULONG entry_input), ULONG entry_input, VOID *stack_start, ULONG stack_size, UINT priority, UINT preempt_threshold, ULONG time_slice, UINT auto_start, UINT thread_control_block_size) { UINT return_value; diff --git a/common_modules/module_lib/src/txm_thread_info_get.c b/common_modules/module_lib/src/txm_thread_info_get.c index d956c0319..e50fc4462 100644 --- a/common_modules/module_lib/src/txm_thread_info_get.c +++ b/common_modules/module_lib/src/txm_thread_info_get.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -67,7 +69,7 @@ /* Module application code */ /* */ /**************************************************************************/ -UINT _txe_thread_info_get(TX_THREAD *thread_ptr, CHAR **name, UINT *state, ULONG *run_count, UINT *priority, UINT *preemption_threshold, ULONG *time_slice, TX_THREAD **next_thread, TX_THREAD **next_suspended_thread) +UINT _txe_thread_info_get(TX_THREAD *thread_ptr, TX_NAME_CONST CHAR **name, UINT *state, ULONG *run_count, UINT *priority, UINT *preemption_threshold, ULONG *time_slice, TX_THREAD **next_thread, TX_THREAD **next_suspended_thread) { UINT return_value; diff --git a/common_modules/module_lib/src/txm_timer_create.c b/common_modules/module_lib/src/txm_timer_create.c index d65989ebd..7adba9010 100644 --- a/common_modules/module_lib/src/txm_timer_create.c +++ b/common_modules/module_lib/src/txm_timer_create.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -65,7 +67,7 @@ /* Module application code */ /* */ /**************************************************************************/ -UINT _txe_timer_create(TX_TIMER *timer_ptr, CHAR *name_ptr, VOID (*expiration_function)(ULONG), ULONG expiration_input, ULONG initial_ticks, ULONG reschedule_ticks, UINT auto_activate, UINT timer_control_block_size) +UINT _txe_timer_create(TX_TIMER *timer_ptr, TX_NAME_CONST CHAR *name_ptr, VOID (*expiration_function)(ULONG), ULONG expiration_input, ULONG initial_ticks, ULONG reschedule_ticks, UINT auto_activate, UINT timer_control_block_size) { UINT return_value; diff --git a/common_modules/module_lib/src/txm_timer_info_get.c b/common_modules/module_lib/src/txm_timer_info_get.c index f918ca67b..d431ed931 100644 --- a/common_modules/module_lib/src/txm_timer_info_get.c +++ b/common_modules/module_lib/src/txm_timer_info_get.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -63,7 +65,7 @@ /* Module application code */ /* */ /**************************************************************************/ -UINT _txe_timer_info_get(TX_TIMER *timer_ptr, CHAR **name, UINT *active, ULONG *remaining_ticks, ULONG *reschedule_ticks, TX_TIMER **next_timer) +UINT _txe_timer_info_get(TX_TIMER *timer_ptr, TX_NAME_CONST CHAR **name, UINT *active, ULONG *remaining_ticks, ULONG *reschedule_ticks, TX_TIMER **next_timer) { UINT return_value; diff --git a/common_modules/module_manager/inc/txm_module_manager_dispatch.h b/common_modules/module_manager/inc/txm_module_manager_dispatch.h index 9210c9893..e8c0629b5 100644 --- a/common_modules/module_manager/inc/txm_module_manager_dispatch.h +++ b/common_modules/module_manager/inc/txm_module_manager_dispatch.h @@ -54,7 +54,7 @@ ALIGN_TYPE return_value; #ifndef TXM_BLOCK_POOL_CREATE_CALL_NOT_USED /* UINT _txe_block_pool_create( TX_BLOCK_POOL *pool_ptr, -> param_0 - CHAR *name_ptr, -> param_1 + TX_NAME_CONST CHAR *name_ptr, -> param_1 ULONG block_size, -> extra_parameters[0] VOID *pool_start, -> extra_parameters[1] ULONG pool_size, -> extra_parameters[2] @@ -82,7 +82,7 @@ ALIGN_TYPE return_value; return_value = (ALIGN_TYPE) _txe_block_pool_create( (TX_BLOCK_POOL *) param_0, - (CHAR *) param_1, + (TX_NAME_CONST CHAR *) param_1, (ULONG) extra_parameters[0], (VOID *) extra_parameters[1], (ULONG) extra_parameters[2], @@ -126,7 +126,7 @@ ALIGN_TYPE return_value; #ifndef TXM_BLOCK_POOL_INFO_GET_CALL_NOT_USED /* UINT _txe_block_pool_info_get( TX_BLOCK_POOL *pool_ptr, -> param_0 - CHAR **name, -> param_1 + TX_NAME_CONST CHAR **name, -> param_1 ULONG *available_blocks, -> extra_parameters[0] ULONG *total_blocks, -> extra_parameters[1] TX_THREAD **first_suspended, -> extra_parameters[2] @@ -167,7 +167,7 @@ ALIGN_TYPE return_value; return_value = (ALIGN_TYPE) _txe_block_pool_info_get( (TX_BLOCK_POOL *) param_0, - (CHAR **) param_1, + (TX_NAME_CONST CHAR **) param_1, (ULONG *) extra_parameters[0], (ULONG *) extra_parameters[1], (TX_THREAD **) extra_parameters[2], @@ -363,7 +363,7 @@ ALIGN_TYPE return_value; #ifndef TXM_BYTE_POOL_CREATE_CALL_NOT_USED /* UINT _txe_byte_pool_create( TX_BYTE_POOL *pool_ptr, -> param_0 - CHAR *name_ptr, -> param_1 + TX_NAME_CONST CHAR *name_ptr, -> param_1 VOID *pool_start, -> extra_parameters[0] ULONG pool_size, -> extra_parameters[1] UINT pool_control_block_size -> extra_parameters[2] @@ -390,7 +390,7 @@ ALIGN_TYPE return_value; return_value = (ALIGN_TYPE) _txe_byte_pool_create( (TX_BYTE_POOL *) param_0, - (CHAR *) param_1, + (TX_NAME_CONST CHAR *) param_1, (VOID *) extra_parameters[0], (ULONG) extra_parameters[1], (UINT) extra_parameters[2] @@ -433,7 +433,7 @@ ALIGN_TYPE return_value; #ifndef TXM_BYTE_POOL_INFO_GET_CALL_NOT_USED /* UINT _txe_byte_pool_info_get( TX_BYTE_POOL *pool_ptr, -> param_0 - CHAR **name, -> param_1 + TX_NAME_CONST CHAR **name, -> param_1 ULONG *available_bytes, -> extra_parameters[0] ULONG *fragments, -> extra_parameters[1] TX_THREAD **first_suspended, -> extra_parameters[2] @@ -474,7 +474,7 @@ ALIGN_TYPE return_value; return_value = (ALIGN_TYPE) _txe_byte_pool_info_get( (TX_BYTE_POOL *) param_0, - (CHAR **) param_1, + (TX_NAME_CONST CHAR **) param_1, (ULONG *) extra_parameters[0], (ULONG *) extra_parameters[1], (TX_THREAD **) extra_parameters[2], @@ -666,7 +666,7 @@ ALIGN_TYPE block_header_start; #ifndef TXM_EVENT_FLAGS_CREATE_CALL_NOT_USED /* UINT _txe_event_flags_create( TX_EVENT_FLAGS_GROUP *group_ptr, -> param_0 - CHAR *name_ptr, -> param_1 + TX_NAME_CONST CHAR *name_ptr, -> param_1 UINT event_control_block_size -> param_2 ); */ static ALIGN_TYPE _txm_module_manager_tx_event_flags_create_dispatch(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE param_0, ALIGN_TYPE param_1, ALIGN_TYPE param_2) @@ -685,7 +685,7 @@ ALIGN_TYPE return_value; return_value = (ALIGN_TYPE) _txe_event_flags_create( (TX_EVENT_FLAGS_GROUP *) param_0, - (CHAR *) param_1, + (TX_NAME_CONST CHAR *) param_1, (UINT) param_2 ); return(return_value); @@ -762,7 +762,7 @@ ALIGN_TYPE return_value; #ifndef TXM_EVENT_FLAGS_INFO_GET_CALL_NOT_USED /* UINT _txe_event_flags_info_get( TX_EVENT_FLAGS_GROUP *group_ptr, -> param_0 - CHAR **name, -> param_1 + TX_NAME_CONST CHAR **name, -> param_1 ULONG *current_flags, -> extra_parameters[0] TX_THREAD **first_suspended, -> extra_parameters[1] ULONG *suspended_count, -> extra_parameters[2] @@ -799,7 +799,7 @@ ALIGN_TYPE return_value; return_value = (ALIGN_TYPE) _txe_event_flags_info_get( (TX_EVENT_FLAGS_GROUP *) param_0, - (CHAR **) param_1, + (TX_NAME_CONST CHAR **) param_1, (ULONG *) extra_parameters[0], (TX_THREAD **) extra_parameters[1], (ULONG *) extra_parameters[2], @@ -969,7 +969,7 @@ VOID (*events_set_notify)(TX_EVENT_FLAGS_GROUP *); #ifndef TXM_MUTEX_CREATE_CALL_NOT_USED /* UINT _txe_mutex_create( TX_MUTEX *mutex_ptr, -> param_0 - CHAR *name_ptr, -> param_1 + TX_NAME_CONST CHAR *name_ptr, -> param_1 UINT inherit, -> extra_parameters[0] UINT mutex_control_block_size -> extra_parameters[1] ); */ @@ -992,7 +992,7 @@ ALIGN_TYPE return_value; return_value = (ALIGN_TYPE) _txe_mutex_create( (TX_MUTEX *) param_0, - (CHAR *) param_1, + (TX_NAME_CONST CHAR *) param_1, (UINT) extra_parameters[0], (UINT) extra_parameters[1] ); @@ -1058,7 +1058,7 @@ ALIGN_TYPE return_value; #ifndef TXM_MUTEX_INFO_GET_CALL_NOT_USED /* UINT _txe_mutex_info_get( TX_MUTEX *mutex_ptr, -> param_0 - CHAR **name, -> param_1 + TX_NAME_CONST CHAR **name, -> param_1 ULONG *count, -> extra_parameters[0] TX_THREAD **owner, -> extra_parameters[1] TX_THREAD **first_suspended, -> extra_parameters[2] @@ -1099,7 +1099,7 @@ ALIGN_TYPE return_value; return_value = (ALIGN_TYPE) _txe_mutex_info_get( (TX_MUTEX *) param_0, - (CHAR **) param_1, + (TX_NAME_CONST CHAR **) param_1, (ULONG *) extra_parameters[0], (TX_THREAD **) extra_parameters[1], (TX_THREAD **) extra_parameters[2], @@ -1262,7 +1262,7 @@ ALIGN_TYPE return_value; #ifndef TXM_QUEUE_CREATE_CALL_NOT_USED /* UINT _txe_queue_create( TX_QUEUE *queue_ptr, -> param_0 - CHAR *name_ptr, -> param_1 + TX_NAME_CONST CHAR *name_ptr, -> param_1 UINT message_size, -> extra_parameters[0] VOID *queue_start, -> extra_parameters[1] ULONG queue_size, -> extra_parameters[2] @@ -1290,7 +1290,7 @@ ALIGN_TYPE return_value; return_value = (ALIGN_TYPE) _txe_queue_create( (TX_QUEUE *) param_0, - (CHAR *) param_1, + (TX_NAME_CONST CHAR *) param_1, (UINT) extra_parameters[0], (VOID *) extra_parameters[1], (ULONG) extra_parameters[2], @@ -1388,7 +1388,7 @@ TX_QUEUE *queue_ptr; #ifndef TXM_QUEUE_INFO_GET_CALL_NOT_USED /* UINT _txe_queue_info_get( TX_QUEUE *queue_ptr, -> param_0 - CHAR **name, -> param_1 + TX_NAME_CONST CHAR **name, -> param_1 ULONG *enqueued, -> extra_parameters[0] ULONG *available_storage, -> extra_parameters[1] TX_THREAD **first_suspended, -> extra_parameters[2] @@ -1429,7 +1429,7 @@ ALIGN_TYPE return_value; return_value = (ALIGN_TYPE) _txe_queue_info_get( (TX_QUEUE *) param_0, - (CHAR **) param_1, + (TX_NAME_CONST CHAR **) param_1, (ULONG *) extra_parameters[0], (ULONG *) extra_parameters[1], (TX_THREAD **) extra_parameters[2], @@ -1704,7 +1704,7 @@ ALIGN_TYPE return_value; #ifndef TXM_SEMAPHORE_CREATE_CALL_NOT_USED /* UINT _txe_semaphore_create( TX_SEMAPHORE *semaphore_ptr, -> param_0 - CHAR *name_ptr, -> param_1 + TX_NAME_CONST CHAR *name_ptr, -> param_1 ULONG initial_count, -> extra_parameters[0] UINT semaphore_control_block_size -> extra_parameters[1] ); */ @@ -1727,7 +1727,7 @@ ALIGN_TYPE return_value; return_value = (ALIGN_TYPE) _txe_semaphore_create( (TX_SEMAPHORE *) param_0, - (CHAR *) param_1, + (TX_NAME_CONST CHAR *) param_1, (ULONG) extra_parameters[0], (UINT) extra_parameters[1] ); @@ -1793,7 +1793,7 @@ ALIGN_TYPE return_value; #ifndef TXM_SEMAPHORE_INFO_GET_CALL_NOT_USED /* UINT _txe_semaphore_info_get( TX_SEMAPHORE *semaphore_ptr, -> param_0 - CHAR **name, -> param_1 + TX_NAME_CONST CHAR **name, -> param_1 ULONG *current_value, -> extra_parameters[0] TX_THREAD **first_suspended, -> extra_parameters[1] ULONG *suspended_count, -> extra_parameters[2] @@ -1830,7 +1830,7 @@ ALIGN_TYPE return_value; return_value = (ALIGN_TYPE) _txe_semaphore_info_get( (TX_SEMAPHORE *) param_0, - (CHAR **) param_1, + (TX_NAME_CONST CHAR **) param_1, (ULONG *) extra_parameters[0], (TX_THREAD **) extra_parameters[1], (ULONG *) extra_parameters[2], @@ -2018,7 +2018,7 @@ VOID (*semaphore_put_notify)(TX_SEMAPHORE *); #ifndef TXM_THREAD_CREATE_CALL_NOT_USED /* UINT _txe_thread_create( TX_THREAD *thread_ptr, -> param_0 - CHAR *name_ptr, -> param_1 + TX_NAME_CONST CHAR *name_ptr, -> param_1 VOID (*entry_function)(ULONG entry_input), -> extra_parameters[0] ULONG entry_input, -> extra_parameters[1] VOID *stack_start, -> extra_parameters[2] @@ -2057,7 +2057,7 @@ ALIGN_TYPE return_value; return_value = (ALIGN_TYPE) _txm_module_manager_thread_create( (TX_THREAD *) param_0, - (CHAR *) param_1, + (TX_NAME_CONST CHAR *) param_1, module_instance -> txm_module_instance_shell_entry_function, (VOID (*)(ULONG entry_input)) extra_parameters[0], (ULONG) extra_parameters[1], @@ -2194,7 +2194,7 @@ ALIGN_TYPE return_value; #ifndef TXM_THREAD_INFO_GET_CALL_NOT_USED /* UINT _txe_thread_info_get( TX_THREAD *thread_ptr, -> param_0 - CHAR **name, -> param_1 + TX_NAME_CONST CHAR **name, -> param_1 UINT *state, -> extra_parameters[0] ULONG *run_count, -> extra_parameters[1] UINT *priority, -> extra_parameters[2] @@ -2243,7 +2243,7 @@ ALIGN_TYPE return_value; return_value = (ALIGN_TYPE) _txe_thread_info_get( (TX_THREAD *) param_0, - (CHAR **) param_1, + (TX_NAME_CONST CHAR **) param_1, (UINT *) extra_parameters[0], (ULONG *) extra_parameters[1], (UINT *) extra_parameters[2], @@ -2811,7 +2811,7 @@ ALIGN_TYPE return_value; #ifndef TXM_TIMER_CREATE_CALL_NOT_USED /* UINT _txe_timer_create( TX_TIMER *timer_ptr, -> param_0 - CHAR *name_ptr, -> param_1 + TX_NAME_CONST CHAR *name_ptr, -> param_1 VOID (*expiration_function)(ULONG), -> extra_parameters[0] ULONG expiration_input, -> extra_parameters[1] ULONG initial_ticks, -> extra_parameters[2] @@ -2854,7 +2854,7 @@ VOID (*expiration_function)(ULONG); return_value = (ALIGN_TYPE) _txe_timer_create( (TX_TIMER *) param_0, - (CHAR *) param_1, + (TX_NAME_CONST CHAR *) param_1, (VOID (*)(ULONG)) expiration_function, (ULONG) extra_parameters[1], (ULONG) extra_parameters[2], @@ -2937,7 +2937,7 @@ ALIGN_TYPE return_value; #ifndef TXM_TIMER_INFO_GET_CALL_NOT_USED /* UINT _txe_timer_info_get( TX_TIMER *timer_ptr, -> param_0 - CHAR **name, -> param_1 + TX_NAME_CONST CHAR **name, -> param_1 UINT *active, -> extra_parameters[0] ULONG *remaining_ticks, -> extra_parameters[1] ULONG *reschedule_ticks, -> extra_parameters[2] @@ -2974,7 +2974,7 @@ ALIGN_TYPE return_value; return_value = (ALIGN_TYPE) _txe_timer_info_get( (TX_TIMER *) param_0, - (CHAR **) param_1, + (TX_NAME_CONST CHAR **) param_1, (UINT *) extra_parameters[0], (ULONG *) extra_parameters[1], (ULONG *) extra_parameters[2], diff --git a/common_modules/module_manager/inc/txm_module_manager_util.h b/common_modules/module_manager/inc/txm_module_manager_util.h index 6b9e5b762..3583edcc6 100644 --- a/common_modules/module_manager/inc/txm_module_manager_util.h +++ b/common_modules/module_manager/inc/txm_module_manager_util.h @@ -186,7 +186,7 @@ UINT _txm_module_manager_object_memory_check(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE object_ptr, ULONG object_size); UINT _txm_module_manager_object_size_check(ALIGN_TYPE object_ptr, ULONG object_size); -UINT _txm_module_manager_object_name_compare(CHAR *object_name1, UINT object_name1_length, CHAR *object_name2); +UINT _txm_module_manager_object_name_compare(CHAR *object_name1, UINT object_name1_length, TX_NAME_CONST CHAR *object_name2); UCHAR _txm_module_manager_created_object_check(TXM_MODULE_INSTANCE *module_instance, void *object_ptr); UINT _txm_module_manager_param_check_object_for_creation(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE object_ptr, ULONG object_size); UINT _txm_module_manager_param_check_object_for_use(TXM_MODULE_INSTANCE *module_instance, ALIGN_TYPE object_ptr, ULONG object_size); diff --git a/common_modules/module_manager/src/txm_module_manager_thread_create.c b/common_modules/module_manager/src/txm_module_manager_thread_create.c index 276f3c16d..51b85e1b4 100644 --- a/common_modules/module_manager/src/txm_module_manager_thread_create.c +++ b/common_modules/module_manager/src/txm_module_manager_thread_create.c @@ -84,7 +84,7 @@ /* _txm_module_manager_kernel_dispatch Kernel dispatch function */ /* */ /**************************************************************************/ -UINT _txm_module_manager_thread_create(TX_THREAD *thread_ptr, CHAR *name_ptr, +UINT _txm_module_manager_thread_create(TX_THREAD *thread_ptr, TX_NAME_CONST CHAR *name_ptr, VOID (*shell_function)(TX_THREAD *, TXM_MODULE_INSTANCE *), VOID (*entry_function)(ULONG id), ULONG entry_input, VOID *stack_start, ULONG stack_size, UINT priority, UINT preempt_threshold, @@ -768,4 +768,3 @@ ULONG i; /* Return success. */ return(TX_SUCCESS); } - diff --git a/common_modules/module_manager/src/txm_module_manager_util.c b/common_modules/module_manager/src/txm_module_manager_util.c index 93516ab22..f3c8beefd 100644 --- a/common_modules/module_manager/src/txm_module_manager_util.c +++ b/common_modules/module_manager/src/txm_module_manager_util.c @@ -281,7 +281,7 @@ UINT return_value; /* 09-30-2020 Scott Larson Initial Version 6.1 */ /* */ /**************************************************************************/ -UINT _txm_module_manager_object_name_compare(CHAR *search_name, UINT search_name_length, CHAR *object_name) +UINT _txm_module_manager_object_name_compare(CHAR *search_name, UINT search_name_length, TX_NAME_CONST CHAR *object_name) { CHAR search_name_char; diff --git a/common_smp/inc/tx_api.h b/common_smp/inc/tx_api.h index 679bfe679..77bd6218b 100644 --- a/common_smp/inc/tx_api.h +++ b/common_smp/inc/tx_api.h @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -64,6 +66,17 @@ extern "C" { #include "tx_port.h" +/* Define the qualifier applied to object name strings. Opting in makes every + object name a pointer to const, which the kernel and its tests are written + for. It is off by default because it changes the type of a public struct + field, and application code that copies a name into a writable pointer stops + compiling. */ +#ifdef TX_ENABLE_CONST_NAMES +#define TX_NAME_CONST const +#else +#define TX_NAME_CONST +#endif + /* If not defined by tx_port.h, default the port-specific memory synchronization macro to whitespace. */ @@ -392,7 +405,7 @@ typedef struct TX_TIMER_STRUCT ULONG tx_timer_id; /* Define the timer's name. */ - CHAR *tx_timer_name; + TX_NAME_CONST CHAR *tx_timer_name; /* Define the actual contents of the timer. This is the block that is used in the actual timer expiration processing. */ @@ -466,7 +479,7 @@ typedef struct TX_THREAD_STRUCT is typically defined to whitespace or a pointer type in tx_port.h. */ TX_THREAD_EXTENSION_0 - CHAR *tx_thread_name; /* Pointer to thread's name */ + TX_NAME_CONST CHAR *tx_thread_name; /* Pointer to thread's name */ UINT tx_thread_priority; /* Priority of thread (0-1023) */ UINT tx_thread_state; /* Thread's execution state */ UINT tx_thread_delayed_suspend; /* Delayed suspend flag */ @@ -632,7 +645,7 @@ typedef struct TX_BLOCK_POOL_STRUCT ULONG tx_block_pool_id; /* Define the block pool's name. */ - CHAR *tx_block_pool_name; + TX_NAME_CONST CHAR *tx_block_pool_name; /* Define the number of available memory blocks in the pool. */ UINT tx_block_pool_available; @@ -710,7 +723,7 @@ typedef struct TX_BYTE_POOL_STRUCT ULONG tx_byte_pool_id; /* Define the byte pool's name. */ - CHAR *tx_byte_pool_name; + TX_NAME_CONST CHAR *tx_byte_pool_name; /* Define the number of available bytes in the pool. */ ULONG tx_byte_pool_available; @@ -789,7 +802,7 @@ typedef struct TX_EVENT_FLAGS_GROUP_STRUCT ULONG tx_event_flags_group_id; /* Define the event flags group's name. */ - CHAR *tx_event_flags_group_name; + TX_NAME_CONST CHAR *tx_event_flags_group_name; /* Define the actual current event flags in this group. A zero in a particular bit indicates the event flag is not set. */ @@ -875,7 +888,7 @@ typedef struct TX_MUTEX_STRUCT ULONG tx_mutex_id; /* Define the mutex's name. */ - CHAR *tx_mutex_name; + TX_NAME_CONST CHAR *tx_mutex_name; /* Define the mutex ownership count. */ UINT tx_mutex_ownership_count; @@ -948,7 +961,7 @@ typedef struct TX_QUEUE_STRUCT ULONG tx_queue_id; /* Define the queue's name. */ - CHAR *tx_queue_name; + TX_NAME_CONST CHAR *tx_queue_name; /* Define the message size that was specified in queue creation. */ UINT tx_queue_message_size; @@ -1027,7 +1040,7 @@ typedef struct TX_SEMAPHORE_STRUCT ULONG tx_semaphore_id; /* Define the semaphore's name. */ - CHAR *tx_semaphore_name; + TX_NAME_CONST CHAR *tx_semaphore_name; /* Define the actual semaphore count. A zero means that no semaphore instance is available. */ @@ -1530,10 +1543,10 @@ VOID tx_application_define(VOID *first_unused_memory); /* Define block memory pool management function prototypes. */ UINT _tx_block_allocate(TX_BLOCK_POOL *pool_ptr, VOID **block_ptr, ULONG wait_option); -UINT _tx_block_pool_create(TX_BLOCK_POOL *pool_ptr, CHAR *name_ptr, ULONG block_size, +UINT _tx_block_pool_create(TX_BLOCK_POOL *pool_ptr, TX_NAME_CONST CHAR *name_ptr, ULONG block_size, VOID *pool_start, ULONG pool_size); UINT _tx_block_pool_delete(TX_BLOCK_POOL *pool_ptr); -UINT _tx_block_pool_info_get(TX_BLOCK_POOL *pool_ptr, CHAR **name, ULONG *available_blocks, +UINT _tx_block_pool_info_get(TX_BLOCK_POOL *pool_ptr, TX_NAME_CONST CHAR **name, ULONG *available_blocks, ULONG *total_blocks, TX_THREAD **first_suspended, ULONG *suspended_count, TX_BLOCK_POOL **next_pool); UINT _tx_block_pool_performance_info_get(TX_BLOCK_POOL *pool_ptr, ULONG *allocates, ULONG *releases, @@ -1548,10 +1561,10 @@ UINT _tx_block_release(VOID *block_ptr); application. */ UINT _txe_block_allocate(TX_BLOCK_POOL *pool_ptr, VOID **block_ptr, ULONG wait_option); -UINT _txe_block_pool_create(TX_BLOCK_POOL *pool_ptr, CHAR *name_ptr, ULONG block_size, +UINT _txe_block_pool_create(TX_BLOCK_POOL *pool_ptr, TX_NAME_CONST CHAR *name_ptr, ULONG block_size, VOID *pool_start, ULONG pool_size, UINT pool_control_block_size); UINT _txe_block_pool_delete(TX_BLOCK_POOL *pool_ptr); -UINT _txe_block_pool_info_get(TX_BLOCK_POOL *pool_ptr, CHAR **name, ULONG *available_blocks, +UINT _txe_block_pool_info_get(TX_BLOCK_POOL *pool_ptr, TX_NAME_CONST CHAR **name, ULONG *available_blocks, ULONG *total_blocks, TX_THREAD **first_suspended, ULONG *suspended_count, TX_BLOCK_POOL **next_pool); UINT _txe_block_pool_prioritize(TX_BLOCK_POOL *pool_ptr); @@ -1562,10 +1575,10 @@ UINT _txe_block_release(VOID *block_ptr); UINT _tx_byte_allocate(TX_BYTE_POOL *pool_ptr, VOID **memory_ptr, ULONG memory_size, ULONG wait_option); -UINT _tx_byte_pool_create(TX_BYTE_POOL *pool_ptr, CHAR *name_ptr, VOID *pool_start, +UINT _tx_byte_pool_create(TX_BYTE_POOL *pool_ptr, TX_NAME_CONST CHAR *name_ptr, VOID *pool_start, ULONG pool_size); UINT _tx_byte_pool_delete(TX_BYTE_POOL *pool_ptr); -UINT _tx_byte_pool_info_get(TX_BYTE_POOL *pool_ptr, CHAR **name, ULONG *available_bytes, +UINT _tx_byte_pool_info_get(TX_BYTE_POOL *pool_ptr, TX_NAME_CONST CHAR **name, ULONG *available_bytes, ULONG *fragments, TX_THREAD **first_suspended, ULONG *suspended_count, TX_BYTE_POOL **next_pool); UINT _tx_byte_pool_performance_info_get(TX_BYTE_POOL *pool_ptr, ULONG *allocates, ULONG *releases, @@ -1581,10 +1594,10 @@ UINT _tx_byte_release(VOID *memory_ptr); UINT _txe_byte_allocate(TX_BYTE_POOL *pool_ptr, VOID **memory_ptr, ULONG memory_size, ULONG wait_option); -UINT _txe_byte_pool_create(TX_BYTE_POOL *pool_ptr, CHAR *name_ptr, VOID *pool_start, +UINT _txe_byte_pool_create(TX_BYTE_POOL *pool_ptr, TX_NAME_CONST CHAR *name_ptr, VOID *pool_start, ULONG pool_size, UINT pool_control_block_size); UINT _txe_byte_pool_delete(TX_BYTE_POOL *pool_ptr); -UINT _txe_byte_pool_info_get(TX_BYTE_POOL *pool_ptr, CHAR **name, ULONG *available_bytes, +UINT _txe_byte_pool_info_get(TX_BYTE_POOL *pool_ptr, TX_NAME_CONST CHAR **name, ULONG *available_bytes, ULONG *fragments, TX_THREAD **first_suspended, ULONG *suspended_count, TX_BYTE_POOL **next_pool); UINT _txe_byte_pool_prioritize(TX_BYTE_POOL *pool_ptr); @@ -1593,11 +1606,11 @@ UINT _txe_byte_release(VOID *memory_ptr); /* Define event flags management function prototypes. */ -UINT _tx_event_flags_create(TX_EVENT_FLAGS_GROUP *group_ptr, CHAR *name_ptr); +UINT _tx_event_flags_create(TX_EVENT_FLAGS_GROUP *group_ptr, TX_NAME_CONST CHAR *name_ptr); UINT _tx_event_flags_delete(TX_EVENT_FLAGS_GROUP *group_ptr); UINT _tx_event_flags_get(TX_EVENT_FLAGS_GROUP *group_ptr, ULONG requested_flags, UINT get_option, ULONG *actual_flags_ptr, ULONG wait_option); -UINT _tx_event_flags_info_get(TX_EVENT_FLAGS_GROUP *group_ptr, CHAR **name, ULONG *current_flags, +UINT _tx_event_flags_info_get(TX_EVENT_FLAGS_GROUP *group_ptr, TX_NAME_CONST CHAR **name, ULONG *current_flags, TX_THREAD **first_suspended, ULONG *suspended_count, TX_EVENT_FLAGS_GROUP **next_group); UINT _tx_event_flags_performance_info_get(TX_EVENT_FLAGS_GROUP *group_ptr, ULONG *sets, ULONG *gets, @@ -1612,11 +1625,11 @@ UINT _tx_event_flags_set_notify(TX_EVENT_FLAGS_GROUP *group_ptr, VOID (*e /* Define error checking shells for API services. These are only referenced by the application. */ -UINT _txe_event_flags_create(TX_EVENT_FLAGS_GROUP *group_ptr, CHAR *name_ptr, UINT event_control_block_size); +UINT _txe_event_flags_create(TX_EVENT_FLAGS_GROUP *group_ptr, TX_NAME_CONST CHAR *name_ptr, UINT event_control_block_size); UINT _txe_event_flags_delete(TX_EVENT_FLAGS_GROUP *group_ptr); UINT _txe_event_flags_get(TX_EVENT_FLAGS_GROUP *group_ptr, ULONG requested_flags, UINT get_option, ULONG *actual_flags_ptr, ULONG wait_option); -UINT _txe_event_flags_info_get(TX_EVENT_FLAGS_GROUP *group_ptr, CHAR **name, ULONG *current_flags, +UINT _txe_event_flags_info_get(TX_EVENT_FLAGS_GROUP *group_ptr, TX_NAME_CONST CHAR **name, ULONG *current_flags, TX_THREAD **first_suspended, ULONG *suspended_count, TX_EVENT_FLAGS_GROUP **next_group); UINT _txe_event_flags_set(TX_EVENT_FLAGS_GROUP *group_ptr, ULONG flags_to_set, @@ -1631,10 +1644,10 @@ VOID _tx_initialize_kernel_enter(VOID); /* Define mutex management function prototypes. */ -UINT _tx_mutex_create(TX_MUTEX *mutex_ptr, CHAR *name_ptr, UINT inherit); +UINT _tx_mutex_create(TX_MUTEX *mutex_ptr, TX_NAME_CONST CHAR *name_ptr, UINT inherit); UINT _tx_mutex_delete(TX_MUTEX *mutex_ptr); UINT _tx_mutex_get(TX_MUTEX *mutex_ptr, ULONG wait_option); -UINT _tx_mutex_info_get(TX_MUTEX *mutex_ptr, CHAR **name, ULONG *count, TX_THREAD **owner, +UINT _tx_mutex_info_get(TX_MUTEX *mutex_ptr, TX_NAME_CONST CHAR **name, ULONG *count, TX_THREAD **owner, TX_THREAD **first_suspended, ULONG *suspended_count, TX_MUTEX **next_mutex); UINT _tx_mutex_performance_info_get(TX_MUTEX *mutex_ptr, ULONG *puts, ULONG *gets, @@ -1648,10 +1661,10 @@ UINT _tx_mutex_put(TX_MUTEX *mutex_ptr); /* Define error checking shells for API services. These are only referenced by the application. */ -UINT _txe_mutex_create(TX_MUTEX *mutex_ptr, CHAR *name_ptr, UINT inherit, UINT mutex_control_block_size); +UINT _txe_mutex_create(TX_MUTEX *mutex_ptr, TX_NAME_CONST CHAR *name_ptr, UINT inherit, UINT mutex_control_block_size); UINT _txe_mutex_delete(TX_MUTEX *mutex_ptr); UINT _txe_mutex_get(TX_MUTEX *mutex_ptr, ULONG wait_option); -UINT _txe_mutex_info_get(TX_MUTEX *mutex_ptr, CHAR **name, ULONG *count, TX_THREAD **owner, +UINT _txe_mutex_info_get(TX_MUTEX *mutex_ptr, TX_NAME_CONST CHAR **name, ULONG *count, TX_THREAD **owner, TX_THREAD **first_suspended, ULONG *suspended_count, TX_MUTEX **next_mutex); UINT _txe_mutex_prioritize(TX_MUTEX *mutex_ptr); @@ -1660,11 +1673,11 @@ UINT _txe_mutex_put(TX_MUTEX *mutex_ptr); /* Define queue management function prototypes. */ -UINT _tx_queue_create(TX_QUEUE *queue_ptr, CHAR *name_ptr, UINT message_size, +UINT _tx_queue_create(TX_QUEUE *queue_ptr, TX_NAME_CONST CHAR *name_ptr, UINT message_size, VOID *queue_start, ULONG queue_size); UINT _tx_queue_delete(TX_QUEUE *queue_ptr); UINT _tx_queue_flush(TX_QUEUE *queue_ptr); -UINT _tx_queue_info_get(TX_QUEUE *queue_ptr, CHAR **name, ULONG *enqueued, ULONG *available_storage, +UINT _tx_queue_info_get(TX_QUEUE *queue_ptr, TX_NAME_CONST CHAR **name, ULONG *enqueued, ULONG *available_storage, TX_THREAD **first_suspended, ULONG *suspended_count, TX_QUEUE **next_queue); UINT _tx_queue_performance_info_get(TX_QUEUE *queue_ptr, ULONG *messages_sent, ULONG *messages_received, ULONG *empty_suspensions, ULONG *full_suspensions, ULONG *full_errors, ULONG *timeouts); @@ -1680,11 +1693,11 @@ UINT _tx_queue_front_send(TX_QUEUE *queue_ptr, VOID *source_ptr, ULONG wa /* Define error checking shells for API services. These are only referenced by the application. */ -UINT _txe_queue_create(TX_QUEUE *queue_ptr, CHAR *name_ptr, UINT message_size, +UINT _txe_queue_create(TX_QUEUE *queue_ptr, TX_NAME_CONST CHAR *name_ptr, UINT message_size, VOID *queue_start, ULONG queue_size, UINT queue_control_block_size); UINT _txe_queue_delete(TX_QUEUE *queue_ptr); UINT _txe_queue_flush(TX_QUEUE *queue_ptr); -UINT _txe_queue_info_get(TX_QUEUE *queue_ptr, CHAR **name, ULONG *enqueued, ULONG *available_storage, +UINT _txe_queue_info_get(TX_QUEUE *queue_ptr, TX_NAME_CONST CHAR **name, ULONG *enqueued, ULONG *available_storage, TX_THREAD **first_suspended, ULONG *suspended_count, TX_QUEUE **next_queue); UINT _txe_queue_prioritize(TX_QUEUE *queue_ptr); UINT _txe_queue_receive(TX_QUEUE *queue_ptr, VOID *destination_ptr, ULONG wait_option); @@ -1696,10 +1709,10 @@ UINT _txe_queue_front_send(TX_QUEUE *queue_ptr, VOID *source_ptr, ULONG w /* Define semaphore management function prototypes. */ UINT _tx_semaphore_ceiling_put(TX_SEMAPHORE *semaphore_ptr, ULONG ceiling); -UINT _tx_semaphore_create(TX_SEMAPHORE *semaphore_ptr, CHAR *name_ptr, ULONG initial_count); +UINT _tx_semaphore_create(TX_SEMAPHORE *semaphore_ptr, TX_NAME_CONST CHAR *name_ptr, ULONG initial_count); UINT _tx_semaphore_delete(TX_SEMAPHORE *semaphore_ptr); UINT _tx_semaphore_get(TX_SEMAPHORE *semaphore_ptr, ULONG wait_option); -UINT _tx_semaphore_info_get(TX_SEMAPHORE *semaphore_ptr, CHAR **name, ULONG *current_value, +UINT _tx_semaphore_info_get(TX_SEMAPHORE *semaphore_ptr, TX_NAME_CONST CHAR **name, ULONG *current_value, TX_THREAD **first_suspended, ULONG *suspended_count, TX_SEMAPHORE **next_semaphore); UINT _tx_semaphore_performance_info_get(TX_SEMAPHORE *semaphore_ptr, ULONG *puts, ULONG *gets, @@ -1714,10 +1727,10 @@ UINT _tx_semaphore_put_notify(TX_SEMAPHORE *semaphore_ptr, VOID (*semapho application. */ UINT _txe_semaphore_ceiling_put(TX_SEMAPHORE *semaphore_ptr, ULONG ceiling); -UINT _txe_semaphore_create(TX_SEMAPHORE *semaphore_ptr, CHAR *name_ptr, ULONG initial_count, UINT semaphore_control_block_size); +UINT _txe_semaphore_create(TX_SEMAPHORE *semaphore_ptr, TX_NAME_CONST CHAR *name_ptr, ULONG initial_count, UINT semaphore_control_block_size); UINT _txe_semaphore_delete(TX_SEMAPHORE *semaphore_ptr); UINT _txe_semaphore_get(TX_SEMAPHORE *semaphore_ptr, ULONG wait_option); -UINT _txe_semaphore_info_get(TX_SEMAPHORE *semaphore_ptr, CHAR **name, ULONG *current_value, +UINT _txe_semaphore_info_get(TX_SEMAPHORE *semaphore_ptr, TX_NAME_CONST CHAR **name, ULONG *current_value, TX_THREAD **first_suspended, ULONG *suspended_count, TX_SEMAPHORE **next_semaphore); UINT _txe_semaphore_prioritize(TX_SEMAPHORE *semaphore_ptr); @@ -1729,7 +1742,7 @@ UINT _txe_semaphore_put_notify(TX_SEMAPHORE *semaphore_ptr, VOID (*semaph VOID _tx_thread_context_save(VOID); VOID _tx_thread_context_restore(VOID); -UINT _tx_thread_create(TX_THREAD *thread_ptr, CHAR *name_ptr, +UINT _tx_thread_create(TX_THREAD *thread_ptr, TX_NAME_CONST CHAR *name_ptr, VOID (*entry_function)(ULONG entry_input), ULONG entry_input, VOID *stack_start, ULONG stack_size, UINT priority, UINT preempt_threshold, @@ -1737,7 +1750,7 @@ UINT _tx_thread_create(TX_THREAD *thread_ptr, CHAR *name_ptr, UINT _tx_thread_delete(TX_THREAD *thread_ptr); UINT _tx_thread_entry_exit_notify(TX_THREAD *thread_ptr, VOID (*thread_entry_exit_notify)(TX_THREAD *notify_thread_ptr, UINT type)); TX_THREAD *_tx_thread_identify(VOID); -UINT _tx_thread_info_get(TX_THREAD *thread_ptr, CHAR **name, UINT *state, ULONG *run_count, +UINT _tx_thread_info_get(TX_THREAD *thread_ptr, TX_NAME_CONST CHAR **name, UINT *state, ULONG *run_count, UINT *priority, UINT *preemption_threshold, ULONG *time_slice, TX_THREAD **next_thread, TX_THREAD **next_suspended_thread); UINT _tx_thread_interrupt_control(UINT new_posture); @@ -1766,14 +1779,14 @@ UINT _tx_thread_wait_abort(TX_THREAD *thread_ptr); /* Define error checking shells for API services. These are only referenced by the application. */ -UINT _txe_thread_create(TX_THREAD *thread_ptr, CHAR *name_ptr, +UINT _txe_thread_create(TX_THREAD *thread_ptr, TX_NAME_CONST CHAR *name_ptr, VOID (*entry_function)(ULONG entry_input), ULONG entry_input, VOID *stack_start, ULONG stack_size, UINT priority, UINT preempt_threshold, ULONG time_slice, UINT auto_start, UINT thread_control_block_size); UINT _txe_thread_delete(TX_THREAD *thread_ptr); UINT _txe_thread_entry_exit_notify(TX_THREAD *thread_ptr, VOID (*thread_entry_exit_notify)(TX_THREAD *notify_thread_ptr, UINT type)); -UINT _txe_thread_info_get(TX_THREAD *thread_ptr, CHAR **name, UINT *state, ULONG *run_count, +UINT _txe_thread_info_get(TX_THREAD *thread_ptr, TX_NAME_CONST CHAR **name, UINT *state, ULONG *run_count, UINT *priority, UINT *preemption_threshold, ULONG *time_slice, TX_THREAD **next_thread, TX_THREAD **next_suspended_thread); UINT _txe_thread_preemption_change(TX_THREAD *thread_ptr, UINT new_threshold, @@ -1793,12 +1806,12 @@ UINT _txe_thread_wait_abort(TX_THREAD *thread_ptr); UINT _tx_timer_activate(TX_TIMER *timer_ptr); UINT _tx_timer_change(TX_TIMER *timer_ptr, ULONG initial_ticks, ULONG reschedule_ticks); -UINT _tx_timer_create(TX_TIMER *timer_ptr, CHAR *name_ptr, +UINT _tx_timer_create(TX_TIMER *timer_ptr, TX_NAME_CONST CHAR *name_ptr, VOID (*expiration_function)(ULONG input), ULONG expiration_input, ULONG initial_ticks, ULONG reschedule_ticks, UINT auto_activate); UINT _tx_timer_deactivate(TX_TIMER *timer_ptr); UINT _tx_timer_delete(TX_TIMER *timer_ptr); -UINT _tx_timer_info_get(TX_TIMER *timer_ptr, CHAR **name, UINT *active, ULONG *remaining_ticks, +UINT _tx_timer_info_get(TX_TIMER *timer_ptr, TX_NAME_CONST CHAR **name, UINT *active, ULONG *remaining_ticks, ULONG *reschedule_ticks, TX_TIMER **next_timer); UINT _tx_timer_performance_info_get(TX_TIMER *timer_ptr, ULONG *activates, ULONG *reactivates, ULONG *deactivates, ULONG *expirations, ULONG *expiration_adjusts); @@ -1814,12 +1827,12 @@ VOID _tx_time_set(ULONG new_time); UINT _txe_timer_activate(TX_TIMER *timer_ptr); UINT _txe_timer_change(TX_TIMER *timer_ptr, ULONG initial_ticks, ULONG reschedule_ticks); -UINT _txe_timer_create(TX_TIMER *timer_ptr, CHAR *name_ptr, +UINT _txe_timer_create(TX_TIMER *timer_ptr, TX_NAME_CONST CHAR *name_ptr, VOID (*expiration_function)(ULONG input), ULONG expiration_input, ULONG initial_ticks, ULONG reschedule_ticks, UINT auto_activate, UINT timer_control_block_size); UINT _txe_timer_deactivate(TX_TIMER *timer_ptr); UINT _txe_timer_delete(TX_TIMER *timer_ptr); -UINT _txe_timer_info_get(TX_TIMER *timer_ptr, CHAR **name, UINT *active, ULONG *remaining_ticks, +UINT _txe_timer_info_get(TX_TIMER *timer_ptr, TX_NAME_CONST CHAR **name, UINT *active, ULONG *remaining_ticks, ULONG *reschedule_ticks, TX_TIMER **next_timer); @@ -1933,7 +1946,8 @@ TX_THREAD *_tx_misra_ulong_to_thread_pointer_convert(ULONG value); VOID *_tx_misra_timer_indirect_to_void_pointer_convert(TX_TIMER_INTERNAL **pointer); CHAR *_tx_misra_const_char_to_char_pointer_convert(const char *pointer); TX_THREAD *_tx_misra_void_to_thread_pointer_convert(VOID *pointer); -UCHAR *_tx_misra_char_to_uchar_pointer_convert(CHAR *pointer); +const UCHAR *_tx_misra_char_to_uchar_pointer_convert(TX_NAME_CONST CHAR *pointer); +const UCHAR *_tx_misra_const_uchar_pointer_add(const UCHAR *pointer, ULONG amount); VOID _tx_misra_event_flags_group_not_used(TX_EVENT_FLAGS_GROUP *group_ptr); VOID _tx_misra_event_flags_set_notify_not_used(VOID (*events_set_notify)(TX_EVENT_FLAGS_GROUP *notify_group_ptr)); VOID _tx_misra_queue_not_used(TX_QUEUE *queue_ptr); @@ -1945,6 +1959,7 @@ VOID _tx_misra_thread_entry_exit_notify_not_used(VOID (*threa #define TX_MEMSET(a,b,c) _tx_misra_memset((a), (UINT) (b), (UINT) (c)) #define TX_UCHAR_POINTER_ADD(a,b) _tx_misra_uchar_pointer_add((UCHAR *) (a), (ULONG) (b)) +#define TX_CONST_UCHAR_POINTER_ADD(a,b) _tx_misra_const_uchar_pointer_add((const UCHAR *) (a), (ULONG) (b)) #define TX_UCHAR_POINTER_SUB(a,b) _tx_misra_uchar_pointer_sub((UCHAR *) (a), (ULONG) (b)) #define TX_UCHAR_POINTER_DIF(a,b) _tx_misra_uchar_pointer_dif((UCHAR *) (a), (UCHAR *) (b)) #define TX_ULONG_POINTER_ADD(a,b) _tx_misra_ulong_pointer_add((ULONG *) (a), (ULONG) (b)) @@ -2005,6 +2020,7 @@ VOID _tx_misra_thread_entry_exit_notify_not_used(VOID (*threa #endif #define TX_UCHAR_POINTER_ADD(a,b) (((UCHAR *) (a)) + ((UINT) (b))) +#define TX_CONST_UCHAR_POINTER_ADD(a,b) (((const UCHAR *) (a)) + ((UINT) (b))) #define TX_UCHAR_POINTER_SUB(a,b) (((UCHAR *) (a)) - ((UINT) (b))) #define TX_UCHAR_POINTER_DIF(a,b) ((ULONG)(((UCHAR *) (a)) - ((UCHAR *) (b)))) #define TX_ULONG_POINTER_ADD(a,b) (((ULONG *) (a)) + ((UINT) (b))) @@ -2052,7 +2068,7 @@ VOID _tx_misra_thread_entry_exit_notify_not_used(VOID (*threa #endif #define TX_CONST_CHAR_TO_CHAR_POINTER_CONVERT(a) ((CHAR *) ((VOID *) (a))) #define TX_VOID_TO_THREAD_POINTER_CONVERT(a) ((TX_THREAD *) ((VOID *) (a))) -#define TX_CHAR_TO_UCHAR_POINTER_CONVERT(a) ((UCHAR *) ((VOID *) (a))) +#define TX_CHAR_TO_UCHAR_POINTER_CONVERT(a) ((const UCHAR *) ((const VOID *) (a))) #ifndef TX_EVENT_FLAGS_GROUP_NOT_USED #define TX_EVENT_FLAGS_GROUP_NOT_USED(a) ((void)(a)) #endif @@ -2343,4 +2359,3 @@ void __ghs_rnerr(char *errMsg, int stackLevels, int stackTraceDisplay, void *hex #endif #endif - diff --git a/common_smp/inc/tx_trace.h b/common_smp/inc/tx_trace.h index ea0e59e56..2f4447d40 100644 --- a/common_smp/inc/tx_trace.h +++ b/common_smp/inc/tx_trace.h @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -452,7 +454,7 @@ TRACE_DECLARE ULONG _tx_trace_registry_search_start #define TX_TRACE_INITIALIZE _tx_trace_initialize(); -#define TX_TRACE_OBJECT_REGISTER(t,p,n,a,b) _tx_trace_object_register((UCHAR) (t), (VOID *) (p), (CHAR *) (n), (ULONG) (a), (ULONG) (b)); +#define TX_TRACE_OBJECT_REGISTER(t,p,n,a,b) _tx_trace_object_register((UCHAR) (t), (VOID *) (p), (n), (ULONG) (a), (ULONG) (b)); #define TX_TRACE_OBJECT_UNREGISTER(o) _tx_trace_object_unregister((VOID *) (o)); #ifndef TX_TRACE_IN_LINE_INSERT #define TX_TRACE_IN_LINE_INSERT(i,a,b,c,d,e) \ @@ -515,7 +517,7 @@ TRACE_DECLARE ULONG _tx_trace_registry_search_start /* Define internal function prototypes of the trace component, only if compiling ThreadX source code. */ VOID _tx_trace_initialize(VOID); -VOID _tx_trace_object_register(UCHAR object_type, VOID *object_ptr, CHAR *object_name, ULONG parameter_1, ULONG parameter_2); +VOID _tx_trace_object_register(UCHAR object_type, VOID *object_ptr, TX_NAME_CONST CHAR *object_name, ULONG parameter_1, ULONG parameter_2); VOID _tx_trace_object_unregister(VOID *object_ptr); diff --git a/common_smp/inc/tx_user_sample.h b/common_smp/inc/tx_user_sample.h index 64ff9aedb..1514a0dbe 100644 --- a/common_smp/inc/tx_user_sample.h +++ b/common_smp/inc/tx_user_sample.h @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -100,6 +102,12 @@ #define TX_TIMER_TICKS_PER_SECOND (100UL) */ +/* Define this option to qualify object names as pointers to const. */ + +/* +#define TX_ENABLE_CONST_NAMES +*/ + /* Determine if there is a FileX pointer in the thread control block. By default, the pointer is there for legacy/backwards compatibility. The pointer must also be there for applications using FileX. @@ -288,4 +296,3 @@ */ #endif - diff --git a/common_smp/src/tx_block_pool_create.c b/common_smp/src/tx_block_pool_create.c index 1d2c803cf..8781dc789 100644 --- a/common_smp/src/tx_block_pool_create.c +++ b/common_smp/src/tx_block_pool_create.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -66,7 +68,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _tx_block_pool_create(TX_BLOCK_POOL *pool_ptr, CHAR *name_ptr, ULONG block_size, +UINT _tx_block_pool_create(TX_BLOCK_POOL *pool_ptr, TX_NAME_CONST CHAR *name_ptr, ULONG block_size, VOID *pool_start, ULONG pool_size) { diff --git a/common_smp/src/tx_block_pool_info_get.c b/common_smp/src/tx_block_pool_info_get.c index 5998f1db4..5e1e89fdd 100644 --- a/common_smp/src/tx_block_pool_info_get.c +++ b/common_smp/src/tx_block_pool_info_get.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -69,7 +71,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _tx_block_pool_info_get(TX_BLOCK_POOL *pool_ptr, CHAR **name, ULONG *available_blocks, +UINT _tx_block_pool_info_get(TX_BLOCK_POOL *pool_ptr, TX_NAME_CONST CHAR **name, ULONG *available_blocks, ULONG *total_blocks, TX_THREAD **first_suspended, ULONG *suspended_count, TX_BLOCK_POOL **next_pool) { diff --git a/common_smp/src/tx_byte_pool_create.c b/common_smp/src/tx_byte_pool_create.c index 21abbe356..f5c8460dc 100644 --- a/common_smp/src/tx_byte_pool_create.c +++ b/common_smp/src/tx_byte_pool_create.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -65,7 +67,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _tx_byte_pool_create(TX_BYTE_POOL *pool_ptr, CHAR *name_ptr, VOID *pool_start, ULONG pool_size) +UINT _tx_byte_pool_create(TX_BYTE_POOL *pool_ptr, TX_NAME_CONST CHAR *name_ptr, VOID *pool_start, ULONG pool_size) { TX_INTERRUPT_SAVE_AREA diff --git a/common_smp/src/tx_byte_pool_info_get.c b/common_smp/src/tx_byte_pool_info_get.c index bd0964407..e9e9efa48 100644 --- a/common_smp/src/tx_byte_pool_info_get.c +++ b/common_smp/src/tx_byte_pool_info_get.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -69,7 +71,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _tx_byte_pool_info_get(TX_BYTE_POOL *pool_ptr, CHAR **name, ULONG *available_bytes, +UINT _tx_byte_pool_info_get(TX_BYTE_POOL *pool_ptr, TX_NAME_CONST CHAR **name, ULONG *available_bytes, ULONG *fragments, TX_THREAD **first_suspended, ULONG *suspended_count, TX_BYTE_POOL **next_pool) { diff --git a/common_smp/src/tx_event_flags_create.c b/common_smp/src/tx_event_flags_create.c index 2a9c042d6..361fafa44 100644 --- a/common_smp/src/tx_event_flags_create.c +++ b/common_smp/src/tx_event_flags_create.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -64,7 +66,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _tx_event_flags_create(TX_EVENT_FLAGS_GROUP *group_ptr, CHAR *name_ptr) +UINT _tx_event_flags_create(TX_EVENT_FLAGS_GROUP *group_ptr, TX_NAME_CONST CHAR *name_ptr) { TX_INTERRUPT_SAVE_AREA diff --git a/common_smp/src/tx_event_flags_info_get.c b/common_smp/src/tx_event_flags_info_get.c index 21e85c9a1..51ec345fa 100644 --- a/common_smp/src/tx_event_flags_info_get.c +++ b/common_smp/src/tx_event_flags_info_get.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -71,7 +73,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _tx_event_flags_info_get(TX_EVENT_FLAGS_GROUP *group_ptr, CHAR **name, ULONG *current_flags, +UINT _tx_event_flags_info_get(TX_EVENT_FLAGS_GROUP *group_ptr, TX_NAME_CONST CHAR **name, ULONG *current_flags, TX_THREAD **first_suspended, ULONG *suspended_count, TX_EVENT_FLAGS_GROUP **next_group) { diff --git a/common_smp/src/tx_misra.c b/common_smp/src/tx_misra.c index f37cebaac..b9144a70c 100644 --- a/common_smp/src/tx_misra.c +++ b/common_smp/src/tx_misra.c @@ -819,15 +819,29 @@ UCHAR *_tx_misra_entry_to_uchar_pointer_convert(TX_TRACE_BUFFER_ENTRY *pointer) /***********************************************************************************************/ /***********************************************************************************************/ /** */ -/** UCHAR *_tx_misra_char_to_uchar_pointer_convert(CHAR *pointer); */ +/** const UCHAR *_tx_misra_char_to_uchar_pointer_convert(TX_NAME_CONST CHAR *pointer); */ /** */ /***********************************************************************************************/ /***********************************************************************************************/ -UCHAR *_tx_misra_char_to_uchar_pointer_convert(CHAR *pointer) +const UCHAR *_tx_misra_char_to_uchar_pointer_convert(TX_NAME_CONST CHAR *pointer) { /* Return a UCHAR pointer. */ - return((UCHAR *) ((VOID *) pointer)); + return((const UCHAR *) ((const VOID *) pointer)); +} + + +/***********************************************************************************************/ +/***********************************************************************************************/ +/** */ +/** const UCHAR *_tx_misra_const_uchar_pointer_add(const UCHAR *ptr, ULONG amount); */ +/** */ +/***********************************************************************************************/ +/***********************************************************************************************/ +const UCHAR *_tx_misra_const_uchar_pointer_add(const UCHAR *ptr, ULONG amount) +{ + ptr = ptr + amount; + return(ptr); } diff --git a/common_smp/src/tx_mutex_create.c b/common_smp/src/tx_mutex_create.c index 436c01f50..a1f5eba85 100644 --- a/common_smp/src/tx_mutex_create.c +++ b/common_smp/src/tx_mutex_create.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -65,7 +67,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _tx_mutex_create(TX_MUTEX *mutex_ptr, CHAR *name_ptr, UINT inherit) +UINT _tx_mutex_create(TX_MUTEX *mutex_ptr, TX_NAME_CONST CHAR *name_ptr, UINT inherit) { TX_INTERRUPT_SAVE_AREA diff --git a/common_smp/src/tx_mutex_info_get.c b/common_smp/src/tx_mutex_info_get.c index a24d1e30e..3be2606bb 100644 --- a/common_smp/src/tx_mutex_info_get.c +++ b/common_smp/src/tx_mutex_info_get.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -70,7 +72,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _tx_mutex_info_get(TX_MUTEX *mutex_ptr, CHAR **name, ULONG *count, TX_THREAD **owner, +UINT _tx_mutex_info_get(TX_MUTEX *mutex_ptr, TX_NAME_CONST CHAR **name, ULONG *count, TX_THREAD **owner, TX_THREAD **first_suspended, ULONG *suspended_count, TX_MUTEX **next_mutex) { diff --git a/common_smp/src/tx_queue_create.c b/common_smp/src/tx_queue_create.c index 59ae154e4..afb5648d5 100644 --- a/common_smp/src/tx_queue_create.c +++ b/common_smp/src/tx_queue_create.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -66,7 +68,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _tx_queue_create(TX_QUEUE *queue_ptr, CHAR *name_ptr, UINT message_size, +UINT _tx_queue_create(TX_QUEUE *queue_ptr, TX_NAME_CONST CHAR *name_ptr, UINT message_size, VOID *queue_start, ULONG queue_size) { diff --git a/common_smp/src/tx_queue_info_get.c b/common_smp/src/tx_queue_info_get.c index d0ecb2b65..e25da54ef 100644 --- a/common_smp/src/tx_queue_info_get.c +++ b/common_smp/src/tx_queue_info_get.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -69,7 +71,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _tx_queue_info_get(TX_QUEUE *queue_ptr, CHAR **name, ULONG *enqueued, ULONG *available_storage, +UINT _tx_queue_info_get(TX_QUEUE *queue_ptr, TX_NAME_CONST CHAR **name, ULONG *enqueued, ULONG *available_storage, TX_THREAD **first_suspended, ULONG *suspended_count, TX_QUEUE **next_queue) { diff --git a/common_smp/src/tx_semaphore_create.c b/common_smp/src/tx_semaphore_create.c index 849f5d3b5..14553ca8d 100644 --- a/common_smp/src/tx_semaphore_create.c +++ b/common_smp/src/tx_semaphore_create.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -64,7 +66,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _tx_semaphore_create(TX_SEMAPHORE *semaphore_ptr, CHAR *name_ptr, ULONG initial_count) +UINT _tx_semaphore_create(TX_SEMAPHORE *semaphore_ptr, TX_NAME_CONST CHAR *name_ptr, ULONG initial_count) { TX_INTERRUPT_SAVE_AREA diff --git a/common_smp/src/tx_semaphore_info_get.c b/common_smp/src/tx_semaphore_info_get.c index 89fd94238..2ffad1f7e 100644 --- a/common_smp/src/tx_semaphore_info_get.c +++ b/common_smp/src/tx_semaphore_info_get.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -69,7 +71,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _tx_semaphore_info_get(TX_SEMAPHORE *semaphore_ptr, CHAR **name, ULONG *current_value, +UINT _tx_semaphore_info_get(TX_SEMAPHORE *semaphore_ptr, TX_NAME_CONST CHAR **name, ULONG *current_value, TX_THREAD **first_suspended, ULONG *suspended_count, TX_SEMAPHORE **next_semaphore) { diff --git a/common_smp/src/tx_thread_create.c b/common_smp/src/tx_thread_create.c index 5be0d05b5..3b158f475 100644 --- a/common_smp/src/tx_thread_create.c +++ b/common_smp/src/tx_thread_create.c @@ -79,7 +79,7 @@ /* _tx_timer_initialize Create system timer thread */ /* */ /**************************************************************************/ -UINT _tx_thread_create(TX_THREAD *thread_ptr, CHAR *name_ptr, +UINT _tx_thread_create(TX_THREAD *thread_ptr, TX_NAME_CONST CHAR *name_ptr, VOID (*entry_function)(ULONG id), ULONG entry_input, VOID *stack_start, ULONG stack_size, UINT priority, UINT preempt_threshold, ULONG time_slice, UINT auto_start) diff --git a/common_smp/src/tx_thread_info_get.c b/common_smp/src/tx_thread_info_get.c index 740a3b95d..cd0df6ec8 100644 --- a/common_smp/src/tx_thread_info_get.c +++ b/common_smp/src/tx_thread_info_get.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -72,7 +74,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _tx_thread_info_get(TX_THREAD *thread_ptr, CHAR **name, UINT *state, ULONG *run_count, +UINT _tx_thread_info_get(TX_THREAD *thread_ptr, TX_NAME_CONST CHAR **name, UINT *state, ULONG *run_count, UINT *priority, UINT *preemption_threshold, ULONG *time_slice, TX_THREAD **next_thread, TX_THREAD **next_suspended_thread) { diff --git a/common_smp/src/tx_timer_create.c b/common_smp/src/tx_timer_create.c index 73fa67cd6..81af4c9b7 100644 --- a/common_smp/src/tx_timer_create.c +++ b/common_smp/src/tx_timer_create.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -68,7 +70,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _tx_timer_create(TX_TIMER *timer_ptr, CHAR *name_ptr, +UINT _tx_timer_create(TX_TIMER *timer_ptr, TX_NAME_CONST CHAR *name_ptr, VOID (*expiration_function)(ULONG id), ULONG expiration_input, ULONG initial_ticks, ULONG reschedule_ticks, UINT auto_activate) { diff --git a/common_smp/src/tx_timer_info_get.c b/common_smp/src/tx_timer_info_get.c index 31c801f9b..0811b5929 100644 --- a/common_smp/src/tx_timer_info_get.c +++ b/common_smp/src/tx_timer_info_get.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -68,7 +70,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _tx_timer_info_get(TX_TIMER *timer_ptr, CHAR **name, UINT *active, ULONG *remaining_ticks, +UINT _tx_timer_info_get(TX_TIMER *timer_ptr, TX_NAME_CONST CHAR **name, UINT *active, ULONG *remaining_ticks, ULONG *reschedule_ticks, TX_TIMER **next_timer) { diff --git a/common_smp/src/tx_trace_object_register.c b/common_smp/src/tx_trace_object_register.c index f7cd4a4a1..a2a1e0b4d 100644 --- a/common_smp/src/tx_trace_object_register.c +++ b/common_smp/src/tx_trace_object_register.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -66,7 +68,7 @@ /* Application Code */ /* */ /**************************************************************************/ -VOID _tx_trace_object_register(UCHAR object_type, VOID *object_ptr, CHAR *object_name, ULONG parameter_1, ULONG parameter_2) +VOID _tx_trace_object_register(UCHAR object_type, VOID *object_ptr, TX_NAME_CONST CHAR *object_name, ULONG parameter_1, ULONG parameter_2) { #ifdef TX_ENABLE_EVENT_TRACE @@ -75,6 +77,7 @@ UINT i, entries; UINT found, loop_break; TX_THREAD *thread_ptr; UCHAR *work_ptr; +const UCHAR *name_ptr; TX_TRACE_OBJECT_ENTRY *entry_ptr; @@ -211,21 +214,21 @@ TX_TRACE_OBJECT_ENTRY *entry_ptr; for (i = ((ULONG) 0); i < (((ULONG) TX_TRACE_OBJECT_REGISTRY_NAME)-((ULONG) 1)); i++) { - /* Setup work pointer to the object name character. */ - work_ptr = TX_CHAR_TO_UCHAR_POINTER_CONVERT(object_name); - work_ptr = TX_UCHAR_POINTER_ADD(work_ptr, i); + /* Setup name pointer to the object name character. */ + name_ptr = TX_CHAR_TO_UCHAR_POINTER_CONVERT(object_name); + name_ptr = TX_CONST_UCHAR_POINTER_ADD(name_ptr, i); - /* Determine if object_name (work_ptr) is null. */ - if (work_ptr == TX_NULL) + /* Determine if object_name (name_ptr) is null. */ + if (name_ptr == TX_NULL) { break; } /* Copy a character of the name. */ - entry_ptr -> tx_trace_object_entry_name[i] = (UCHAR) *work_ptr; + entry_ptr -> tx_trace_object_entry_name[i] = (UCHAR) *name_ptr; /* Determine if we are at the end. */ - if (*work_ptr == ((UCHAR) 0)) + if (*name_ptr == ((UCHAR) 0)) { break; } diff --git a/common_smp/src/txe_block_pool_create.c b/common_smp/src/txe_block_pool_create.c index 08ef7e69d..b4c7e13fe 100644 --- a/common_smp/src/txe_block_pool_create.c +++ b/common_smp/src/txe_block_pool_create.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -74,7 +76,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _txe_block_pool_create(TX_BLOCK_POOL *pool_ptr, CHAR *name_ptr, ULONG block_size, +UINT _txe_block_pool_create(TX_BLOCK_POOL *pool_ptr, TX_NAME_CONST CHAR *name_ptr, ULONG block_size, VOID *pool_start, ULONG pool_size, UINT pool_control_block_size) { diff --git a/common_smp/src/txe_block_pool_info_get.c b/common_smp/src/txe_block_pool_info_get.c index f91ca2060..4c6003d75 100644 --- a/common_smp/src/txe_block_pool_info_get.c +++ b/common_smp/src/txe_block_pool_info_get.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -70,7 +72,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _txe_block_pool_info_get(TX_BLOCK_POOL *pool_ptr, CHAR **name, ULONG *available_blocks, +UINT _txe_block_pool_info_get(TX_BLOCK_POOL *pool_ptr, TX_NAME_CONST CHAR **name, ULONG *available_blocks, ULONG *total_blocks, TX_THREAD **first_suspended, ULONG *suspended_count, TX_BLOCK_POOL **next_pool) { diff --git a/common_smp/src/txe_byte_pool_create.c b/common_smp/src/txe_byte_pool_create.c index 99a896981..9ae72ee99 100644 --- a/common_smp/src/txe_byte_pool_create.c +++ b/common_smp/src/txe_byte_pool_create.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -73,7 +75,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _txe_byte_pool_create(TX_BYTE_POOL *pool_ptr, CHAR *name_ptr, VOID *pool_start, ULONG pool_size, UINT pool_control_block_size) +UINT _txe_byte_pool_create(TX_BYTE_POOL *pool_ptr, TX_NAME_CONST CHAR *name_ptr, VOID *pool_start, ULONG pool_size, UINT pool_control_block_size) { TX_INTERRUPT_SAVE_AREA diff --git a/common_smp/src/txe_byte_pool_info_get.c b/common_smp/src/txe_byte_pool_info_get.c index 85e7a233a..a83c907bc 100644 --- a/common_smp/src/txe_byte_pool_info_get.c +++ b/common_smp/src/txe_byte_pool_info_get.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -70,7 +72,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _txe_byte_pool_info_get(TX_BYTE_POOL *pool_ptr, CHAR **name, ULONG *available_bytes, +UINT _txe_byte_pool_info_get(TX_BYTE_POOL *pool_ptr, TX_NAME_CONST CHAR **name, ULONG *available_bytes, ULONG *fragments, TX_THREAD **first_suspended, ULONG *suspended_count, TX_BYTE_POOL **next_pool) { diff --git a/common_smp/src/txe_event_flags_create.c b/common_smp/src/txe_event_flags_create.c index 4e3fed773..209847381 100644 --- a/common_smp/src/txe_event_flags_create.c +++ b/common_smp/src/txe_event_flags_create.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -70,7 +72,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _txe_event_flags_create(TX_EVENT_FLAGS_GROUP *group_ptr, CHAR *name_ptr, UINT event_control_block_size) +UINT _txe_event_flags_create(TX_EVENT_FLAGS_GROUP *group_ptr, TX_NAME_CONST CHAR *name_ptr, UINT event_control_block_size) { TX_INTERRUPT_SAVE_AREA diff --git a/common_smp/src/txe_event_flags_info_get.c b/common_smp/src/txe_event_flags_info_get.c index e551d025c..d7bddca4e 100644 --- a/common_smp/src/txe_event_flags_info_get.c +++ b/common_smp/src/txe_event_flags_info_get.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -72,7 +74,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _txe_event_flags_info_get(TX_EVENT_FLAGS_GROUP *group_ptr, CHAR **name, ULONG *current_flags, +UINT _txe_event_flags_info_get(TX_EVENT_FLAGS_GROUP *group_ptr, TX_NAME_CONST CHAR **name, ULONG *current_flags, TX_THREAD **first_suspended, ULONG *suspended_count, TX_EVENT_FLAGS_GROUP **next_group) { diff --git a/common_smp/src/txe_mutex_create.c b/common_smp/src/txe_mutex_create.c index 392f8b0ed..a04612949 100644 --- a/common_smp/src/txe_mutex_create.c +++ b/common_smp/src/txe_mutex_create.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -71,7 +73,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _txe_mutex_create(TX_MUTEX *mutex_ptr, CHAR *name_ptr, UINT inherit, UINT mutex_control_block_size) +UINT _txe_mutex_create(TX_MUTEX *mutex_ptr, TX_NAME_CONST CHAR *name_ptr, UINT inherit, UINT mutex_control_block_size) { TX_INTERRUPT_SAVE_AREA diff --git a/common_smp/src/txe_mutex_info_get.c b/common_smp/src/txe_mutex_info_get.c index f4ef4168c..93b43f91a 100644 --- a/common_smp/src/txe_mutex_info_get.c +++ b/common_smp/src/txe_mutex_info_get.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -71,7 +73,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _txe_mutex_info_get(TX_MUTEX *mutex_ptr, CHAR **name, ULONG *count, TX_THREAD **owner, +UINT _txe_mutex_info_get(TX_MUTEX *mutex_ptr, TX_NAME_CONST CHAR **name, ULONG *count, TX_THREAD **owner, TX_THREAD **first_suspended, ULONG *suspended_count, TX_MUTEX **next_mutex) { diff --git a/common_smp/src/txe_queue_create.c b/common_smp/src/txe_queue_create.c index 387eacb66..ca3b85312 100644 --- a/common_smp/src/txe_queue_create.c +++ b/common_smp/src/txe_queue_create.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -72,7 +74,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _txe_queue_create(TX_QUEUE *queue_ptr, CHAR *name_ptr, UINT message_size, +UINT _txe_queue_create(TX_QUEUE *queue_ptr, TX_NAME_CONST CHAR *name_ptr, UINT message_size, VOID *queue_start, ULONG queue_size, UINT queue_control_block_size) { diff --git a/common_smp/src/txe_queue_info_get.c b/common_smp/src/txe_queue_info_get.c index 78d983924..90fdd4108 100644 --- a/common_smp/src/txe_queue_info_get.c +++ b/common_smp/src/txe_queue_info_get.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -70,7 +72,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _txe_queue_info_get(TX_QUEUE *queue_ptr, CHAR **name, ULONG *enqueued, ULONG *available_storage, +UINT _txe_queue_info_get(TX_QUEUE *queue_ptr, TX_NAME_CONST CHAR **name, ULONG *enqueued, ULONG *available_storage, TX_THREAD **first_suspended, ULONG *suspended_count, TX_QUEUE **next_queue) { diff --git a/common_smp/src/txe_semaphore_create.c b/common_smp/src/txe_semaphore_create.c index a190b03c0..d538f5fe1 100644 --- a/common_smp/src/txe_semaphore_create.c +++ b/common_smp/src/txe_semaphore_create.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -70,7 +72,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _txe_semaphore_create(TX_SEMAPHORE *semaphore_ptr, CHAR *name_ptr, ULONG initial_count, UINT semaphore_control_block_size) +UINT _txe_semaphore_create(TX_SEMAPHORE *semaphore_ptr, TX_NAME_CONST CHAR *name_ptr, ULONG initial_count, UINT semaphore_control_block_size) { TX_INTERRUPT_SAVE_AREA diff --git a/common_smp/src/txe_semaphore_info_get.c b/common_smp/src/txe_semaphore_info_get.c index 7695028e4..85747dc32 100644 --- a/common_smp/src/txe_semaphore_info_get.c +++ b/common_smp/src/txe_semaphore_info_get.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -70,7 +72,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _txe_semaphore_info_get(TX_SEMAPHORE *semaphore_ptr, CHAR **name, ULONG *current_value, +UINT _txe_semaphore_info_get(TX_SEMAPHORE *semaphore_ptr, TX_NAME_CONST CHAR **name, ULONG *current_value, TX_THREAD **first_suspended, ULONG *suspended_count, TX_SEMAPHORE **next_semaphore) { diff --git a/common_smp/src/txe_thread_create.c b/common_smp/src/txe_thread_create.c index d319bc9e2..cc5033b29 100644 --- a/common_smp/src/txe_thread_create.c +++ b/common_smp/src/txe_thread_create.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -79,7 +81,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _txe_thread_create(TX_THREAD *thread_ptr, CHAR *name_ptr, +UINT _txe_thread_create(TX_THREAD *thread_ptr, TX_NAME_CONST CHAR *name_ptr, VOID (*entry_function)(ULONG id), ULONG entry_input, VOID *stack_start, ULONG stack_size, UINT priority, UINT preempt_threshold, diff --git a/common_smp/src/txe_thread_info_get.c b/common_smp/src/txe_thread_info_get.c index ad1db3f7f..19e248ebf 100644 --- a/common_smp/src/txe_thread_info_get.c +++ b/common_smp/src/txe_thread_info_get.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -74,7 +76,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _txe_thread_info_get(TX_THREAD *thread_ptr, CHAR **name, UINT *state, ULONG *run_count, +UINT _txe_thread_info_get(TX_THREAD *thread_ptr, TX_NAME_CONST CHAR **name, UINT *state, ULONG *run_count, UINT *priority, UINT *preemption_threshold, ULONG *time_slice, TX_THREAD **next_thread, TX_THREAD **next_suspended_thread) { diff --git a/common_smp/src/txe_timer_create.c b/common_smp/src/txe_timer_create.c index 02cf7c1aa..8c481bde8 100644 --- a/common_smp/src/txe_timer_create.c +++ b/common_smp/src/txe_timer_create.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -74,7 +76,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _txe_timer_create(TX_TIMER *timer_ptr, CHAR *name_ptr, +UINT _txe_timer_create(TX_TIMER *timer_ptr, TX_NAME_CONST CHAR *name_ptr, VOID (*expiration_function)(ULONG id), ULONG expiration_input, ULONG initial_ticks, ULONG reschedule_ticks, UINT auto_activate, UINT timer_control_block_size) { diff --git a/common_smp/src/txe_timer_info_get.c b/common_smp/src/txe_timer_info_get.c index 16ac5f64a..be2e9a13c 100644 --- a/common_smp/src/txe_timer_info_get.c +++ b/common_smp/src/txe_timer_info_get.c @@ -9,6 +9,8 @@ * SPDX-License-Identifier: MIT **************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /**************************************************************************/ /**************************************************************************/ @@ -69,7 +71,7 @@ /* Application Code */ /* */ /**************************************************************************/ -UINT _txe_timer_info_get(TX_TIMER *timer_ptr, CHAR **name, UINT *active, ULONG *remaining_ticks, +UINT _txe_timer_info_get(TX_TIMER *timer_ptr, TX_NAME_CONST CHAR **name, UINT *active, ULONG *remaining_ticks, ULONG *reschedule_ticks, TX_TIMER **next_timer) { diff --git a/test/freertos/regression/txfr_test_harness.c b/test/freertos/regression/txfr_test_harness.c index 9f9ec887e..b5bd45dec 100644 --- a/test/freertos/regression/txfr_test_harness.c +++ b/test/freertos/regression/txfr_test_harness.c @@ -37,17 +37,17 @@ static int txfr_failures; /* The real entry points, supplied by the linker in response to --wrap. */ UINT __real__txe_byte_allocate(TX_BYTE_POOL *pool_ptr, VOID **memory_ptr, ULONG memory_size, ULONG wait_option); UINT __real__txe_byte_release(VOID *memory_ptr); -UINT __real__txe_semaphore_create(TX_SEMAPHORE *semaphore_ptr, CHAR *name_ptr, ULONG initial_count, UINT semaphore_control_block_size); +UINT __real__txe_semaphore_create(TX_SEMAPHORE *semaphore_ptr, TX_NAME_CONST CHAR *name_ptr, ULONG initial_count, UINT semaphore_control_block_size); UINT __real__txe_semaphore_delete(TX_SEMAPHORE *semaphore_ptr); -UINT __real__txe_mutex_create(TX_MUTEX *mutex_ptr, CHAR *name_ptr, UINT inherit, UINT mutex_control_block_size); +UINT __real__txe_mutex_create(TX_MUTEX *mutex_ptr, TX_NAME_CONST CHAR *name_ptr, UINT inherit, UINT mutex_control_block_size); UINT __real__txe_mutex_delete(TX_MUTEX *mutex_ptr); -UINT __real__txe_event_flags_create(TX_EVENT_FLAGS_GROUP *group_ptr, CHAR *name_ptr, UINT event_control_block_size); +UINT __real__txe_event_flags_create(TX_EVENT_FLAGS_GROUP *group_ptr, TX_NAME_CONST CHAR *name_ptr, UINT event_control_block_size); UINT __real__txe_event_flags_delete(TX_EVENT_FLAGS_GROUP *group_ptr); -UINT __real__txe_timer_create(TX_TIMER *timer_ptr, CHAR *name_ptr, VOID (*expiration_function)(ULONG input), +UINT __real__txe_timer_create(TX_TIMER *timer_ptr, TX_NAME_CONST CHAR *name_ptr, VOID (*expiration_function)(ULONG input), ULONG expiration_input, ULONG initial_ticks, ULONG reschedule_ticks, UINT auto_activate, UINT timer_control_block_size); UINT __real__txe_timer_delete(TX_TIMER *timer_ptr); -UINT __real__txe_thread_create(TX_THREAD *thread_ptr, CHAR *name_ptr, VOID (*entry_function)(ULONG entry_input), +UINT __real__txe_thread_create(TX_THREAD *thread_ptr, TX_NAME_CONST CHAR *name_ptr, VOID (*entry_function)(ULONG entry_input), ULONG entry_input, VOID *stack_start, ULONG stack_size, UINT priority, UINT preempt_threshold, ULONG time_slice, UINT auto_start, UINT thread_control_block_size); @@ -93,7 +93,7 @@ UINT __wrap__txe_byte_release(VOID *memory_ptr) } -UINT __wrap__txe_semaphore_create(TX_SEMAPHORE *semaphore_ptr, CHAR *name_ptr, ULONG initial_count, UINT semaphore_control_block_size) +UINT __wrap__txe_semaphore_create(TX_SEMAPHORE *semaphore_ptr, TX_NAME_CONST CHAR *name_ptr, ULONG initial_count, UINT semaphore_control_block_size) { if(txfr_should_fail(TXFR_INJECT_SEMAPHORE_CREATE) != 0) { @@ -121,7 +121,7 @@ UINT __wrap__txe_semaphore_delete(TX_SEMAPHORE *semaphore_ptr) } -UINT __wrap__txe_mutex_create(TX_MUTEX *mutex_ptr, CHAR *name_ptr, UINT inherit, UINT mutex_control_block_size) +UINT __wrap__txe_mutex_create(TX_MUTEX *mutex_ptr, TX_NAME_CONST CHAR *name_ptr, UINT inherit, UINT mutex_control_block_size) { if(txfr_should_fail(TXFR_INJECT_MUTEX_CREATE) != 0) { @@ -149,7 +149,7 @@ UINT __wrap__txe_mutex_delete(TX_MUTEX *mutex_ptr) } -UINT __wrap__txe_event_flags_create(TX_EVENT_FLAGS_GROUP *group_ptr, CHAR *name_ptr, UINT event_control_block_size) +UINT __wrap__txe_event_flags_create(TX_EVENT_FLAGS_GROUP *group_ptr, TX_NAME_CONST CHAR *name_ptr, UINT event_control_block_size) { if(txfr_should_fail(TXFR_INJECT_EVENT_FLAGS_CREATE) != 0) { @@ -177,7 +177,7 @@ UINT __wrap__txe_event_flags_delete(TX_EVENT_FLAGS_GROUP *group_ptr) } -UINT __wrap__txe_timer_create(TX_TIMER *timer_ptr, CHAR *name_ptr, VOID (*expiration_function)(ULONG input), +UINT __wrap__txe_timer_create(TX_TIMER *timer_ptr, TX_NAME_CONST CHAR *name_ptr, VOID (*expiration_function)(ULONG input), ULONG expiration_input, ULONG initial_ticks, ULONG reschedule_ticks, UINT auto_activate, UINT timer_control_block_size) { @@ -208,7 +208,7 @@ UINT __wrap__txe_timer_delete(TX_TIMER *timer_ptr) } -UINT __wrap__txe_thread_create(TX_THREAD *thread_ptr, CHAR *name_ptr, VOID (*entry_function)(ULONG entry_input), +UINT __wrap__txe_thread_create(TX_THREAD *thread_ptr, TX_NAME_CONST CHAR *name_ptr, VOID (*entry_function)(ULONG entry_input), ULONG entry_input, VOID *stack_start, ULONG stack_size, UINT priority, UINT preempt_threshold, ULONG time_slice, UINT auto_start, UINT thread_control_block_size) diff --git a/test/smp/regression/threadx_block_memory_basic_test.c b/test/smp/regression/threadx_block_memory_basic_test.c index 28edee3fc..27990f88a 100644 --- a/test/smp/regression/threadx_block_memory_basic_test.c +++ b/test/smp/regression/threadx_block_memory_basic_test.c @@ -9,6 +9,8 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /* This test is designed to test simple memory block pool creation, deletion, and allocates and releases. */ @@ -72,7 +74,7 @@ void test_control_return(UINT status); /* Prototype direct call to block pool core service. */ -UINT _tx_block_pool_create(TX_BLOCK_POOL *pool_ptr, CHAR *name_ptr, ULONG block_size, +UINT _tx_block_pool_create(TX_BLOCK_POOL *pool_ptr, TX_NAME_CONST CHAR *name_ptr, ULONG block_size, VOID *pool_start, ULONG pool_size); diff --git a/test/smp/regression/threadx_block_memory_error_detection_test.c b/test/smp/regression/threadx_block_memory_error_detection_test.c index 41148120f..b0303b762 100644 --- a/test/smp/regression/threadx_block_memory_error_detection_test.c +++ b/test/smp/regression/threadx_block_memory_error_detection_test.c @@ -9,6 +9,8 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /* This test is designed to test error detection for simple memory block operations. */ #include @@ -29,7 +31,7 @@ static CHAR *pointer; static void thread_0_entry(ULONG thread_input); -UINT _txe_block_pool_create(TX_BLOCK_POOL *pool_ptr, CHAR *name_ptr, ULONG block_size, +UINT _txe_block_pool_create(TX_BLOCK_POOL *pool_ptr, TX_NAME_CONST CHAR *name_ptr, ULONG block_size, VOID *pool_start, ULONG pool_size, UINT pool_control_block_size); diff --git a/test/smp/regression/threadx_block_memory_information_test.c b/test/smp/regression/threadx_block_memory_information_test.c index 82d57f40a..0c04cb7ee 100644 --- a/test/smp/regression/threadx_block_memory_information_test.c +++ b/test/smp/regression/threadx_block_memory_information_test.c @@ -9,6 +9,8 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /* This test is designed to test block memory information services. */ #include @@ -68,7 +70,7 @@ static void thread_5_entry(ULONG thread_input); static void thread_6_entry(ULONG thread_input); /* Direct core function to bypass the error checking shell. */ -UINT _tx_block_pool_info_get(TX_BLOCK_POOL *pool_ptr, CHAR **name, ULONG *available_blocks, +UINT _tx_block_pool_info_get(TX_BLOCK_POOL *pool_ptr, TX_NAME_CONST CHAR **name, ULONG *available_blocks, ULONG *total_blocks, TX_THREAD **first_suspended, ULONG *suspended_count, TX_BLOCK_POOL **next_pool); @@ -227,7 +229,7 @@ static void thread_0_entry(ULONG thread_input) UINT status; VOID *pointer; -CHAR *name; +TX_NAME_CONST CHAR *name; ULONG available; ULONG total_blocks; TX_THREAD *first_suspended; @@ -369,7 +371,7 @@ ULONG timeouts; status += tx_block_pool_info_get(&block_pool_0, &name, &available, &total_blocks, &first_suspended, &suspended_count, &next_pool); /* Check for an error condition. */ - if ((status) || (available != block_pool_0.tx_block_pool_available) || (total_blocks != block_pool_0.tx_block_pool_total) || + if ((status) || (name != block_pool_0.tx_block_pool_name) || (available != block_pool_0.tx_block_pool_available) || (total_blocks != block_pool_0.tx_block_pool_total) || (first_suspended != &thread_4) || (suspended_count != block_pool_0.tx_block_pool_suspended_count) || (next_pool != &block_pool_0)) { diff --git a/test/smp/regression/threadx_byte_memory_basic_test.c b/test/smp/regression/threadx_byte_memory_basic_test.c index 45a2518d5..d7c1232e1 100644 --- a/test/smp/regression/threadx_byte_memory_basic_test.c +++ b/test/smp/regression/threadx_byte_memory_basic_test.c @@ -9,6 +9,8 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /* This test is designed to test simple memory byte pool creation, deletion, and allocates and releases. */ @@ -42,7 +44,7 @@ extern UINT test_byte_pool_create_init; extern VOID (*test_isr_dispatch)(void); -UINT _txe_byte_pool_create(TX_BYTE_POOL *pool_ptr, CHAR *name_ptr, VOID *pool_start, +UINT _txe_byte_pool_create(TX_BYTE_POOL *pool_ptr, TX_NAME_CONST CHAR *name_ptr, VOID *pool_start, ULONG pool_size, UINT pool_control_block_size); diff --git a/test/smp/regression/threadx_byte_memory_information_test.c b/test/smp/regression/threadx_byte_memory_information_test.c index f1624a65a..f65efac3f 100644 --- a/test/smp/regression/threadx_byte_memory_information_test.c +++ b/test/smp/regression/threadx_byte_memory_information_test.c @@ -9,6 +9,8 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /* This test is designed to test byte memory information. */ #include @@ -226,7 +228,7 @@ static void thread_0_entry(ULONG thread_input) UINT status; VOID *pointer; -CHAR *name; +TX_NAME_CONST CHAR *name; ULONG available; ULONG fragments; TX_THREAD *first_suspended; @@ -369,7 +371,7 @@ ULONG timeouts; status += tx_byte_pool_info_get(&byte_pool_0, &name, &available, &fragments, &first_suspended, &suspended_count, &next_pool); /* Check the status. */ - if ((status != TX_SUCCESS) || (available != byte_pool_0.tx_byte_pool_available) || (fragments != byte_pool_0.tx_byte_pool_fragments) || + if ((status != TX_SUCCESS) || (name != byte_pool_0.tx_byte_pool_name) || (available != byte_pool_0.tx_byte_pool_available) || (fragments != byte_pool_0.tx_byte_pool_fragments) || (first_suspended != &thread_4) || (suspended_count != byte_pool_0.tx_byte_pool_suspended_count) || (next_pool != &byte_pool_0)) { diff --git a/test/smp/regression/threadx_byte_memory_long_search_test.c b/test/smp/regression/threadx_byte_memory_long_search_test.c index 86a99be05..8f076335d 100644 --- a/test/smp/regression/threadx_byte_memory_long_search_test.c +++ b/test/smp/regression/threadx_byte_memory_long_search_test.c @@ -133,7 +133,7 @@ void threadx_byte_memory_long_search_application_define(void *first_unused_me UINT status; CHAR *pointer; UINT i; -CHAR *name; +TX_NAME_CONST CHAR *name; ULONG available; ULONG fragments; void *probe_ptr; @@ -259,7 +259,7 @@ static void thread_0_entry(ULONG thread_input) UINT status; UINT i; -CHAR *name; +TX_NAME_CONST CHAR *name; ULONG available; ULONG fragments; diff --git a/test/smp/regression/threadx_event_flag_basic_test.c b/test/smp/regression/threadx_event_flag_basic_test.c index 8ab990f7a..fed424a65 100644 --- a/test/smp/regression/threadx_event_flag_basic_test.c +++ b/test/smp/regression/threadx_event_flag_basic_test.c @@ -9,6 +9,8 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /* This test is designed to test simple event flag group creation, deletion, gets and sets. */ @@ -57,7 +59,7 @@ static TX_EVENT_FLAGS_GROUP group_3; static void thread_0_entry(ULONG thread_input); static void thread_1_entry(ULONG thread_input); -UINT _txe_event_flags_create(TX_EVENT_FLAGS_GROUP *group_ptr, CHAR *name_ptr, UINT event_control_block_size); +UINT _txe_event_flags_create(TX_EVENT_FLAGS_GROUP *group_ptr, TX_NAME_CONST CHAR *name_ptr, UINT event_control_block_size); /* Prototype for test control return. */ diff --git a/test/smp/regression/threadx_event_flag_information_test.c b/test/smp/regression/threadx_event_flag_information_test.c index 45e547f9c..1c7cfd2d8 100644 --- a/test/smp/regression/threadx_event_flag_information_test.c +++ b/test/smp/regression/threadx_event_flag_information_test.c @@ -9,6 +9,8 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /* This test is designed to test the event flag group information gathering services. */ #include @@ -134,7 +136,7 @@ static void thread_0_entry(ULONG thread_input) UINT status; ULONG actual_events; -CHAR *name; +TX_NAME_CONST CHAR *name; ULONG current_flags; TX_THREAD *first_suspended; ULONG suspended_count; @@ -356,7 +358,7 @@ ULONG timeouts; status += tx_event_flags_info_get(&group_0, &name, ¤t_flags, &first_suspended, &suspended_count, &next_group); /* Check the status. */ - if ((status != TX_SUCCESS) || (current_flags != group_0.tx_event_flags_group_current) || (first_suspended != TX_NULL) || (suspended_count != 0) || (next_group != &group_1)) + if ((status != TX_SUCCESS) || (name != group_0.tx_event_flags_group_name) || (current_flags != group_0.tx_event_flags_group_current) || (first_suspended != TX_NULL) || (suspended_count != 0) || (next_group != &group_1)) { /* Event flag error. */ diff --git a/test/smp/regression/threadx_mutex_basic_test.c b/test/smp/regression/threadx_mutex_basic_test.c index bb81eb9a3..5a652843c 100644 --- a/test/smp/regression/threadx_mutex_basic_test.c +++ b/test/smp/regression/threadx_mutex_basic_test.c @@ -9,6 +9,8 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /* This test is designed to test the mutex create/delete and immediate return gets and puts. */ @@ -69,7 +71,7 @@ static void thread_2_entry(ULONG thread_input); static void thread_3_entry(ULONG thread_input); static void thread_4_entry(ULONG thread_input); -UINT _txe_mutex_create(TX_MUTEX *mutex_ptr, CHAR *name_ptr, UINT inherit, UINT mutex_control_block_size); +UINT _txe_mutex_create(TX_MUTEX *mutex_ptr, TX_NAME_CONST CHAR *name_ptr, UINT inherit, UINT mutex_control_block_size); /* Prototype for test control return. */ diff --git a/test/smp/regression/threadx_mutex_information_test.c b/test/smp/regression/threadx_mutex_information_test.c index 3829122ce..fea78c043 100644 --- a/test/smp/regression/threadx_mutex_information_test.c +++ b/test/smp/regression/threadx_mutex_information_test.c @@ -9,6 +9,8 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /* This test is designed to test the mutex information services. */ #include @@ -134,7 +136,7 @@ static void thread_0_entry(ULONG thread_input) { UINT status; -CHAR *name; +TX_NAME_CONST CHAR *name; ULONG count; TX_THREAD *owner; TX_THREAD *first_suspended; @@ -300,7 +302,7 @@ ULONG inheritances; status += tx_mutex_info_get(&mutex_2, &name, &count, &owner, &first_suspended, &suspended_count, &next_mutex); /* Check status. */ - if ((status != TX_SUCCESS) || (count != mutex_2.tx_mutex_ownership_count) || (owner != mutex_2.tx_mutex_owner) || + if ((status != TX_SUCCESS) || (name != mutex_2.tx_mutex_name) || (count != mutex_2.tx_mutex_ownership_count) || (owner != mutex_2.tx_mutex_owner) || (first_suspended != mutex_2.tx_mutex_suspension_list) || (suspended_count != mutex_2.tx_mutex_suspended_count) || (next_mutex != mutex_2.tx_mutex_created_next)) { diff --git a/test/smp/regression/threadx_queue_basic_one_word_test.c b/test/smp/regression/threadx_queue_basic_one_word_test.c index 1abb69861..58142471e 100644 --- a/test/smp/regression/threadx_queue_basic_one_word_test.c +++ b/test/smp/regression/threadx_queue_basic_one_word_test.c @@ -9,6 +9,8 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /* This test is designed to test immediate response queue services including create and delete. This test is for queue sizes of 1 ULONG. Two queues are used one with a capacity of 1 message and another with a capacity of 3 messages. */ @@ -51,7 +53,7 @@ static void thread_0_entry(ULONG thread_input); static void thread_1_entry(ULONG thread_input); -UINT _txe_queue_create(TX_QUEUE *queue_ptr, CHAR *name_ptr, UINT message_size, +UINT _txe_queue_create(TX_QUEUE *queue_ptr, TX_NAME_CONST CHAR *name_ptr, UINT message_size, VOID *queue_start, ULONG queue_size, UINT queue_control_block_size); diff --git a/test/smp/regression/threadx_queue_information_test.c b/test/smp/regression/threadx_queue_information_test.c index f884bd0d6..8929c465b 100644 --- a/test/smp/regression/threadx_queue_information_test.c +++ b/test/smp/regression/threadx_queue_information_test.c @@ -9,6 +9,8 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /* This test is designed to test the queue information services. */ #include @@ -102,7 +104,7 @@ UINT status; ULONG source_message = 0x12345678UL; ULONG dest_message; ULONG expected_message; -CHAR *name; +TX_NAME_CONST CHAR *name; ULONG enqueued; ULONG available_storage; TX_THREAD *first_suspended; @@ -409,7 +411,7 @@ ULONG timeouts; status += tx_queue_info_get(&queue_0, &name, &enqueued, &available_storage, &first_suspended, &suspended_count, &next_queue); /* Check for errors. */ - if ((status != TX_SUCCESS) || (enqueued != queue_0.tx_queue_enqueued) || (available_storage != queue_0.tx_queue_available_storage) || + if ((status != TX_SUCCESS) || (name != queue_0.tx_queue_name) || (enqueued != queue_0.tx_queue_enqueued) || (available_storage != queue_0.tx_queue_available_storage) || (first_suspended != queue_0.tx_queue_suspension_list) || (suspended_count != queue_0.tx_queue_suspended_count) || (next_queue != queue_0.tx_queue_created_next)) { diff --git a/test/smp/regression/threadx_semaphore_basic_test.c b/test/smp/regression/threadx_semaphore_basic_test.c index 3209b5865..a1a3d3407 100644 --- a/test/smp/regression/threadx_semaphore_basic_test.c +++ b/test/smp/regression/threadx_semaphore_basic_test.c @@ -9,6 +9,8 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /* This test is designed to test the semaphore create/delete and immediate return gets and puts. */ #include @@ -62,7 +64,7 @@ static TX_SEMAPHORE semaphore_3; static void thread_0_entry(ULONG thread_input); static void thread_1_entry(ULONG thread_input); -UINT _txe_semaphore_create(TX_SEMAPHORE *semaphore_ptr, CHAR *name_ptr, ULONG initial_count, UINT semaphore_control_block_size); +UINT _txe_semaphore_create(TX_SEMAPHORE *semaphore_ptr, TX_NAME_CONST CHAR *name_ptr, ULONG initial_count, UINT semaphore_control_block_size); /* Prototype for test control return. */ diff --git a/test/smp/regression/threadx_semaphore_information_test.c b/test/smp/regression/threadx_semaphore_information_test.c index ede276e97..c0bb3c724 100644 --- a/test/smp/regression/threadx_semaphore_information_test.c +++ b/test/smp/regression/threadx_semaphore_information_test.c @@ -9,6 +9,8 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /* This test is designed to test the semaphore information services. */ #include @@ -100,7 +102,7 @@ static void thread_0_entry(ULONG thread_input) { UINT status; -CHAR *name; +TX_NAME_CONST CHAR *name; ULONG current_value; TX_THREAD *first_suspended; ULONG suspended_count; @@ -211,7 +213,7 @@ ULONG timeouts; status += tx_semaphore_info_get(&semaphore_0, &name, ¤t_value, &first_suspended, &suspended_count, &next_semaphore); /* Check status. */ - if ((status != TX_SUCCESS) || (current_value != semaphore_0.tx_semaphore_count) || + if ((status != TX_SUCCESS) || (name != semaphore_0.tx_semaphore_name) || (current_value != semaphore_0.tx_semaphore_count) || (first_suspended != semaphore_0.tx_semaphore_suspension_list) || (suspended_count != semaphore_0.tx_semaphore_suspended_count) || (next_semaphore != semaphore_0.tx_semaphore_created_next)) { diff --git a/test/smp/regression/threadx_thread_basic_execution_test.c b/test/smp/regression/threadx_thread_basic_execution_test.c index d90d07696..b0acc8424 100644 --- a/test/smp/regression/threadx_thread_basic_execution_test.c +++ b/test/smp/regression/threadx_thread_basic_execution_test.c @@ -9,6 +9,8 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /* This test is designed to see if one thread can be created and executed. It thread_0_entry is hit, then the thread was successfully scheduled. On success, thread_0_counter gets incremented. */ @@ -69,7 +71,7 @@ static unsigned long isr_executed = 0; static void thread_0_entry(ULONG task_input); -UINT _txe_thread_create(TX_THREAD *thread_ptr, CHAR *name_ptr, +UINT _txe_thread_create(TX_THREAD *thread_ptr, TX_NAME_CONST CHAR *name_ptr, VOID (*entry_function)(ULONG), ULONG entry_input, VOID *stack_start, ULONG stack_size, UINT priority, UINT preempt_threshold, diff --git a/test/smp/regression/threadx_thread_information_test.c b/test/smp/regression/threadx_thread_information_test.c index b5d06e71e..fef3473ff 100644 --- a/test/smp/regression/threadx_thread_information_test.c +++ b/test/smp/regression/threadx_thread_information_test.c @@ -9,6 +9,8 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /* This test is for the thread information services. */ #include @@ -63,7 +65,7 @@ static void thread_0_entry(ULONG thread_input) { UINT status; -CHAR *name; +TX_NAME_CONST CHAR *name; UINT state; ULONG run_count; UINT priority; @@ -96,7 +98,7 @@ ULONG idle_returns; status += tx_thread_info_get(&thread_0, &name, &state, &run_count, &priority, &preemption_threshold, &time_slice, &next_thread, &suspended_thread); /* Check for error status. */ - if ((status != TX_SUCCESS) || (state != TX_READY) || (run_count != thread_0.tx_thread_run_count) || (priority != 16) || (preemption_threshold != 16) || + if ((status != TX_SUCCESS) || (name != thread_0.tx_thread_name) || (state != TX_READY) || (run_count != thread_0.tx_thread_run_count) || (priority != 16) || (preemption_threshold != 16) || (time_slice != 0) || (next_thread != thread_0.tx_thread_created_next) || (suspended_thread != thread_0.tx_thread_suspended_next)) { diff --git a/test/smp/regression/threadx_timer_information_test.c b/test/smp/regression/threadx_timer_information_test.c index ae3bb4141..cbb882397 100644 --- a/test/smp/regression/threadx_timer_information_test.c +++ b/test/smp/regression/threadx_timer_information_test.c @@ -9,6 +9,8 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /* This test is designed to test timer information services. */ #include @@ -104,7 +106,7 @@ static void thread_0_entry(ULONG thread_input) UINT status; UINT interrupt_status; -CHAR *name; +TX_NAME_CONST CHAR *name; UINT active; ULONG remaining_ticks; ULONG reschedule_ticks; @@ -231,7 +233,7 @@ TX_TIMER_INTERNAL **list_head; status += tx_timer_info_get(&timer_0, &name, &active, &remaining_ticks, &reschedule_ticks, &next_timer); /* Check for successful completion. */ - if ((status != TX_SUCCESS) || (active != TX_TRUE) || (remaining_ticks != 100) || (reschedule_ticks != 200) || (next_timer != &timer_1)) + if ((status != TX_SUCCESS) || (name != timer_0.tx_timer_name) || (active != TX_TRUE) || (remaining_ticks != 100) || (reschedule_ticks != 200) || (next_timer != &timer_1)) { /* Application timer error. */ diff --git a/test/smp/regression/threadx_timer_simple_test.c b/test/smp/regression/threadx_timer_simple_test.c index e2272bd2e..5abd1d3c9 100644 --- a/test/smp/regression/threadx_timer_simple_test.c +++ b/test/smp/regression/threadx_timer_simple_test.c @@ -9,6 +9,8 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /* This test is designed to test a simple application timer services, including create, activate, deactivate, change, and delete. */ @@ -63,7 +65,7 @@ static void thread_1_entry(ULONG thread_input); static void timer_0_expiration(ULONG timer_input); static void timer_1_expiration(ULONG timer_input); -UINT _txe_timer_create(TX_TIMER *timer_ptr, CHAR *name_ptr, +UINT _txe_timer_create(TX_TIMER *timer_ptr, TX_NAME_CONST CHAR *name_ptr, VOID (*expiration_function)(ULONG), ULONG expiration_input, ULONG initial_ticks, ULONG reschedule_ticks, UINT auto_activate, UINT timer_control_block_size); diff --git a/test/smp/regression/threadx_trace_basic_test.c b/test/smp/regression/threadx_trace_basic_test.c index 51fa6256c..10b927bb0 100644 --- a/test/smp/regression/threadx_trace_basic_test.c +++ b/test/smp/regression/threadx_trace_basic_test.c @@ -9,6 +9,8 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /* This test is designed to test trace functionality in ThreadX. */ #include @@ -30,7 +32,7 @@ extern VOID (*test_isr_dispatch)(void); extern UINT _tx_trace_interrupt_control(UINT new_posture); -extern VOID _tx_trace_object_register(UCHAR object_type, VOID *object_ptr, CHAR *object_name, ULONG parameter_1, ULONG parameter_2); +extern VOID _tx_trace_object_register(UCHAR object_type, VOID *object_ptr, TX_NAME_CONST CHAR *object_name, ULONG parameter_1, ULONG parameter_2); extern VOID _tx_trace_object_unregister(VOID *object_ptr); static unsigned long thread_0_counter = 0; diff --git a/test/tx/module_manager/threadx_module_manager_block_pool_parameters_test.c b/test/tx/module_manager/threadx_module_manager_block_pool_parameters_test.c index fb3f6ff96..4fbd3e50b 100644 --- a/test/tx/module_manager/threadx_module_manager_block_pool_parameters_test.c +++ b/test/tx/module_manager/threadx_module_manager_block_pool_parameters_test.c @@ -414,7 +414,7 @@ static UINT test_service_record(ALIGN_TYPE object_ptr, ALIGN_TYPE name_ptr, ULO } -UINT _txe_block_pool_create(TX_BLOCK_POOL *pool_ptr, CHAR *name_ptr, ULONG block_size, +UINT _txe_block_pool_create(TX_BLOCK_POOL *pool_ptr, TX_NAME_CONST CHAR *name_ptr, ULONG block_size, VOID *pool_start, ULONG pool_size, UINT pool_control_block_size) { @@ -446,7 +446,7 @@ UINT status; } -UINT _txe_byte_pool_create(TX_BYTE_POOL *pool_ptr, CHAR *name_ptr, VOID *pool_start, +UINT _txe_byte_pool_create(TX_BYTE_POOL *pool_ptr, TX_NAME_CONST CHAR *name_ptr, VOID *pool_start, ULONG pool_size, UINT pool_control_block_size) { @@ -478,7 +478,7 @@ UINT status; } -UINT _txe_queue_create(TX_QUEUE *queue_ptr, CHAR *name_ptr, UINT message_size, +UINT _txe_queue_create(TX_QUEUE *queue_ptr, TX_NAME_CONST CHAR *name_ptr, UINT message_size, VOID *queue_start, ULONG queue_size, UINT queue_control_block_size) { diff --git a/test/tx/regression/threadx_block_memory_basic_test.c b/test/tx/regression/threadx_block_memory_basic_test.c index 94cc87935..d7c609d24 100644 --- a/test/tx/regression/threadx_block_memory_basic_test.c +++ b/test/tx/regression/threadx_block_memory_basic_test.c @@ -9,6 +9,8 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /* This test is designed to test simple memory block pool creation, deletion, and allocates and releases. */ @@ -72,7 +74,7 @@ void test_control_return(UINT status); /* Prototype direct call to block pool core service. */ -UINT _tx_block_pool_create(TX_BLOCK_POOL *pool_ptr, CHAR *name_ptr, ULONG block_size, +UINT _tx_block_pool_create(TX_BLOCK_POOL *pool_ptr, TX_NAME_CONST CHAR *name_ptr, ULONG block_size, VOID *pool_start, ULONG pool_size); diff --git a/test/tx/regression/threadx_block_memory_error_detection_test.c b/test/tx/regression/threadx_block_memory_error_detection_test.c index 41148120f..b0303b762 100644 --- a/test/tx/regression/threadx_block_memory_error_detection_test.c +++ b/test/tx/regression/threadx_block_memory_error_detection_test.c @@ -9,6 +9,8 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /* This test is designed to test error detection for simple memory block operations. */ #include @@ -29,7 +31,7 @@ static CHAR *pointer; static void thread_0_entry(ULONG thread_input); -UINT _txe_block_pool_create(TX_BLOCK_POOL *pool_ptr, CHAR *name_ptr, ULONG block_size, +UINT _txe_block_pool_create(TX_BLOCK_POOL *pool_ptr, TX_NAME_CONST CHAR *name_ptr, ULONG block_size, VOID *pool_start, ULONG pool_size, UINT pool_control_block_size); diff --git a/test/tx/regression/threadx_block_memory_information_test.c b/test/tx/regression/threadx_block_memory_information_test.c index 82d57f40a..0c04cb7ee 100644 --- a/test/tx/regression/threadx_block_memory_information_test.c +++ b/test/tx/regression/threadx_block_memory_information_test.c @@ -9,6 +9,8 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /* This test is designed to test block memory information services. */ #include @@ -68,7 +70,7 @@ static void thread_5_entry(ULONG thread_input); static void thread_6_entry(ULONG thread_input); /* Direct core function to bypass the error checking shell. */ -UINT _tx_block_pool_info_get(TX_BLOCK_POOL *pool_ptr, CHAR **name, ULONG *available_blocks, +UINT _tx_block_pool_info_get(TX_BLOCK_POOL *pool_ptr, TX_NAME_CONST CHAR **name, ULONG *available_blocks, ULONG *total_blocks, TX_THREAD **first_suspended, ULONG *suspended_count, TX_BLOCK_POOL **next_pool); @@ -227,7 +229,7 @@ static void thread_0_entry(ULONG thread_input) UINT status; VOID *pointer; -CHAR *name; +TX_NAME_CONST CHAR *name; ULONG available; ULONG total_blocks; TX_THREAD *first_suspended; @@ -369,7 +371,7 @@ ULONG timeouts; status += tx_block_pool_info_get(&block_pool_0, &name, &available, &total_blocks, &first_suspended, &suspended_count, &next_pool); /* Check for an error condition. */ - if ((status) || (available != block_pool_0.tx_block_pool_available) || (total_blocks != block_pool_0.tx_block_pool_total) || + if ((status) || (name != block_pool_0.tx_block_pool_name) || (available != block_pool_0.tx_block_pool_available) || (total_blocks != block_pool_0.tx_block_pool_total) || (first_suspended != &thread_4) || (suspended_count != block_pool_0.tx_block_pool_suspended_count) || (next_pool != &block_pool_0)) { diff --git a/test/tx/regression/threadx_byte_memory_basic_test.c b/test/tx/regression/threadx_byte_memory_basic_test.c index 45f92e121..6b916f678 100644 --- a/test/tx/regression/threadx_byte_memory_basic_test.c +++ b/test/tx/regression/threadx_byte_memory_basic_test.c @@ -9,6 +9,8 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /* This test is designed to test simple memory byte pool creation, deletion, and allocates and releases. */ @@ -51,7 +53,7 @@ extern UINT test_byte_pool_create_init; extern VOID (*test_isr_dispatch)(void); -UINT _txe_byte_pool_create(TX_BYTE_POOL *pool_ptr, CHAR *name_ptr, VOID *pool_start, +UINT _txe_byte_pool_create(TX_BYTE_POOL *pool_ptr, TX_NAME_CONST CHAR *name_ptr, VOID *pool_start, ULONG pool_size, UINT pool_control_block_size); diff --git a/test/tx/regression/threadx_byte_memory_information_test.c b/test/tx/regression/threadx_byte_memory_information_test.c index f1624a65a..f65efac3f 100644 --- a/test/tx/regression/threadx_byte_memory_information_test.c +++ b/test/tx/regression/threadx_byte_memory_information_test.c @@ -9,6 +9,8 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /* This test is designed to test byte memory information. */ #include @@ -226,7 +228,7 @@ static void thread_0_entry(ULONG thread_input) UINT status; VOID *pointer; -CHAR *name; +TX_NAME_CONST CHAR *name; ULONG available; ULONG fragments; TX_THREAD *first_suspended; @@ -369,7 +371,7 @@ ULONG timeouts; status += tx_byte_pool_info_get(&byte_pool_0, &name, &available, &fragments, &first_suspended, &suspended_count, &next_pool); /* Check the status. */ - if ((status != TX_SUCCESS) || (available != byte_pool_0.tx_byte_pool_available) || (fragments != byte_pool_0.tx_byte_pool_fragments) || + if ((status != TX_SUCCESS) || (name != byte_pool_0.tx_byte_pool_name) || (available != byte_pool_0.tx_byte_pool_available) || (fragments != byte_pool_0.tx_byte_pool_fragments) || (first_suspended != &thread_4) || (suspended_count != byte_pool_0.tx_byte_pool_suspended_count) || (next_pool != &byte_pool_0)) { diff --git a/test/tx/regression/threadx_event_flag_basic_test.c b/test/tx/regression/threadx_event_flag_basic_test.c index 8ab990f7a..fed424a65 100644 --- a/test/tx/regression/threadx_event_flag_basic_test.c +++ b/test/tx/regression/threadx_event_flag_basic_test.c @@ -9,6 +9,8 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /* This test is designed to test simple event flag group creation, deletion, gets and sets. */ @@ -57,7 +59,7 @@ static TX_EVENT_FLAGS_GROUP group_3; static void thread_0_entry(ULONG thread_input); static void thread_1_entry(ULONG thread_input); -UINT _txe_event_flags_create(TX_EVENT_FLAGS_GROUP *group_ptr, CHAR *name_ptr, UINT event_control_block_size); +UINT _txe_event_flags_create(TX_EVENT_FLAGS_GROUP *group_ptr, TX_NAME_CONST CHAR *name_ptr, UINT event_control_block_size); /* Prototype for test control return. */ diff --git a/test/tx/regression/threadx_event_flag_information_test.c b/test/tx/regression/threadx_event_flag_information_test.c index 45e547f9c..1c7cfd2d8 100644 --- a/test/tx/regression/threadx_event_flag_information_test.c +++ b/test/tx/regression/threadx_event_flag_information_test.c @@ -9,6 +9,8 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /* This test is designed to test the event flag group information gathering services. */ #include @@ -134,7 +136,7 @@ static void thread_0_entry(ULONG thread_input) UINT status; ULONG actual_events; -CHAR *name; +TX_NAME_CONST CHAR *name; ULONG current_flags; TX_THREAD *first_suspended; ULONG suspended_count; @@ -356,7 +358,7 @@ ULONG timeouts; status += tx_event_flags_info_get(&group_0, &name, ¤t_flags, &first_suspended, &suspended_count, &next_group); /* Check the status. */ - if ((status != TX_SUCCESS) || (current_flags != group_0.tx_event_flags_group_current) || (first_suspended != TX_NULL) || (suspended_count != 0) || (next_group != &group_1)) + if ((status != TX_SUCCESS) || (name != group_0.tx_event_flags_group_name) || (current_flags != group_0.tx_event_flags_group_current) || (first_suspended != TX_NULL) || (suspended_count != 0) || (next_group != &group_1)) { /* Event flag error. */ diff --git a/test/tx/regression/threadx_mutex_basic_test.c b/test/tx/regression/threadx_mutex_basic_test.c index bb81eb9a3..5a652843c 100644 --- a/test/tx/regression/threadx_mutex_basic_test.c +++ b/test/tx/regression/threadx_mutex_basic_test.c @@ -9,6 +9,8 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /* This test is designed to test the mutex create/delete and immediate return gets and puts. */ @@ -69,7 +71,7 @@ static void thread_2_entry(ULONG thread_input); static void thread_3_entry(ULONG thread_input); static void thread_4_entry(ULONG thread_input); -UINT _txe_mutex_create(TX_MUTEX *mutex_ptr, CHAR *name_ptr, UINT inherit, UINT mutex_control_block_size); +UINT _txe_mutex_create(TX_MUTEX *mutex_ptr, TX_NAME_CONST CHAR *name_ptr, UINT inherit, UINT mutex_control_block_size); /* Prototype for test control return. */ diff --git a/test/tx/regression/threadx_mutex_information_test.c b/test/tx/regression/threadx_mutex_information_test.c index 3829122ce..fea78c043 100644 --- a/test/tx/regression/threadx_mutex_information_test.c +++ b/test/tx/regression/threadx_mutex_information_test.c @@ -9,6 +9,8 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /* This test is designed to test the mutex information services. */ #include @@ -134,7 +136,7 @@ static void thread_0_entry(ULONG thread_input) { UINT status; -CHAR *name; +TX_NAME_CONST CHAR *name; ULONG count; TX_THREAD *owner; TX_THREAD *first_suspended; @@ -300,7 +302,7 @@ ULONG inheritances; status += tx_mutex_info_get(&mutex_2, &name, &count, &owner, &first_suspended, &suspended_count, &next_mutex); /* Check status. */ - if ((status != TX_SUCCESS) || (count != mutex_2.tx_mutex_ownership_count) || (owner != mutex_2.tx_mutex_owner) || + if ((status != TX_SUCCESS) || (name != mutex_2.tx_mutex_name) || (count != mutex_2.tx_mutex_ownership_count) || (owner != mutex_2.tx_mutex_owner) || (first_suspended != mutex_2.tx_mutex_suspension_list) || (suspended_count != mutex_2.tx_mutex_suspended_count) || (next_mutex != mutex_2.tx_mutex_created_next)) { diff --git a/test/tx/regression/threadx_queue_basic_one_word_test.c b/test/tx/regression/threadx_queue_basic_one_word_test.c index 1abb69861..58142471e 100644 --- a/test/tx/regression/threadx_queue_basic_one_word_test.c +++ b/test/tx/regression/threadx_queue_basic_one_word_test.c @@ -9,6 +9,8 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /* This test is designed to test immediate response queue services including create and delete. This test is for queue sizes of 1 ULONG. Two queues are used one with a capacity of 1 message and another with a capacity of 3 messages. */ @@ -51,7 +53,7 @@ static void thread_0_entry(ULONG thread_input); static void thread_1_entry(ULONG thread_input); -UINT _txe_queue_create(TX_QUEUE *queue_ptr, CHAR *name_ptr, UINT message_size, +UINT _txe_queue_create(TX_QUEUE *queue_ptr, TX_NAME_CONST CHAR *name_ptr, UINT message_size, VOID *queue_start, ULONG queue_size, UINT queue_control_block_size); diff --git a/test/tx/regression/threadx_queue_information_test.c b/test/tx/regression/threadx_queue_information_test.c index f884bd0d6..8929c465b 100644 --- a/test/tx/regression/threadx_queue_information_test.c +++ b/test/tx/regression/threadx_queue_information_test.c @@ -9,6 +9,8 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /* This test is designed to test the queue information services. */ #include @@ -102,7 +104,7 @@ UINT status; ULONG source_message = 0x12345678UL; ULONG dest_message; ULONG expected_message; -CHAR *name; +TX_NAME_CONST CHAR *name; ULONG enqueued; ULONG available_storage; TX_THREAD *first_suspended; @@ -409,7 +411,7 @@ ULONG timeouts; status += tx_queue_info_get(&queue_0, &name, &enqueued, &available_storage, &first_suspended, &suspended_count, &next_queue); /* Check for errors. */ - if ((status != TX_SUCCESS) || (enqueued != queue_0.tx_queue_enqueued) || (available_storage != queue_0.tx_queue_available_storage) || + if ((status != TX_SUCCESS) || (name != queue_0.tx_queue_name) || (enqueued != queue_0.tx_queue_enqueued) || (available_storage != queue_0.tx_queue_available_storage) || (first_suspended != queue_0.tx_queue_suspension_list) || (suspended_count != queue_0.tx_queue_suspended_count) || (next_queue != queue_0.tx_queue_created_next)) { diff --git a/test/tx/regression/threadx_semaphore_basic_test.c b/test/tx/regression/threadx_semaphore_basic_test.c index 3209b5865..a1a3d3407 100644 --- a/test/tx/regression/threadx_semaphore_basic_test.c +++ b/test/tx/regression/threadx_semaphore_basic_test.c @@ -9,6 +9,8 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /* This test is designed to test the semaphore create/delete and immediate return gets and puts. */ #include @@ -62,7 +64,7 @@ static TX_SEMAPHORE semaphore_3; static void thread_0_entry(ULONG thread_input); static void thread_1_entry(ULONG thread_input); -UINT _txe_semaphore_create(TX_SEMAPHORE *semaphore_ptr, CHAR *name_ptr, ULONG initial_count, UINT semaphore_control_block_size); +UINT _txe_semaphore_create(TX_SEMAPHORE *semaphore_ptr, TX_NAME_CONST CHAR *name_ptr, ULONG initial_count, UINT semaphore_control_block_size); /* Prototype for test control return. */ diff --git a/test/tx/regression/threadx_semaphore_information_test.c b/test/tx/regression/threadx_semaphore_information_test.c index ede276e97..c0bb3c724 100644 --- a/test/tx/regression/threadx_semaphore_information_test.c +++ b/test/tx/regression/threadx_semaphore_information_test.c @@ -9,6 +9,8 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /* This test is designed to test the semaphore information services. */ #include @@ -100,7 +102,7 @@ static void thread_0_entry(ULONG thread_input) { UINT status; -CHAR *name; +TX_NAME_CONST CHAR *name; ULONG current_value; TX_THREAD *first_suspended; ULONG suspended_count; @@ -211,7 +213,7 @@ ULONG timeouts; status += tx_semaphore_info_get(&semaphore_0, &name, ¤t_value, &first_suspended, &suspended_count, &next_semaphore); /* Check status. */ - if ((status != TX_SUCCESS) || (current_value != semaphore_0.tx_semaphore_count) || + if ((status != TX_SUCCESS) || (name != semaphore_0.tx_semaphore_name) || (current_value != semaphore_0.tx_semaphore_count) || (first_suspended != semaphore_0.tx_semaphore_suspension_list) || (suspended_count != semaphore_0.tx_semaphore_suspended_count) || (next_semaphore != semaphore_0.tx_semaphore_created_next)) { diff --git a/test/tx/regression/threadx_thread_basic_execution_test.c b/test/tx/regression/threadx_thread_basic_execution_test.c index 8e9586f28..ea9b11773 100644 --- a/test/tx/regression/threadx_thread_basic_execution_test.c +++ b/test/tx/regression/threadx_thread_basic_execution_test.c @@ -73,7 +73,7 @@ extern TX_TIMER_INTERNAL *_tx_timer_expired_timer_ptr; static void thread_0_entry(ULONG task_input); -UINT _txe_thread_create(TX_THREAD *thread_ptr, CHAR *name_ptr, +UINT _txe_thread_create(TX_THREAD *thread_ptr, TX_NAME_CONST CHAR *name_ptr, VOID (*entry_function)(ULONG), ULONG entry_input, VOID *stack_start, ULONG stack_size, UINT priority, UINT preempt_threshold, diff --git a/test/tx/regression/threadx_thread_information_test.c b/test/tx/regression/threadx_thread_information_test.c index b5d06e71e..fef3473ff 100644 --- a/test/tx/regression/threadx_thread_information_test.c +++ b/test/tx/regression/threadx_thread_information_test.c @@ -9,6 +9,8 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /* This test is for the thread information services. */ #include @@ -63,7 +65,7 @@ static void thread_0_entry(ULONG thread_input) { UINT status; -CHAR *name; +TX_NAME_CONST CHAR *name; UINT state; ULONG run_count; UINT priority; @@ -96,7 +98,7 @@ ULONG idle_returns; status += tx_thread_info_get(&thread_0, &name, &state, &run_count, &priority, &preemption_threshold, &time_slice, &next_thread, &suspended_thread); /* Check for error status. */ - if ((status != TX_SUCCESS) || (state != TX_READY) || (run_count != thread_0.tx_thread_run_count) || (priority != 16) || (preemption_threshold != 16) || + if ((status != TX_SUCCESS) || (name != thread_0.tx_thread_name) || (state != TX_READY) || (run_count != thread_0.tx_thread_run_count) || (priority != 16) || (preemption_threshold != 16) || (time_slice != 0) || (next_thread != thread_0.tx_thread_created_next) || (suspended_thread != thread_0.tx_thread_suspended_next)) { diff --git a/test/tx/regression/threadx_timer_information_test.c b/test/tx/regression/threadx_timer_information_test.c index ae3bb4141..cbb882397 100644 --- a/test/tx/regression/threadx_timer_information_test.c +++ b/test/tx/regression/threadx_timer_information_test.c @@ -9,6 +9,8 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /* This test is designed to test timer information services. */ #include @@ -104,7 +106,7 @@ static void thread_0_entry(ULONG thread_input) UINT status; UINT interrupt_status; -CHAR *name; +TX_NAME_CONST CHAR *name; UINT active; ULONG remaining_ticks; ULONG reschedule_ticks; @@ -231,7 +233,7 @@ TX_TIMER_INTERNAL **list_head; status += tx_timer_info_get(&timer_0, &name, &active, &remaining_ticks, &reschedule_ticks, &next_timer); /* Check for successful completion. */ - if ((status != TX_SUCCESS) || (active != TX_TRUE) || (remaining_ticks != 100) || (reschedule_ticks != 200) || (next_timer != &timer_1)) + if ((status != TX_SUCCESS) || (name != timer_0.tx_timer_name) || (active != TX_TRUE) || (remaining_ticks != 100) || (reschedule_ticks != 200) || (next_timer != &timer_1)) { /* Application timer error. */ diff --git a/test/tx/regression/threadx_timer_simple_test.c b/test/tx/regression/threadx_timer_simple_test.c index cad670861..f9c93ee42 100644 --- a/test/tx/regression/threadx_timer_simple_test.c +++ b/test/tx/regression/threadx_timer_simple_test.c @@ -9,6 +9,8 @@ /* SPDX-License-Identifier: MIT */ /***************************************************************************/ +/* Portions of this file were generated with AI assistance. */ + /* This test is designed to test a simple application timer services, including create, activate, deactivate, change, and delete. */ @@ -63,7 +65,7 @@ static void thread_1_entry(ULONG thread_input); static void timer_0_expiration(ULONG timer_input); static void timer_1_expiration(ULONG timer_input); -UINT _txe_timer_create(TX_TIMER *timer_ptr, CHAR *name_ptr, +UINT _txe_timer_create(TX_TIMER *timer_ptr, TX_NAME_CONST CHAR *name_ptr, VOID (*expiration_function)(ULONG), ULONG expiration_input, ULONG initial_ticks, ULONG reschedule_ticks, UINT auto_activate, UINT timer_control_block_size); diff --git a/test/tx/regression/threadx_trace_basic_test.c b/test/tx/regression/threadx_trace_basic_test.c index 19f6953be..cacf72b36 100644 --- a/test/tx/regression/threadx_trace_basic_test.c +++ b/test/tx/regression/threadx_trace_basic_test.c @@ -25,7 +25,7 @@ extern VOID (*test_isr_dispatch)(void); extern UINT _tx_trace_interrupt_control(UINT new_posture); -extern VOID _tx_trace_object_register(UCHAR object_type, VOID *object_ptr, CHAR *object_name, ULONG parameter_1, ULONG parameter_2); +extern VOID _tx_trace_object_register(UCHAR object_type, VOID *object_ptr, TX_NAME_CONST CHAR *object_name, ULONG parameter_1, ULONG parameter_2); extern VOID _tx_trace_object_unregister(VOID *object_ptr); static unsigned long thread_0_counter = 0; diff --git a/utility/rtos_compatibility_layers/FreeRTOS/tx_freertos.c b/utility/rtos_compatibility_layers/FreeRTOS/tx_freertos.c index 1cceafb3b..3391bf8af 100644 --- a/utility/rtos_compatibility_layers/FreeRTOS/tx_freertos.c +++ b/utility/rtos_compatibility_layers/FreeRTOS/tx_freertos.c @@ -652,7 +652,7 @@ void vTaskPrioritySet(TaskHandle_t xTask, char *pcTaskGetName(TaskHandle_t xTaskToQuery) { TX_THREAD *p_thread; - char *p_task_name; + const char *p_task_name; UINT ret; if(xTaskToQuery == NULL) { @@ -667,7 +667,8 @@ char *pcTaskGetName(TaskHandle_t xTaskToQuery) return 0; } - return p_task_name; + /* FreeRTOS exposes task names through a writable pointer type. */ + return (char *)p_task_name; } From a7ded6a3b9e12985a6c52af4df419d2326cccc0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 28 Sep 2026 14:36:10 -0400 Subject: [PATCH 174/181] Updated ThreadX version constants and port strings to 6.5.2.202603 (#781) ThreadX still declares 6.5.1.202602 with hotfix 'a', which is the previous release rather than the one being cut. prepare_release.sh updated the five version constants in tx_api.h and the version string in 211 port headers across ports, ports_smp, ports_arch and ports_module. The hotfix letter is cleared, since the target has none. Nothing else changed: every line in the port commit carries a version, and no file outside an inc/tx_port.h was touched. The port consistency checks passed before the branch was cut, which is what the script gates on. Host regression 113/113 with zero warnings, and the AI disclosure check passes. Assisted-by: Claude Code (Opus 5) --- common/inc/tx_api.h | 6 +++--- ports/arc_em/metaware/inc/tx_port.h | 2 +- ports/arc_hs/metaware/inc/tx_port.h | 2 +- ports/arm11/ac5/inc/tx_port.h | 2 +- ports/arm11/gnu/inc/tx_port.h | 2 +- ports/arm11/iar/inc/tx_port.h | 2 +- ports/arm9/ac5/inc/tx_port.h | 2 +- ports/arm9/gnu/inc/tx_port.h | 2 +- ports/arm9/iar/inc/tx_port.h | 2 +- ports/c667x/ccs/inc/tx_port.h | 2 +- ports/cortex_a12/ac6/inc/tx_port.h | 2 +- ports/cortex_a12/gnu/inc/tx_port.h | 2 +- ports/cortex_a15/ac6/inc/tx_port.h | 2 +- ports/cortex_a15/gnu/inc/tx_port.h | 2 +- ports/cortex_a15/iar/inc/tx_port.h | 2 +- ports/cortex_a17/ac6/inc/tx_port.h | 2 +- ports/cortex_a17/gnu/inc/tx_port.h | 2 +- ports/cortex_a34/ac6/inc/tx_port.h | 2 +- ports/cortex_a34/gnu/inc/tx_port.h | 2 +- ports/cortex_a35/ac6/inc/tx_port.h | 2 +- ports/cortex_a35/gnu/inc/tx_port.h | 2 +- ports/cortex_a5/ac5/inc/tx_port.h | 2 +- ports/cortex_a5/ac6/inc/tx_port.h | 2 +- ports/cortex_a5/ghs/inc/tx_port.h | 2 +- ports/cortex_a5/gnu/inc/tx_port.h | 2 +- ports/cortex_a5/iar/inc/tx_port.h | 2 +- ports/cortex_a53/ac6/inc/tx_port.h | 2 +- ports/cortex_a53/gnu/inc/tx_port.h | 2 +- ports/cortex_a55/ac6/inc/tx_port.h | 2 +- ports/cortex_a55/gnu/inc/tx_port.h | 2 +- ports/cortex_a57/ac6/inc/tx_port.h | 2 +- ports/cortex_a57/gnu/inc/tx_port.h | 2 +- ports/cortex_a5x/ac6/inc/tx_port.h | 2 +- ports/cortex_a65/ac6/inc/tx_port.h | 2 +- ports/cortex_a65/gnu/inc/tx_port.h | 2 +- ports/cortex_a65ae/ac6/inc/tx_port.h | 2 +- ports/cortex_a65ae/gnu/inc/tx_port.h | 2 +- ports/cortex_a7/ac5/inc/tx_port.h | 2 +- ports/cortex_a7/ac6/inc/tx_port.h | 2 +- ports/cortex_a7/ghs/inc/tx_port.h | 2 +- ports/cortex_a7/gnu/inc/tx_port.h | 2 +- ports/cortex_a7/iar/inc/tx_port.h | 2 +- ports/cortex_a72/ac6/inc/tx_port.h | 2 +- ports/cortex_a72/gnu/inc/tx_port.h | 2 +- ports/cortex_a73/ac6/inc/tx_port.h | 2 +- ports/cortex_a73/gnu/inc/tx_port.h | 2 +- ports/cortex_a75/ac6/inc/tx_port.h | 2 +- ports/cortex_a75/gnu/inc/tx_port.h | 2 +- ports/cortex_a76/ac6/inc/tx_port.h | 2 +- ports/cortex_a76/gnu/inc/tx_port.h | 2 +- ports/cortex_a76ae/ac6/inc/tx_port.h | 2 +- ports/cortex_a76ae/gnu/inc/tx_port.h | 2 +- ports/cortex_a77/ac6/inc/tx_port.h | 2 +- ports/cortex_a77/gnu/inc/tx_port.h | 2 +- ports/cortex_a8/ac5/inc/tx_port.h | 2 +- ports/cortex_a8/ac6/inc/tx_port.h | 2 +- ports/cortex_a8/ghs/inc/tx_port.h | 2 +- ports/cortex_a8/gnu/inc/tx_port.h | 2 +- ports/cortex_a8/iar/inc/tx_port.h | 2 +- ports/cortex_a9/ac5/inc/tx_port.h | 2 +- ports/cortex_a9/ac6/inc/tx_port.h | 2 +- ports/cortex_a9/ghs/inc/tx_port.h | 2 +- ports/cortex_a9/gnu/inc/tx_port.h | 2 +- ports/cortex_a9/iar/inc/tx_port.h | 2 +- ports/cortex_m0/ac5/inc/tx_port.h | 2 +- ports/cortex_m0/ac6/inc/tx_port.h | 2 +- ports/cortex_m0/gnu/inc/tx_port.h | 2 +- ports/cortex_m0/iar/inc/tx_port.h | 2 +- ports/cortex_m0/keil/inc/tx_port.h | 2 +- ports/cortex_m23/ac6/inc/tx_port.h | 2 +- ports/cortex_m23/gnu/inc/tx_port.h | 2 +- ports/cortex_m23/iar/inc/tx_port.h | 2 +- ports/cortex_m3/ac5/inc/tx_port.h | 2 +- ports/cortex_m3/ac6/inc/tx_port.h | 2 +- ports/cortex_m3/ghs/inc/tx_port.h | 2 +- ports/cortex_m3/gnu/inc/tx_port.h | 2 +- ports/cortex_m3/iar/inc/tx_port.h | 2 +- ports/cortex_m3/keil/inc/tx_port.h | 2 +- ports/cortex_m33/ac6/inc/tx_port.h | 2 +- ports/cortex_m33/gnu/inc/tx_port.h | 2 +- ports/cortex_m33/iar/inc/tx_port.h | 2 +- ports/cortex_m4/ac5/inc/tx_port.h | 2 +- ports/cortex_m4/ac6/inc/tx_port.h | 2 +- ports/cortex_m4/ghs/inc/tx_port.h | 2 +- ports/cortex_m4/gnu/inc/tx_port.h | 2 +- ports/cortex_m4/iar/inc/tx_port.h | 2 +- ports/cortex_m4/keil/inc/tx_port.h | 2 +- ports/cortex_m52/ac6/inc/tx_port.h | 2 +- ports/cortex_m52/gnu/inc/tx_port.h | 2 +- ports/cortex_m52/iar/inc/tx_port.h | 2 +- ports/cortex_m55/ac6/inc/tx_port.h | 2 +- ports/cortex_m55/gnu/inc/tx_port.h | 2 +- ports/cortex_m55/iar/inc/tx_port.h | 2 +- ports/cortex_m7/ac5/inc/tx_port.h | 2 +- ports/cortex_m7/ac6/inc/tx_port.h | 2 +- ports/cortex_m7/ghs/inc/tx_port.h | 2 +- ports/cortex_m7/gnu/inc/tx_port.h | 2 +- ports/cortex_m7/iar/inc/tx_port.h | 2 +- ports/cortex_m85/ac6/inc/tx_port.h | 2 +- ports/cortex_m85/gnu/inc/tx_port.h | 2 +- ports/cortex_m85/iar/inc/tx_port.h | 2 +- ports/cortex_r4/ac5/inc/tx_port.h | 2 +- ports/cortex_r4/ac6/inc/tx_port.h | 2 +- ports/cortex_r4/ghs/inc/tx_port.h | 2 +- ports/cortex_r4/gnu/inc/tx_port.h | 2 +- ports/cortex_r4/iar/inc/tx_port.h | 2 +- ports/cortex_r5/ac5/inc/tx_port.h | 2 +- ports/cortex_r5/ac6/inc/tx_port.h | 2 +- ports/cortex_r5/ghs/inc/tx_port.h | 2 +- ports/cortex_r5/gnu/inc/tx_port.h | 2 +- ports/cortex_r5/iar/inc/tx_port.h | 2 +- ports/cortex_r52/gnu/inc/tx_port.h | 2 +- ports/cortex_r7/ghs/inc/tx_port.h | 2 +- ports/linux/gnu/inc/tx_port.h | 2 +- ports/risc-v32/clang/inc/tx_port.h | 2 +- ports/risc-v32/gnu/inc/tx_port.h | 2 +- ports/risc-v64/gnu/inc/tx_port.h | 2 +- ports/rxv1/ccrx/inc/tx_port.h | 2 +- ports/rxv1/gnu/inc/tx_port.h | 2 +- ports/rxv1/iar/inc/tx_port.h | 2 +- ports/rxv2/ccrx/inc/tx_port.h | 2 +- ports/rxv2/gnu/inc/tx_port.h | 2 +- ports/rxv2/iar/inc/tx_port.h | 2 +- ports/rxv3/ccrx/inc/tx_port.h | 2 +- ports/rxv3/gnu/inc/tx_port.h | 2 +- ports/rxv3/iar/inc/tx_port.h | 2 +- ports/win32/vs_2019/inc/tx_port.h | 2 +- ports/win64/vs_2022/inc/tx_port.h | 2 +- ports/xtensa/xcc/inc/tx_port.h | 2 +- ports_arch/ARMv7-A/threadx/common/inc/tx_port.h | 2 +- ports_arch/ARMv7-M/threadx/ghs/inc/tx_port.h | 2 +- ports_arch/ARMv7-M/threadx/inc/tx_port.h | 2 +- ports_arch/ARMv7-M/threadx_modules/inc/tx_port.h | 2 +- ports_arch/ARMv8-A/threadx/common/inc/tx_port.h | 2 +- ports_arch/ARMv8-A/threadx_smp/common/inc/tx_port.h | 2 +- ports_arch/ARMv8-M/threadx/inc/tx_port.h | 2 +- ports_module/cortex_a35/ac6/inc/tx_port.h | 2 +- ports_module/cortex_a35/gnu/inc/tx_port.h | 2 +- ports_module/cortex_a35_smp/ac6/inc/tx_port.h | 2 +- ports_module/cortex_a35_smp/gnu/inc/tx_port.h | 2 +- ports_module/cortex_a7/ac5/inc/tx_port.h | 2 +- ports_module/cortex_a7/gnu/inc/tx_port.h | 2 +- ports_module/cortex_a7/iar/inc/tx_port.h | 2 +- ports_module/cortex_m0+/ac6/inc/tx_port.h | 2 +- ports_module/cortex_m0+/gnu/inc/tx_port.h | 2 +- ports_module/cortex_m0+/iar/inc/tx_port.h | 2 +- ports_module/cortex_m23/ac6/inc/tx_port.h | 2 +- ports_module/cortex_m23/gnu/inc/tx_port.h | 2 +- ports_module/cortex_m23/iar/inc/tx_port.h | 2 +- ports_module/cortex_m3/ac5/inc/tx_port.h | 2 +- ports_module/cortex_m3/ac6/inc/tx_port.h | 2 +- ports_module/cortex_m3/gnu/inc/tx_port.h | 2 +- ports_module/cortex_m3/iar/inc/tx_port.h | 2 +- ports_module/cortex_m33/ac6/inc/tx_port.h | 2 +- ports_module/cortex_m33/gnu/inc/tx_port.h | 2 +- ports_module/cortex_m33/iar/inc/tx_port.h | 2 +- ports_module/cortex_m4/ac5/inc/tx_port.h | 2 +- ports_module/cortex_m4/ac6/inc/tx_port.h | 2 +- ports_module/cortex_m4/gnu/inc/tx_port.h | 2 +- ports_module/cortex_m4/iar/inc/tx_port.h | 2 +- ports_module/cortex_m7/ac5/inc/tx_port.h | 2 +- ports_module/cortex_m7/ac6/inc/tx_port.h | 2 +- ports_module/cortex_m7/gnu/inc/tx_port.h | 2 +- ports_module/cortex_m7/iar/inc/tx_port.h | 2 +- ports_module/cortex_r4/ac6/inc/tx_port.h | 2 +- ports_module/cortex_r4/iar/inc/tx_port.h | 2 +- ports_module/cortex_r52/gnu/inc/tx_port.h | 2 +- ports_module/rxv2/iar/inc/tx_port.h | 2 +- ports_smp/arc_hs_smp/metaware/inc/tx_port.h | 2 +- ports_smp/cortex_a34_smp/ac6/inc/tx_port.h | 2 +- ports_smp/cortex_a34_smp/gnu/inc/tx_port.h | 2 +- ports_smp/cortex_a35_smp/ac6/inc/tx_port.h | 2 +- ports_smp/cortex_a35_smp/gnu/inc/tx_port.h | 2 +- ports_smp/cortex_a53_smp/ac6/inc/tx_port.h | 2 +- ports_smp/cortex_a53_smp/gnu/inc/tx_port.h | 2 +- ports_smp/cortex_a55_smp/ac6/inc/tx_port.h | 2 +- ports_smp/cortex_a55_smp/gnu/inc/tx_port.h | 2 +- ports_smp/cortex_a57_smp/ac6/inc/tx_port.h | 2 +- ports_smp/cortex_a57_smp/gnu/inc/tx_port.h | 2 +- ports_smp/cortex_a5_smp/ac5/inc/tx_port.h | 2 +- ports_smp/cortex_a5_smp/gnu/inc/tx_port.h | 2 +- ports_smp/cortex_a5x_smp/ac6/inc/tx_port.h | 2 +- ports_smp/cortex_a5x_smp/gnu/inc/tx_port.h | 2 +- ports_smp/cortex_a5x_smp/green/inc/tx_port.h | 2 +- ports_smp/cortex_a5x_smp/iar/inc/tx_port.h | 2 +- ports_smp/cortex_a65_smp/ac6/inc/tx_port.h | 2 +- ports_smp/cortex_a65_smp/gnu/inc/tx_port.h | 2 +- ports_smp/cortex_a65ae_smp/ac6/inc/tx_port.h | 2 +- ports_smp/cortex_a65ae_smp/gnu/inc/tx_port.h | 2 +- ports_smp/cortex_a72_smp/ac6/inc/tx_port.h | 2 +- ports_smp/cortex_a72_smp/gnu/inc/tx_port.h | 2 +- ports_smp/cortex_a73_smp/ac6/inc/tx_port.h | 2 +- ports_smp/cortex_a73_smp/gnu/inc/tx_port.h | 2 +- ports_smp/cortex_a75_smp/ac6/inc/tx_port.h | 2 +- ports_smp/cortex_a75_smp/gnu/inc/tx_port.h | 2 +- ports_smp/cortex_a76_smp/ac6/inc/tx_port.h | 2 +- ports_smp/cortex_a76_smp/gnu/inc/tx_port.h | 2 +- ports_smp/cortex_a76ae_smp/ac6/inc/tx_port.h | 2 +- ports_smp/cortex_a76ae_smp/gnu/inc/tx_port.h | 2 +- ports_smp/cortex_a77_smp/ac6/inc/tx_port.h | 2 +- ports_smp/cortex_a77_smp/gnu/inc/tx_port.h | 2 +- ports_smp/cortex_a78_smp/ac6/inc/tx_port.h | 2 +- ports_smp/cortex_a78_smp/gnu/inc/tx_port.h | 2 +- ports_smp/cortex_a7_smp/ac5/inc/tx_port.h | 2 +- ports_smp/cortex_a7_smp/gnu/inc/tx_port.h | 2 +- ports_smp/cortex_a9_smp/ac5/inc/tx_port.h | 2 +- ports_smp/cortex_a9_smp/gnu/inc/tx_port.h | 2 +- ports_smp/cortex_r8_smp/ac5/inc/tx_port.h | 2 +- ports_smp/linux/gnu/inc/tx_port.h | 2 +- ports_smp/mips32_interaptiv_smp/gnu/inc/tx_port.h | 2 +- ports_smp/mips32_interaptiv_smp/green/inc/tx_port.h | 2 +- ports_smp/win64/vs_2022/inc/tx_port.h | 2 +- 212 files changed, 214 insertions(+), 214 deletions(-) diff --git a/common/inc/tx_api.h b/common/inc/tx_api.h index bac617e5d..ed1f82918 100644 --- a/common/inc/tx_api.h +++ b/common/inc/tx_api.h @@ -90,9 +90,9 @@ extern "C" { #define AZURE_RTOS_THREADX #define THREADX_MAJOR_VERSION 6 #define THREADX_MINOR_VERSION 5 -#define THREADX_PATCH_VERSION 1 -#define THREADX_BUILD_VERSION 202602 -#define THREADX_HOTFIX_VERSION 'a' +#define THREADX_PATCH_VERSION 2 +#define THREADX_BUILD_VERSION 202603 +#define THREADX_HOTFIX_VERSION ' ' /* Define the following symbol for backward compatibility */ #define EL_PRODUCT_THREADX diff --git a/ports/arc_em/metaware/inc/tx_port.h b/ports/arc_em/metaware/inc/tx_port.h index 9dec1e6b7..c30cfc951 100644 --- a/ports/arc_em/metaware/inc/tx_port.h +++ b/ports/arc_em/metaware/inc/tx_port.h @@ -308,7 +308,7 @@ void _tx_initialize_start_interrupts(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARCv2_EM/MetaWare Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARCv2_EM/MetaWare Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/arc_hs/metaware/inc/tx_port.h b/ports/arc_hs/metaware/inc/tx_port.h index 724cba6c1..959cd7c4d 100644 --- a/ports/arc_hs/metaware/inc/tx_port.h +++ b/ports/arc_hs/metaware/inc/tx_port.h @@ -322,7 +322,7 @@ VOID tx_thread_register_bank_assign(VOID *thread_ptr, UINT register_bank); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARC_HS/MetaWare Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARC_HS/MetaWare Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/arm11/ac5/inc/tx_port.h b/ports/arm11/ac5/inc/tx_port.h index aa741362e..0b66bda47 100644 --- a/ports/arm11/ac5/inc/tx_port.h +++ b/ports/arm11/ac5/inc/tx_port.h @@ -311,7 +311,7 @@ unsigned int _tx_thread_interrupt_restore(UINT old_posture); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARM11/AC5 Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARM11/AC5 Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/arm11/gnu/inc/tx_port.h b/ports/arm11/gnu/inc/tx_port.h index 998b153fd..02555994e 100644 --- a/ports/arm11/gnu/inc/tx_port.h +++ b/ports/arm11/gnu/inc/tx_port.h @@ -300,7 +300,7 @@ unsigned int _tx_thread_interrupt_restore(UINT old_posture); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARM11/GNU Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARM11/GNU Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/arm11/iar/inc/tx_port.h b/ports/arm11/iar/inc/tx_port.h index fd139ac76..d5aeac8db 100644 --- a/ports/arm11/iar/inc/tx_port.h +++ b/ports/arm11/iar/inc/tx_port.h @@ -366,7 +366,7 @@ void _tx_thread_interrupt_restore(UINT old_posture); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARM11/IAR Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARM11/IAR Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/arm9/ac5/inc/tx_port.h b/ports/arm9/ac5/inc/tx_port.h index 3a8318721..34e6fec22 100644 --- a/ports/arm9/ac5/inc/tx_port.h +++ b/ports/arm9/ac5/inc/tx_port.h @@ -313,7 +313,7 @@ unsigned int _tx_thread_interrupt_restore(UINT old_posture); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARM9/AC5 Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARM9/AC5 Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/arm9/gnu/inc/tx_port.h b/ports/arm9/gnu/inc/tx_port.h index 4da69b821..d77d48e14 100644 --- a/ports/arm9/gnu/inc/tx_port.h +++ b/ports/arm9/gnu/inc/tx_port.h @@ -300,7 +300,7 @@ unsigned int _tx_thread_interrupt_restore(UINT old_posture); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARM9/GNU Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARM9/GNU Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/arm9/iar/inc/tx_port.h b/ports/arm9/iar/inc/tx_port.h index 69e409543..a01805844 100644 --- a/ports/arm9/iar/inc/tx_port.h +++ b/ports/arm9/iar/inc/tx_port.h @@ -366,7 +366,7 @@ void _tx_thread_interrupt_restore(UINT old_posture); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARM9/IAR Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARM9/IAR Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/c667x/ccs/inc/tx_port.h b/ports/c667x/ccs/inc/tx_port.h index 6bf627a3a..3f18eb1b6 100644 --- a/ports/c667x/ccs/inc/tx_port.h +++ b/ports/c667x/ccs/inc/tx_port.h @@ -258,7 +258,7 @@ unsigned int _tx_thread_interrupt_control(unsigned int); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX C667x/TI Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX C667x/TI Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a12/ac6/inc/tx_port.h b/ports/cortex_a12/ac6/inc/tx_port.h index 15d6c3c51..798dc4579 100644 --- a/ports/cortex_a12/ac6/inc/tx_port.h +++ b/ports/cortex_a12/ac6/inc/tx_port.h @@ -307,7 +307,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-A Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-A Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a12/gnu/inc/tx_port.h b/ports/cortex_a12/gnu/inc/tx_port.h index 15d6c3c51..798dc4579 100644 --- a/ports/cortex_a12/gnu/inc/tx_port.h +++ b/ports/cortex_a12/gnu/inc/tx_port.h @@ -307,7 +307,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-A Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-A Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a15/ac6/inc/tx_port.h b/ports/cortex_a15/ac6/inc/tx_port.h index 15d6c3c51..798dc4579 100644 --- a/ports/cortex_a15/ac6/inc/tx_port.h +++ b/ports/cortex_a15/ac6/inc/tx_port.h @@ -307,7 +307,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-A Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-A Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a15/gnu/inc/tx_port.h b/ports/cortex_a15/gnu/inc/tx_port.h index 15d6c3c51..798dc4579 100644 --- a/ports/cortex_a15/gnu/inc/tx_port.h +++ b/ports/cortex_a15/gnu/inc/tx_port.h @@ -307,7 +307,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-A Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-A Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a15/iar/inc/tx_port.h b/ports/cortex_a15/iar/inc/tx_port.h index 3d0f3b5d1..bea21f9d3 100644 --- a/ports/cortex_a15/iar/inc/tx_port.h +++ b/ports/cortex_a15/iar/inc/tx_port.h @@ -376,7 +376,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A15/IAR Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A15/IAR Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_a17/ac6/inc/tx_port.h b/ports/cortex_a17/ac6/inc/tx_port.h index 15d6c3c51..798dc4579 100644 --- a/ports/cortex_a17/ac6/inc/tx_port.h +++ b/ports/cortex_a17/ac6/inc/tx_port.h @@ -307,7 +307,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-A Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-A Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a17/gnu/inc/tx_port.h b/ports/cortex_a17/gnu/inc/tx_port.h index 15d6c3c51..798dc4579 100644 --- a/ports/cortex_a17/gnu/inc/tx_port.h +++ b/ports/cortex_a17/gnu/inc/tx_port.h @@ -307,7 +307,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-A Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-A Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a34/ac6/inc/tx_port.h b/ports/cortex_a34/ac6/inc/tx_port.h index 4487de47e..691fedd8d 100644 --- a/ports/cortex_a34/ac6/inc/tx_port.h +++ b/ports/cortex_a34/ac6/inc/tx_port.h @@ -361,7 +361,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a34/gnu/inc/tx_port.h b/ports/cortex_a34/gnu/inc/tx_port.h index 4487de47e..691fedd8d 100644 --- a/ports/cortex_a34/gnu/inc/tx_port.h +++ b/ports/cortex_a34/gnu/inc/tx_port.h @@ -361,7 +361,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a35/ac6/inc/tx_port.h b/ports/cortex_a35/ac6/inc/tx_port.h index 4487de47e..691fedd8d 100644 --- a/ports/cortex_a35/ac6/inc/tx_port.h +++ b/ports/cortex_a35/ac6/inc/tx_port.h @@ -361,7 +361,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a35/gnu/inc/tx_port.h b/ports/cortex_a35/gnu/inc/tx_port.h index 4487de47e..691fedd8d 100644 --- a/ports/cortex_a35/gnu/inc/tx_port.h +++ b/ports/cortex_a35/gnu/inc/tx_port.h @@ -361,7 +361,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a5/ac5/inc/tx_port.h b/ports/cortex_a5/ac5/inc/tx_port.h index 0b7fcfbef..e1b055712 100644 --- a/ports/cortex_a5/ac5/inc/tx_port.h +++ b/ports/cortex_a5/ac5/inc/tx_port.h @@ -318,7 +318,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A5/AC5 Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A5/AC5 Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a5/ac6/inc/tx_port.h b/ports/cortex_a5/ac6/inc/tx_port.h index 15d6c3c51..798dc4579 100644 --- a/ports/cortex_a5/ac6/inc/tx_port.h +++ b/ports/cortex_a5/ac6/inc/tx_port.h @@ -307,7 +307,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-A Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-A Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a5/ghs/inc/tx_port.h b/ports/cortex_a5/ghs/inc/tx_port.h index 6cd9015bb..38d4789be 100644 --- a/ports/cortex_a5/ghs/inc/tx_port.h +++ b/ports/cortex_a5/ghs/inc/tx_port.h @@ -386,7 +386,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A5/Green Hills Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A5/Green Hills Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a5/gnu/inc/tx_port.h b/ports/cortex_a5/gnu/inc/tx_port.h index 15d6c3c51..798dc4579 100644 --- a/ports/cortex_a5/gnu/inc/tx_port.h +++ b/ports/cortex_a5/gnu/inc/tx_port.h @@ -307,7 +307,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-A Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-A Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a5/iar/inc/tx_port.h b/ports/cortex_a5/iar/inc/tx_port.h index 9d56c284e..af5047bff 100644 --- a/ports/cortex_a5/iar/inc/tx_port.h +++ b/ports/cortex_a5/iar/inc/tx_port.h @@ -374,7 +374,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A5/IAR Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A5/IAR Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_a53/ac6/inc/tx_port.h b/ports/cortex_a53/ac6/inc/tx_port.h index 4487de47e..691fedd8d 100644 --- a/ports/cortex_a53/ac6/inc/tx_port.h +++ b/ports/cortex_a53/ac6/inc/tx_port.h @@ -361,7 +361,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a53/gnu/inc/tx_port.h b/ports/cortex_a53/gnu/inc/tx_port.h index 4487de47e..691fedd8d 100644 --- a/ports/cortex_a53/gnu/inc/tx_port.h +++ b/ports/cortex_a53/gnu/inc/tx_port.h @@ -361,7 +361,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a55/ac6/inc/tx_port.h b/ports/cortex_a55/ac6/inc/tx_port.h index 4487de47e..691fedd8d 100644 --- a/ports/cortex_a55/ac6/inc/tx_port.h +++ b/ports/cortex_a55/ac6/inc/tx_port.h @@ -361,7 +361,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a55/gnu/inc/tx_port.h b/ports/cortex_a55/gnu/inc/tx_port.h index 4487de47e..691fedd8d 100644 --- a/ports/cortex_a55/gnu/inc/tx_port.h +++ b/ports/cortex_a55/gnu/inc/tx_port.h @@ -361,7 +361,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a57/ac6/inc/tx_port.h b/ports/cortex_a57/ac6/inc/tx_port.h index 4487de47e..691fedd8d 100644 --- a/ports/cortex_a57/ac6/inc/tx_port.h +++ b/ports/cortex_a57/ac6/inc/tx_port.h @@ -361,7 +361,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a57/gnu/inc/tx_port.h b/ports/cortex_a57/gnu/inc/tx_port.h index 4487de47e..691fedd8d 100644 --- a/ports/cortex_a57/gnu/inc/tx_port.h +++ b/ports/cortex_a57/gnu/inc/tx_port.h @@ -361,7 +361,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a5x/ac6/inc/tx_port.h b/ports/cortex_a5x/ac6/inc/tx_port.h index 5ad090736..0a9899272 100644 --- a/ports/cortex_a5x/ac6/inc/tx_port.h +++ b/ports/cortex_a5x/ac6/inc/tx_port.h @@ -348,7 +348,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A5x/ARM Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A5x/ARM Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a65/ac6/inc/tx_port.h b/ports/cortex_a65/ac6/inc/tx_port.h index 4487de47e..691fedd8d 100644 --- a/ports/cortex_a65/ac6/inc/tx_port.h +++ b/ports/cortex_a65/ac6/inc/tx_port.h @@ -361,7 +361,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a65/gnu/inc/tx_port.h b/ports/cortex_a65/gnu/inc/tx_port.h index 4487de47e..691fedd8d 100644 --- a/ports/cortex_a65/gnu/inc/tx_port.h +++ b/ports/cortex_a65/gnu/inc/tx_port.h @@ -361,7 +361,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a65ae/ac6/inc/tx_port.h b/ports/cortex_a65ae/ac6/inc/tx_port.h index 4487de47e..691fedd8d 100644 --- a/ports/cortex_a65ae/ac6/inc/tx_port.h +++ b/ports/cortex_a65ae/ac6/inc/tx_port.h @@ -361,7 +361,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a65ae/gnu/inc/tx_port.h b/ports/cortex_a65ae/gnu/inc/tx_port.h index 4487de47e..691fedd8d 100644 --- a/ports/cortex_a65ae/gnu/inc/tx_port.h +++ b/ports/cortex_a65ae/gnu/inc/tx_port.h @@ -361,7 +361,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a7/ac5/inc/tx_port.h b/ports/cortex_a7/ac5/inc/tx_port.h index a98e5fa64..7a11cde90 100644 --- a/ports/cortex_a7/ac5/inc/tx_port.h +++ b/ports/cortex_a7/ac5/inc/tx_port.h @@ -318,7 +318,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A7/AC5 Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A7/AC5 Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a7/ac6/inc/tx_port.h b/ports/cortex_a7/ac6/inc/tx_port.h index 15d6c3c51..798dc4579 100644 --- a/ports/cortex_a7/ac6/inc/tx_port.h +++ b/ports/cortex_a7/ac6/inc/tx_port.h @@ -307,7 +307,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-A Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-A Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a7/ghs/inc/tx_port.h b/ports/cortex_a7/ghs/inc/tx_port.h index 395802a26..c8604415d 100644 --- a/ports/cortex_a7/ghs/inc/tx_port.h +++ b/ports/cortex_a7/ghs/inc/tx_port.h @@ -386,7 +386,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A7/Green Hills Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A7/Green Hills Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a7/gnu/inc/tx_port.h b/ports/cortex_a7/gnu/inc/tx_port.h index 15d6c3c51..798dc4579 100644 --- a/ports/cortex_a7/gnu/inc/tx_port.h +++ b/ports/cortex_a7/gnu/inc/tx_port.h @@ -307,7 +307,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-A Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-A Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a7/iar/inc/tx_port.h b/ports/cortex_a7/iar/inc/tx_port.h index 0f54867f7..ff4b9dff1 100644 --- a/ports/cortex_a7/iar/inc/tx_port.h +++ b/ports/cortex_a7/iar/inc/tx_port.h @@ -374,7 +374,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A7/IAR Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A7/IAR Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a72/ac6/inc/tx_port.h b/ports/cortex_a72/ac6/inc/tx_port.h index 4487de47e..691fedd8d 100644 --- a/ports/cortex_a72/ac6/inc/tx_port.h +++ b/ports/cortex_a72/ac6/inc/tx_port.h @@ -361,7 +361,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a72/gnu/inc/tx_port.h b/ports/cortex_a72/gnu/inc/tx_port.h index 4487de47e..691fedd8d 100644 --- a/ports/cortex_a72/gnu/inc/tx_port.h +++ b/ports/cortex_a72/gnu/inc/tx_port.h @@ -361,7 +361,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a73/ac6/inc/tx_port.h b/ports/cortex_a73/ac6/inc/tx_port.h index 4487de47e..691fedd8d 100644 --- a/ports/cortex_a73/ac6/inc/tx_port.h +++ b/ports/cortex_a73/ac6/inc/tx_port.h @@ -361,7 +361,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a73/gnu/inc/tx_port.h b/ports/cortex_a73/gnu/inc/tx_port.h index 4487de47e..691fedd8d 100644 --- a/ports/cortex_a73/gnu/inc/tx_port.h +++ b/ports/cortex_a73/gnu/inc/tx_port.h @@ -361,7 +361,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a75/ac6/inc/tx_port.h b/ports/cortex_a75/ac6/inc/tx_port.h index 4487de47e..691fedd8d 100644 --- a/ports/cortex_a75/ac6/inc/tx_port.h +++ b/ports/cortex_a75/ac6/inc/tx_port.h @@ -361,7 +361,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a75/gnu/inc/tx_port.h b/ports/cortex_a75/gnu/inc/tx_port.h index 4487de47e..691fedd8d 100644 --- a/ports/cortex_a75/gnu/inc/tx_port.h +++ b/ports/cortex_a75/gnu/inc/tx_port.h @@ -361,7 +361,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a76/ac6/inc/tx_port.h b/ports/cortex_a76/ac6/inc/tx_port.h index 4487de47e..691fedd8d 100644 --- a/ports/cortex_a76/ac6/inc/tx_port.h +++ b/ports/cortex_a76/ac6/inc/tx_port.h @@ -361,7 +361,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a76/gnu/inc/tx_port.h b/ports/cortex_a76/gnu/inc/tx_port.h index 4487de47e..691fedd8d 100644 --- a/ports/cortex_a76/gnu/inc/tx_port.h +++ b/ports/cortex_a76/gnu/inc/tx_port.h @@ -361,7 +361,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a76ae/ac6/inc/tx_port.h b/ports/cortex_a76ae/ac6/inc/tx_port.h index 4487de47e..691fedd8d 100644 --- a/ports/cortex_a76ae/ac6/inc/tx_port.h +++ b/ports/cortex_a76ae/ac6/inc/tx_port.h @@ -361,7 +361,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a76ae/gnu/inc/tx_port.h b/ports/cortex_a76ae/gnu/inc/tx_port.h index 4487de47e..691fedd8d 100644 --- a/ports/cortex_a76ae/gnu/inc/tx_port.h +++ b/ports/cortex_a76ae/gnu/inc/tx_port.h @@ -361,7 +361,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a77/ac6/inc/tx_port.h b/ports/cortex_a77/ac6/inc/tx_port.h index 4487de47e..691fedd8d 100644 --- a/ports/cortex_a77/ac6/inc/tx_port.h +++ b/ports/cortex_a77/ac6/inc/tx_port.h @@ -361,7 +361,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a77/gnu/inc/tx_port.h b/ports/cortex_a77/gnu/inc/tx_port.h index 4487de47e..691fedd8d 100644 --- a/ports/cortex_a77/gnu/inc/tx_port.h +++ b/ports/cortex_a77/gnu/inc/tx_port.h @@ -361,7 +361,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a8/ac5/inc/tx_port.h b/ports/cortex_a8/ac5/inc/tx_port.h index d786edf8c..fc3008ae0 100644 --- a/ports/cortex_a8/ac5/inc/tx_port.h +++ b/ports/cortex_a8/ac5/inc/tx_port.h @@ -318,7 +318,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A8/AC5 Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A8/AC5 Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a8/ac6/inc/tx_port.h b/ports/cortex_a8/ac6/inc/tx_port.h index 15d6c3c51..798dc4579 100644 --- a/ports/cortex_a8/ac6/inc/tx_port.h +++ b/ports/cortex_a8/ac6/inc/tx_port.h @@ -307,7 +307,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-A Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-A Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a8/ghs/inc/tx_port.h b/ports/cortex_a8/ghs/inc/tx_port.h index bfcbdc71a..f505e3b8a 100644 --- a/ports/cortex_a8/ghs/inc/tx_port.h +++ b/ports/cortex_a8/ghs/inc/tx_port.h @@ -386,7 +386,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A8/Green Hills Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A8/Green Hills Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a8/gnu/inc/tx_port.h b/ports/cortex_a8/gnu/inc/tx_port.h index 15d6c3c51..798dc4579 100644 --- a/ports/cortex_a8/gnu/inc/tx_port.h +++ b/ports/cortex_a8/gnu/inc/tx_port.h @@ -307,7 +307,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-A Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-A Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a8/iar/inc/tx_port.h b/ports/cortex_a8/iar/inc/tx_port.h index 68c62eb93..22a86e1ca 100644 --- a/ports/cortex_a8/iar/inc/tx_port.h +++ b/ports/cortex_a8/iar/inc/tx_port.h @@ -375,7 +375,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A8/IAR Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A8/IAR Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_a9/ac5/inc/tx_port.h b/ports/cortex_a9/ac5/inc/tx_port.h index 02ec4369d..2b1d4beb3 100644 --- a/ports/cortex_a9/ac5/inc/tx_port.h +++ b/ports/cortex_a9/ac5/inc/tx_port.h @@ -318,7 +318,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A9/AC5 Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A9/AC5 Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a9/ac6/inc/tx_port.h b/ports/cortex_a9/ac6/inc/tx_port.h index 15d6c3c51..798dc4579 100644 --- a/ports/cortex_a9/ac6/inc/tx_port.h +++ b/ports/cortex_a9/ac6/inc/tx_port.h @@ -307,7 +307,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-A Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-A Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a9/ghs/inc/tx_port.h b/ports/cortex_a9/ghs/inc/tx_port.h index 8a67b6c89..010a216c2 100644 --- a/ports/cortex_a9/ghs/inc/tx_port.h +++ b/ports/cortex_a9/ghs/inc/tx_port.h @@ -386,7 +386,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A9/Green Hills Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A9/Green Hills Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a9/gnu/inc/tx_port.h b/ports/cortex_a9/gnu/inc/tx_port.h index 15d6c3c51..798dc4579 100644 --- a/ports/cortex_a9/gnu/inc/tx_port.h +++ b/ports/cortex_a9/gnu/inc/tx_port.h @@ -307,7 +307,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-A Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-A Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_a9/iar/inc/tx_port.h b/ports/cortex_a9/iar/inc/tx_port.h index 6821edca1..0678e5068 100644 --- a/ports/cortex_a9/iar/inc/tx_port.h +++ b/ports/cortex_a9/iar/inc/tx_port.h @@ -376,7 +376,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A9/IAR Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A9/IAR Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_m0/ac5/inc/tx_port.h b/ports/cortex_m0/ac5/inc/tx_port.h index 5ddf74bb1..53018a6f4 100644 --- a/ports/cortex_m0/ac5/inc/tx_port.h +++ b/ports/cortex_m0/ac5/inc/tx_port.h @@ -312,7 +312,7 @@ unsigned int was_masked; #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M0/AC5 Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M0/AC5 Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_m0/ac6/inc/tx_port.h b/ports/cortex_m0/ac6/inc/tx_port.h index 8b33dfec2..8b02e6e32 100644 --- a/ports/cortex_m0/ac6/inc/tx_port.h +++ b/ports/cortex_m0/ac6/inc/tx_port.h @@ -359,7 +359,7 @@ unsigned int interrupt_save; #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M0/AC6 Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M0/AC6 Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_m0/gnu/inc/tx_port.h b/ports/cortex_m0/gnu/inc/tx_port.h index 215293155..6d8a77c98 100644 --- a/ports/cortex_m0/gnu/inc/tx_port.h +++ b/ports/cortex_m0/gnu/inc/tx_port.h @@ -359,7 +359,7 @@ unsigned int interrupt_save; #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M0/GNU Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M0/GNU Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_m0/iar/inc/tx_port.h b/ports/cortex_m0/iar/inc/tx_port.h index 195261c16..6c9621d64 100644 --- a/ports/cortex_m0/iar/inc/tx_port.h +++ b/ports/cortex_m0/iar/inc/tx_port.h @@ -342,7 +342,7 @@ __istate_t interrupt_save; #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M0/IAR Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M0/IAR Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_m0/keil/inc/tx_port.h b/ports/cortex_m0/keil/inc/tx_port.h index 5ddf74bb1..53018a6f4 100644 --- a/ports/cortex_m0/keil/inc/tx_port.h +++ b/ports/cortex_m0/keil/inc/tx_port.h @@ -312,7 +312,7 @@ unsigned int was_masked; #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M0/AC5 Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M0/AC5 Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_m23/ac6/inc/tx_port.h b/ports/cortex_m23/ac6/inc/tx_port.h index 25cfae013..b4437373a 100644 --- a/ports/cortex_m23/ac6/inc/tx_port.h +++ b/ports/cortex_m23/ac6/inc/tx_port.h @@ -394,7 +394,7 @@ unsigned int was_masked; #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M23/AC6 Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M23/AC6 Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_m23/gnu/inc/tx_port.h b/ports/cortex_m23/gnu/inc/tx_port.h index f1ca30e3c..0c1d88d23 100644 --- a/ports/cortex_m23/gnu/inc/tx_port.h +++ b/ports/cortex_m23/gnu/inc/tx_port.h @@ -426,7 +426,7 @@ unsigned int interrupt_save; #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M23/GNU Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M23/GNU Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_m23/iar/inc/tx_port.h b/ports/cortex_m23/iar/inc/tx_port.h index e1da96da7..c7468b019 100644 --- a/ports/cortex_m23/iar/inc/tx_port.h +++ b/ports/cortex_m23/iar/inc/tx_port.h @@ -417,7 +417,7 @@ __istate_t interrupt_save; #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M23/IAR Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M23/IAR Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_m3/ac5/inc/tx_port.h b/ports/cortex_m3/ac5/inc/tx_port.h index 947910f90..654501d52 100644 --- a/ports/cortex_m3/ac5/inc/tx_port.h +++ b/ports/cortex_m3/ac5/inc/tx_port.h @@ -704,7 +704,7 @@ void tx_thread_fpu_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M3/AC5 Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M3/AC5 Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_m3/ac6/inc/tx_port.h b/ports/cortex_m3/ac6/inc/tx_port.h index e05de4d97..8b68842f5 100644 --- a/ports/cortex_m3/ac6/inc/tx_port.h +++ b/ports/cortex_m3/ac6/inc/tx_port.h @@ -704,7 +704,7 @@ void tx_thread_fpu_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M3/AC6 Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M3/AC6 Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_m3/ghs/inc/tx_port.h b/ports/cortex_m3/ghs/inc/tx_port.h index faded3096..9a2d34207 100644 --- a/ports/cortex_m3/ghs/inc/tx_port.h +++ b/ports/cortex_m3/ghs/inc/tx_port.h @@ -371,7 +371,7 @@ asm void restore_ints(int a) #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M3/GHS Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M3/GHS Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_m3/gnu/inc/tx_port.h b/ports/cortex_m3/gnu/inc/tx_port.h index 5748f69c8..38f89929a 100644 --- a/ports/cortex_m3/gnu/inc/tx_port.h +++ b/ports/cortex_m3/gnu/inc/tx_port.h @@ -704,7 +704,7 @@ void tx_thread_fpu_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M3/GNU Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M3/GNU Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_m3/iar/inc/tx_port.h b/ports/cortex_m3/iar/inc/tx_port.h index b8d81f202..c4d90a570 100644 --- a/ports/cortex_m3/iar/inc/tx_port.h +++ b/ports/cortex_m3/iar/inc/tx_port.h @@ -704,7 +704,7 @@ void tx_thread_fpu_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M3/IAR Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M3/IAR Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_m3/keil/inc/tx_port.h b/ports/cortex_m3/keil/inc/tx_port.h index f66b80fe9..984024be8 100644 --- a/ports/cortex_m3/keil/inc/tx_port.h +++ b/ports/cortex_m3/keil/inc/tx_port.h @@ -704,7 +704,7 @@ void tx_thread_fpu_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M3/Keil Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M3/Keil Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_m33/ac6/inc/tx_port.h b/ports/cortex_m33/ac6/inc/tx_port.h index a52374927..927b36f3c 100644 --- a/ports/cortex_m33/ac6/inc/tx_port.h +++ b/ports/cortex_m33/ac6/inc/tx_port.h @@ -618,7 +618,7 @@ VOID _tx_thread_interrupt_restore(UIN #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M33/AC6 Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M33/AC6 Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_m33/gnu/inc/tx_port.h b/ports/cortex_m33/gnu/inc/tx_port.h index 605d85a97..7c2c6e62e 100644 --- a/ports/cortex_m33/gnu/inc/tx_port.h +++ b/ports/cortex_m33/gnu/inc/tx_port.h @@ -618,7 +618,7 @@ VOID _tx_thread_interrupt_restore(UIN #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M33/GNU Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M33/GNU Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_m33/iar/inc/tx_port.h b/ports/cortex_m33/iar/inc/tx_port.h index 96341bac5..3d8e09568 100644 --- a/ports/cortex_m33/iar/inc/tx_port.h +++ b/ports/cortex_m33/iar/inc/tx_port.h @@ -618,7 +618,7 @@ VOID _tx_thread_interrupt_restore(UIN #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M33/IAR Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M33/IAR Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_m4/ac5/inc/tx_port.h b/ports/cortex_m4/ac5/inc/tx_port.h index b8d903bcf..694b75466 100644 --- a/ports/cortex_m4/ac5/inc/tx_port.h +++ b/ports/cortex_m4/ac5/inc/tx_port.h @@ -704,7 +704,7 @@ void tx_thread_fpu_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M4/AC5 Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M4/AC5 Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_m4/ac6/inc/tx_port.h b/ports/cortex_m4/ac6/inc/tx_port.h index 6c3ef0767..a72c15ed9 100644 --- a/ports/cortex_m4/ac6/inc/tx_port.h +++ b/ports/cortex_m4/ac6/inc/tx_port.h @@ -704,7 +704,7 @@ void tx_thread_fpu_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M4/AC6 Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M4/AC6 Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_m4/ghs/inc/tx_port.h b/ports/cortex_m4/ghs/inc/tx_port.h index 4b1ef2adc..8cd09af85 100644 --- a/ports/cortex_m4/ghs/inc/tx_port.h +++ b/ports/cortex_m4/ghs/inc/tx_port.h @@ -378,7 +378,7 @@ void tx_thread_fpu_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M4/GHS Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M4/GHS Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_m4/gnu/inc/tx_port.h b/ports/cortex_m4/gnu/inc/tx_port.h index 8cf28e949..ab7626552 100644 --- a/ports/cortex_m4/gnu/inc/tx_port.h +++ b/ports/cortex_m4/gnu/inc/tx_port.h @@ -704,7 +704,7 @@ void tx_thread_fpu_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M4/GNU Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M4/GNU Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_m4/iar/inc/tx_port.h b/ports/cortex_m4/iar/inc/tx_port.h index cd180f948..fab459e12 100644 --- a/ports/cortex_m4/iar/inc/tx_port.h +++ b/ports/cortex_m4/iar/inc/tx_port.h @@ -704,7 +704,7 @@ void tx_thread_fpu_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M4/IAR Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M4/IAR Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_m4/keil/inc/tx_port.h b/ports/cortex_m4/keil/inc/tx_port.h index 2e7416849..7f70020a2 100644 --- a/ports/cortex_m4/keil/inc/tx_port.h +++ b/ports/cortex_m4/keil/inc/tx_port.h @@ -704,7 +704,7 @@ void tx_thread_fpu_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M4/Keil Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M4/Keil Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_m52/ac6/inc/tx_port.h b/ports/cortex_m52/ac6/inc/tx_port.h index ae528beeb..0b1124223 100644 --- a/ports/cortex_m52/ac6/inc/tx_port.h +++ b/ports/cortex_m52/ac6/inc/tx_port.h @@ -618,7 +618,7 @@ VOID _tx_thread_interrupt_restore(UIN #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M52/AC6 Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M52/AC6 Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_m52/gnu/inc/tx_port.h b/ports/cortex_m52/gnu/inc/tx_port.h index 7ebc7bdcf..e276ada9b 100644 --- a/ports/cortex_m52/gnu/inc/tx_port.h +++ b/ports/cortex_m52/gnu/inc/tx_port.h @@ -618,7 +618,7 @@ VOID _tx_thread_interrupt_restore(UIN #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M52/GNU Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M52/GNU Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_m52/iar/inc/tx_port.h b/ports/cortex_m52/iar/inc/tx_port.h index fc3d1b253..6af030e92 100644 --- a/ports/cortex_m52/iar/inc/tx_port.h +++ b/ports/cortex_m52/iar/inc/tx_port.h @@ -618,7 +618,7 @@ VOID _tx_thread_interrupt_restore(UIN #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M52/IAR Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M52/IAR Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_m55/ac6/inc/tx_port.h b/ports/cortex_m55/ac6/inc/tx_port.h index 4d4760637..a4ecc5d5f 100644 --- a/ports/cortex_m55/ac6/inc/tx_port.h +++ b/ports/cortex_m55/ac6/inc/tx_port.h @@ -618,7 +618,7 @@ VOID _tx_thread_interrupt_restore(UIN #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M55/AC6 Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M55/AC6 Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_m55/gnu/inc/tx_port.h b/ports/cortex_m55/gnu/inc/tx_port.h index 2bd806425..50919cefd 100644 --- a/ports/cortex_m55/gnu/inc/tx_port.h +++ b/ports/cortex_m55/gnu/inc/tx_port.h @@ -618,7 +618,7 @@ VOID _tx_thread_interrupt_restore(UIN #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M55/GNU Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M55/GNU Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_m55/iar/inc/tx_port.h b/ports/cortex_m55/iar/inc/tx_port.h index d908ac7fa..dac7ba6c6 100644 --- a/ports/cortex_m55/iar/inc/tx_port.h +++ b/ports/cortex_m55/iar/inc/tx_port.h @@ -618,7 +618,7 @@ VOID _tx_thread_interrupt_restore(UIN #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M55/IAR Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M55/IAR Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_m7/ac5/inc/tx_port.h b/ports/cortex_m7/ac5/inc/tx_port.h index a753eb3f0..0f9f49e35 100644 --- a/ports/cortex_m7/ac5/inc/tx_port.h +++ b/ports/cortex_m7/ac5/inc/tx_port.h @@ -704,7 +704,7 @@ void tx_thread_fpu_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M7/AC5 Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M7/AC5 Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_m7/ac6/inc/tx_port.h b/ports/cortex_m7/ac6/inc/tx_port.h index 6b08b6117..5d2808538 100644 --- a/ports/cortex_m7/ac6/inc/tx_port.h +++ b/ports/cortex_m7/ac6/inc/tx_port.h @@ -704,7 +704,7 @@ void tx_thread_fpu_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M7/AC6 Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M7/AC6 Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_m7/ghs/inc/tx_port.h b/ports/cortex_m7/ghs/inc/tx_port.h index af6296d5c..4a6fe92ed 100644 --- a/ports/cortex_m7/ghs/inc/tx_port.h +++ b/ports/cortex_m7/ghs/inc/tx_port.h @@ -378,7 +378,7 @@ void tx_thread_fpu_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M7/GHS Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M7/GHS Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_m7/gnu/inc/tx_port.h b/ports/cortex_m7/gnu/inc/tx_port.h index 7b2a3d5ea..5343a300c 100644 --- a/ports/cortex_m7/gnu/inc/tx_port.h +++ b/ports/cortex_m7/gnu/inc/tx_port.h @@ -704,7 +704,7 @@ void tx_thread_fpu_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M7/GNU Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M7/GNU Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_m7/iar/inc/tx_port.h b/ports/cortex_m7/iar/inc/tx_port.h index 7a0d5b021..9c1d4717c 100644 --- a/ports/cortex_m7/iar/inc/tx_port.h +++ b/ports/cortex_m7/iar/inc/tx_port.h @@ -704,7 +704,7 @@ void tx_thread_fpu_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M7/IAR Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M7/IAR Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_m85/ac6/inc/tx_port.h b/ports/cortex_m85/ac6/inc/tx_port.h index 9b9e09544..59203b709 100644 --- a/ports/cortex_m85/ac6/inc/tx_port.h +++ b/ports/cortex_m85/ac6/inc/tx_port.h @@ -618,7 +618,7 @@ VOID _tx_thread_interrupt_restore(UIN #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M85/AC6 Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M85/AC6 Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_m85/gnu/inc/tx_port.h b/ports/cortex_m85/gnu/inc/tx_port.h index 02b93e1d6..353159b37 100644 --- a/ports/cortex_m85/gnu/inc/tx_port.h +++ b/ports/cortex_m85/gnu/inc/tx_port.h @@ -618,7 +618,7 @@ VOID _tx_thread_interrupt_restore(UIN #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M85/GNU Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M85/GNU Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_m85/iar/inc/tx_port.h b/ports/cortex_m85/iar/inc/tx_port.h index afe9fc914..15f845fd6 100644 --- a/ports/cortex_m85/iar/inc/tx_port.h +++ b/ports/cortex_m85/iar/inc/tx_port.h @@ -618,7 +618,7 @@ VOID _tx_thread_interrupt_restore(UIN #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M85/IAR Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M85/IAR Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_r4/ac5/inc/tx_port.h b/ports/cortex_r4/ac5/inc/tx_port.h index c9d8600a6..a3824f26e 100644 --- a/ports/cortex_r4/ac5/inc/tx_port.h +++ b/ports/cortex_r4/ac5/inc/tx_port.h @@ -318,7 +318,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-R4/AC5 Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-R4/AC5 Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_r4/ac6/inc/tx_port.h b/ports/cortex_r4/ac6/inc/tx_port.h index 8c3cfce81..97d6b50ab 100644 --- a/ports/cortex_r4/ac6/inc/tx_port.h +++ b/ports/cortex_r4/ac6/inc/tx_port.h @@ -321,7 +321,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-R4/AC6 Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-R4/AC6 Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_r4/ghs/inc/tx_port.h b/ports/cortex_r4/ghs/inc/tx_port.h index 6a636f2c6..2247f128f 100644 --- a/ports/cortex_r4/ghs/inc/tx_port.h +++ b/ports/cortex_r4/ghs/inc/tx_port.h @@ -376,7 +376,7 @@ asm void restore_ints(int a) #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-R4/Green Hills Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-R4/Green Hills Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_r4/gnu/inc/tx_port.h b/ports/cortex_r4/gnu/inc/tx_port.h index 0351c6835..ada1a46a7 100644 --- a/ports/cortex_r4/gnu/inc/tx_port.h +++ b/ports/cortex_r4/gnu/inc/tx_port.h @@ -322,7 +322,7 @@ unsigned int _tx_thread_interrupt_restore(UINT old_posture); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-R4/GNU Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-R4/GNU Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_r4/iar/inc/tx_port.h b/ports/cortex_r4/iar/inc/tx_port.h index 8937bf13f..2d1a27653 100644 --- a/ports/cortex_r4/iar/inc/tx_port.h +++ b/ports/cortex_r4/iar/inc/tx_port.h @@ -358,7 +358,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-R4/IAR Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-R4/IAR Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_r5/ac5/inc/tx_port.h b/ports/cortex_r5/ac5/inc/tx_port.h index 832866be2..5a81759fe 100644 --- a/ports/cortex_r5/ac5/inc/tx_port.h +++ b/ports/cortex_r5/ac5/inc/tx_port.h @@ -322,7 +322,7 @@ unsigned int _tx_thread_interrupt_restore(UINT old_posture); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-R5/AC5 Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-R5/AC5 Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_r5/ac6/inc/tx_port.h b/ports/cortex_r5/ac6/inc/tx_port.h index 674b7acdb..420f96e27 100644 --- a/ports/cortex_r5/ac6/inc/tx_port.h +++ b/ports/cortex_r5/ac6/inc/tx_port.h @@ -322,7 +322,7 @@ unsigned int _tx_thread_interrupt_restore(UINT old_posture); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-R5/AC6 Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-R5/AC6 Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_r5/ghs/inc/tx_port.h b/ports/cortex_r5/ghs/inc/tx_port.h index afc61675d..d7f307fa0 100644 --- a/ports/cortex_r5/ghs/inc/tx_port.h +++ b/ports/cortex_r5/ghs/inc/tx_port.h @@ -386,7 +386,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-R5/Green Hills Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-R5/Green Hills Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_r5/gnu/inc/tx_port.h b/ports/cortex_r5/gnu/inc/tx_port.h index 012f75e1d..b9b9ab2aa 100644 --- a/ports/cortex_r5/gnu/inc/tx_port.h +++ b/ports/cortex_r5/gnu/inc/tx_port.h @@ -322,7 +322,7 @@ unsigned int _tx_thread_interrupt_restore(UINT old_posture); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-R5/GNU Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-R5/GNU Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_r5/iar/inc/tx_port.h b/ports/cortex_r5/iar/inc/tx_port.h index 14a42c827..589f7f6c9 100644 --- a/ports/cortex_r5/iar/inc/tx_port.h +++ b/ports/cortex_r5/iar/inc/tx_port.h @@ -358,7 +358,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-R5/IAR Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-R5/IAR Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports/cortex_r52/gnu/inc/tx_port.h b/ports/cortex_r52/gnu/inc/tx_port.h index 207d9c66b..afc67c111 100644 --- a/ports/cortex_r52/gnu/inc/tx_port.h +++ b/ports/cortex_r52/gnu/inc/tx_port.h @@ -383,7 +383,7 @@ unsigned int _tx_thread_interrupt_restore(UINT old_posture); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadXCortex-R52/GNU Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadXCortex-R52/GNU Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/cortex_r7/ghs/inc/tx_port.h b/ports/cortex_r7/ghs/inc/tx_port.h index 2e73a182e..b89c4a703 100644 --- a/ports/cortex_r7/ghs/inc/tx_port.h +++ b/ports/cortex_r7/ghs/inc/tx_port.h @@ -386,7 +386,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-R7/Green Hills Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-R7/Green Hills Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/linux/gnu/inc/tx_port.h b/ports/linux/gnu/inc/tx_port.h index db837e4f9..def3e28fd 100644 --- a/ports/linux/gnu/inc/tx_port.h +++ b/ports/linux/gnu/inc/tx_port.h @@ -543,7 +543,7 @@ VOID _tx_thread_interrupt_restore(UINT previous_posture); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "Copyright (c) Microsoft Corporation * ThreadX Linux/gcc Version 6.5.1.202602a *"; + "Copyright (c) Microsoft Corporation * ThreadX Linux/gcc Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/risc-v32/clang/inc/tx_port.h b/ports/risc-v32/clang/inc/tx_port.h index 762095927..5499b0db2 100644 --- a/ports/risc-v32/clang/inc/tx_port.h +++ b/ports/risc-v32/clang/inc/tx_port.h @@ -56,7 +56,7 @@ #ifndef __ASSEMBLER__ #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX RISC-V32/GNU Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX RISC-V32/GNU Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif /* TX_THREAD_INIT */ diff --git a/ports/risc-v32/gnu/inc/tx_port.h b/ports/risc-v32/gnu/inc/tx_port.h index 642b12750..3ca02ec98 100644 --- a/ports/risc-v32/gnu/inc/tx_port.h +++ b/ports/risc-v32/gnu/inc/tx_port.h @@ -197,7 +197,7 @@ extern TEST_FLAG test_forced_mutex_timeout; #ifndef __ASSEMBLER__ #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX RISC-V32/GNU Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX RISC-V32/GNU Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif /* TX_THREAD_INIT */ diff --git a/ports/risc-v64/gnu/inc/tx_port.h b/ports/risc-v64/gnu/inc/tx_port.h index e771f4513..5c29404c0 100644 --- a/ports/risc-v64/gnu/inc/tx_port.h +++ b/ports/risc-v64/gnu/inc/tx_port.h @@ -475,7 +475,7 @@ extern TEST_FLAG test_forced_mutex_timeout; #ifndef __ASSEMBLER__ #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX RISC-V64/GNU Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX RISC-V64/GNU Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif /* TX_THREAD_INIT */ diff --git a/ports/rxv1/ccrx/inc/tx_port.h b/ports/rxv1/ccrx/inc/tx_port.h index bdd8c7f49..bc870ba10 100644 --- a/ports/rxv1/ccrx/inc/tx_port.h +++ b/ports/rxv1/ccrx/inc/tx_port.h @@ -260,7 +260,7 @@ static void _tx_thread_system_return_inline(void) #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX RXv1/CCRX Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX RXv1/CCRX Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/rxv1/gnu/inc/tx_port.h b/ports/rxv1/gnu/inc/tx_port.h index 1bd542fda..def347fb3 100644 --- a/ports/rxv1/gnu/inc/tx_port.h +++ b/ports/rxv1/gnu/inc/tx_port.h @@ -257,7 +257,7 @@ static void _tx_thread_system_return_inline(void) #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX RXv1/GNURX Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX RXv1/GNURX Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/rxv1/iar/inc/tx_port.h b/ports/rxv1/iar/inc/tx_port.h index 47575a866..9186cec87 100644 --- a/ports/rxv1/iar/inc/tx_port.h +++ b/ports/rxv1/iar/inc/tx_port.h @@ -257,7 +257,7 @@ static void _tx_thread_system_return_inline(void) #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX RXv1/IAR Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX RXv1/IAR Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/rxv2/ccrx/inc/tx_port.h b/ports/rxv2/ccrx/inc/tx_port.h index 3055f8a57..eca357f1a 100644 --- a/ports/rxv2/ccrx/inc/tx_port.h +++ b/ports/rxv2/ccrx/inc/tx_port.h @@ -260,7 +260,7 @@ static void _tx_thread_system_return_inline(void) #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX RXv2/CCRX Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX RXv2/CCRX Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/rxv2/gnu/inc/tx_port.h b/ports/rxv2/gnu/inc/tx_port.h index 8df14a087..bff3cb4a1 100644 --- a/ports/rxv2/gnu/inc/tx_port.h +++ b/ports/rxv2/gnu/inc/tx_port.h @@ -257,7 +257,7 @@ static void _tx_thread_system_return_inline(void) #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX RXv2/GNURX Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX RXv2/GNURX Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/rxv2/iar/inc/tx_port.h b/ports/rxv2/iar/inc/tx_port.h index 3a909e3ea..29e86e9fc 100644 --- a/ports/rxv2/iar/inc/tx_port.h +++ b/ports/rxv2/iar/inc/tx_port.h @@ -256,7 +256,7 @@ static void _tx_thread_system_return_inline(void) #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX RXv2/IAR Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX RXv2/IAR Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/rxv3/ccrx/inc/tx_port.h b/ports/rxv3/ccrx/inc/tx_port.h index 5db2d42a5..7622ad1d7 100644 --- a/ports/rxv3/ccrx/inc/tx_port.h +++ b/ports/rxv3/ccrx/inc/tx_port.h @@ -265,7 +265,7 @@ void tx_thread_fpu_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX RXv3/CCRX Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX RXv3/CCRX Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/rxv3/gnu/inc/tx_port.h b/ports/rxv3/gnu/inc/tx_port.h index 9e8a5fb26..ec395335f 100644 --- a/ports/rxv3/gnu/inc/tx_port.h +++ b/ports/rxv3/gnu/inc/tx_port.h @@ -262,7 +262,7 @@ void tx_thread_fpu_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX RXv3/GNURX Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX RXv3/GNURX Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/rxv3/iar/inc/tx_port.h b/ports/rxv3/iar/inc/tx_port.h index 018a8aed3..e341f98d7 100644 --- a/ports/rxv3/iar/inc/tx_port.h +++ b/ports/rxv3/iar/inc/tx_port.h @@ -262,7 +262,7 @@ void tx_thread_fpu_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX RXv3/IAR Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX RXv3/IAR Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/win32/vs_2019/inc/tx_port.h b/ports/win32/vs_2019/inc/tx_port.h index 7c882a632..f878bd0e0 100644 --- a/ports/win32/vs_2019/inc/tx_port.h +++ b/ports/win32/vs_2019/inc/tx_port.h @@ -483,7 +483,7 @@ VOID _tx_thread_interrupt_restore(UINT previous_posture); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Win32/Visual Studio Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Win32/Visual Studio Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/win64/vs_2022/inc/tx_port.h b/ports/win64/vs_2022/inc/tx_port.h index 412143546..a5623b847 100644 --- a/ports/win64/vs_2022/inc/tx_port.h +++ b/ports/win64/vs_2022/inc/tx_port.h @@ -549,7 +549,7 @@ VOID _tx_thread_interrupt_restore(UINT previous_posture); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2026 Eclipse ThreadX contributors. * ThreadX Win64/MSVC Version 6.5.1.202602a *"; + "(c) 2026 Eclipse ThreadX contributors. * ThreadX Win64/MSVC Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports/xtensa/xcc/inc/tx_port.h b/ports/xtensa/xcc/inc/tx_port.h index a6c55a974..7482c37dd 100644 --- a/ports/xtensa/xcc/inc/tx_port.h +++ b/ports/xtensa/xcc/inc/tx_port.h @@ -461,7 +461,7 @@ extern int xt_timer_intnum; #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * Azure RTOS Xtensa Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * Azure RTOS Xtensa Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_arch/ARMv7-A/threadx/common/inc/tx_port.h b/ports_arch/ARMv7-A/threadx/common/inc/tx_port.h index 15d6c3c51..798dc4579 100644 --- a/ports_arch/ARMv7-A/threadx/common/inc/tx_port.h +++ b/ports_arch/ARMv7-A/threadx/common/inc/tx_port.h @@ -307,7 +307,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-A Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-A Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_arch/ARMv7-M/threadx/ghs/inc/tx_port.h b/ports_arch/ARMv7-M/threadx/ghs/inc/tx_port.h index 41b32b434..b28ef5c51 100644 --- a/ports_arch/ARMv7-M/threadx/ghs/inc/tx_port.h +++ b/ports_arch/ARMv7-M/threadx/ghs/inc/tx_port.h @@ -387,7 +387,7 @@ void tx_thread_fpu_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-M Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-M Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports_arch/ARMv7-M/threadx/inc/tx_port.h b/ports_arch/ARMv7-M/threadx/inc/tx_port.h index 088a8f91e..d3d4771c9 100644 --- a/ports_arch/ARMv7-M/threadx/inc/tx_port.h +++ b/ports_arch/ARMv7-M/threadx/inc/tx_port.h @@ -704,7 +704,7 @@ void tx_thread_fpu_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-Mx Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-Mx Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports_arch/ARMv7-M/threadx_modules/inc/tx_port.h b/ports_arch/ARMv7-M/threadx_modules/inc/tx_port.h index 746586f3b..1675be09b 100644 --- a/ports_arch/ARMv7-M/threadx_modules/inc/tx_port.h +++ b/ports_arch/ARMv7-M/threadx_modules/inc/tx_port.h @@ -711,7 +711,7 @@ void tx_thread_fpu_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-Mx Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-Mx Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports_arch/ARMv8-A/threadx/common/inc/tx_port.h b/ports_arch/ARMv8-A/threadx/common/inc/tx_port.h index 4487de47e..691fedd8d 100644 --- a/ports_arch/ARMv8-A/threadx/common/inc/tx_port.h +++ b/ports_arch/ARMv8-A/threadx/common/inc/tx_port.h @@ -361,7 +361,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_arch/ARMv8-A/threadx_smp/common/inc/tx_port.h b/ports_arch/ARMv8-A/threadx_smp/common/inc/tx_port.h index e97d78d5f..38c86cb23 100644 --- a/ports_arch/ARMv8-A/threadx_smp/common/inc/tx_port.h +++ b/ports_arch/ARMv8-A/threadx_smp/common/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_arch/ARMv8-M/threadx/inc/tx_port.h b/ports_arch/ARMv8-M/threadx/inc/tx_port.h index 625ca2bec..c59feb719 100644 --- a/ports_arch/ARMv8-M/threadx/inc/tx_port.h +++ b/ports_arch/ARMv8-M/threadx/inc/tx_port.h @@ -618,7 +618,7 @@ VOID _tx_thread_interrupt_restore(UIN #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-Mxx Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-Mxx Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports_module/cortex_a35/ac6/inc/tx_port.h b/ports_module/cortex_a35/ac6/inc/tx_port.h index 937c99c6d..9d4522228 100644 --- a/ports_module/cortex_a35/ac6/inc/tx_port.h +++ b/ports_module/cortex_a35/ac6/inc/tx_port.h @@ -381,7 +381,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Modules Cortex-A35/AC6 Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Modules Cortex-A35/AC6 Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_module/cortex_a35/gnu/inc/tx_port.h b/ports_module/cortex_a35/gnu/inc/tx_port.h index 96e5f3b44..4e22d7360 100644 --- a/ports_module/cortex_a35/gnu/inc/tx_port.h +++ b/ports_module/cortex_a35/gnu/inc/tx_port.h @@ -381,7 +381,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Modules Cortex-A35/GNU Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Modules Cortex-A35/GNU Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_module/cortex_a35_smp/ac6/inc/tx_port.h b/ports_module/cortex_a35_smp/ac6/inc/tx_port.h index c84f86164..fa9c581a4 100644 --- a/ports_module/cortex_a35_smp/ac6/inc/tx_port.h +++ b/ports_module/cortex_a35_smp/ac6/inc/tx_port.h @@ -435,7 +435,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Modules Cortex-A35-SMP/AC6 Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Modules Cortex-A35-SMP/AC6 Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_module/cortex_a35_smp/gnu/inc/tx_port.h b/ports_module/cortex_a35_smp/gnu/inc/tx_port.h index 5d2794a64..8271445d4 100644 --- a/ports_module/cortex_a35_smp/gnu/inc/tx_port.h +++ b/ports_module/cortex_a35_smp/gnu/inc/tx_port.h @@ -435,7 +435,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Modules Cortex-A35-SMP/GNU Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Modules Cortex-A35-SMP/GNU Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_module/cortex_a7/ac5/inc/tx_port.h b/ports_module/cortex_a7/ac5/inc/tx_port.h index 21d8878b1..42bea41ba 100644 --- a/ports_module/cortex_a7/ac5/inc/tx_port.h +++ b/ports_module/cortex_a7/ac5/inc/tx_port.h @@ -336,7 +336,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A7/AC5 Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A7/AC5 Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_module/cortex_a7/gnu/inc/tx_port.h b/ports_module/cortex_a7/gnu/inc/tx_port.h index 5475ab4af..8d3b88eb6 100644 --- a/ports_module/cortex_a7/gnu/inc/tx_port.h +++ b/ports_module/cortex_a7/gnu/inc/tx_port.h @@ -321,7 +321,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-A Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-A Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_module/cortex_a7/iar/inc/tx_port.h b/ports_module/cortex_a7/iar/inc/tx_port.h index 6fe0c2741..b20563b92 100644 --- a/ports_module/cortex_a7/iar/inc/tx_port.h +++ b/ports_module/cortex_a7/iar/inc/tx_port.h @@ -399,7 +399,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A7/IAR Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A7/IAR Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports_module/cortex_m0+/ac6/inc/tx_port.h b/ports_module/cortex_m0+/ac6/inc/tx_port.h index 233662b45..b7eb1061e 100644 --- a/ports_module/cortex_m0+/ac6/inc/tx_port.h +++ b/ports_module/cortex_m0+/ac6/inc/tx_port.h @@ -509,7 +509,7 @@ void tx_thread_fpu_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M0+/AC6 Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M0+/AC6 Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_module/cortex_m0+/gnu/inc/tx_port.h b/ports_module/cortex_m0+/gnu/inc/tx_port.h index fa3fd7192..6e1d9b762 100644 --- a/ports_module/cortex_m0+/gnu/inc/tx_port.h +++ b/ports_module/cortex_m0+/gnu/inc/tx_port.h @@ -523,7 +523,7 @@ void tx_thread_fpu_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M0+/AC6 Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M0+/AC6 Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_module/cortex_m0+/iar/inc/tx_port.h b/ports_module/cortex_m0+/iar/inc/tx_port.h index 63ba51e4b..15073a787 100644 --- a/ports_module/cortex_m0+/iar/inc/tx_port.h +++ b/ports_module/cortex_m0+/iar/inc/tx_port.h @@ -559,7 +559,7 @@ void tx_thread_fpu_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M0+/IAR Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M0+/IAR Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports_module/cortex_m23/ac6/inc/tx_port.h b/ports_module/cortex_m23/ac6/inc/tx_port.h index e46a9e0c8..4c84de581 100644 --- a/ports_module/cortex_m23/ac6/inc/tx_port.h +++ b/ports_module/cortex_m23/ac6/inc/tx_port.h @@ -564,7 +564,7 @@ unsigned int was_masked; #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M23/AC6 Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M23/AC6 Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports_module/cortex_m23/gnu/inc/tx_port.h b/ports_module/cortex_m23/gnu/inc/tx_port.h index 70dae5815..fa33b766b 100644 --- a/ports_module/cortex_m23/gnu/inc/tx_port.h +++ b/ports_module/cortex_m23/gnu/inc/tx_port.h @@ -465,7 +465,7 @@ unsigned int interrupt_save; #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M23/GNU Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M23/GNU Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports_module/cortex_m23/iar/inc/tx_port.h b/ports_module/cortex_m23/iar/inc/tx_port.h index e84243ad2..313613f15 100644 --- a/ports_module/cortex_m23/iar/inc/tx_port.h +++ b/ports_module/cortex_m23/iar/inc/tx_port.h @@ -695,7 +695,7 @@ VOID _tx_thread_interrupt_restore(UIN #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M23/IAR Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M23/IAR Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports_module/cortex_m3/ac5/inc/tx_port.h b/ports_module/cortex_m3/ac5/inc/tx_port.h index 115d5a3d8..77f8faa9d 100644 --- a/ports_module/cortex_m3/ac5/inc/tx_port.h +++ b/ports_module/cortex_m3/ac5/inc/tx_port.h @@ -711,7 +711,7 @@ void tx_thread_fpu_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M3 Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M3 Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports_module/cortex_m3/ac6/inc/tx_port.h b/ports_module/cortex_m3/ac6/inc/tx_port.h index 115d5a3d8..77f8faa9d 100644 --- a/ports_module/cortex_m3/ac6/inc/tx_port.h +++ b/ports_module/cortex_m3/ac6/inc/tx_port.h @@ -711,7 +711,7 @@ void tx_thread_fpu_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M3 Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M3 Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports_module/cortex_m3/gnu/inc/tx_port.h b/ports_module/cortex_m3/gnu/inc/tx_port.h index 115d5a3d8..77f8faa9d 100644 --- a/ports_module/cortex_m3/gnu/inc/tx_port.h +++ b/ports_module/cortex_m3/gnu/inc/tx_port.h @@ -711,7 +711,7 @@ void tx_thread_fpu_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M3 Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M3 Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports_module/cortex_m3/iar/inc/tx_port.h b/ports_module/cortex_m3/iar/inc/tx_port.h index 115d5a3d8..77f8faa9d 100644 --- a/ports_module/cortex_m3/iar/inc/tx_port.h +++ b/ports_module/cortex_m3/iar/inc/tx_port.h @@ -711,7 +711,7 @@ void tx_thread_fpu_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M3 Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M3 Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports_module/cortex_m33/ac6/inc/tx_port.h b/ports_module/cortex_m33/ac6/inc/tx_port.h index bf859fbca..14bc8a19f 100644 --- a/ports_module/cortex_m33/ac6/inc/tx_port.h +++ b/ports_module/cortex_m33/ac6/inc/tx_port.h @@ -675,7 +675,7 @@ VOID _tx_thread_interrupt_restore(UIN #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M33 Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M33 Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports_module/cortex_m33/gnu/inc/tx_port.h b/ports_module/cortex_m33/gnu/inc/tx_port.h index bf859fbca..14bc8a19f 100644 --- a/ports_module/cortex_m33/gnu/inc/tx_port.h +++ b/ports_module/cortex_m33/gnu/inc/tx_port.h @@ -675,7 +675,7 @@ VOID _tx_thread_interrupt_restore(UIN #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M33 Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M33 Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports_module/cortex_m33/iar/inc/tx_port.h b/ports_module/cortex_m33/iar/inc/tx_port.h index bf859fbca..14bc8a19f 100644 --- a/ports_module/cortex_m33/iar/inc/tx_port.h +++ b/ports_module/cortex_m33/iar/inc/tx_port.h @@ -675,7 +675,7 @@ VOID _tx_thread_interrupt_restore(UIN #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M33 Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M33 Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports_module/cortex_m4/ac5/inc/tx_port.h b/ports_module/cortex_m4/ac5/inc/tx_port.h index 14dbe9626..ab64b09b5 100644 --- a/ports_module/cortex_m4/ac5/inc/tx_port.h +++ b/ports_module/cortex_m4/ac5/inc/tx_port.h @@ -711,7 +711,7 @@ void tx_thread_fpu_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M4 Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M4 Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports_module/cortex_m4/ac6/inc/tx_port.h b/ports_module/cortex_m4/ac6/inc/tx_port.h index 14dbe9626..ab64b09b5 100644 --- a/ports_module/cortex_m4/ac6/inc/tx_port.h +++ b/ports_module/cortex_m4/ac6/inc/tx_port.h @@ -711,7 +711,7 @@ void tx_thread_fpu_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M4 Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M4 Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports_module/cortex_m4/gnu/inc/tx_port.h b/ports_module/cortex_m4/gnu/inc/tx_port.h index 14dbe9626..ab64b09b5 100644 --- a/ports_module/cortex_m4/gnu/inc/tx_port.h +++ b/ports_module/cortex_m4/gnu/inc/tx_port.h @@ -711,7 +711,7 @@ void tx_thread_fpu_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M4 Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M4 Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports_module/cortex_m4/iar/inc/tx_port.h b/ports_module/cortex_m4/iar/inc/tx_port.h index 14dbe9626..ab64b09b5 100644 --- a/ports_module/cortex_m4/iar/inc/tx_port.h +++ b/ports_module/cortex_m4/iar/inc/tx_port.h @@ -711,7 +711,7 @@ void tx_thread_fpu_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M4 Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M4 Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports_module/cortex_m7/ac5/inc/tx_port.h b/ports_module/cortex_m7/ac5/inc/tx_port.h index 70b6c5a93..9a0095968 100644 --- a/ports_module/cortex_m7/ac5/inc/tx_port.h +++ b/ports_module/cortex_m7/ac5/inc/tx_port.h @@ -711,7 +711,7 @@ void tx_thread_fpu_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M7 Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M7 Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports_module/cortex_m7/ac6/inc/tx_port.h b/ports_module/cortex_m7/ac6/inc/tx_port.h index 70b6c5a93..9a0095968 100644 --- a/ports_module/cortex_m7/ac6/inc/tx_port.h +++ b/ports_module/cortex_m7/ac6/inc/tx_port.h @@ -711,7 +711,7 @@ void tx_thread_fpu_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M7 Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M7 Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports_module/cortex_m7/gnu/inc/tx_port.h b/ports_module/cortex_m7/gnu/inc/tx_port.h index 70b6c5a93..9a0095968 100644 --- a/ports_module/cortex_m7/gnu/inc/tx_port.h +++ b/ports_module/cortex_m7/gnu/inc/tx_port.h @@ -711,7 +711,7 @@ void tx_thread_fpu_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M7 Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M7 Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports_module/cortex_m7/iar/inc/tx_port.h b/ports_module/cortex_m7/iar/inc/tx_port.h index 70b6c5a93..9a0095968 100644 --- a/ports_module/cortex_m7/iar/inc/tx_port.h +++ b/ports_module/cortex_m7/iar/inc/tx_port.h @@ -711,7 +711,7 @@ void tx_thread_fpu_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M7 Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-M7 Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports_module/cortex_r4/ac6/inc/tx_port.h b/ports_module/cortex_r4/ac6/inc/tx_port.h index 10f3f624c..20368188e 100644 --- a/ports_module/cortex_r4/ac6/inc/tx_port.h +++ b/ports_module/cortex_r4/ac6/inc/tx_port.h @@ -337,7 +337,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-R4/AC6 Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-R4/AC6 Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_module/cortex_r4/iar/inc/tx_port.h b/ports_module/cortex_r4/iar/inc/tx_port.h index 509685528..26db35d47 100644 --- a/ports_module/cortex_r4/iar/inc/tx_port.h +++ b/ports_module/cortex_r4/iar/inc/tx_port.h @@ -386,7 +386,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-R4/IAR Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-R4/IAR Version 6.5.2.202603 *"; #else #ifdef TX_MISRA_ENABLE extern CHAR _tx_version_id[100]; diff --git a/ports_module/cortex_r52/gnu/inc/tx_port.h b/ports_module/cortex_r52/gnu/inc/tx_port.h index 9f6e8e3da..8f099300a 100644 --- a/ports_module/cortex_r52/gnu/inc/tx_port.h +++ b/ports_module/cortex_r52/gnu/inc/tx_port.h @@ -432,7 +432,7 @@ unsigned int _tx_thread_interrupt_restore(UINT old_posture); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadXCortex-R52/GNU Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadXCortex-R52/GNU Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_module/rxv2/iar/inc/tx_port.h b/ports_module/rxv2/iar/inc/tx_port.h index 2ed9abf3c..23162277b 100644 --- a/ports_module/rxv2/iar/inc/tx_port.h +++ b/ports_module/rxv2/iar/inc/tx_port.h @@ -273,7 +273,7 @@ static void _tx_thread_system_return_inline(void) #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX RXv2/IAR Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX RXv2/IAR Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/arc_hs_smp/metaware/inc/tx_port.h b/ports_smp/arc_hs_smp/metaware/inc/tx_port.h index 8b0841603..335ec252e 100644 --- a/ports_smp/arc_hs_smp/metaware/inc/tx_port.h +++ b/ports_smp/arc_hs_smp/metaware/inc/tx_port.h @@ -395,7 +395,7 @@ typedef struct TX_THREAD_SMP_PROTECT_STRUCT #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX SMP/ARC_HS/MetaWare Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX SMP/ARC_HS/MetaWare Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a34_smp/ac6/inc/tx_port.h b/ports_smp/cortex_a34_smp/ac6/inc/tx_port.h index e97d78d5f..38c86cb23 100644 --- a/ports_smp/cortex_a34_smp/ac6/inc/tx_port.h +++ b/ports_smp/cortex_a34_smp/ac6/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a34_smp/gnu/inc/tx_port.h b/ports_smp/cortex_a34_smp/gnu/inc/tx_port.h index e97d78d5f..38c86cb23 100644 --- a/ports_smp/cortex_a34_smp/gnu/inc/tx_port.h +++ b/ports_smp/cortex_a34_smp/gnu/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a35_smp/ac6/inc/tx_port.h b/ports_smp/cortex_a35_smp/ac6/inc/tx_port.h index e97d78d5f..38c86cb23 100644 --- a/ports_smp/cortex_a35_smp/ac6/inc/tx_port.h +++ b/ports_smp/cortex_a35_smp/ac6/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a35_smp/gnu/inc/tx_port.h b/ports_smp/cortex_a35_smp/gnu/inc/tx_port.h index e97d78d5f..38c86cb23 100644 --- a/ports_smp/cortex_a35_smp/gnu/inc/tx_port.h +++ b/ports_smp/cortex_a35_smp/gnu/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a53_smp/ac6/inc/tx_port.h b/ports_smp/cortex_a53_smp/ac6/inc/tx_port.h index e97d78d5f..38c86cb23 100644 --- a/ports_smp/cortex_a53_smp/ac6/inc/tx_port.h +++ b/ports_smp/cortex_a53_smp/ac6/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a53_smp/gnu/inc/tx_port.h b/ports_smp/cortex_a53_smp/gnu/inc/tx_port.h index e97d78d5f..38c86cb23 100644 --- a/ports_smp/cortex_a53_smp/gnu/inc/tx_port.h +++ b/ports_smp/cortex_a53_smp/gnu/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a55_smp/ac6/inc/tx_port.h b/ports_smp/cortex_a55_smp/ac6/inc/tx_port.h index e97d78d5f..38c86cb23 100644 --- a/ports_smp/cortex_a55_smp/ac6/inc/tx_port.h +++ b/ports_smp/cortex_a55_smp/ac6/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a55_smp/gnu/inc/tx_port.h b/ports_smp/cortex_a55_smp/gnu/inc/tx_port.h index e97d78d5f..38c86cb23 100644 --- a/ports_smp/cortex_a55_smp/gnu/inc/tx_port.h +++ b/ports_smp/cortex_a55_smp/gnu/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a57_smp/ac6/inc/tx_port.h b/ports_smp/cortex_a57_smp/ac6/inc/tx_port.h index e97d78d5f..38c86cb23 100644 --- a/ports_smp/cortex_a57_smp/ac6/inc/tx_port.h +++ b/ports_smp/cortex_a57_smp/ac6/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a57_smp/gnu/inc/tx_port.h b/ports_smp/cortex_a57_smp/gnu/inc/tx_port.h index e97d78d5f..38c86cb23 100644 --- a/ports_smp/cortex_a57_smp/gnu/inc/tx_port.h +++ b/ports_smp/cortex_a57_smp/gnu/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a5_smp/ac5/inc/tx_port.h b/ports_smp/cortex_a5_smp/ac5/inc/tx_port.h index 0db5a2928..30e2719a9 100644 --- a/ports_smp/cortex_a5_smp/ac5/inc/tx_port.h +++ b/ports_smp/cortex_a5_smp/ac5/inc/tx_port.h @@ -388,7 +388,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX SMP/Cortex-A5/AC5 Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX SMP/Cortex-A5/AC5 Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a5_smp/gnu/inc/tx_port.h b/ports_smp/cortex_a5_smp/gnu/inc/tx_port.h index deb717683..b60e132f3 100644 --- a/ports_smp/cortex_a5_smp/gnu/inc/tx_port.h +++ b/ports_smp/cortex_a5_smp/gnu/inc/tx_port.h @@ -391,7 +391,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX SMP/Cortex-A5/GNU Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX SMP/Cortex-A5/GNU Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a5x_smp/ac6/inc/tx_port.h b/ports_smp/cortex_a5x_smp/ac6/inc/tx_port.h index 2000b6f5e..14b1f783b 100644 --- a/ports_smp/cortex_a5x_smp/ac6/inc/tx_port.h +++ b/ports_smp/cortex_a5x_smp/ac6/inc/tx_port.h @@ -412,7 +412,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "Copyright (c) 1996-2019 Express Logic Inc. * ThreadX Cortex-A5x-SMP/AC6 Version 6.5.1.202602a *"; + "Copyright (c) 1996-2019 Express Logic Inc. * ThreadX Cortex-A5x-SMP/AC6 Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a5x_smp/gnu/inc/tx_port.h b/ports_smp/cortex_a5x_smp/gnu/inc/tx_port.h index 90e2da851..254944381 100644 --- a/ports_smp/cortex_a5x_smp/gnu/inc/tx_port.h +++ b/ports_smp/cortex_a5x_smp/gnu/inc/tx_port.h @@ -412,7 +412,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A5x-SMP/GNU Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A5x-SMP/GNU Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a5x_smp/green/inc/tx_port.h b/ports_smp/cortex_a5x_smp/green/inc/tx_port.h index 50476b1c4..bae66fef6 100644 --- a/ports_smp/cortex_a5x_smp/green/inc/tx_port.h +++ b/ports_smp/cortex_a5x_smp/green/inc/tx_port.h @@ -432,7 +432,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A5x-SMP/GHS Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A5x-SMP/GHS Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a5x_smp/iar/inc/tx_port.h b/ports_smp/cortex_a5x_smp/iar/inc/tx_port.h index 0bd495284..29003aee6 100644 --- a/ports_smp/cortex_a5x_smp/iar/inc/tx_port.h +++ b/ports_smp/cortex_a5x_smp/iar/inc/tx_port.h @@ -441,7 +441,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A5x-SMP/IAR Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX Cortex-A5x-SMP/IAR Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a65_smp/ac6/inc/tx_port.h b/ports_smp/cortex_a65_smp/ac6/inc/tx_port.h index e97d78d5f..38c86cb23 100644 --- a/ports_smp/cortex_a65_smp/ac6/inc/tx_port.h +++ b/ports_smp/cortex_a65_smp/ac6/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a65_smp/gnu/inc/tx_port.h b/ports_smp/cortex_a65_smp/gnu/inc/tx_port.h index e97d78d5f..38c86cb23 100644 --- a/ports_smp/cortex_a65_smp/gnu/inc/tx_port.h +++ b/ports_smp/cortex_a65_smp/gnu/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a65ae_smp/ac6/inc/tx_port.h b/ports_smp/cortex_a65ae_smp/ac6/inc/tx_port.h index e97d78d5f..38c86cb23 100644 --- a/ports_smp/cortex_a65ae_smp/ac6/inc/tx_port.h +++ b/ports_smp/cortex_a65ae_smp/ac6/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a65ae_smp/gnu/inc/tx_port.h b/ports_smp/cortex_a65ae_smp/gnu/inc/tx_port.h index e97d78d5f..38c86cb23 100644 --- a/ports_smp/cortex_a65ae_smp/gnu/inc/tx_port.h +++ b/ports_smp/cortex_a65ae_smp/gnu/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a72_smp/ac6/inc/tx_port.h b/ports_smp/cortex_a72_smp/ac6/inc/tx_port.h index e97d78d5f..38c86cb23 100644 --- a/ports_smp/cortex_a72_smp/ac6/inc/tx_port.h +++ b/ports_smp/cortex_a72_smp/ac6/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a72_smp/gnu/inc/tx_port.h b/ports_smp/cortex_a72_smp/gnu/inc/tx_port.h index e97d78d5f..38c86cb23 100644 --- a/ports_smp/cortex_a72_smp/gnu/inc/tx_port.h +++ b/ports_smp/cortex_a72_smp/gnu/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a73_smp/ac6/inc/tx_port.h b/ports_smp/cortex_a73_smp/ac6/inc/tx_port.h index e97d78d5f..38c86cb23 100644 --- a/ports_smp/cortex_a73_smp/ac6/inc/tx_port.h +++ b/ports_smp/cortex_a73_smp/ac6/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a73_smp/gnu/inc/tx_port.h b/ports_smp/cortex_a73_smp/gnu/inc/tx_port.h index e97d78d5f..38c86cb23 100644 --- a/ports_smp/cortex_a73_smp/gnu/inc/tx_port.h +++ b/ports_smp/cortex_a73_smp/gnu/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a75_smp/ac6/inc/tx_port.h b/ports_smp/cortex_a75_smp/ac6/inc/tx_port.h index e97d78d5f..38c86cb23 100644 --- a/ports_smp/cortex_a75_smp/ac6/inc/tx_port.h +++ b/ports_smp/cortex_a75_smp/ac6/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a75_smp/gnu/inc/tx_port.h b/ports_smp/cortex_a75_smp/gnu/inc/tx_port.h index e97d78d5f..38c86cb23 100644 --- a/ports_smp/cortex_a75_smp/gnu/inc/tx_port.h +++ b/ports_smp/cortex_a75_smp/gnu/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a76_smp/ac6/inc/tx_port.h b/ports_smp/cortex_a76_smp/ac6/inc/tx_port.h index e97d78d5f..38c86cb23 100644 --- a/ports_smp/cortex_a76_smp/ac6/inc/tx_port.h +++ b/ports_smp/cortex_a76_smp/ac6/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a76_smp/gnu/inc/tx_port.h b/ports_smp/cortex_a76_smp/gnu/inc/tx_port.h index e97d78d5f..38c86cb23 100644 --- a/ports_smp/cortex_a76_smp/gnu/inc/tx_port.h +++ b/ports_smp/cortex_a76_smp/gnu/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a76ae_smp/ac6/inc/tx_port.h b/ports_smp/cortex_a76ae_smp/ac6/inc/tx_port.h index e97d78d5f..38c86cb23 100644 --- a/ports_smp/cortex_a76ae_smp/ac6/inc/tx_port.h +++ b/ports_smp/cortex_a76ae_smp/ac6/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a76ae_smp/gnu/inc/tx_port.h b/ports_smp/cortex_a76ae_smp/gnu/inc/tx_port.h index e97d78d5f..38c86cb23 100644 --- a/ports_smp/cortex_a76ae_smp/gnu/inc/tx_port.h +++ b/ports_smp/cortex_a76ae_smp/gnu/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a77_smp/ac6/inc/tx_port.h b/ports_smp/cortex_a77_smp/ac6/inc/tx_port.h index e97d78d5f..38c86cb23 100644 --- a/ports_smp/cortex_a77_smp/ac6/inc/tx_port.h +++ b/ports_smp/cortex_a77_smp/ac6/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a77_smp/gnu/inc/tx_port.h b/ports_smp/cortex_a77_smp/gnu/inc/tx_port.h index e97d78d5f..38c86cb23 100644 --- a/ports_smp/cortex_a77_smp/gnu/inc/tx_port.h +++ b/ports_smp/cortex_a77_smp/gnu/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a78_smp/ac6/inc/tx_port.h b/ports_smp/cortex_a78_smp/ac6/inc/tx_port.h index e97d78d5f..38c86cb23 100644 --- a/ports_smp/cortex_a78_smp/ac6/inc/tx_port.h +++ b/ports_smp/cortex_a78_smp/ac6/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a78_smp/gnu/inc/tx_port.h b/ports_smp/cortex_a78_smp/gnu/inc/tx_port.h index e97d78d5f..38c86cb23 100644 --- a/ports_smp/cortex_a78_smp/gnu/inc/tx_port.h +++ b/ports_smp/cortex_a78_smp/gnu/inc/tx_port.h @@ -411,7 +411,7 @@ VOID tx_thread_fp_disable(VOID); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv8-A-SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a7_smp/ac5/inc/tx_port.h b/ports_smp/cortex_a7_smp/ac5/inc/tx_port.h index c5af63c84..807629317 100644 --- a/ports_smp/cortex_a7_smp/ac5/inc/tx_port.h +++ b/ports_smp/cortex_a7_smp/ac5/inc/tx_port.h @@ -388,7 +388,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX SMP/Cortex-A7/AC5 Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX SMP/Cortex-A7/AC5 Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a7_smp/gnu/inc/tx_port.h b/ports_smp/cortex_a7_smp/gnu/inc/tx_port.h index 93b89ff9a..31725d3ef 100644 --- a/ports_smp/cortex_a7_smp/gnu/inc/tx_port.h +++ b/ports_smp/cortex_a7_smp/gnu/inc/tx_port.h @@ -386,7 +386,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX SMP/Cortex-A7/GNU Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX SMP/Cortex-A7/GNU Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a9_smp/ac5/inc/tx_port.h b/ports_smp/cortex_a9_smp/ac5/inc/tx_port.h index 1f2ab286d..b36a314fa 100644 --- a/ports_smp/cortex_a9_smp/ac5/inc/tx_port.h +++ b/ports_smp/cortex_a9_smp/ac5/inc/tx_port.h @@ -393,7 +393,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX SMP/Cortex-A9/AC5 Version Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX SMP/Cortex-A9/AC5 Version Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_a9_smp/gnu/inc/tx_port.h b/ports_smp/cortex_a9_smp/gnu/inc/tx_port.h index c43fcb7a0..564970576 100644 --- a/ports_smp/cortex_a9_smp/gnu/inc/tx_port.h +++ b/ports_smp/cortex_a9_smp/gnu/inc/tx_port.h @@ -386,7 +386,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX SMP/Cortex-A9/GNU Version Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX SMP/Cortex-A9/GNU Version Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/cortex_r8_smp/ac5/inc/tx_port.h b/ports_smp/cortex_r8_smp/ac5/inc/tx_port.h index cc17a732e..10743d13c 100644 --- a/ports_smp/cortex_r8_smp/ac5/inc/tx_port.h +++ b/ports_smp/cortex_r8_smp/ac5/inc/tx_port.h @@ -393,7 +393,7 @@ void tx_thread_vfp_disable(void); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-R SMP Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX ARMv7-R SMP Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/linux/gnu/inc/tx_port.h b/ports_smp/linux/gnu/inc/tx_port.h index 53a4dc03f..b7da882ab 100644 --- a/ports_smp/linux/gnu/inc/tx_port.h +++ b/ports_smp/linux/gnu/inc/tx_port.h @@ -642,7 +642,7 @@ void _tx_thread_smp_debug_entry_insert(ULONG id, ULONG su #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX SMP/Linux/gcc Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX SMP/Linux/gcc Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/mips32_interaptiv_smp/gnu/inc/tx_port.h b/ports_smp/mips32_interaptiv_smp/gnu/inc/tx_port.h index 87ee3fcc6..6e15542c1 100644 --- a/ports_smp/mips32_interaptiv_smp/gnu/inc/tx_port.h +++ b/ports_smp/mips32_interaptiv_smp/gnu/inc/tx_port.h @@ -419,7 +419,7 @@ THREAD_SMP_DECLARE ULONG _tx_thread_smp_initial_fpu_control_register; #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX SMP MIPS32_interAptiv/GNU Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX SMP MIPS32_interAptiv/GNU Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/mips32_interaptiv_smp/green/inc/tx_port.h b/ports_smp/mips32_interaptiv_smp/green/inc/tx_port.h index 06d0142ef..20b1d56be 100644 --- a/ports_smp/mips32_interaptiv_smp/green/inc/tx_port.h +++ b/ports_smp/mips32_interaptiv_smp/green/inc/tx_port.h @@ -509,7 +509,7 @@ THREAD_SMP_DECLARE ULONG _tx_thread_smp_initial_fpu_control_register; #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX SMP MIPS32_interAptiv/Green Hills Version 6.5.1.202602a *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX SMP MIPS32_interAptiv/Green Hills Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/ports_smp/win64/vs_2022/inc/tx_port.h b/ports_smp/win64/vs_2022/inc/tx_port.h index 15225230d..949c812ef 100644 --- a/ports_smp/win64/vs_2022/inc/tx_port.h +++ b/ports_smp/win64/vs_2022/inc/tx_port.h @@ -441,7 +441,7 @@ UINT _tx_thread_interrupt_control(UINT new_posture); #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2026 Eclipse ThreadX contributors. * ThreadX SMP/Win64/MSVC Version 6.5.1.202602a *"; + "(c) 2026 Eclipse ThreadX contributors. * ThreadX SMP/Win64/MSVC Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif From 80dfbe7797f4e03bb878f06b9557ddc4041cf212 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 28 Sep 2026 14:50:27 -0400 Subject: [PATCH 175/181] Added the release and disclosure passes to the blame ignore list (#782) Two commits on dev are mechanical and repository-wide, and neither is in the list. The disclosure normalisation is the second half of a pass whose first half, #740, is already listed, so blame behaves differently either side of it. The version pass is the same shape as the two release preparations above it. Both are now listed with their file counts. The const object names change is deliberately absent: it alters behaviour, and size is not the criterion. All thirteen revisions in the file resolve, and git accepts it as an ignore file. Assisted-by: Claude Code (Opus 5) --- .git-blame-ignore-revs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index cf90f4143..3b36e8329 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -52,3 +52,11 @@ df30b8b96e4c0c6d72e0bb80d2a2ec31666e5afe # 2026-09-15 Normalized the AI disclosure comment to one fixed line per file (#740) # 455 files 9e4c57138dfa004cd512b60259c1c5047a8b3dd1 + +# 2026-09-28 Normalized the AI disclosure comment and added a check that keeps it so (#762) +# 158 files +83361990cb4d03da8851e30030688ed3abb4d840 + +# 2026-09-28 Updated ThreadX version constants and port strings to 6.5.2.202603 (#781) +# 212 files +a7ded6a3b9e12985a6c52af4df419d2326cccc0a From 0a52df8f87d473c85b7f9631457fac54718bafd0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Mon, 28 Sep 2026 19:56:37 -0400 Subject: [PATCH 176/181] Stopped the version pass skipping ports in silence (#786) The port stage matched a version only where "Version" was followed immediately by four dotted numbers. A port writing three numbers, or a stray letter before the first, was passed over and kept its old release, and the pass reported success either way. The RISC-V32/IAR port is one of them. It reads "Version G6.5.0.202601", and the letter in front of the number has kept it out of every pass since, so it has advertised 6.5.0.202601 across two releases it was not part of. Its string now reads the current release. The pattern accepts three or four numbers and tolerates a leading letter. A check follows it: any port header that names a release other than the one being prepared is listed and the pass stops, so a port the substitution cannot reach fails the release instead of shipping a version that misreports itself. Verified: every ThreadX port header now advertises 6.5.2.202603. Against a FileX tree, a port the substitution cannot reach makes the pass name the file and exit non-zero, and correcting that string lets the pass complete. Assisted-by: Claude Code (Opus 5) --- ports/risc-v32/iar/inc/tx_port.h | 2 +- scripts/prepare_release.sh | 31 +++++++++++++++++++++++++++++-- 2 files changed, 30 insertions(+), 3 deletions(-) diff --git a/ports/risc-v32/iar/inc/tx_port.h b/ports/risc-v32/iar/inc/tx_port.h index d6232b953..4f6cff834 100644 --- a/ports/risc-v32/iar/inc/tx_port.h +++ b/ports/risc-v32/iar/inc/tx_port.h @@ -257,7 +257,7 @@ unsigned int _tx_thread_interrupt_control(uns #ifdef TX_THREAD_INIT CHAR _tx_version_id[] = - "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX RISC-V32/IAR Version G6.5.0.202601 *"; + "(c) 2024 Microsoft Corp. (c) 2026-present Eclipse ThreadX contributors. * ThreadX RISC-V32/IAR Version 6.5.2.202603 *"; #else extern CHAR _tx_version_id[]; #endif diff --git a/scripts/prepare_release.sh b/scripts/prepare_release.sh index 0c4536670..02e3df839 100755 --- a/scripts/prepare_release.sh +++ b/scripts/prepare_release.sh @@ -159,15 +159,42 @@ PORT_FILES=$(printf "%s" "${PORT_FILES}" | grep -v '^[[:space:]]*$' || true) if [ -z "${PORT_FILES}" ]; then printf "Warning: No port header files found. Skipping port version string commit.\n" else + # A port advertises its release in the string the library reports at run time. + # The pattern accepts three or four dotted numbers and tolerates a stray + # letter before the first one, so a port that writes its version slightly + # differently is still reached. + VERSION_RE='Version[[:space:]]+[A-Za-z]?[0-9]+(\.[0-9]+)+[a-z]*' while IFS= read -r port_file; do - if [ -n "${port_file}" ] && grep -qE "Version [0-9]" "${port_file}" 2>/dev/null; then - sed -i -E "s/Version [0-9]+\.[0-9]+\.[0-9]+\.[0-9]+[a-z]*/Version ${VERSION}/g" "${port_file}" + if [ -n "${port_file}" ] && grep -qE "${VERSION_RE}" "${port_file}" 2>/dev/null; then + sed -i -E "s/${VERSION_RE}/Version ${VERSION}/g" "${port_file}" printf " Updated: %s\n" "${port_file#${REPO_ROOT}/}" fi done </dev/null || true) + [ -n "${advertised}" ] || continue + if ! printf "%s" "${advertised}" | grep -qF "${VERSION}"; then + STALE="${STALE} ${port_file#${REPO_ROOT}/} +" + fi + done <&2 + printf "Correct them so the substitution above reaches them, then re-run.\n" >&2 + exit 1 + fi + git -C "${REPO_ROOT}" add -u if git -C "${REPO_ROOT}" diff --cached --quiet; then printf "No port version string changes staged. Skipping commit.\n" From 7212b366aeb0e02eae4cc1cdc6f9787b19bfd79e Mon Sep 17 00:00:00 2001 From: Afonso Oliveira Date: Wed, 30 Sep 2026 12:13:03 +0100 Subject: [PATCH 177/181] Added an Erbium example to the RISC-V64 GNU port ThreadX had no board support for Erbium, the OpenHW Foundation CORE-ET RISC-V platform that Zephyr and NuttX support. Its hart implements only part of the F extension, needs a 4 KiB aligned mtvec and uses the original Shakti UART. The example runs the standard demo on hart 0 in machine mode. It builds the library and the demo for rv64imc_zicsr_zifencei with the soft-float lp64 ABI and links without libc or libgcc, so the pinned riscv64-unknown-elf toolchain can build it. It programs the machine timer, a polling UART console and the PLIC, writing the source priorities and threshold that silicon hardwires because the simulator resets them to 0. No shared file changes. The demo built without warnings and ran on erbium_emu from et-platform 836a4ab, with all eight threads reporting and five thread 0 wakeups in 100M cycles, which matches the 2 MHz tick. Separate test images took five PLIC UART interrupts through the ThreadX ISR path and halted with mcause 2 on an illegal instruction. check_ai_disclosure.sh and check_ports.sh passed. Assisted-by: Claude Code (Opus 5.5) --- .../gnu/example_build/erbium/CMakeLists.txt | 43 ++ .../gnu/example_build/erbium/README.md | 125 ++++++ .../risc-v64/gnu/example_build/erbium/board.c | 49 +++ .../gnu/example_build/erbium/build.sh | 28 ++ ports/risc-v64/gnu/example_build/erbium/csr.h | 66 +++ .../gnu/example_build/erbium/demo_threadx.c | 382 ++++++++++++++++++ .../risc-v64/gnu/example_build/erbium/entry.S | 50 +++ .../gnu/example_build/erbium/erbium_gnu.cmake | 39 ++ .../gnu/example_build/erbium/hwtimer.c | 42 ++ .../gnu/example_build/erbium/hwtimer.h | 41 ++ .../gnu/example_build/erbium/link.lds | 92 +++++ .../risc-v64/gnu/example_build/erbium/plic.c | 112 +++++ .../risc-v64/gnu/example_build/erbium/plic.h | 54 +++ .../risc-v64/gnu/example_build/erbium/trap.c | 78 ++++ .../erbium/tx_initialize_low_level.S | 142 +++++++ .../risc-v64/gnu/example_build/erbium/uart.c | 106 +++++ .../risc-v64/gnu/example_build/erbium/uart.h | 40 ++ 17 files changed, 1489 insertions(+) create mode 100644 ports/risc-v64/gnu/example_build/erbium/CMakeLists.txt create mode 100644 ports/risc-v64/gnu/example_build/erbium/README.md create mode 100644 ports/risc-v64/gnu/example_build/erbium/board.c create mode 100755 ports/risc-v64/gnu/example_build/erbium/build.sh create mode 100644 ports/risc-v64/gnu/example_build/erbium/csr.h create mode 100644 ports/risc-v64/gnu/example_build/erbium/demo_threadx.c create mode 100644 ports/risc-v64/gnu/example_build/erbium/entry.S create mode 100644 ports/risc-v64/gnu/example_build/erbium/erbium_gnu.cmake create mode 100644 ports/risc-v64/gnu/example_build/erbium/hwtimer.c create mode 100644 ports/risc-v64/gnu/example_build/erbium/hwtimer.h create mode 100644 ports/risc-v64/gnu/example_build/erbium/link.lds create mode 100644 ports/risc-v64/gnu/example_build/erbium/plic.c create mode 100644 ports/risc-v64/gnu/example_build/erbium/plic.h create mode 100644 ports/risc-v64/gnu/example_build/erbium/trap.c create mode 100644 ports/risc-v64/gnu/example_build/erbium/tx_initialize_low_level.S create mode 100644 ports/risc-v64/gnu/example_build/erbium/uart.c create mode 100644 ports/risc-v64/gnu/example_build/erbium/uart.h diff --git a/ports/risc-v64/gnu/example_build/erbium/CMakeLists.txt b/ports/risc-v64/gnu/example_build/erbium/CMakeLists.txt new file mode 100644 index 000000000..244d7656e --- /dev/null +++ b/ports/risc-v64/gnu/example_build/erbium/CMakeLists.txt @@ -0,0 +1,43 @@ +cmake_minimum_required(VERSION 3.13 FATAL_ERROR) + +project(demo_threadx_erbium LANGUAGES C ASM) +set(CMAKE_C_STANDARD 99) +set(CMAKE_C_STANDARD_REQUIRED ON) + +set(ERBIUM_DIR ${CMAKE_CURRENT_LIST_DIR}) +set(THREADX_ROOT ${CMAKE_CURRENT_LIST_DIR}/../../../../..) + +add_subdirectory(${THREADX_ROOT} threadx) + +add_executable(demo_threadx + ${ERBIUM_DIR}/entry.S + ${ERBIUM_DIR}/tx_initialize_low_level.S + ${ERBIUM_DIR}/board.c + ${ERBIUM_DIR}/hwtimer.c + ${ERBIUM_DIR}/plic.c + ${ERBIUM_DIR}/trap.c + ${ERBIUM_DIR}/uart.c + ${ERBIUM_DIR}/demo_threadx.c +) +set_target_properties(demo_threadx PROPERTIES + OUTPUT_NAME "demo_threadx.elf" + LINK_DEPENDS ${ERBIUM_DIR}/link.lds +) + +target_include_directories(demo_threadx PRIVATE ${ERBIUM_DIR}) + +target_link_libraries(demo_threadx PRIVATE threadx) + +target_compile_options(demo_threadx PRIVATE + -Wall + -ffreestanding + -ffunction-sections + -fdata-sections +) + +target_link_options(demo_threadx PRIVATE + -T${ERBIUM_DIR}/link.lds + -nostdlib + -Wl,--gc-sections + -Wl,-Map=${CMAKE_CURRENT_BINARY_DIR}/demo_threadx.map +) diff --git a/ports/risc-v64/gnu/example_build/erbium/README.md b/ports/risc-v64/gnu/example_build/erbium/README.md new file mode 100644 index 000000000..826d7cab7 --- /dev/null +++ b/ports/risc-v64/gnu/example_build/erbium/README.md @@ -0,0 +1,125 @@ +# ThreadX example for Erbium + +This directory runs the standard ThreadX demo on one hart of Erbium, the +16-hart RISC-V platform of the OpenHW Foundation CORE-ET project, using the +RISC-V64 GNU port in machine mode. The public `et-platform` functional +simulator, `erbium_emu`, is the reference target. + +## Hardware used + +| Item | Address | Notes | +|------|---------|-------| +| Hart 0 | - | RV64IMC, machine mode; other harts are parked | +| MRAM | `0x4000_0200` | 16 MiB window; the first 512 bytes belong to the boot flow | +| System registers | `0x0200_0000` | `SystemConfig` bit 6 enables the UART | +| UART0 | `0x0200_4000` | Original Shakti integration, polling, 115200 8N1 | +| Machine timer | `0x80F4_0200` | `mtime`, with `mtimecmp` at `+0x08` | +| PLIC | `0xA000_0000` | Machine-mode context of hart 0; sources 1 to 6 | + +## Port notes + +* **Soft float.** Erbium implements only part of the F extension: divide, + square root and conversions between single precision and 64-bit integers + raise an emulation exception. The example and the ThreadX library are + built for `rv64imc_zicsr_zifencei` with the `lp64` ABI, so the port saves + no FP state. `csr.h` rejects a build with F enabled. +* **No C library.** The `riscv64-unknown-elf` toolchain installed by + `scripts/install_riscv.sh` ships `lp64d` libraries only, so the example + links with `-nostdlib` and `board.c` provides `memset`. A missing runtime + helper shows up as a link error, not as a mix of ABIs. +* **No WFI.** The example never executes `wfi`, like the Zephyr Erbium + port. `TX_USE_WFI_IDLE` stays undefined, so the scheduler spins while + idle, and parked harts and fatal-trap halts spin as well. +* **Trap vector.** Erbium ignores `mtvec` base bits 11:1, so the trap + vector must be 4 KiB aligned. `trap_entry` is placed in its own 4 KiB + aligned section and used in direct mode. +* **PLIC.** The silicon hardwires source priorities to 1 and thresholds to + 0. The simulator models them as writable registers that reset to 0, so + `plic_init()` writes the hardwired values. Drivers register a callback and + enable their source with `plic_irq_enable()`. +* **Clocks.** The UART divisor assumes a 400 MHz input clock and the tick + assumes a 2 MHz `mtime` rate, the values used by the Zephyr and NuttX + Erbium ports. If the boot firmware programs other rates, define + `ERBIUM_UART_CLOCK_HZ` and `ERBIUM_MTIME_FREQ_HZ` when you build. +* **UART.** The console only polls. `uart_init()` sets the UART enable bit + in `SystemConfig` with a read-modify-write, which leaves the watchdog + setting as the boot flow left it. + +## Building + +Install the toolchain with `scripts/install_riscv.sh`, or put another +`riscv64-unknown-elf` GCC on `PATH`, then run: + +```bash +./build.sh +``` + +This configures `CMakeLists.txt` with `erbium_gnu.cmake`, builds +`libthreadx.a` for the soft-float ABI and links `build/demo_threadx.elf`. +Set `BUILD_DIR` to build elsewhere. + +## Running on the simulator + +Build `erbium_emu` from +[et-platform](https://github.com/aifoundry-org/et-platform). The example was +tested at revision `836a4ab600e93c3059bb58c898edbc37744cd8d0`: + +```bash +git clone https://github.com/aifoundry-org/et-platform.git +cd et-platform +git checkout 836a4ab600e93c3059bb58c898edbc37744cd8d0 +cmake -S erbium-hal -B build-hal -DCMAKE_INSTALL_PREFIX="$PWD/install" +cmake --build build-hal --target install +cmake -S sw-sysemu -B build-emu -GNinja -DCMAKE_BUILD_TYPE=Release \ + -DCMAKE_CXX_FLAGS=-Wno-error=unused-result \ + -DCMAKE_PREFIX_PATH="$PWD/install" +cmake --build build-emu --target erbium_emu +``` + +At that revision a release build with a distribution GCC that enables +`_FORTIFY_SOURCE` stops on an unused `write()` result in the UART model; +the `CMAKE_CXX_FLAGS` setting above keeps that warning from being an error. + +Load the ELF and start hart 0 at the MRAM load address, bypassing the boot +ROM: + +```bash +erbium_emu -elf_load build/demo_threadx.elf -reset_pc 0x40000200 \ + -minions 1 -single_thread -max_cycles 100000000 \ + -uart_rx_file /dev/null -uart_tx_file uart.log +cat uart.log +``` + +The log starts with `[UART0] : Erbium UART initialized`, followed by lines +from all eight demo threads. The simulator ends with a `max cycles reached` +error once the cycle budget is spent; judge the run by the UART log, not by +the exit status. With the default clocks one ThreadX tick is 2,000,000 +simulated cycles, so the 100,000,000-cycle run shows `thread_0` five times. + +The simulator verifies register accesses, the trap flow and the console. +It does not verify baud timing or the timer rate of real silicon. + +## Files + +| File | Purpose | +|------|---------| +| `entry.S` | Reset entry: parks other harts, sets `gp`, stack and `.bss` | +| `tx_initialize_low_level.S` | Trap vector and `_tx_initialize_low_level` | +| `trap.c` | Dispatches the timer, the PLIC and fatal exceptions | +| `board.c` | `board_init()` and `memset` | +| `plic.c`, `plic.h` | PLIC driver for the hart's machine-mode context | +| `hwtimer.c`, `hwtimer.h` | Periodic tick from `mtime` and `mtimecmp` | +| `uart.c`, `uart.h` | Polling console | +| `demo_threadx.c` | The standard ThreadX demo | +| `link.lds` | MRAM layout | +| `erbium_gnu.cmake` | Toolchain file: `rv64imc_zicsr_zifencei`, `lp64` | +| `CMakeLists.txt`, `build.sh` | Build of the library and the demo | + +## References + +* [Erbium processor](https://github.com/openhwfoundation/core-et-erbium) +* [UART registers](https://github.com/openhwfoundation/core-et-erbium/blob/325b32b7efaa2c2ab9c91001c89d3f49a4740826/doc/uart.md) +* [CPU memory map](https://github.com/openhwfoundation/core-et-erbium/blob/325b32b7efaa2c2ab9c91001c89d3f49a4740826/doc/cpu_mm.md) +* [Platform interrupts](https://github.com/openhwfoundation/core-et-erbium/blob/325b32b7efaa2c2ab9c91001c89d3f49a4740826/doc/interrupts.md) +* [CPU subsystem](https://github.com/openhwfoundation/core-et-erbium/blob/325b32b7efaa2c2ab9c91001c89d3f49a4740826/doc/cpu_subsystem.md) +* [et-platform simulator](https://github.com/aifoundry-org/et-platform) diff --git a/ports/risc-v64/gnu/example_build/erbium/board.c b/ports/risc-v64/gnu/example_build/erbium/board.c new file mode 100644 index 000000000..b801b55d4 --- /dev/null +++ b/ports/risc-v64/gnu/example_build/erbium/board.c @@ -0,0 +1,49 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5.5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +#include "plic.h" +#include "hwtimer.h" +#include "uart.h" +#include +#include + +/* The example links without a C library; ThreadX needs memset. */ +void *memset(void *des, int c, size_t n) +{ + unsigned char *target = des; + + for (size_t i = 0; i < n; i++) + target[i] = (unsigned char)c; + return des; +} + +int board_init(void) +{ + int ret; + + ret = plic_init(); + if (ret) + return ret; + + ret = uart_init(); + if (ret) + return ret; + + ret = hwtimer_init(); + if (ret) + return ret; + + return 0; +} diff --git a/ports/risc-v64/gnu/example_build/erbium/build.sh b/ports/risc-v64/gnu/example_build/erbium/build.sh new file mode 100755 index 000000000..effaed0ad --- /dev/null +++ b/ports/risc-v64/gnu/example_build/erbium/build.sh @@ -0,0 +1,28 @@ +#!/bin/bash +############################################################################## +# 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. +# +# AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5.5). +# The AI-generated portions may be considered public domain (CC0-1.0) +# and not subject to the project's licence. The human contributor has +# reviewed and verified that the code is correct. +# +# SPDX-License-Identifier: MIT and CC0-1.0 +############################################################################## + +# Build the ThreadX library and the Erbium demo, build/demo_threadx.elf. + +set -eu + +SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd) +BUILD_DIR=${BUILD_DIR:-"${SCRIPT_DIR}/build"} + +cmake -S "${SCRIPT_DIR}" -B "${BUILD_DIR}" -GNinja \ + -DCMAKE_TOOLCHAIN_FILE="${SCRIPT_DIR}/erbium_gnu.cmake" +cmake --build "${BUILD_DIR}" --target demo_threadx + +printf 'Built %s\n' "${BUILD_DIR}/demo_threadx.elf" diff --git a/ports/risc-v64/gnu/example_build/erbium/csr.h b/ports/risc-v64/gnu/example_build/erbium/csr.h new file mode 100644 index 000000000..e2aa4e182 --- /dev/null +++ b/ports/risc-v64/gnu/example_build/erbium/csr.h @@ -0,0 +1,66 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5.5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/* Machine-mode CSR definitions and helpers for the Erbium example. */ + +#ifndef RISCV_CSR_H +#define RISCV_CSR_H + +/* The Erbium FPU implements only part of the F extension: single-precision + divide, square root and conversions to and from 64-bit integers raise an + emulation exception that this example does not handle. Build for the + integer ISA with the soft-float lp64 ABI. */ +#ifdef __riscv_flen +#error "The Erbium example requires a soft-float build: use -march=rv64imc_zicsr_zifencei -mabi=lp64." +#endif + +/* Machine Status Register, mstatus */ +#define MSTATUS_MIE (1L << 3) /* machine-mode interrupt enable */ +#define MSTATUS_MPIE (1L << 7) /* previous MIE */ +#define MSTATUS_MPP_M (3L << 11) /* previous mode: machine */ + +/* Machine Interrupt Enable, mie */ +#define MIE_MTIE (1L << 7) /* machine timer */ +#define MIE_MEIE (1L << 11) /* machine external */ + +#ifndef __ASSEMBLER__ + +#include + +static inline uintptr_t riscv_get_core(void) +{ + uintptr_t x; + __asm__ volatile("csrr %0, mhartid" : "=r" (x)); + return x; +} + +/* Clear mstatus.MIE and return whether it was set. */ +static inline int riscv_mintr_save(void) +{ + uintptr_t x; + __asm__ volatile("csrrci %0, mstatus, %1" : "=r" (x) : "i" (MSTATUS_MIE) : "memory"); + return (x & MSTATUS_MIE) != 0; +} + +/* Set mstatus.MIE again if riscv_mintr_save found it set. */ +static inline void riscv_mintr_restore(int enabled) +{ + if (enabled) + __asm__ volatile("csrsi mstatus, %0" : : "i" (MSTATUS_MIE) : "memory"); +} + +#endif /* __ASSEMBLER__ */ + +#endif /* RISCV_CSR_H */ diff --git a/ports/risc-v64/gnu/example_build/erbium/demo_threadx.c b/ports/risc-v64/gnu/example_build/erbium/demo_threadx.c new file mode 100644 index 000000000..2023df128 --- /dev/null +++ b/ports/risc-v64/gnu/example_build/erbium/demo_threadx.c @@ -0,0 +1,382 @@ +/***************************************************************************/ +/* Copyright (c) 2024 Microsoft Corporation */ +/* 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 */ +/***************************************************************************/ + +/* This is a small demo of the high-performance ThreadX kernel. It includes examples of eight + threads of different priorities, using a message queue, semaphore, mutex, event flags group, + byte pool, and block pool. */ + +#include "tx_api.h" +#include "uart.h" +#define DEMO_STACK_SIZE 1024 +#define DEMO_BYTE_POOL_SIZE 9180 +#define DEMO_BLOCK_POOL_SIZE 100 +#define DEMO_QUEUE_SIZE 100 + + +/* Define the ThreadX object control blocks... */ + +TX_THREAD thread_0; +TX_THREAD thread_1; +TX_THREAD thread_2; +TX_THREAD thread_3; +TX_THREAD thread_4; +TX_THREAD thread_5; +TX_THREAD thread_6; +TX_THREAD thread_7; +TX_QUEUE queue_0; +TX_SEMAPHORE semaphore_0; +TX_MUTEX mutex_0; +TX_EVENT_FLAGS_GROUP event_flags_0; +TX_BYTE_POOL byte_pool_0; +TX_BLOCK_POOL block_pool_0; +UCHAR memory_area[DEMO_BYTE_POOL_SIZE]; + + +/* Define the counters used in the demo application... */ + +ULONG thread_0_counter; +ULONG thread_1_counter; +ULONG thread_1_messages_sent; +ULONG thread_2_counter; +ULONG thread_2_messages_received; +ULONG thread_3_counter; +ULONG thread_4_counter; +ULONG thread_5_counter; +ULONG thread_6_counter; +ULONG thread_7_counter; + + +/* Define thread prototypes. */ + +void thread_0_entry(ULONG thread_input); +void thread_1_entry(ULONG thread_input); +void thread_2_entry(ULONG thread_input); +void thread_3_and_4_entry(ULONG thread_input); +void thread_5_entry(ULONG thread_input); +void thread_6_and_7_entry(ULONG thread_input); + + +/* Define main entry point. */ + +int main() +{ + + /* Enter the ThreadX kernel. */ + tx_kernel_enter(); +} + + +/* Define what the initial system looks like. */ + +void tx_application_define(void *first_unused_memory) +{ + +CHAR *pointer = TX_NULL; + + + /* Create a byte memory pool from which to allocate the thread stacks. */ + tx_byte_pool_create(&byte_pool_0, "byte pool 0", memory_area, DEMO_BYTE_POOL_SIZE); + + /* Put system definition stuff in here, e.g. thread creates and other assorted + create information. */ + + /* Allocate the stack for thread 0. */ + tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); + + /* Create the main thread. */ + tx_thread_create(&thread_0, "thread 0", thread_0_entry, 0, + pointer, DEMO_STACK_SIZE, + 1, 1, TX_NO_TIME_SLICE, TX_AUTO_START); + + + /* Allocate the stack for thread 1. */ + tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); + + /* Create threads 1 and 2. These threads pass information through a ThreadX + message queue. It is also interesting to note that these threads have a time + slice. */ + tx_thread_create(&thread_1, "thread 1", thread_1_entry, 1, + pointer, DEMO_STACK_SIZE, + 16, 16, 4, TX_AUTO_START); + + /* Allocate the stack for thread 2. */ + tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); + + tx_thread_create(&thread_2, "thread 2", thread_2_entry, 2, + pointer, DEMO_STACK_SIZE, + 16, 16, 4, TX_AUTO_START); + + /* Allocate the stack for thread 3. */ + tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); + + /* Create threads 3 and 4. These threads compete for a ThreadX counting semaphore. + An interesting thing here is that both threads share the same instruction area. */ + tx_thread_create(&thread_3, "thread 3", thread_3_and_4_entry, 3, + pointer, DEMO_STACK_SIZE, + 8, 8, TX_NO_TIME_SLICE, TX_AUTO_START); + + /* Allocate the stack for thread 4. */ + tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); + + tx_thread_create(&thread_4, "thread 4", thread_3_and_4_entry, 4, + pointer, DEMO_STACK_SIZE, + 8, 8, TX_NO_TIME_SLICE, TX_AUTO_START); + + /* Allocate the stack for thread 5. */ + tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); + + /* Create thread 5. This thread simply pends on an event flag which will be set + by thread_0. */ + tx_thread_create(&thread_5, "thread 5", thread_5_entry, 5, + pointer, DEMO_STACK_SIZE, + 4, 4, TX_NO_TIME_SLICE, TX_AUTO_START); + + /* Allocate the stack for thread 6. */ + tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); + + /* Create threads 6 and 7. These threads compete for a ThreadX mutex. */ + tx_thread_create(&thread_6, "thread 6", thread_6_and_7_entry, 6, + pointer, DEMO_STACK_SIZE, + 8, 8, TX_NO_TIME_SLICE, TX_AUTO_START); + + /* Allocate the stack for thread 7. */ + tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_STACK_SIZE, TX_NO_WAIT); + + tx_thread_create(&thread_7, "thread 7", thread_6_and_7_entry, 7, + pointer, DEMO_STACK_SIZE, + 8, 8, TX_NO_TIME_SLICE, TX_AUTO_START); + + /* Allocate the message queue. */ + tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_QUEUE_SIZE*sizeof(ULONG), TX_NO_WAIT); + + /* Create the message queue shared by threads 1 and 2. */ + tx_queue_create(&queue_0, "queue 0", TX_1_ULONG, pointer, DEMO_QUEUE_SIZE*sizeof(ULONG)); + + /* Create the semaphore used by threads 3 and 4. */ + tx_semaphore_create(&semaphore_0, "semaphore 0", 1); + + /* Create the event flags group used by threads 1 and 5. */ + tx_event_flags_create(&event_flags_0, "event flags 0"); + + /* Create the mutex used by thread 6 and 7 without priority inheritance. */ + tx_mutex_create(&mutex_0, "mutex 0", TX_NO_INHERIT); + + /* Allocate the memory for a small block pool. */ + tx_byte_allocate(&byte_pool_0, (VOID **) &pointer, DEMO_BLOCK_POOL_SIZE, TX_NO_WAIT); + + /* Create a block memory pool to allocate a message buffer from. */ + tx_block_pool_create(&block_pool_0, "block pool 0", sizeof(ULONG), pointer, DEMO_BLOCK_POOL_SIZE); + + /* Allocate a block and release the block memory. */ + tx_block_allocate(&block_pool_0, (VOID **) &pointer, TX_NO_WAIT); + + /* Release the block back to the pool. */ + tx_block_release(pointer); +} + + + +/* Define the test threads. */ + +void thread_0_entry(ULONG thread_input) +{ + +UINT status; + + + /* This thread simply sits in while-forever-sleep loop. */ + while(1) + { + puts("[Thread] : thread_0_entry is here!"); + /* Increment the thread counter. */ + thread_0_counter++; + + /* Sleep for 10 ticks. */ + tx_thread_sleep(10); + + /* Set event flag 0 to wakeup thread 5. */ + status = tx_event_flags_set(&event_flags_0, 0x1, TX_OR); + + /* Check status. */ + if (status != TX_SUCCESS) + break; + } +} + + +void thread_1_entry(ULONG thread_input) +{ + +UINT status; + + + /* This thread simply sends messages to a queue shared by thread 2. */ + while(1) + { + puts("[Thread] : thread_1_entry is here!"); + /* Increment the thread counter. */ + thread_1_counter++; + + /* Send message to queue 0. */ + status = tx_queue_send(&queue_0, &thread_1_messages_sent, TX_WAIT_FOREVER); + + /* Check completion status. */ + if (status != TX_SUCCESS) + break; + + /* Increment the message sent. */ + thread_1_messages_sent++; + } +} + + +void thread_2_entry(ULONG thread_input) +{ + +ULONG received_message; +UINT status; + + /* This thread retrieves messages placed on the queue by thread 1. */ + while(1) + { + puts("[Thread] : thread_2_entry is here!"); + /* Increment the thread counter. */ + thread_2_counter++; + + /* Retrieve a message from the queue. */ + status = tx_queue_receive(&queue_0, &received_message, TX_WAIT_FOREVER); + + /* Check completion status and make sure the message is what we + expected. */ + if ((status != TX_SUCCESS) || (received_message != thread_2_messages_received)) + break; + + /* Otherwise, all is okay. Increment the received message count. */ + thread_2_messages_received++; + } +} + + +void thread_3_and_4_entry(ULONG thread_input) +{ + +UINT status; + + + /* This function is executed from thread 3 and thread 4. As the loop + below shows, these function compete for ownership of semaphore_0. */ + while(1) + { + puts("[Thread] : thread_3_and_4_entry is here!"); + + /* Increment the thread counter. */ + if (thread_input == 3) + thread_3_counter++; + else + thread_4_counter++; + + /* Get the semaphore with suspension. */ + status = tx_semaphore_get(&semaphore_0, TX_WAIT_FOREVER); + + /* Check status. */ + if (status != TX_SUCCESS) + break; + + /* Sleep for 2 ticks to hold the semaphore. */ + tx_thread_sleep(2); + + /* Release the semaphore. */ + status = tx_semaphore_put(&semaphore_0); + + /* Check status. */ + if (status != TX_SUCCESS) + break; + } +} + + +void thread_5_entry(ULONG thread_input) +{ + +UINT status; +ULONG actual_flags; + + + /* This thread simply waits for an event in a forever loop. */ + while(1) + { + puts("[Thread] : thread_5_entry is here!"); + /* Increment the thread counter. */ + thread_5_counter++; + + /* Wait for event flag 0. */ + status = tx_event_flags_get(&event_flags_0, 0x1, TX_OR_CLEAR, + &actual_flags, TX_WAIT_FOREVER); + + /* Check status. */ + if ((status != TX_SUCCESS) || (actual_flags != 0x1)) + break; + } +} + + +void thread_6_and_7_entry(ULONG thread_input) +{ + +UINT status; + + + /* This function is executed from thread 6 and thread 7. As the loop + below shows, these function compete for ownership of mutex_0. */ + while(1) + { + puts("[Thread] : thread_6_and_7_entry is here!"); + /* Increment the thread counter. */ + if (thread_input == 6) + thread_6_counter++; + else + thread_7_counter++; + + /* Get the mutex with suspension. */ + status = tx_mutex_get(&mutex_0, TX_WAIT_FOREVER); + + /* Check status. */ + if (status != TX_SUCCESS) + break; + + /* Get the mutex again with suspension. This shows + that an owning thread may retrieve the mutex it + owns multiple times. */ + status = tx_mutex_get(&mutex_0, TX_WAIT_FOREVER); + + /* Check status. */ + if (status != TX_SUCCESS) + break; + + /* Sleep for 2 ticks to hold the mutex. */ + tx_thread_sleep(2); + + /* Release the mutex. */ + status = tx_mutex_put(&mutex_0); + + /* Check status. */ + if (status != TX_SUCCESS) + break; + + /* Release the mutex again. This will actually + release ownership since it was obtained twice. */ + status = tx_mutex_put(&mutex_0); + + /* Check status. */ + if (status != TX_SUCCESS) + break; + } +} diff --git a/ports/risc-v64/gnu/example_build/erbium/entry.S b/ports/risc-v64/gnu/example_build/erbium/entry.S new file mode 100644 index 000000000..201f986e4 --- /dev/null +++ b/ports/risc-v64/gnu/example_build/erbium/entry.S @@ -0,0 +1,50 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5.5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/* Reset entry for the Erbium example. Hart 0 sets up the global pointer, + the system stack and .bss, then calls main(). Any other hart is parked. */ + + .section .text.entry, "ax", @progbits + .align 2 + .global _start + .extern main + .extern _sysstack_end + .extern _bss_start + .extern _bss_end +_start: + csrr t0, mhartid + bnez t0, _park + +.option push +.option norelax + la gp, __global_pointer$ // norelax keeps this load absolute +.option pop + + la sp, _sysstack_end + + la t0, _bss_start // .bss is 16-byte aligned in link.lds + la t1, _bss_end +_bss_clear: + bgeu t0, t1, _bss_done + sd zero, 0(t0) + addi t0, t0, 8 + j _bss_clear +_bss_done: + + call main + + /* The example never executes WFI; a parked hart spins. */ +_park: + j _park diff --git a/ports/risc-v64/gnu/example_build/erbium/erbium_gnu.cmake b/ports/risc-v64/gnu/example_build/erbium/erbium_gnu.cmake new file mode 100644 index 000000000..0d55dd89f --- /dev/null +++ b/ports/risc-v64/gnu/example_build/erbium/erbium_gnu.cmake @@ -0,0 +1,39 @@ +# /*************************************************************************** +# * 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. +# * +# * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5.5). +# * The AI-generated portions may be considered public domain (CC0-1.0) +# * and not subject to the project's licence. The human contributor has +# * reviewed and verified that the code is correct. +# * +# * SPDX-License-Identifier: MIT and CC0-1.0 +# ***************************************************************************/ + +# CMake toolchain file for the Erbium example. +# +# Erbium implements only part of the F extension, so the example and the +# ThreadX library are built for the integer ISA with the soft-float lp64 ABI. +# +# Target ISA : rv64imc_zicsr_zifencei +# ABI : lp64 (64-bit long/ptr, soft-float) +# Code model : medany (MRAM at 0x40000000, peripherals above 2 GiB) +# +# The riscv64-unknown-elf toolchain installed by scripts/install_riscv.sh is +# built for lp64d only, so the example links without libc and libgcc +# (-nostdlib); a missing helper is a link error rather than an ABI mix. + +set(CMAKE_SYSTEM_NAME Generic) +set(CMAKE_SYSTEM_PROCESSOR risc-v64) + +set(THREADX_ARCH "risc-v64") +set(THREADX_TOOLCHAIN "gnu") +set(ARCH_FLAGS "-g -march=rv64imc_zicsr_zifencei -mabi=lp64 -mcmodel=medany") +set(CFLAGS "${ARCH_FLAGS}") +set(ASFLAGS "${ARCH_FLAGS}") +set(LDFLAGS "${ARCH_FLAGS}") + +include(${CMAKE_CURRENT_LIST_DIR}/../../../../../cmake/riscv64-unknown-elf.cmake) diff --git a/ports/risc-v64/gnu/example_build/erbium/hwtimer.c b/ports/risc-v64/gnu/example_build/erbium/hwtimer.c new file mode 100644 index 000000000..511bea596 --- /dev/null +++ b/ports/risc-v64/gnu/example_build/erbium/hwtimer.c @@ -0,0 +1,42 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5.5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +#include "tx_api.h" +#include "hwtimer.h" + +/* Naturally aligned 64-bit MMIO accesses are single loads and stores on + RV64; volatile keeps the compiler from caching or reordering them. */ +#define MTIME (*(volatile uint64_t *)ERBIUM_MTIME) +#define MTIMECMP (*(volatile uint64_t *)ERBIUM_MTIMECMP) + +int hwtimer_init(void) +{ + MTIMECMP = MTIME + TICKNUM_PER_TIMER; + return 0; +} + +int hwtimer_handler(void) +{ + /* Advance from the previous compare value, so trap latency does not + accumulate as tick drift. */ + uint64_t next = MTIMECMP + TICKNUM_PER_TIMER; + uint64_t now = MTIME; + + if (next <= now) + next = now + TICKNUM_PER_TIMER; + + MTIMECMP = next; + return 0; +} diff --git a/ports/risc-v64/gnu/example_build/erbium/hwtimer.h b/ports/risc-v64/gnu/example_build/erbium/hwtimer.h new file mode 100644 index 000000000..3b9bf4e3d --- /dev/null +++ b/ports/risc-v64/gnu/example_build/erbium/hwtimer.h @@ -0,0 +1,41 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5.5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +#ifndef RISCV_HWTIMER_H +#define RISCV_HWTIMER_H + +#include + +/* Erbium machine timer. mtime and a single mtimecmp live in the CPU + register block; mtime_local_target selects which harts see the timer + interrupt and resets to all harts. + + The mtime rate depends on the reference clock and time_config, which the + boot firmware programs. The default is the 2 MHz timebase used by the + Zephyr and NuttX Erbium ports; define ERBIUM_MTIME_FREQ_HZ when the + firmware selects another rate. */ +#define ERBIUM_MTIME 0x80F40200UL +#define ERBIUM_MTIMECMP 0x80F40208UL + +#ifndef ERBIUM_MTIME_FREQ_HZ +#define ERBIUM_MTIME_FREQ_HZ 2000000UL +#endif + +#define TICKNUM_PER_TIMER (ERBIUM_MTIME_FREQ_HZ / TX_TIMER_TICKS_PER_SECOND) + +int hwtimer_init(void); +int hwtimer_handler(void); + +#endif /* RISCV_HWTIMER_H */ diff --git a/ports/risc-v64/gnu/example_build/erbium/link.lds b/ports/risc-v64/gnu/example_build/erbium/link.lds new file mode 100644 index 000000000..25ba92190 --- /dev/null +++ b/ports/risc-v64/gnu/example_build/erbium/link.lds @@ -0,0 +1,92 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5.5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/* Erbium memory layout. + * + * Address Size Usage + * ───────────── ──────── ────────────────────────────────────── + * 0x0200_0000 4 KiB System registers (SystemConfig at +0x08) + * 0x0200_4000 4 KiB UART0 + * 0x4000_0000 512 B MRAM, reserved for the boot flow + * 0x4000_0200 ~16 MiB MRAM: code, data, stacks and free memory + * 0x80F4_0200 16 B mtime, mtimecmp + * 0xA000_0000 64 MiB PLIC + * + * MRAM is directly readable, writable and executable, so .data runs in + * place and needs no copy from a load address. + */ + +OUTPUT_ARCH( "riscv" ) +ENTRY( _start ) + +MEMORY +{ + MRAM (rwx) : ORIGIN = 0x40000200, LENGTH = 0x00FFFE00 +} + +PHDRS +{ + text PT_LOAD FLAGS(5); /* PF_R | PF_X */ + data PT_LOAD FLAGS(6); /* PF_R | PF_W */ +} + +SECTIONS +{ + /* _start must stay at the load address, so the 4 KiB aligned trap + vector goes in the next output section rather than this one. */ + .text.entry : { + KEEP(*(.text.entry)) + } > MRAM :text + + .text : { + KEEP(*(.text.trap)) + *(.text .text.*) + } > MRAM :text + + .rodata : { + . = ALIGN(16); + *(.srodata .srodata.*) + . = ALIGN(16); + *(.rodata .rodata.*) + } > MRAM :text + + .data : { + . = ALIGN(16); + PROVIDE( __global_pointer$ = . + 0x800 ); + *(.sdata .sdata.*) + . = ALIGN(16); + *(.data .data.*) + } > MRAM :data + + .bss (NOLOAD) : { + . = ALIGN(16); + _bss_start = .; + *(.sbss .sbss.*) + . = ALIGN(16); + *(.bss .bss.*) + *(COMMON) + . = ALIGN(16); + _bss_end = .; + } > MRAM :data + + .stack (NOLOAD) : { + . = ALIGN(16); + _sysstack_start = .; + . += 0x1000; + _sysstack_end = .; + } > MRAM :data + + PROVIDE(_end = .); +} diff --git a/ports/risc-v64/gnu/example_build/erbium/plic.c b/ports/risc-v64/gnu/example_build/erbium/plic.c new file mode 100644 index 000000000..93b1f3171 --- /dev/null +++ b/ports/risc-v64/gnu/example_build/erbium/plic.c @@ -0,0 +1,112 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5.5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/* PLIC driver for Erbium, machine-mode context of the current hart. */ + +#include "plic.h" +#include + +static irq_callback callbacks[MAX_CALLBACK_NUM]; + +/* Source 0 is reserved and the six sources fit in the first enable word. */ +static int plic_source_valid(int irqno) +{ + return (irqno > 0) && (irqno < MAX_CALLBACK_NUM); +} + +void plic_irq_enable(int irqno) +{ + volatile uint32_t *reg = (volatile uint32_t *)PLIC_MENABLE(riscv_get_core()); + + if (!plic_source_valid(irqno)) + return; + + *reg = *reg | (1u << (unsigned int)irqno); +} + +void plic_irq_disable(int irqno) +{ + volatile uint32_t *reg = (volatile uint32_t *)PLIC_MENABLE(riscv_get_core()); + + if (!plic_source_valid(irqno)) + return; + + *reg = *reg & ~(1u << (unsigned int)irqno); +} + +int plic_register_callback(int irqno, irq_callback callback) +{ + if (!plic_source_valid(irqno)) + return -1; + callbacks[irqno] = callback; + return 0; +} + +int plic_unregister_callback(int irqno) +{ + return plic_register_callback(irqno, NULL); +} + +int plic_init(void) +{ + uintptr_t hart = riscv_get_core(); + + for (int i = 0; i < MAX_CALLBACK_NUM; i++) + callbacks[i] = NULL; + + /* Do not depend on the reset state or on a prior boot stage: start + with every source disabled for this context. Drivers enable their + own sources. */ + *(volatile uint32_t *)PLIC_MENABLE(hart) = 0; + + /* The values the silicon hardwires; see plic.h. */ + *(volatile uint32_t *)PLIC_MTHRESHOLD(hart) = 0; + for (int i = 1; i <= PLIC_NUM_SOURCES; i++) + *(volatile uint32_t *)PLIC_PRIORITY(i) = 1; + + return 0; +} + +int plic_claim(void) +{ + return (int)(*(volatile uint32_t *)PLIC_MCLAIM(riscv_get_core())); +} + +void plic_complete(int irqno) +{ + *(volatile uint32_t *)PLIC_MCOMPLETE(riscv_get_core()) = (uint32_t)irqno; +} + +int plic_irq_intr(void) +{ + int ret = -1; + int irqno = plic_claim(); + + /* Nothing pending: another context claimed it first. */ + if (irqno == 0) + return 0; + + if (!plic_source_valid(irqno)) + { + plic_complete(irqno); + return -1; + } + + if (callbacks[irqno] != NULL) + ret = (callbacks[irqno])(irqno); + + plic_complete(irqno); + return ret; +} diff --git a/ports/risc-v64/gnu/example_build/erbium/plic.h b/ports/risc-v64/gnu/example_build/erbium/plic.h new file mode 100644 index 000000000..ffc3a5391 --- /dev/null +++ b/ports/risc-v64/gnu/example_build/erbium/plic.h @@ -0,0 +1,54 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5.5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +#ifndef RISCV_PLIC_H +#define RISCV_PLIC_H + +#include "csr.h" +#include + +/* Erbium PLIC, RISC-V PLIC 1.0. Each hart has two contexts, machine mode + first, so hart h uses context 2h. + + The silicon hardwires source priorities to 1 and context thresholds to + 0, so an enabled, pending source always interrupts. The et-platform + simulator implements them as writable registers that reset to 0, which + masks every source, so plic_init() programs the silicon values. There is + no priority control beyond that. + + Sources: 1 MRAM, 2 QSPI, 3 UART, 4 system register, 5 xSPI, 6 GPIO. */ +#define PLIC 0xA0000000UL +#define PLIC_PRIORITY(irqno) (PLIC + (unsigned long)(irqno) * 4UL) +#define PLIC_MENABLE(hart) (PLIC + 0x2000UL + (hart) * 0x100UL) +#define PLIC_MTHRESHOLD(hart) (PLIC + 0x200000UL + (hart) * 0x2000UL) +#define PLIC_MCLAIM(hart) (PLIC + 0x200004UL + (hart) * 0x2000UL) +#define PLIC_MCOMPLETE(hart) PLIC_MCLAIM(hart) + +#define PLIC_NUM_SOURCES 6 +#define MAX_CALLBACK_NUM (PLIC_NUM_SOURCES + 1) + +typedef int (*irq_callback)(int irqno); + +void plic_irq_enable(int irqno); +void plic_irq_disable(int irqno); +int plic_register_callback(int irqno, irq_callback callback); +int plic_unregister_callback(int irqno); +int plic_init(void); +int plic_claim(void); +void plic_complete(int irqno); + +int plic_irq_intr(void); + +#endif /* RISCV_PLIC_H */ diff --git a/ports/risc-v64/gnu/example_build/erbium/trap.c b/ports/risc-v64/gnu/example_build/erbium/trap.c new file mode 100644 index 000000000..d839e6eab --- /dev/null +++ b/ports/risc-v64/gnu/example_build/erbium/trap.c @@ -0,0 +1,78 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5.5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/* Machine-mode trap dispatcher for the Erbium example. */ + +#include "csr.h" +#include "uart.h" +#include "hwtimer.h" +#include "plic.h" +#include +#include + +#define MCAUSE_INT_BIT ((uintptr_t)1 << (__riscv_xlen - 1)) +#define MCAUSE_M_TIMER (MCAUSE_INT_BIT | 7u) +#define MCAUSE_M_EXTERNAL (MCAUSE_INT_BIT | 11u) + +extern void _tx_timer_interrupt(void); + +static void print_hex(uintptr_t val) +{ + const char digits[] = "0123456789ABCDEF"; + + uart_putc('0'); + uart_putc('x'); + for (int i = (int)(sizeof(uintptr_t) * 2) - 1; i >= 0; i--) + uart_putc(digits[(val >> (i * 4)) & 0xFu]); + uart_putc('\r'); + uart_putc('\n'); +} + +static void trap_halt(const char *reason, uintptr_t mcause, uintptr_t mepc, uintptr_t mtval) +{ + uart_puts(reason); + uart_puts("mcause:"); + print_hex(mcause); + uart_puts("mepc:"); + print_hex(mepc); + uart_puts("mtval:"); + print_hex(mtval); + + /* Spin rather than WFI, as everywhere else in this example. */ + while (1) + ; +} + +void trap_handler(uintptr_t mcause, uintptr_t mepc, uintptr_t mtval) +{ + if (mcause == MCAUSE_M_TIMER) + { + hwtimer_handler(); + _tx_timer_interrupt(); + } + else if (mcause == MCAUSE_M_EXTERNAL) + { + if (plic_irq_intr() != 0) + trap_halt("[INTERRUPT]: external interrupt not handled, halting", mcause, mepc, mtval); + } + else if ((mcause & MCAUSE_INT_BIT) != 0u) + { + trap_halt("[INTERRUPT]: unexpected interrupt, halting", mcause, mepc, mtval); + } + else + { + trap_halt("[EXCEPTION]: unhandled exception, halting", mcause, mepc, mtval); + } +} diff --git a/ports/risc-v64/gnu/example_build/erbium/tx_initialize_low_level.S b/ports/risc-v64/gnu/example_build/erbium/tx_initialize_low_level.S new file mode 100644 index 000000000..fe0653ae8 --- /dev/null +++ b/ports/risc-v64/gnu/example_build/erbium/tx_initialize_low_level.S @@ -0,0 +1,142 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5.5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +#include "csr.h" +#include "tx_port.h" + +/* Erbium ignores mtvec base bits 11:1, so the trap vector must be 4 KiB + aligned. */ + .section .text.trap, "ax", @progbits + .balign 4096 +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* trap_entry RISC-V64/GNU */ +/* */ +/* DESCRIPTION */ +/* */ +/* This function is the machine-mode trap vector (direct mode). It */ +/* saves the interrupted context, calls trap_handler with mcause, */ +/* mepc and mtval, and leaves through the ThreadX context restore. */ +/* */ +/* INPUT */ +/* */ +/* None */ +/* */ +/* OUTPUT */ +/* */ +/* None */ +/* */ +/* CALLS */ +/* */ +/* _tx_thread_context_save Save interrupted context */ +/* trap_handler Dispatch the trap */ +/* _tx_thread_context_restore Restore or schedule a thread */ +/* */ +/* CALLED BY */ +/* */ +/* Hardware trap */ +/* */ +/**************************************************************************/ + .global trap_entry + .extern trap_handler + .extern _tx_thread_context_save + .extern _tx_thread_context_restore +trap_entry: + addi sp, sp, -TX_RISCV_TRAP_FRAME_SIZE // Interrupt frame from the port contract + sd x1, 28*8(sp) // Save RA before the call below overwrites it + + call _tx_thread_context_save + + csrr a0, mcause + csrr a1, mepc + csrr a2, mtval + addi sp, sp, -16 // 16 bytes keep sp 16-byte aligned at the call + sd ra, 0(sp) + call trap_handler + ld ra, 0(sp) + addi sp, sp, 16 + + call _tx_thread_context_restore + /* _tx_thread_context_restore does not return. */ +_trap_entry_hang: + j _trap_entry_hang + + + .section .text +/**************************************************************************/ +/* */ +/* FUNCTION RELEASE */ +/* */ +/* _tx_initialize_low_level RISC-V64/GNU */ +/* */ +/* 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 */ +/* */ +/* board_init Initialize the peripherals */ +/* */ +/* CALLED BY */ +/* */ +/* _tx_initialize_kernel_enter ThreadX entry function */ +/* */ +/**************************************************************************/ +/* VOID _tx_initialize_low_level(VOID) +{ */ + .global _tx_initialize_low_level // Strong definition: must beat the port's weak default + .extern _end + .extern board_init + .extern _tx_thread_system_stack_ptr + .extern _tx_initialize_unused_memory +_tx_initialize_low_level: + la t0, _tx_thread_system_stack_ptr + sd sp, 0(t0) // Save system stack pointer + + la t0, _end // Pickup first free address + la t1, _tx_initialize_unused_memory + sd t0, 0(t1) // Save unused memory address + + li t0, MSTATUS_MIE + csrrc zero, mstatus, t0 // Keep interrupts off until the scheduler runs + li t0, (MSTATUS_MPP_M | MSTATUS_MPIE) + csrrs zero, mstatus, t0 // mret stays in M-mode with interrupts enabled + li t0, (MIE_MTIE | MIE_MEIE) + csrrs zero, mie, t0 // Enable timer and external interrupts + + addi sp, sp, -16 // 16 bytes keep sp 16-byte aligned at the call + sd ra, 0(sp) + call board_init + ld ra, 0(sp) + addi sp, sp, 16 + + la t0, trap_entry + csrw mtvec, t0 // Direct mode: trap_entry is 4 KiB aligned + ret +/* } */ diff --git a/ports/risc-v64/gnu/example_build/erbium/uart.c b/ports/risc-v64/gnu/example_build/erbium/uart.c new file mode 100644 index 000000000..ee065e8a7 --- /dev/null +++ b/ports/risc-v64/gnu/example_build/erbium/uart.c @@ -0,0 +1,106 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5.5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +/* Polling console driver for the Erbium UART (original Shakti integration). + * + * Offset Name Access Description + * ────── ──────────── ────── ───────────────────────────────────── + * 0x00 BaudReg R/W Divisor: clock / (16 * baud) + * 0x08 TxReg W Transmit data + * 0x10 RxReg R Receive data + * 0x18 StatusReg R FIFO and error status + * 0x20 DelayReg R/W Transmit delay + * 0x28 ControlReg R/W Character size, parity, stop bits + * 0x30 InterruptEn R/W Interrupt enables + * 0x40 Rx_Threshold R/W Receive FIFO threshold + * + * All registers are accessed as 32-bit words. The transmit and receive + * FIFOs hold 16 entries each. + */ + +#include "uart.h" +#include "csr.h" +#include + +#define UART_DIVISOR (ERBIUM_UART_CLOCK_HZ / (16UL * ERBIUM_UART_BAUD)) + +#if (UART_DIVISOR == 0) || (UART_DIVISOR > 0xFFFF) +#error "The Erbium UART baud divisor must be in the range 1..65535." +#endif + +/* SystemConfig in the system register block gates the UART. */ +#define SYSREG_SYSTEM_CONFIG 0x02000008UL +#define SYSTEM_CONFIG_UART_EN (1u << 6) + +#define UART_BAUD 0x00 +#define UART_TX 0x08 +#define UART_STATUS 0x18 +#define UART_DELAY 0x20 +#define UART_CONTROL 0x28 +#define UART_IEN 0x30 +#define UART_RX_THRESHOLD 0x40 + +#define STATUS_TX_FULL (1u << 1) + +#define CONTROL_CHARSIZE_SHIFT 5 /* bits 10:5; stop bits and parity 0 */ + +#define REG32(addr) (*(volatile uint32_t *)(addr)) +#define UART_REG(off) REG32(UART0 + (off)) + +int uart_init(void) +{ + /* Ungate the UART. Read-modify-write keeps the watchdog and the + other peripheral enables as the boot flow left them. */ + REG32(SYSREG_SYSTEM_CONFIG) = REG32(SYSREG_SYSTEM_CONFIG) | SYSTEM_CONFIG_UART_EN; + + /* Polling only: no UART interrupts. */ + UART_REG(UART_IEN) = 0; + + /* 8 data bits, no parity, one stop bit. */ + UART_REG(UART_BAUD) = (uint32_t)UART_DIVISOR; + UART_REG(UART_CONTROL) = 8u << CONTROL_CHARSIZE_SHIFT; + UART_REG(UART_DELAY) = 0; + UART_REG(UART_RX_THRESHOLD) = 0; + + puts("[UART0] : Erbium UART initialized"); + return 0; +} + +static inline void uart_putc_nolock(int ch) +{ + while ((UART_REG(UART_STATUS) & STATUS_TX_FULL) != 0u) + ; + UART_REG(UART_TX) = (uint32_t)(ch & 0xFF); +} + +int uart_putc(int ch) +{ + int intr_enable = riscv_mintr_save(); + uart_putc_nolock(ch); + riscv_mintr_restore(intr_enable); + return 1; +} + +int uart_puts(const char *str) +{ + int i; + int intr_enable = riscv_mintr_save(); + for (i = 0; str[i] != 0; i++) + uart_putc_nolock(str[i]); + uart_putc_nolock('\r'); + uart_putc_nolock('\n'); + riscv_mintr_restore(intr_enable); + return i; +} diff --git a/ports/risc-v64/gnu/example_build/erbium/uart.h b/ports/risc-v64/gnu/example_build/erbium/uart.h new file mode 100644 index 000000000..74a6c1d05 --- /dev/null +++ b/ports/risc-v64/gnu/example_build/erbium/uart.h @@ -0,0 +1,40 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Claude Code (Opus 5.5). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + **************************************************************************/ + +#ifndef RISCV_UART_H +#define RISCV_UART_H + +/* Erbium UART0: the original Shakti UART integration, with 32-bit registers + at eight-byte intervals. It is PLIC source 3. */ +#define UART0 0x02004000UL +#define UART0_IRQ 3 + +/* The UART input clock and the console rate. The defaults match the + public et-platform simulator; define these on the command line when the + boot firmware programs a different peripheral clock. */ +#ifndef ERBIUM_UART_CLOCK_HZ +#define ERBIUM_UART_CLOCK_HZ 400000000UL +#endif +#ifndef ERBIUM_UART_BAUD +#define ERBIUM_UART_BAUD 115200UL +#endif + +#define puts uart_puts + +int uart_init(void); +int uart_putc(int ch); +int uart_puts(const char *str); + +#endif /* RISCV_UART_H */ From f19d8c267d4b9f9495407f36e154c7ea6deea63a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Wed, 30 Sep 2026 09:40:59 -0400 Subject: [PATCH 178/181] Added simulator tests for Erbium interrupt regressions Long polling UART writes can mask timer interrupts across several tick periods. PLIC enable-word updates can overwrite a change made by an interrupt handler. The board example had no simulator tests for either case. Added two simulator images and a runner. One compares hardware timer progress with ThreadX ticks after a long print. The other toggles one PLIC source in timer context while a thread changes another. Both tests fail on the PR code and pass with the corresponding local fixes. GCC 15.2.0 and Ninja built both images. erbium_emu reproduced both failures; control runs passed both tests. Port consistency checks passed. No silicon run. Assisted-by: Codex (GPT-6-Sol) --- .../gnu/example_build/erbium/CMakeLists.txt | 25 ++++++ .../erbium/test/run_simulator_tests.sh | 55 ++++++++++++ .../erbium/test/test_plic_race.c | 90 +++++++++++++++++++ .../erbium/test/test_plic_trap.c | 55 ++++++++++++ .../erbium/test/test_uart_ticks.c | 81 +++++++++++++++++ 5 files changed, 306 insertions(+) create mode 100755 ports/risc-v64/gnu/example_build/erbium/test/run_simulator_tests.sh create mode 100644 ports/risc-v64/gnu/example_build/erbium/test/test_plic_race.c create mode 100644 ports/risc-v64/gnu/example_build/erbium/test/test_plic_trap.c create mode 100644 ports/risc-v64/gnu/example_build/erbium/test/test_uart_ticks.c diff --git a/ports/risc-v64/gnu/example_build/erbium/CMakeLists.txt b/ports/risc-v64/gnu/example_build/erbium/CMakeLists.txt index 244d7656e..51b077149 100644 --- a/ports/risc-v64/gnu/example_build/erbium/CMakeLists.txt +++ b/ports/risc-v64/gnu/example_build/erbium/CMakeLists.txt @@ -41,3 +41,28 @@ target_link_options(demo_threadx PRIVATE -Wl,--gc-sections -Wl,-Map=${CMAKE_CURRENT_BINARY_DIR}/demo_threadx.map ) + +function(add_erbium_test name source handler) + add_executable(${name} + ${ERBIUM_DIR}/entry.S + ${ERBIUM_DIR}/tx_initialize_low_level.S + ${ERBIUM_DIR}/board.c + ${ERBIUM_DIR}/hwtimer.c + ${ERBIUM_DIR}/plic.c + ${ERBIUM_DIR}/uart.c + ${source} + ${handler} + ) + target_include_directories(${name} PRIVATE ${ERBIUM_DIR}) + target_link_libraries(${name} PRIVATE threadx) + target_compile_options(${name} PRIVATE -ffreestanding) + target_link_options(${name} PRIVATE + -T${ERBIUM_DIR}/link.lds + -nostdlib + -Wl,--gc-sections + ) + set_target_properties(${name} PROPERTIES LINK_DEPENDS ${ERBIUM_DIR}/link.lds) +endfunction() + +add_erbium_test(test_uart_ticks ${ERBIUM_DIR}/test/test_uart_ticks.c ${ERBIUM_DIR}/trap.c) +add_erbium_test(test_plic_race ${ERBIUM_DIR}/test/test_plic_race.c ${ERBIUM_DIR}/test/test_plic_trap.c) diff --git a/ports/risc-v64/gnu/example_build/erbium/test/run_simulator_tests.sh b/ports/risc-v64/gnu/example_build/erbium/test/run_simulator_tests.sh new file mode 100755 index 000000000..7d54a5f8a --- /dev/null +++ b/ports/risc-v64/gnu/example_build/erbium/test/run_simulator_tests.sh @@ -0,0 +1,55 @@ +#!/bin/sh +############################################################################## +# 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. +# +# AI Disclosure: This file was largely AI-generated by Codex (GPT-6-Sol). +# The AI-generated portions may be considered public domain (CC0-1.0) +# and not subject to the project's licence. The human contributor has +# reviewed and verified that the code is correct. +# +# SPDX-License-Identifier: MIT and CC0-1.0 +############################################################################## + +set -eu + +ERBIUM_EMU=${ERBIUM_EMU:?Set ERBIUM_EMU to the erbium_emu executable} +TEST_DIR=$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd) +BUILD_DIR=${BUILD_DIR:-"${TEST_DIR}/build-tests"} +RUN_DIR=$(mktemp -d) +trap 'rm -rf "$RUN_DIR"' EXIT HUP INT TERM +failed=0 + +cmake -S "$TEST_DIR" -B "$BUILD_DIR" -GNinja \ + -DCMAKE_TOOLCHAIN_FILE="$TEST_DIR/erbium_gnu.cmake" +cmake --build "$BUILD_DIR" --target test_uart_ticks test_plic_race + +for name in uart_ticks plic_race; do + case "$name" in + uart_ticks) + cycles=20000000 + expected=TEST_UART_NO_LOST_TICKS + ;; + plic_race) + cycles=50000000 + expected=TEST_PLIC_NO_LOST_UPDATE + ;; + esac + "$ERBIUM_EMU" -elf_load "$BUILD_DIR/test_$name" \ + -reset_pc 0x40000200 -minions 1 -single_thread \ + -max_cycles "$cycles" -uart_rx_file /dev/null \ + -uart_tx_file "$RUN_DIR/$name.uart" > "$RUN_DIR/$name.run" 2>&1 || true + if grep -q -F "$expected" "$RUN_DIR/$name.uart" && + grep -q -F 'max cycles reached' "$RUN_DIR/$name.run"; then + printf '%s: PASS\n' "$name" + else + printf '%s: FAIL: ' "$name" + grep -Eo 'TEST_[A-Z_]+' "$RUN_DIR/$name.uart" | tail -1 || true + failed=1 + fi +done + +exit "$failed" diff --git a/ports/risc-v64/gnu/example_build/erbium/test/test_plic_race.c b/ports/risc-v64/gnu/example_build/erbium/test/test_plic_race.c new file mode 100644 index 000000000..d6f2a3b57 --- /dev/null +++ b/ports/risc-v64/gnu/example_build/erbium/test/test_plic_race.c @@ -0,0 +1,90 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Codex (GPT-6-Sol). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + ***************************************************************************/ + +#include "tx_api.h" +#include "csr.h" +#include "hwtimer.h" +#include "plic.h" +#include "uart.h" + +#define TEST_TIMER_INTERVAL 8u +#define TEST_REQUIRED_INTERRUPTS 10000u + +static TX_THREAD test_thread; +static UCHAR test_stack[2048]; +volatile unsigned int test_irq_count; +volatile unsigned int test_expected_bit; + +/* Run the kernel with the board's normal interrupt setup. */ +int main(void) +{ + tx_kernel_enter(); + return 0; +} + +/* Compare the PLIC word and the ISR's expected bit atomically. */ +static int test_bit_matches(void) +{ + int enabled = riscv_mintr_save(); + /* MISRA C:2012 Rule 11.4 deviation: the PLIC has a fixed MMIO address. */ + uint32_t actual = *(volatile uint32_t *)PLIC_MENABLE(0u) & (1u << 2); + unsigned int expected = test_expected_bit; + + riscv_mintr_restore(enabled); + return actual == (expected != 0u ? (1u << 2) : 0u); +} + +/* Change source 1 while the timer ISR changes source 2. */ +static void test_entry(ULONG input) +{ + (void)input; + /* MISRA C:2012 Rule 11.4 deviation: the timer has a fixed MMIO address. */ + *(volatile uint64_t *)ERBIUM_MTIMECMP = + *(volatile uint64_t *)ERBIUM_MTIME + TEST_TIMER_INTERVAL; + + while (test_irq_count < TEST_REQUIRED_INTERRUPTS) + { + plic_irq_enable(1); + if (!test_bit_matches()) + { + uart_puts("TEST_PLIC_LOST_UPDATE"); + for (;;) + { + } + } + plic_irq_disable(1); + if (!test_bit_matches()) + { + uart_puts("TEST_PLIC_LOST_UPDATE"); + for (;;) + { + } + } + } + + uart_puts("TEST_PLIC_NO_LOST_UPDATE"); + for (;;) + { + } +} + +/* Start one test thread. */ +void tx_application_define(void *first_unused_memory) +{ + (void)first_unused_memory; + (void)tx_thread_create(&test_thread, "plic test", test_entry, 0u, + test_stack, sizeof(test_stack), 1u, 1u, + TX_NO_TIME_SLICE, TX_AUTO_START); +} diff --git a/ports/risc-v64/gnu/example_build/erbium/test/test_plic_trap.c b/ports/risc-v64/gnu/example_build/erbium/test/test_plic_trap.c new file mode 100644 index 000000000..8dabb42b2 --- /dev/null +++ b/ports/risc-v64/gnu/example_build/erbium/test/test_plic_trap.c @@ -0,0 +1,55 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Codex (GPT-6-Sol). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + ***************************************************************************/ + +#include "tx_api.h" +#include "hwtimer.h" +#include "plic.h" +#include "uart.h" +#include + +#define TEST_TIMER_INTERVAL 8u +#define TEST_MCAUSE_TIMER (((uintptr_t)1u << 63) | 7u) + +extern volatile unsigned int test_irq_count; +extern volatile unsigned int test_expected_bit; + +/* Toggle source 2 in timer context to preempt source 1 updates. */ +void trap_handler(uintptr_t mcause, uintptr_t mepc, uintptr_t mtval) +{ + (void)mepc; + (void)mtval; + if (mcause != TEST_MCAUSE_TIMER) + { + uart_puts("TEST_PLIC_UNEXPECTED_TRAP"); + for (;;) + { + } + } + + /* MISRA C:2012 Rule 11.4 deviation: the timer has a fixed MMIO address. */ + *(volatile uint64_t *)ERBIUM_MTIMECMP = + *(volatile uint64_t *)ERBIUM_MTIME + TEST_TIMER_INTERVAL; + if (test_expected_bit == 0u) + { + plic_irq_enable(2); + test_expected_bit = 1u; + } + else + { + plic_irq_disable(2); + test_expected_bit = 0u; + } + test_irq_count++; +} diff --git a/ports/risc-v64/gnu/example_build/erbium/test/test_uart_ticks.c b/ports/risc-v64/gnu/example_build/erbium/test/test_uart_ticks.c new file mode 100644 index 000000000..188af2e7d --- /dev/null +++ b/ports/risc-v64/gnu/example_build/erbium/test/test_uart_ticks.c @@ -0,0 +1,81 @@ +/*************************************************************************** + * 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. + * + * AI Disclosure: This file was largely AI-generated by Codex (GPT-6-Sol). + * The AI-generated portions may be considered public domain (CC0-1.0) + * and not subject to the project's licence. The human contributor has + * reviewed and verified that the code is correct. + * + * SPDX-License-Identifier: MIT and CC0-1.0 + ***************************************************************************/ + +#include "tx_api.h" +#include "uart.h" +#include "hwtimer.h" + +#define TEST_TEXT_SIZE 160000u + +static TX_THREAD test_thread; +static UCHAR test_stack[2048]; +static char test_text[TEST_TEXT_SIZE + 1u]; + +/* Run the kernel with the board's normal interrupt setup. */ +int main(void) +{ + tx_kernel_enter(); + return 0; +} + +/* Print long enough to span several hardware timer intervals. */ +static void test_entry(ULONG input) +{ + uint64_t start; + uint64_t elapsed; + ULONG ticks_before; + ULONG ticks_after; + size_t i; + + (void)input; + for (i = 0u; i < TEST_TEXT_SIZE; i++) + { + test_text[i] = 'X'; + } + test_text[TEST_TEXT_SIZE] = '\0'; + + /* MISRA C:2012 Rule 11.4 deviation: the timer has a fixed MMIO address. */ + start = *(volatile uint64_t *)ERBIUM_MTIME; + ticks_before = tx_time_get(); + (void)uart_puts(test_text); + elapsed = *(volatile uint64_t *)ERBIUM_MTIME - start; + ticks_after = tx_time_get(); + + if (elapsed <= (2u * TICKNUM_PER_TIMER)) + { + uart_puts("TEST_UART_TOO_SHORT"); + } + else if ((ticks_after - ticks_before) < 2u) + { + uart_puts("TEST_UART_LOST_TICKS"); + } + else + { + uart_puts("TEST_UART_NO_LOST_TICKS"); + } + + for (;;) + { + } +} + +/* Start one test thread. */ +void tx_application_define(void *first_unused_memory) +{ + (void)first_unused_memory; + (void)tx_thread_create(&test_thread, "uart test", test_entry, 0u, + test_stack, sizeof(test_stack), 1u, 1u, + TX_NO_TIME_SLICE, TX_AUTO_START); +} From fb4a8761fc04cad7d259f6563c85460f8aeb6a7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Wed, 30 Sep 2026 09:55:51 -0400 Subject: [PATCH 179/181] Fixed Erbium interrupt masking and PLIC update races Polling UART output held machine interrupts off for an entire string, which could lose ThreadX ticks. PLIC enable-word changes could overwrite an update made by an interrupt handler. The UART now polls with interrupts enabled and protects only the final status check and byte write. PLIC enable and disable changes are protected across their read-modify-write. The README explains the new simulator tests. Both simulator tests failed on the original code and passed with these fixes. The 100-million-cycle demo run reported all eight threads and five thread 0 wakeups. AI disclosure and port consistency checks passed. No silicon run. Assisted-by: Codex (GPT-6-Sol) --- .../gnu/example_build/erbium/README.md | 15 ++++++++ .../risc-v64/gnu/example_build/erbium/plic.c | 6 ++++ .../risc-v64/gnu/example_build/erbium/uart.c | 35 ++++++++++--------- 3 files changed, 40 insertions(+), 16 deletions(-) diff --git a/ports/risc-v64/gnu/example_build/erbium/README.md b/ports/risc-v64/gnu/example_build/erbium/README.md index 826d7cab7..8cfa28282 100644 --- a/ports/risc-v64/gnu/example_build/erbium/README.md +++ b/ports/risc-v64/gnu/example_build/erbium/README.md @@ -99,6 +99,20 @@ simulated cycles, so the 100,000,000-cycle run shows `thread_0` five times. The simulator verifies register accesses, the trap flow and the console. It does not verify baud timing or the timer rate of real silicon. +## Simulator regression tests + +With `erbium_emu` on `PATH`, run: + +```bash +ERBIUM_EMU=erbium_emu ./test/run_simulator_tests.sh +``` + +The UART test checks that a long polling write does not lose ThreadX ticks. +The PLIC test changes one source in timer context while a thread changes +another, and checks that neither update is lost. The runner builds both +images with CMake and Ninja and reports a failure if either check fails. +These tests use the simulator's UART drain rate, not physical baud timing. + ## Files | File | Purpose | @@ -114,6 +128,7 @@ It does not verify baud timing or the timer rate of real silicon. | `link.lds` | MRAM layout | | `erbium_gnu.cmake` | Toolchain file: `rv64imc_zicsr_zifencei`, `lp64` | | `CMakeLists.txt`, `build.sh` | Build of the library and the demo | +| `test/` | Simulator tests for UART timekeeping and PLIC updates | ## References diff --git a/ports/risc-v64/gnu/example_build/erbium/plic.c b/ports/risc-v64/gnu/example_build/erbium/plic.c index 93b1f3171..9ca25f1b0 100644 --- a/ports/risc-v64/gnu/example_build/erbium/plic.c +++ b/ports/risc-v64/gnu/example_build/erbium/plic.c @@ -29,21 +29,27 @@ static int plic_source_valid(int irqno) void plic_irq_enable(int irqno) { volatile uint32_t *reg = (volatile uint32_t *)PLIC_MENABLE(riscv_get_core()); + int intr_enable; if (!plic_source_valid(irqno)) return; + intr_enable = riscv_mintr_save(); *reg = *reg | (1u << (unsigned int)irqno); + riscv_mintr_restore(intr_enable); } void plic_irq_disable(int irqno) { volatile uint32_t *reg = (volatile uint32_t *)PLIC_MENABLE(riscv_get_core()); + int intr_enable; if (!plic_source_valid(irqno)) return; + intr_enable = riscv_mintr_save(); *reg = *reg & ~(1u << (unsigned int)irqno); + riscv_mintr_restore(intr_enable); } int plic_register_callback(int irqno, irq_callback callback) diff --git a/ports/risc-v64/gnu/example_build/erbium/uart.c b/ports/risc-v64/gnu/example_build/erbium/uart.c index ee065e8a7..1b8f2dfc7 100644 --- a/ports/risc-v64/gnu/example_build/erbium/uart.c +++ b/ports/risc-v64/gnu/example_build/erbium/uart.c @@ -78,29 +78,32 @@ int uart_init(void) return 0; } -static inline void uart_putc_nolock(int ch) -{ - while ((UART_REG(UART_STATUS) & STATUS_TX_FULL) != 0u) - ; - UART_REG(UART_TX) = (uint32_t)(ch & 0xFF); -} - int uart_putc(int ch) { - int intr_enable = riscv_mintr_save(); - uart_putc_nolock(ch); - riscv_mintr_restore(intr_enable); - return 1; + int intr_enable; + + for (;;) + { + while ((UART_REG(UART_STATUS) & STATUS_TX_FULL) != 0u) + ; + + intr_enable = riscv_mintr_save(); + if ((UART_REG(UART_STATUS) & STATUS_TX_FULL) == 0u) + { + UART_REG(UART_TX) = (uint32_t)(ch & 0xFF); + riscv_mintr_restore(intr_enable); + return 1; + } + riscv_mintr_restore(intr_enable); + } } int uart_puts(const char *str) { int i; - int intr_enable = riscv_mintr_save(); for (i = 0; str[i] != 0; i++) - uart_putc_nolock(str[i]); - uart_putc_nolock('\r'); - uart_putc_nolock('\n'); - riscv_mintr_restore(intr_enable); + uart_putc(str[i]); + uart_putc('\r'); + uart_putc('\n'); return i; } From f09846d75ace90fc57fffe89ea8c286db3a08d6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Wed, 30 Sep 2026 12:00:52 -0400 Subject: [PATCH 180/181] Made the install step timeout a template input (#790) The install step is capped at ten minutes for every consumer. That suits a consumer that only installs packages, which is all of them bar one: measured install steps run 0.2 to 0.5 minutes, and NetX Duo's secure interoperability job, which builds OpenSSL and wolfSSL from source, takes 2.1 to 2.8. GUIX does not fit. Its regression suite is staged across the install, build and test steps to keep each inside its limit, so the install step also builds a configuration, and on a slow mirror the packages and the ThreadX checkout leave too little of the ten minutes for it. Three runs on dev were lost that way. The cap is now an input defaulting to ten, so a consumer that needs longer asks for it and every other consumer keeps the timeout it has today. Assisted-by: Claude Code (Opus 5) --- .github/workflows/regression_template.yml | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/.github/workflows/regression_template.yml b/.github/workflows/regression_template.yml index 267b1b585..eca637def 100644 --- a/.github/workflows/regression_template.yml +++ b/.github/workflows/regression_template.yml @@ -21,6 +21,17 @@ on: default: './test/cmake' required: false type: string + # Minutes for the install step. Ten suits a consumer that only installs + # packages, which is all of them bar GUIX: measured install steps run 0.2 + # to 0.5 minutes, and NetX Duo's secure interoperability job, which builds + # OpenSSL and wolfSSL from source, takes 2.1 to 2.8. GUIX also builds a + # configuration here, because its regression suite is staged across the + # install, build and test steps to fit their limits, so it needs longer. + # The default keeps every other consumer exactly where it was. + install_timeout_minutes: + default: 10 + required: false + type: number skip_test: default: false required: false @@ -108,7 +119,7 @@ jobs: # stall ran until the six hour job limit and cost a whole run rather than # failing and being retried. - name: Install softwares - timeout-minutes: 10 + timeout-minutes: ${{ inputs.install_timeout_minutes }} run: ${{ inputs.install_script }} # TX_COVERAGE instruments every build configuration rather than only the one From 729959fed0fc380d68c2bdcb2b4d7a5430f5c21a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fr=C3=A9d=C3=A9ric=20Desbiens?= Date: Wed, 30 Sep 2026 12:42:59 -0400 Subject: [PATCH 181/181] Made the build step timeout a template input (#791) The build step is capped at fifteen minutes for every consumer, on the same shape of assumption the install step carried: that a consumer builds once. Measured build steps are 0.5 minutes for LevelX, 1.1 for FileX and 6.4 for USBX, so fifteen is right for them. GUIX builds five configurations in that step, because its suite is staged across the three steps, and reaches 11.8 minutes. That is 79 per cent of the cap, and it grows with every regression test added -- six advisories landed tests this week. The cap is now an input defaulting to fifteen, matching install_timeout_minutes above. No consumer changes unless it asks to. Assisted-by: Claude Code (Opus 5) --- .github/workflows/regression_template.yml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/.github/workflows/regression_template.yml b/.github/workflows/regression_template.yml index eca637def..064f2ebea 100644 --- a/.github/workflows/regression_template.yml +++ b/.github/workflows/regression_template.yml @@ -32,6 +32,15 @@ on: default: 10 required: false type: number + # Minutes for the build step, on the same reasoning as the install step + # above. Fifteen suits a consumer that builds once: measured build steps + # are 0.5 minutes for LevelX, 1.1 for FileX and 6.4 for USBX. GUIX builds + # five configurations here as part of its staging and reaches 11.8, which + # is 79 per cent of the cap and shrinking as tests are added. + build_timeout_minutes: + default: 15 + required: false + type: number skip_test: default: false required: false @@ -127,7 +136,7 @@ jobs: # test: the build is where -fprofile-arcs is decided, and the test run is # where the reports are collected and merged. - name: Build - timeout-minutes: 15 + timeout-minutes: ${{ inputs.build_timeout_minutes }} env: TX_COVERAGE: ${{ inputs.skip_coverage && 'OFF' || 'ON' }} run: ${{ inputs.build_script }}